Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 16362adb76 |
@@ -1,453 +0,0 @@
|
||||
# Configuration Reference Guide
|
||||
|
||||
This guide provides a comprehensive reference for configuring CleverAgents. Configuration is primarily managed through environment variables, with sensible defaults for most settings.
|
||||
|
||||
## Overview
|
||||
|
||||
CleverAgents uses a **Pydantic-based settings system** that reads configuration from environment variables with the `CLEVERAGENTS_` prefix. The configuration system is designed to be:
|
||||
|
||||
- **Environment-first**: All configuration comes from environment variables, making it ideal for containerized and cloud-native deployments
|
||||
- **Hierarchical**: Settings are organized by functional area (runtime, providers, storage, observability, etc.)
|
||||
- **Validated**: All configuration values are validated at startup with clear error messages
|
||||
- **Sensible defaults**: Most settings have reasonable defaults suitable for development and production
|
||||
|
||||
### Configuration Loading Order
|
||||
|
||||
1. **Environment variables** (highest priority) — `CLEVERAGENTS_*` prefixed variables
|
||||
2. **Provider-specific environment variables** — Native provider variables (e.g., `OPENAI_API_KEY`)
|
||||
3. **Default values** — Hardcoded defaults in the settings schema
|
||||
|
||||
When a setting is not explicitly configured, the system falls back to the next level in the order above.
|
||||
|
||||
### Configuration File Locations
|
||||
|
||||
CleverAgents stores configuration and data in the following locations:
|
||||
|
||||
| Purpose | Default Location | Environment Variable |
|
||||
|---------|------------------|----------------------|
|
||||
| User data (sessions, personas, etc.) | `~/.cleveragents/` | `CLEVERAGENTS_DATA_DIR` |
|
||||
| Database | `~/.cleveragents/cleveragents.db` | `CLEVERAGENTS_DATABASE_URL` |
|
||||
| Logs | `./logs/` | `CLEVERAGENTS_LOG_DIR` |
|
||||
| Storage (plans, resources, etc.) | `./data/` | `CLEVERAGENTS_STORAGE_BASE_PATH` |
|
||||
| Vector store | `./.cleveragents/vector_store/` | `CLEVERAGENTS_VECTOR_STORE_PATH` |
|
||||
|
||||
## Environment Variables Reference
|
||||
|
||||
All environment variables are organized by functional area. Each entry includes:
|
||||
|
||||
- **Variable name** — The full `CLEVERAGENTS_*` environment variable name
|
||||
- **Type** — The expected data type (string, integer, boolean, etc.)
|
||||
- **Default** — The default value if not set
|
||||
- **Description** — What the setting controls
|
||||
- **Example** — A practical example value
|
||||
|
||||
### Runtime & Server Configuration
|
||||
|
||||
#### `CLEVERAGENTS_ENV`
|
||||
- **Type:** String
|
||||
- **Default:** `development`
|
||||
- **Valid values:** `development`, `production`, `staging`, `test`
|
||||
- **Description:** The runtime environment. Controls logging verbosity, debug features, and validation strictness.
|
||||
- **Example:** `export CLEVERAGENTS_ENV=production`
|
||||
|
||||
#### `CLEVERAGENTS_DEBUG_ENABLED`
|
||||
- **Type:** Boolean
|
||||
- **Default:** `false`
|
||||
- **Description:** Enable debug mode with verbose logging and additional runtime checks. Should never be enabled in production.
|
||||
- **Example:** `export CLEVERAGENTS_DEBUG_ENABLED=true`
|
||||
|
||||
#### `CLEVERAGENTS_SERVER_HOST`
|
||||
- **Type:** String (IP address)
|
||||
- **Default:** `0.0.0.0`
|
||||
- **Description:** The host address for the CleverAgents server to bind to.
|
||||
- **Example:** `export CLEVERAGENTS_SERVER_HOST=127.0.0.1`
|
||||
|
||||
#### `CLEVERAGENTS_SERVER_PORT`
|
||||
- **Type:** Integer
|
||||
- **Default:** `8080`
|
||||
- **Valid range:** 1-65535
|
||||
- **Description:** The port for the CleverAgents server to listen on.
|
||||
- **Example:** `export CLEVERAGENTS_SERVER_PORT=9000`
|
||||
|
||||
#### `CLEVERAGENTS_SERVER_RELOAD`
|
||||
- **Type:** Boolean
|
||||
- **Default:** `false`
|
||||
- **Description:** Enable auto-reload on code changes (development only). Never use in production.
|
||||
- **Example:** `export CLEVERAGENTS_SERVER_RELOAD=true`
|
||||
|
||||
#### `CLEVERAGENTS_SERVER_URL`
|
||||
- **Type:** String (URL)
|
||||
- **Default:** `None` (local mode)
|
||||
- **Description:** URL of a remote CleverAgents server to connect to. When set, the CLI operates in server mode.
|
||||
- **Example:** `export CLEVERAGENTS_SERVER_URL=https://cleveragents.example.com`
|
||||
|
||||
#### `CLEVERAGENTS_SERVER_TOKEN`
|
||||
- **Type:** String
|
||||
- **Default:** `None`
|
||||
- **Description:** Authentication token for connecting to a remote CleverAgents server. Required when `CLEVERAGENTS_SERVER_URL` is set.
|
||||
- **Example:** `export CLEVERAGENTS_SERVER_TOKEN=sk-1234567890abcdef`
|
||||
|
||||
### AI Provider Configuration
|
||||
|
||||
#### Provider API Keys
|
||||
|
||||
Each AI provider requires its API key to be configured. CleverAgents supports multiple providers simultaneously and automatically selects the best available one.
|
||||
|
||||
| Provider | Primary Variable | Fallback Variables | Example |
|
||||
|----------|------------------|-------------------|---------|
|
||||
| OpenAI | `OPENAI_API_KEY` | `CLEVERAGENTS_OPENAI_API_KEY` | `sk-proj-...` |
|
||||
| Anthropic | `ANTHROPIC_API_KEY` | `CLEVERAGENTS_ANTHROPIC_API_KEY` | `sk-ant-...` |
|
||||
| Google | `GOOGLE_API_KEY` | `GOOGLE_GENAI_API_KEY`, `CLEVERAGENTS_GOOGLE_API_KEY` | `AIza...` |
|
||||
| Azure OpenAI | `AZURE_OPENAI_API_KEY` | `AZURE_API_KEY`, `CLEVERAGENTS_AZURE_API_KEY` | `...` |
|
||||
| OpenRouter | `OPENROUTER_API_KEY` | `CLEVERAGENTS_OPENROUTER_API_KEY` | `sk-or-...` |
|
||||
| Gemini | `GEMINI_API_KEY` | `GOOGLE_GEMINI_API_KEY`, `CLEVERAGENTS_GEMINI_API_KEY` | `AIza...` |
|
||||
| Cohere | `COHERE_API_KEY` | `CLEVERAGENTS_COHERE_API_KEY` | `...` |
|
||||
| Groq | `GROQ_API_KEY` | `CLEVERAGENTS_GROQ_API_KEY` | `gsk_...` |
|
||||
| Together | `TOGETHER_API_KEY` | `CLEVERAGENTS_TOGETHER_API_KEY` | `...` |
|
||||
| HuggingFace | `HF_TOKEN` | `HUGGINGFACEHUB_API_TOKEN`, `HUGGING_FACE_HUB_TOKEN` | `hf_...` |
|
||||
| Perplexity | `PERPLEXITY_API_KEY` | `CLEVERAGENTS_PERPLEXITY_API_KEY` | `pplx-...` |
|
||||
|
||||
#### `CLEVERAGENTS_DEFAULT_PROVIDER`
|
||||
- **Type:** String
|
||||
- **Default:** `None` (auto-detect from configured providers)
|
||||
- **Valid values:** `openai`, `anthropic`, `google`, `azure`, `openrouter`, `gemini`, `cohere`, `groq`, `together`, `huggingface`, `perplexity`
|
||||
- **Description:** Pin the default AI provider. When not set, the system automatically selects the first available configured provider in the fallback order.
|
||||
- **Example:** `export CLEVERAGENTS_DEFAULT_PROVIDER=anthropic`
|
||||
|
||||
#### `CLEVERAGENTS_DEFAULT_MODEL`
|
||||
- **Type:** String
|
||||
- **Default:** `None` (provider-specific default)
|
||||
- **Description:** Pin the default model for the selected provider. When not set, each provider's published default is used (e.g., `gpt-4o` for OpenAI, `claude-sonnet-4-20250514` for Anthropic).
|
||||
- **Example:** `export CLEVERAGENTS_DEFAULT_MODEL=gpt-4-turbo`
|
||||
|
||||
#### `CLEVERAGENTS_MOCK_PROVIDERS`
|
||||
- **Type:** Boolean
|
||||
- **Default:** `false`
|
||||
- **Description:** Enable mock AI providers for testing. Must not be used in production. Useful for development and CI/CD pipelines.
|
||||
- **Example:** `export CLEVERAGENTS_MOCK_PROVIDERS=true`
|
||||
|
||||
#### `CLEVERAGENTS_TESTING_USE_MOCK_AI`
|
||||
- **Type:** Boolean
|
||||
- **Default:** `false`
|
||||
- **Description:** Force the in-repo mock provider for Behave/Robot test suites to prevent external API calls.
|
||||
- **Example:** `export CLEVERAGENTS_TESTING_USE_MOCK_AI=true`
|
||||
|
||||
### Logging & Paths
|
||||
|
||||
#### `CLEVERAGENTS_LOG_LEVEL`
|
||||
- **Type:** String
|
||||
- **Default:** `INFO`
|
||||
- **Valid values:** `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL`
|
||||
- **Description:** The logging level for standard output and file logs.
|
||||
- **Example:** `export CLEVERAGENTS_LOG_LEVEL=DEBUG`
|
||||
|
||||
#### `CLEVERAGENTS_LOG_DIR`
|
||||
- **Type:** Path
|
||||
- **Default:** `./logs/`
|
||||
- **Description:** Directory where log files are written.
|
||||
- **Example:** `export CLEVERAGENTS_LOG_DIR=/var/log/cleveragents`
|
||||
|
||||
#### `CLEVERAGENTS_DATA_DIR`
|
||||
- **Type:** Path
|
||||
- **Default:** `~/.cleveragents/`
|
||||
- **Description:** Directory for user data, sessions, personas, and other persistent state.
|
||||
- **Example:** `export CLEVERAGENTS_DATA_DIR=/data/cleveragents`
|
||||
|
||||
#### `CLEVERAGENTS_STORAGE_BASE_PATH`
|
||||
- **Type:** Path
|
||||
- **Default:** `./data/`
|
||||
- **Description:** Base directory for plan storage, checkpoints, and other runtime data.
|
||||
- **Example:** `export CLEVERAGENTS_STORAGE_BASE_PATH=/storage/cleveragents`
|
||||
|
||||
### Database & Persistence
|
||||
|
||||
#### `CLEVERAGENTS_DATABASE_URL`
|
||||
- **Type:** String (database URL)
|
||||
- **Default:** `sqlite:///$HOME/.cleveragents/cleveragents.db`
|
||||
- **Supported formats:**
|
||||
- SQLite: `sqlite:///path/to/database.db`
|
||||
- PostgreSQL: `postgresql://user:password@host:port/database`
|
||||
- MySQL: `mysql+pymysql://user:password@host:port/database`
|
||||
- DuckDB: `duckdb:///path/to/database.duckdb`
|
||||
- **Description:** The database URL for storing sessions, plans, and other persistent data.
|
||||
- **Example:** `export CLEVERAGENTS_DATABASE_URL=postgresql://user:pass@localhost/cleveragents`
|
||||
|
||||
### Cost Controls & Budgets
|
||||
|
||||
#### `CLEVERAGENTS_SESSION_MAX_COST_USD`
|
||||
- **Type:** Float
|
||||
- **Default:** `None` (unlimited)
|
||||
- **Valid range:** >= 0.0
|
||||
- **Description:** Maximum USD spend per session across all plans. `None` means unlimited.
|
||||
- **Example:** `export CLEVERAGENTS_SESSION_MAX_COST_USD=100.00`
|
||||
|
||||
#### `CLEVERAGENTS_ORG_MAX_COST_USD`
|
||||
- **Type:** Float
|
||||
- **Default:** `None` (unlimited)
|
||||
- **Valid range:** >= 0.0
|
||||
- **Description:** Maximum USD spend per organization across all sessions. `None` means unlimited.
|
||||
- **Example:** `export CLEVERAGENTS_ORG_MAX_COST_USD=1000.00`
|
||||
|
||||
#### `CLEVERAGENTS_BUDGET_PER_PLAN`
|
||||
- **Type:** Float
|
||||
- **Default:** `None` (unlimited)
|
||||
- **Valid range:** >= 0.0
|
||||
- **Description:** Maximum USD spend per plan execution. `None` means unlimited.
|
||||
- **Example:** `export CLEVERAGENTS_BUDGET_PER_PLAN=50.00`
|
||||
|
||||
#### `CLEVERAGENTS_BUDGET_PER_DAY`
|
||||
- **Type:** Float
|
||||
- **Default:** `None` (unlimited)
|
||||
- **Valid range:** >= 0.0
|
||||
- **Description:** Maximum USD spend per calendar day across all plans. `None` means unlimited.
|
||||
- **Example:** `export CLEVERAGENTS_BUDGET_PER_DAY=500.00`
|
||||
|
||||
### Observability & Logging
|
||||
|
||||
#### LangSmith Tracing
|
||||
|
||||
#### `CLEVERAGENTS_LANGSMITH_ENABLED`
|
||||
- **Type:** Boolean
|
||||
- **Default:** `false`
|
||||
- **Aliases:** `LANGCHAIN_TRACING_V2`, `LANGSMITH_TRACING_V2`
|
||||
- **Description:** Enable LangSmith tracing for LangChain/LangGraph agents.
|
||||
- **Example:** `export CLEVERAGENTS_LANGSMITH_ENABLED=true`
|
||||
|
||||
#### `CLEVERAGENTS_LANGSMITH_API_KEY`
|
||||
- **Type:** String
|
||||
- **Default:** `None`
|
||||
- **Aliases:** `LANGSMITH_API_KEY`, `LANGCHAIN_API_KEY`
|
||||
- **Description:** API key for LangSmith. Required when tracing is enabled.
|
||||
- **Example:** `export CLEVERAGENTS_LANGSMITH_API_KEY=ls_...`
|
||||
|
||||
#### `CLEVERAGENTS_LANGSMITH_PROJECT`
|
||||
- **Type:** String
|
||||
- **Default:** `None`
|
||||
- **Aliases:** `LANGSMITH_PROJECT`, `LANGCHAIN_PROJECT`
|
||||
- **Description:** LangSmith project name. Required when tracing is enabled.
|
||||
- **Example:** `export CLEVERAGENTS_LANGSMITH_PROJECT=my-project`
|
||||
|
||||
### Cleanup & Retention Policies
|
||||
|
||||
#### `CLEVERAGENTS_CLEANUP_SANDBOX_MAX_AGE_HOURS`
|
||||
- **Type:** Integer
|
||||
- **Default:** `48`
|
||||
- **Valid range:** >= 1
|
||||
- **Description:** Maximum age (in hours) before stale sandboxes are eligible for cleanup.
|
||||
- **Example:** `export CLEVERAGENTS_CLEANUP_SANDBOX_MAX_AGE_HOURS=72`
|
||||
|
||||
#### `CLEVERAGENTS_CHECKPOINT_MAX`
|
||||
- **Type:** Integer
|
||||
- **Default:** `50`
|
||||
- **Valid range:** >= 2
|
||||
- **Description:** Maximum number of checkpoints to keep per plan. Oldest checkpoints are pruned first, but the first and most recent are always preserved.
|
||||
- **Example:** `export CLEVERAGENTS_CHECKPOINT_MAX=100`
|
||||
|
||||
### Audit Logging
|
||||
|
||||
#### `CLEVERAGENTS_AUDIT_RETENTION_DAYS`
|
||||
- **Type:** Integer
|
||||
- **Default:** `0` (keep indefinitely)
|
||||
- **Valid range:** >= 0
|
||||
- **Description:** Days to retain audit log entries before pruning. `0` means keep indefinitely (spec default for compliance).
|
||||
- **Example:** `export CLEVERAGENTS_AUDIT_RETENTION_DAYS=365`
|
||||
|
||||
#### `CLEVERAGENTS_AUDIT_ASYNC`
|
||||
- **Type:** Boolean
|
||||
- **Default:** `true`
|
||||
- **Description:** When true, audit entries are written asynchronously via a write-behind queue on a background thread. Set to false for synchronous behavior (useful for debugging).
|
||||
- **Example:** `export CLEVERAGENTS_AUDIT_ASYNC=false`
|
||||
|
||||
### Metrics & Observability
|
||||
|
||||
#### `CLEVERAGENTS_METRICS_ENABLED`
|
||||
- **Type:** Boolean
|
||||
- **Default:** `true`
|
||||
- **Description:** Enable structured metric collection and emission.
|
||||
- **Example:** `export CLEVERAGENTS_METRICS_ENABLED=false`
|
||||
|
||||
#### `CLEVERAGENTS_METRICS_EXPORT_PROMETHEUS`
|
||||
- **Type:** Boolean
|
||||
- **Default:** `false`
|
||||
- **Description:** Enable Prometheus metrics export endpoint.
|
||||
- **Example:** `export CLEVERAGENTS_METRICS_EXPORT_PROMETHEUS=true`
|
||||
|
||||
### Retry & Circuit Breaker Configuration
|
||||
|
||||
#### `CLEVERAGENTS_RETRY_MAX_ATTEMPTS`
|
||||
- **Type:** Integer
|
||||
- **Default:** `3`
|
||||
- **Valid range:** 1-50
|
||||
- **Description:** Default maximum retry attempts for service operations.
|
||||
- **Example:** `export CLEVERAGENTS_RETRY_MAX_ATTEMPTS=5`
|
||||
|
||||
#### `CLEVERAGENTS_RETRY_BASE_DELAY`
|
||||
- **Type:** Float
|
||||
- **Default:** `1.0`
|
||||
- **Valid range:** 0.0-300.0
|
||||
- **Description:** Default base delay in seconds between retries.
|
||||
- **Example:** `export CLEVERAGENTS_RETRY_BASE_DELAY=0.5`
|
||||
|
||||
#### `CLEVERAGENTS_RETRY_MAX_DELAY`
|
||||
- **Type:** Float
|
||||
- **Default:** `60.0`
|
||||
- **Valid range:** 0.0-3600.0
|
||||
- **Description:** Default maximum delay in seconds between retries.
|
||||
- **Example:** `export CLEVERAGENTS_RETRY_MAX_DELAY=120.0`
|
||||
|
||||
#### `CLEVERAGENTS_RETRY_BACKOFF_STRATEGY`
|
||||
- **Type:** String
|
||||
- **Default:** `exponential`
|
||||
- **Valid values:** `exponential`, `linear`, `fixed`, `jitter`, `none`
|
||||
- **Description:** Default backoff strategy for retries.
|
||||
- **Example:** `export CLEVERAGENTS_RETRY_BACKOFF_STRATEGY=linear`
|
||||
|
||||
### Security & Secrets
|
||||
|
||||
#### `CLEVERAGENTS_SHOW_SECRETS`
|
||||
- **Type:** Boolean
|
||||
- **Default:** `false`
|
||||
- **Description:** When true, secrets are shown in CLI output and logs. Should never be enabled in production.
|
||||
- **Example:** `export CLEVERAGENTS_SHOW_SECRETS=true`
|
||||
|
||||
### Automation & Output
|
||||
|
||||
#### `CLEVERAGENTS_AUTOMATION_PROFILE`
|
||||
- **Type:** String
|
||||
- **Default:** `` (empty, manual mode)
|
||||
- **Valid values:** `manual`, `auto`, `full-auto` (or custom profile names)
|
||||
- **Description:** Default automation profile name controlling plan execution behavior.
|
||||
- **Example:** `export CLEVERAGENTS_AUTOMATION_PROFILE=auto`
|
||||
|
||||
#### `CLEVERAGENTS_FORMAT`
|
||||
- **Type:** String
|
||||
- **Default:** `None` (uses default format)
|
||||
- **Valid values:** `json`, `markdown`, `text`, `yaml`
|
||||
- **Description:** Default output format for CLI commands.
|
||||
- **Example:** `export CLEVERAGENTS_FORMAT=json`
|
||||
|
||||
## Configuration Best Practices
|
||||
|
||||
### Development Environment
|
||||
|
||||
For local development, create a `.env` file in your project root:
|
||||
|
||||
```bash
|
||||
# .env
|
||||
CLEVERAGENTS_ENV=development
|
||||
CLEVERAGENTS_DEBUG_ENABLED=true
|
||||
CLEVERAGENTS_LOG_LEVEL=DEBUG
|
||||
OPENAI_API_KEY=sk-proj-...
|
||||
CLEVERAGENTS_DATABASE_URL=sqlite:///./dev.db
|
||||
```
|
||||
|
||||
### Production Environment
|
||||
|
||||
For production deployments:
|
||||
|
||||
```bash
|
||||
# Use strong, randomly generated secrets
|
||||
export CLEVERAGENTS_ENV=production
|
||||
export CLEVERAGENTS_DEBUG_ENABLED=false
|
||||
export CLEVERAGENTS_LOG_LEVEL=WARNING
|
||||
export CLEVERAGENTS_SHOW_SECRETS=false
|
||||
|
||||
# Use a production database
|
||||
export CLEVERAGENTS_DATABASE_URL=postgresql://user:password@db.example.com/cleveragents
|
||||
|
||||
# Configure cost controls
|
||||
export CLEVERAGENTS_SESSION_MAX_COST_USD=100
|
||||
export CLEVERAGENTS_ORG_MAX_COST_USD=1000
|
||||
|
||||
# Enable observability
|
||||
export CLEVERAGENTS_METRICS_ENABLED=true
|
||||
export CLEVERAGENTS_LANGSMITH_ENABLED=true
|
||||
export CLEVERAGENTS_LANGSMITH_API_KEY=ls_...
|
||||
export CLEVERAGENTS_LANGSMITH_PROJECT=production
|
||||
```
|
||||
|
||||
### Multi-Provider Setup
|
||||
|
||||
To support multiple AI providers with automatic fallback:
|
||||
|
||||
```bash
|
||||
# Configure multiple providers
|
||||
export OPENAI_API_KEY=sk-proj-...
|
||||
export ANTHROPIC_API_KEY=sk-ant-...
|
||||
export GOOGLE_API_KEY=AIza...
|
||||
|
||||
# Set primary provider (optional)
|
||||
export CLEVERAGENTS_DEFAULT_PROVIDER=anthropic
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Secrets Management
|
||||
|
||||
1. **Never commit secrets** — Use environment variables or a secrets manager (Vault, AWS Secrets Manager, etc.)
|
||||
2. **Use strong API keys** — Ensure all provider API keys are strong and rotated regularly
|
||||
3. **Restrict access** — Limit who can view or modify configuration in your deployment
|
||||
4. **Audit logging** — Enable audit logging to track configuration changes and API usage
|
||||
5. **Redaction** — CleverAgents automatically redacts secrets in logs and output
|
||||
|
||||
### Database Security
|
||||
|
||||
- **Use encrypted connections** — Always use TLS/SSL for database connections
|
||||
- **Strong credentials** — Use strong, randomly generated database passwords
|
||||
- **Network isolation** — Restrict database access to authorized services only
|
||||
|
||||
### API Key Security
|
||||
|
||||
- **Rotate keys regularly** — Implement automated key rotation (e.g., monthly)
|
||||
- **Use scoped keys** — If your provider supports it, use keys with minimal required permissions
|
||||
- **Monitor usage** — Track API usage and set up alerts for unusual activity
|
||||
|
||||
## Troubleshooting Configuration Issues
|
||||
|
||||
### No AI Provider Configured
|
||||
|
||||
**Error:** `ValueError: No AI providers configured and mock_providers is disabled.`
|
||||
|
||||
**Solution:**
|
||||
1. Set at least one provider API key: `export OPENAI_API_KEY=sk-proj-...`
|
||||
2. Or enable mock providers for testing: `export CLEVERAGENTS_MOCK_PROVIDERS=true`
|
||||
3. Verify the key is set: `echo $OPENAI_API_KEY`
|
||||
|
||||
### LangSmith Configuration Incomplete
|
||||
|
||||
**Error:** `LangSmith API key is required` or `LangSmith project name is required`
|
||||
|
||||
**Solution:**
|
||||
1. Set both required variables:
|
||||
```bash
|
||||
export CLEVERAGENTS_LANGSMITH_API_KEY=ls_...
|
||||
export CLEVERAGENTS_LANGSMITH_PROJECT=my-project
|
||||
```
|
||||
2. Or disable LangSmith: `export CLEVERAGENTS_LANGSMITH_ENABLED=false`
|
||||
|
||||
### Database Connection Failed
|
||||
|
||||
**Error:** `sqlalchemy.exc.OperationalError: (psycopg2.OperationalError) could not connect to server`
|
||||
|
||||
**Solution:**
|
||||
1. Verify the database URL: `echo $CLEVERAGENTS_DATABASE_URL`
|
||||
2. Check database credentials and host
|
||||
3. Ensure the database is running and accessible
|
||||
|
||||
### Configuration Not Taking Effect
|
||||
|
||||
**Problem:** Environment variable changes not reflected
|
||||
|
||||
**Solution:**
|
||||
1. Verify the variable is set: `env | grep CLEVERAGENTS`
|
||||
2. Restart the application (singleton settings are cached)
|
||||
3. Check for typos in variable names (case-sensitive)
|
||||
4. Ensure the variable is exported: `export CLEVERAGENTS_VAR=value`
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Architecture Guide](../architecture.md) — System design and component overview
|
||||
- [API Reference - Configuration](../api/config.md) — Detailed API documentation
|
||||
- [Development Guide](../development/quality-automation.md) — Development setup and workflows
|
||||
- [Specification](../specification.md) — Authoritative design documentation
|
||||
- [FAQ](../faq.md) — Frequently asked questions
|
||||
@@ -0,0 +1,998 @@
|
||||
# Context Management Deep Dive
|
||||
|
||||
This comprehensive guide explores the Adaptive Context Management System (ACMS) architecture, strategies, and best practices for managing context in cleveragents-core.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Context Management Architecture Overview](#context-management-architecture-overview)
|
||||
2. [ACMS Pipeline Components](#acms-pipeline-components)
|
||||
3. [Context Strategy Patterns](#context-strategy-patterns)
|
||||
4. [Context Inheritance and Scope Resolution](#context-inheritance-and-scope-resolution)
|
||||
5. [Budget Allocation and Utilization Metrics](#budget-allocation-and-utilization-metrics)
|
||||
6. [Implementation Guide for Custom Strategies](#implementation-guide-for-custom-strategies)
|
||||
7. [Best Practices and Performance Considerations](#best-practices-and-performance-considerations)
|
||||
8. [Integration with Plan Execution](#integration-with-plan-execution)
|
||||
9. [Real-world Examples](#real-world-examples)
|
||||
|
||||
## Context Management Architecture Overview
|
||||
|
||||
### What is Context Management?
|
||||
|
||||
Context management is the process of selecting, prioritizing, and packaging relevant information from a project's knowledge base to provide to language models (LMs) during plan execution. The ACMS ensures that:
|
||||
|
||||
- **Relevance**: Only the most pertinent information is included
|
||||
- **Budget Compliance**: Token limits are strictly respected
|
||||
- **Efficiency**: Context assembly is fast and deterministic
|
||||
- **Traceability**: All context is provenance-tracked back to its source
|
||||
|
||||
### The Three-Tier Context Model
|
||||
|
||||
ACMS organizes context into three priority tiers:
|
||||
|
||||
| Tier | Purpose | Inclusion Strategy |
|
||||
|------|---------|-------------------|
|
||||
| **hot** | Critical context that must be included | Always included first; highest priority |
|
||||
| **warm** | Standard context included when budget allows | Included after hot tier; default tier |
|
||||
| **cold** | Low-priority context included only if space remains | Included last; only if budget permits |
|
||||
|
||||
> **Note:** In v1, tiers are sort-priority labels for ranking during assembly. Full storage-tier semantics with retention policies and promotion/demotion will be implemented in future milestones.
|
||||
|
||||
### Core Concepts
|
||||
|
||||
#### Context Fragments
|
||||
|
||||
A **ContextFragment** is the atomic unit of context. Each fragment represents a single piece of information:
|
||||
|
||||
```python
|
||||
ContextFragment(
|
||||
uko_node="project://myapp/src/main.py", # UKO URI of source
|
||||
content="def main(): ...", # Rendered text content
|
||||
detail_depth=3, # Depth level (0-9)
|
||||
token_count=100, # Actual token count
|
||||
relevance_score=0.9, # Relevance (0.0-1.0)
|
||||
tier="hot", # Priority tier
|
||||
provenance=FragmentProvenance( # Source tracking
|
||||
resource_uri="project://myapp/src/main.py",
|
||||
location="line 1-10",
|
||||
resource_type="source_file"
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
**Key Properties:**
|
||||
- `fragment_id`: Unique ULID identifier (auto-generated)
|
||||
- `content`: Max 1,000,000 characters
|
||||
- `detail_depth`: Resolved depth from 0 (MODULE_LISTING) to 9 (FULL_SOURCE)
|
||||
- `token_count`: Must be >= 0; used for budget calculations
|
||||
- `relevance_score`: 0.0 (irrelevant) to 1.0 (highly relevant)
|
||||
- `metadata`: Arbitrary key-value pairs (max 64 entries)
|
||||
- `created_at`: UTC timestamp for recency-based sorting
|
||||
|
||||
#### Context Budget
|
||||
|
||||
The **ContextBudget** defines token constraints:
|
||||
|
||||
```python
|
||||
budget = ContextBudget(
|
||||
max_tokens=4096, # Total available tokens
|
||||
reserved_tokens=512 # Tokens reserved for system prompt
|
||||
)
|
||||
# Available tokens = max_tokens - reserved_tokens = 3584
|
||||
```
|
||||
|
||||
**Budget Rules:**
|
||||
- `available_tokens = max_tokens - reserved_tokens`
|
||||
- `reserved_tokens` must be < `max_tokens`
|
||||
- Pipeline never exceeds `available_tokens`
|
||||
- Fragments exceeding budget are skipped
|
||||
|
||||
#### Context Payload
|
||||
|
||||
The assembled **ContextPayload** is the final output:
|
||||
|
||||
```python
|
||||
payload = ContextPayload(
|
||||
payload_id="01ARZ3NDEKTSV4RRFFQ69G5FAV", # ULID
|
||||
plan_id="plan-1", # Associated plan
|
||||
fragments=(fragment1, fragment2, ...), # Selected fragments
|
||||
total_tokens=2048, # Sum of fragment tokens
|
||||
budget=budget, # Budget used
|
||||
budget_used=0.57, # Fraction consumed
|
||||
strategies_used=("simple-keyword",), # Contributing strategies
|
||||
context_hash="abc123...", # SHA-256 hash
|
||||
preamble="Context includes 2 files...", # Optional summary
|
||||
provenance_map={...}, # Fragment ID -> provenance
|
||||
assembled_at=datetime.now(timezone.utc) # Assembly timestamp
|
||||
)
|
||||
```
|
||||
|
||||
**Key Properties:**
|
||||
- `is_within_budget`: True if total_tokens <= available_tokens
|
||||
- `remaining_tokens`: available_tokens - total_tokens
|
||||
|
||||
### Context Request Protocol (CRP)
|
||||
|
||||
The **ContextRequest** specifies what context is needed:
|
||||
|
||||
```python
|
||||
request = ContextRequest(
|
||||
focus_nodes=["project://myapp/src/main.py"], # Primary focus
|
||||
breadth=2, # Graph traversal breadth
|
||||
depth=3, # Graph traversal depth
|
||||
keywords=["async", "io"], # Search keywords
|
||||
resource_types=["source_file", "decision"], # Filter by type
|
||||
detail_level=3, # Desired detail depth
|
||||
temporal_window="7d", # Historical window
|
||||
strategy_hints=["semantic-embedding"], # Preferred strategies
|
||||
)
|
||||
```
|
||||
|
||||
## ACMS Pipeline Components
|
||||
|
||||
The ACMS pipeline implements a 10-component architecture across three phases:
|
||||
|
||||
### Phase 1: Strategy Orchestration
|
||||
|
||||
#### 1. StrategySelector
|
||||
|
||||
**Purpose**: Determine which strategies can handle the request.
|
||||
|
||||
**Process**:
|
||||
1. Poll all registered strategies with `can_handle(request)`
|
||||
2. Each strategy returns confidence (0.0-1.0)
|
||||
3. Select strategies above confidence threshold
|
||||
4. Rank by confidence score
|
||||
|
||||
#### 2. BudgetAllocator
|
||||
|
||||
**Purpose**: Distribute token budget among selected strategies.
|
||||
|
||||
**Allocation Strategies**:
|
||||
- **Proportional**: Allocate based on confidence scores
|
||||
- **Equal**: Divide equally among strategies
|
||||
- **Priority**: Allocate to highest-confidence first
|
||||
|
||||
#### 3. StrategyExecutor
|
||||
|
||||
**Purpose**: Execute strategies in parallel with timeout and circuit breaker.
|
||||
|
||||
**Features**:
|
||||
- Parallel execution with configurable workers
|
||||
- Per-strategy timeout (default 30s)
|
||||
- Circuit breaker after N failures
|
||||
- Graceful degradation on timeout
|
||||
|
||||
### Phase 2: Fragment Fusion
|
||||
|
||||
#### 4. FragmentDeduplicator
|
||||
|
||||
**Purpose**: Remove duplicate fragments based on UKO node and content hash.
|
||||
|
||||
**Deduplication Rules**:
|
||||
- Same `uko_node` + same content hash = duplicate
|
||||
- Keep fragment with highest relevance score
|
||||
- Preserve provenance from all duplicates
|
||||
|
||||
#### 5. DetailDepthResolver
|
||||
|
||||
**Purpose**: Resolve appropriate detail depth for each fragment.
|
||||
|
||||
**Resolution Logic**:
|
||||
- Start with requested detail level
|
||||
- Adjust based on token budget
|
||||
- Respect fragment's max depth
|
||||
- Prefer higher depth for hot tier
|
||||
|
||||
#### 6. FragmentScorer
|
||||
|
||||
**Purpose**: Score fragments based on multiple factors.
|
||||
|
||||
**Scoring Factors**:
|
||||
- Relevance score (from strategy)
|
||||
- Tier priority (hot > warm > cold)
|
||||
- Recency (created_at)
|
||||
- Plan context alignment
|
||||
- Resource type affinity
|
||||
|
||||
#### 7. BudgetPacker
|
||||
|
||||
**Purpose**: Select fragments to fit within token budget.
|
||||
|
||||
**Packing Algorithm**:
|
||||
1. Sort fragments by score (descending)
|
||||
2. Greedily add fragments until budget exhausted
|
||||
3. Respect tier ordering (hot → warm → cold)
|
||||
4. Early termination when budget full
|
||||
|
||||
#### 8. FragmentOrderer
|
||||
|
||||
**Purpose**: Determine final fragment order in payload.
|
||||
|
||||
**Ordering Strategies**:
|
||||
- **Relevance**: By relevance_score (descending)
|
||||
- **Recency**: By created_at (descending)
|
||||
- **Tier-Relevance**: By tier, then relevance
|
||||
- **Custom**: User-defined ordering
|
||||
|
||||
### Phase 3: Context Finalization
|
||||
|
||||
#### 9. PreambleGenerator
|
||||
|
||||
**Purpose**: Generate optional summary of assembled context.
|
||||
|
||||
**Preamble Contents**:
|
||||
- Number of fragments and sources
|
||||
- Token usage and budget utilization
|
||||
- Strategies used
|
||||
- Key topics covered
|
||||
- Temporal range
|
||||
|
||||
#### 10. SkeletonCompressor
|
||||
|
||||
**Purpose**: Compress context for child plans while preserving critical information.
|
||||
|
||||
**Compression Strategy**:
|
||||
- Identify critical fragments for child focus
|
||||
- Remove redundant details
|
||||
- Preserve decision context
|
||||
- Maintain provenance
|
||||
|
||||
## Context Strategy Patterns
|
||||
|
||||
### Strategy Architecture
|
||||
|
||||
All strategies implement the `ContextStrategy` protocol:
|
||||
|
||||
```python
|
||||
class ContextStrategy(Protocol):
|
||||
@property
|
||||
def name(self) -> str:
|
||||
"""Unique strategy identifier"""
|
||||
...
|
||||
|
||||
@property
|
||||
def capabilities(self) -> StrategyCapabilities:
|
||||
"""Declare backend requirements and quality"""
|
||||
...
|
||||
|
||||
def can_handle(
|
||||
self,
|
||||
request: ContextRequest,
|
||||
backends: BackendSet
|
||||
) -> float:
|
||||
"""Return confidence (0.0-1.0) for handling request"""
|
||||
...
|
||||
|
||||
def assemble(
|
||||
self,
|
||||
request: ContextRequest,
|
||||
backends: BackendSet,
|
||||
budget: ContextBudget,
|
||||
plan_context: PlanContext
|
||||
) -> list[ContextFragment]:
|
||||
"""Execute strategy and return fragments"""
|
||||
...
|
||||
|
||||
def explain(self) -> str:
|
||||
"""Human-readable description"""
|
||||
...
|
||||
```
|
||||
|
||||
### Built-in Strategies
|
||||
|
||||
#### 1. Simple Keyword Strategy
|
||||
|
||||
**Quality Score**: 0.3 (baseline)
|
||||
|
||||
**Backend Requirements**: TextBackend
|
||||
|
||||
**How It Works**:
|
||||
1. Extract keywords from request
|
||||
2. Search TextBackend using keywords
|
||||
3. Rank results by match frequency
|
||||
4. Pack greedily into budget
|
||||
|
||||
**Best For**:
|
||||
- Quick searches with clear keywords
|
||||
- Projects with good text indexing
|
||||
- Fallback when other backends unavailable
|
||||
|
||||
#### 2. Semantic Embedding Strategy
|
||||
|
||||
**Quality Score**: 0.6 (good)
|
||||
|
||||
**Backend Requirements**: VectorBackend
|
||||
|
||||
**How It Works**:
|
||||
1. Embed request using character-frequency model (v1)
|
||||
2. Search VectorBackend for similar embeddings
|
||||
3. Rank by cosine similarity
|
||||
4. Pack budget-aware results
|
||||
|
||||
**Best For**:
|
||||
- Semantic similarity searches
|
||||
- Conceptual relationships
|
||||
- Cross-domain context discovery
|
||||
|
||||
#### 3. Breadth-Depth Navigator Strategy
|
||||
|
||||
**Quality Score**: 0.85 (excellent)
|
||||
|
||||
**Backend Requirements**: GraphBackend
|
||||
|
||||
**How It Works**:
|
||||
1. Start from focus nodes in request
|
||||
2. Traverse graph outward by breadth hops
|
||||
3. Traverse downward by depth hops
|
||||
4. Collect all reachable nodes
|
||||
5. Rank by distance and relevance
|
||||
6. Pack into budget
|
||||
|
||||
**Best For**:
|
||||
- Exploring related code and decisions
|
||||
- Understanding dependencies
|
||||
- Comprehensive context assembly
|
||||
|
||||
#### 4. ARCE Strategy (Advanced Retrieval with Context Enrichment)
|
||||
|
||||
**Quality Score**: 0.95 (highest)
|
||||
|
||||
**Backend Requirements**: TextBackend, VectorBackend, GraphBackend
|
||||
|
||||
**How It Works**:
|
||||
1. **Phase 1 (40% budget)**: Text search using keywords
|
||||
2. **Phase 2 (40% budget)**: Vector similarity search
|
||||
3. **Phase 3 (20% budget)**: Graph traversal from results
|
||||
4. Merge and deduplicate results
|
||||
5. Rank by combined score
|
||||
6. Pack into budget
|
||||
|
||||
**Best For**:
|
||||
- Comprehensive context assembly
|
||||
- Multi-modal queries
|
||||
- Production use cases
|
||||
|
||||
#### 5. Temporal Archaeology Strategy
|
||||
|
||||
**Quality Score**: 0.5 (moderate)
|
||||
|
||||
**Backend Requirements**: GraphBackend, TemporalBackend (cold tier)
|
||||
|
||||
**How It Works**:
|
||||
1. Query TemporalBackend for historical nodes
|
||||
2. Filter by temporal window
|
||||
3. Traverse graph from historical nodes
|
||||
4. Collect related current nodes
|
||||
5. Rank by recency and relevance
|
||||
6. Pack into budget
|
||||
|
||||
**Best For**:
|
||||
- Understanding historical context
|
||||
- Decision archaeology
|
||||
- Long-term project evolution
|
||||
|
||||
#### 6. Plan-Decision Context Strategy
|
||||
|
||||
**Quality Score**: 0.7 (good)
|
||||
|
||||
**Backend Requirements**: TemporalBackend (warm/cold), GraphBackend
|
||||
|
||||
**How It Works**:
|
||||
1. Walk parent and ancestor plan hierarchy
|
||||
2. Retrieve decision records from warm/cold tiers
|
||||
3. Traverse graph from decisions
|
||||
4. Collect related context
|
||||
5. Rank by plan proximity and relevance
|
||||
6. Pack into budget
|
||||
|
||||
**Best For**:
|
||||
- Understanding plan context
|
||||
- Decision inheritance
|
||||
- Multi-level plan coordination
|
||||
|
||||
### Strategy Comparison Matrix
|
||||
|
||||
| Strategy | Quality | Speed | Coverage | Best For |
|
||||
|----------|---------|-------|----------|----------|
|
||||
| Simple Keyword | 0.3 | ⚡⚡⚡ | Narrow | Quick searches |
|
||||
| Semantic Embedding | 0.6 | ⚡⚡ | Broad | Semantic similarity |
|
||||
| Breadth-Depth Navigator | 0.85 | ⚡ | Very Broad | Comprehensive context |
|
||||
| ARCE | 0.95 | 🐢 | Comprehensive | Production use |
|
||||
| Temporal Archaeology | 0.5 | 🐢 | Historical | Historical context |
|
||||
| Plan-Decision Context | 0.7 | ⚡ | Hierarchical | Plan coordination |
|
||||
|
||||
## Context Inheritance and Scope Resolution
|
||||
|
||||
### Scope Hierarchy
|
||||
|
||||
Context is organized in a hierarchy of scopes:
|
||||
|
||||
```
|
||||
Global Scope
|
||||
├── Project Scope
|
||||
│ ├── Module Scope
|
||||
│ │ ├── Class Scope
|
||||
│ │ │ └── Method Scope
|
||||
│ │ └── Function Scope
|
||||
│ └── Decision Scope
|
||||
└── Temporal Scope
|
||||
├── Current
|
||||
├── Recent (7d)
|
||||
└── Historical (30d+)
|
||||
```
|
||||
|
||||
### Scope Resolution Rules
|
||||
|
||||
When assembling context for a request:
|
||||
|
||||
1. **Start at Request Focus**: Begin with explicitly requested nodes
|
||||
2. **Expand Upward**: Include parent scopes (module → project → global)
|
||||
3. **Expand Downward**: Include child scopes (class → methods)
|
||||
4. **Expand Sideways**: Include sibling scopes (related classes)
|
||||
5. **Apply Filters**: Remove out-of-scope items based on resource types
|
||||
6. **Respect Budget**: Stop expansion when budget exhausted
|
||||
|
||||
### Context Inheritance
|
||||
|
||||
Child plans inherit context from parent plans:
|
||||
|
||||
```python
|
||||
# Parent plan context
|
||||
parent_payload = ContextPayload(
|
||||
fragments=[
|
||||
ContextFragment(uko_node="project://myapp/src/main.py", ...),
|
||||
ContextFragment(uko_node="project://myapp/src/utils.py", ...),
|
||||
ContextFragment(uko_node="project://myapp/decisions/001", ...),
|
||||
]
|
||||
)
|
||||
|
||||
# Child plan inherits and specializes
|
||||
child_request = ContextRequest(
|
||||
focus_nodes=["project://myapp/src/main.py"],
|
||||
parent_context=parent_payload,
|
||||
inherit_strategy="skeleton" # Compress parent context
|
||||
)
|
||||
|
||||
# Result: Child gets focused context + compressed parent context
|
||||
child_payload = pipeline.assemble(child_request)
|
||||
```
|
||||
|
||||
**Inheritance Strategies**:
|
||||
- **Full**: Include all parent context (if budget allows)
|
||||
- **Skeleton**: Compress parent context to essentials
|
||||
- **None**: Start fresh (no parent context)
|
||||
|
||||
## Budget Allocation and Utilization Metrics
|
||||
|
||||
### Budget Planning
|
||||
|
||||
Effective budget allocation requires understanding token costs:
|
||||
|
||||
```python
|
||||
# Typical token costs
|
||||
costs = {
|
||||
"system_prompt": 512, # Reserved
|
||||
"user_request": 200, # Typical request
|
||||
"model_response": 1024, # Expected response
|
||||
"context": 2048, # Available for context
|
||||
}
|
||||
|
||||
total_budget = 4096
|
||||
reserved = 512
|
||||
available = total_budget - reserved # 3584 tokens
|
||||
```
|
||||
|
||||
### Budget Allocation Strategies
|
||||
|
||||
#### Proportional Allocation
|
||||
|
||||
Allocate based on strategy confidence scores:
|
||||
|
||||
```python
|
||||
candidates = [
|
||||
(semantic_embedding, 0.95),
|
||||
(breadth_depth, 0.85),
|
||||
(simple_keyword, 0.3)
|
||||
]
|
||||
|
||||
total_confidence = 0.95 + 0.85 + 0.3 # 2.1
|
||||
allocations = {
|
||||
semantic_embedding: int(3584 * 0.95 / 2.1), # 1621
|
||||
breadth_depth: int(3584 * 0.85 / 2.1), # 1450
|
||||
simple_keyword: int(3584 * 0.3 / 2.1), # 513
|
||||
}
|
||||
```
|
||||
|
||||
#### Priority Allocation
|
||||
|
||||
Allocate to highest-confidence strategies first:
|
||||
|
||||
```python
|
||||
allocations = {}
|
||||
remaining = 3584
|
||||
|
||||
for strategy, confidence in sorted(candidates, key=lambda x: x[1], reverse=True):
|
||||
# Allocate 50% of remaining budget
|
||||
allocation = remaining // 2
|
||||
allocations[strategy] = allocation
|
||||
remaining -= allocation
|
||||
```
|
||||
|
||||
#### Tier-Based Allocation
|
||||
|
||||
Allocate based on tier requirements:
|
||||
|
||||
```python
|
||||
allocations = {
|
||||
"hot_tier": 1000, # 28% - Critical context
|
||||
"warm_tier": 2000, # 56% - Standard context
|
||||
"cold_tier": 584, # 16% - Low-priority context
|
||||
}
|
||||
```
|
||||
|
||||
### Utilization Metrics
|
||||
|
||||
Track context assembly efficiency:
|
||||
|
||||
```python
|
||||
metrics = {
|
||||
"budget_used": payload.budget_used, # 0.57 (57%)
|
||||
"remaining_tokens": payload.remaining_tokens, # 1536
|
||||
"fragments_selected": len(payload.fragments), # 12
|
||||
"fragments_total": 45, # Total available
|
||||
"coverage": 12 / 45, # 26.7%
|
||||
"strategies_used": payload.strategies_used, # ("semantic-embedding",)
|
||||
"assembly_time_ms": 234, # Execution time
|
||||
"avg_fragment_tokens": 2048 / 12, # 170.7
|
||||
"avg_relevance": 0.82, # Mean relevance score
|
||||
}
|
||||
```
|
||||
|
||||
### Budget Optimization
|
||||
|
||||
Techniques to improve budget utilization:
|
||||
|
||||
1. **Increase Reserved Tokens**: Allocate more for system prompt
|
||||
2. **Reduce Detail Depth**: Lower detail_depth for less critical fragments
|
||||
3. **Increase Relevance Threshold**: Filter low-relevance fragments
|
||||
4. **Use Skeleton Compression**: Compress parent context for child plans
|
||||
5. **Tier-Based Filtering**: Exclude cold tier if budget tight
|
||||
|
||||
## Implementation Guide for Custom Strategies
|
||||
|
||||
### Creating a Custom Strategy
|
||||
|
||||
#### Step 1: Define Strategy Class
|
||||
|
||||
```python
|
||||
from cleveragents.application.services.acms_service import (
|
||||
ContextStrategy,
|
||||
StrategyCapabilities,
|
||||
)
|
||||
from cleveragents.domain.models.core.context_fragment import (
|
||||
ContextBudget,
|
||||
ContextFragment,
|
||||
)
|
||||
from typing import Sequence, Any
|
||||
|
||||
|
||||
class MyCustomStrategy:
|
||||
"""Custom context strategy for specialized retrieval."""
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
"""Unique strategy identifier."""
|
||||
return "my-custom-strategy"
|
||||
|
||||
@property
|
||||
def capabilities(self) -> StrategyCapabilities:
|
||||
"""Declare backend requirements and quality."""
|
||||
return StrategyCapabilities(
|
||||
uses_text=True,
|
||||
uses_vector=False,
|
||||
uses_graph=True,
|
||||
uses_temporal=False,
|
||||
resource_types=("source_file", "decision"),
|
||||
quality_score=0.75,
|
||||
supports_depth_breadth=True,
|
||||
supports_plan_hierarchy=False,
|
||||
supports_temporal=False,
|
||||
)
|
||||
|
||||
def can_handle(self, request: dict[str, Any]) -> float:
|
||||
"""Return confidence (0.0-1.0) for handling request."""
|
||||
# Check if request has required fields
|
||||
if "focus_nodes" not in request:
|
||||
return 0.0
|
||||
|
||||
# Check for specific keywords
|
||||
keywords = request.get("keywords", [])
|
||||
if any(kw in ["async", "io", "performance"] for kw in keywords):
|
||||
return 0.9 # High confidence for performance-related queries
|
||||
|
||||
return 0.6 # Moderate confidence for general queries
|
||||
|
||||
def assemble(
|
||||
self,
|
||||
fragments: Sequence[ContextFragment],
|
||||
budget: ContextBudget,
|
||||
) -> Sequence[ContextFragment]:
|
||||
"""Execute strategy and return fragments."""
|
||||
# Custom ranking logic
|
||||
ranked = sorted(
|
||||
fragments,
|
||||
key=lambda f: (
|
||||
f.tier == "hot", # Hot tier first
|
||||
f.relevance_score, # Then by relevance
|
||||
f.created_at, # Then by recency
|
||||
),
|
||||
reverse=True
|
||||
)
|
||||
|
||||
# Pack into budget
|
||||
selected = []
|
||||
total_tokens = 0
|
||||
|
||||
for fragment in ranked:
|
||||
if total_tokens + fragment.token_count <= budget.available_tokens:
|
||||
selected.append(fragment)
|
||||
total_tokens += fragment.token_count
|
||||
else:
|
||||
break # Budget exhausted
|
||||
|
||||
return selected
|
||||
|
||||
def explain(self) -> str:
|
||||
"""Human-readable description."""
|
||||
return (
|
||||
"Custom strategy that prioritizes hot-tier fragments "
|
||||
"and performance-related keywords."
|
||||
)
|
||||
```
|
||||
|
||||
#### Step 2: Register Strategy
|
||||
|
||||
```python
|
||||
from cleveragents.application.services.acms_service import ACMSPipeline
|
||||
|
||||
# Create pipeline
|
||||
pipeline = ACMSPipeline()
|
||||
|
||||
# Register custom strategy
|
||||
strategy = MyCustomStrategy()
|
||||
pipeline.register_strategy(strategy.name, strategy)
|
||||
|
||||
# Use in assembly
|
||||
payload = pipeline.assemble(
|
||||
plan_id="plan-1",
|
||||
fragments=fragments,
|
||||
budget=budget,
|
||||
strategy="my-custom-strategy"
|
||||
)
|
||||
```
|
||||
|
||||
#### Step 3: Configure in TOML
|
||||
|
||||
```toml
|
||||
[context.strategies]
|
||||
enabled = ["simple-keyword", "my-custom-strategy"]
|
||||
|
||||
[context.strategies.custom]
|
||||
"my-custom-strategy" = "my_package.strategies:MyCustomStrategy"
|
||||
|
||||
[context.strategies."my-custom-strategy"]
|
||||
enabled = true
|
||||
timeout_seconds = 30
|
||||
max_fragments = 100
|
||||
```
|
||||
|
||||
## Best Practices and Performance Considerations
|
||||
|
||||
### Performance Optimization
|
||||
|
||||
#### 1. Strategy Selection
|
||||
|
||||
**Best Practice**: Use strategy confidence scores to avoid unnecessary execution.
|
||||
|
||||
#### 2. Budget Allocation
|
||||
|
||||
**Best Practice**: Allocate more budget to higher-confidence strategies.
|
||||
|
||||
#### 3. Timeout Management
|
||||
|
||||
**Best Practice**: Set appropriate timeouts based on strategy complexity.
|
||||
|
||||
#### 4. Fragment Deduplication
|
||||
|
||||
**Best Practice**: Deduplicate early to reduce downstream processing.
|
||||
|
||||
#### 5. Detail Depth Resolution
|
||||
|
||||
**Best Practice**: Reduce detail depth for less critical fragments.
|
||||
|
||||
### Memory Efficiency
|
||||
|
||||
#### 1. Fragment Streaming
|
||||
|
||||
**Best Practice**: Stream fragments instead of loading all at once.
|
||||
|
||||
#### 2. Lazy Evaluation
|
||||
|
||||
**Best Practice**: Defer expensive operations until needed.
|
||||
|
||||
### Reliability and Robustness
|
||||
|
||||
#### 1. Circuit Breaker Pattern
|
||||
|
||||
**Best Practice**: Implement circuit breaker for failing strategies.
|
||||
|
||||
#### 2. Graceful Degradation
|
||||
|
||||
**Best Practice**: Fall back to simpler strategies when complex ones fail.
|
||||
|
||||
#### 3. Timeout Handling
|
||||
|
||||
**Best Practice**: Set reasonable timeouts with fallback.
|
||||
|
||||
### Monitoring and Observability
|
||||
|
||||
#### 1. Metrics Collection
|
||||
|
||||
**Best Practice**: Collect comprehensive metrics for monitoring.
|
||||
|
||||
#### 2. Logging
|
||||
|
||||
**Best Practice**: Log key decisions and failures.
|
||||
|
||||
## Integration with Plan Execution
|
||||
|
||||
### Context Assembly in Plan Execution
|
||||
|
||||
Context is assembled at key points in plan execution:
|
||||
|
||||
```
|
||||
Plan Execution Flow
|
||||
├── Plan Created
|
||||
│ └── Initial Context Assembly
|
||||
│ ├── StrategySelector: Choose strategies
|
||||
│ ├── BudgetAllocator: Allocate tokens
|
||||
│ └── StrategyExecutor: Execute strategies
|
||||
├── Plan Step Execution
|
||||
│ └── Context Refresh (optional)
|
||||
│ └── Incremental context updates
|
||||
├── Subplan Creation
|
||||
│ └── Context Inheritance
|
||||
│ ├── Inherit parent context
|
||||
│ └── Specialize for subplan focus
|
||||
└── Plan Completion
|
||||
└── Context Archive
|
||||
└── Store for historical reference
|
||||
```
|
||||
|
||||
### Context Request from Plan
|
||||
|
||||
Plans generate context requests based on their focus.
|
||||
|
||||
### Context Injection into Plan
|
||||
|
||||
Assembled context is injected into plan execution.
|
||||
|
||||
### Subplan Context Inheritance
|
||||
|
||||
Child plans inherit and specialize context.
|
||||
|
||||
## Real-world Examples
|
||||
|
||||
### Example 1: Implementing a New Feature
|
||||
|
||||
**Scenario**: Implement async I/O support in a Python project.
|
||||
|
||||
**Context Assembly**:
|
||||
|
||||
```python
|
||||
# 1. Create context request
|
||||
request = ContextRequest(
|
||||
focus_nodes=[
|
||||
"project://myapp/src/main.py",
|
||||
"project://myapp/src/io.py"
|
||||
],
|
||||
keywords=["async", "io", "performance"],
|
||||
breadth=2,
|
||||
depth=3,
|
||||
resource_types=["source_file", "decision"],
|
||||
detail_level=4
|
||||
)
|
||||
|
||||
# 2. Assemble context
|
||||
payload = pipeline.assemble(
|
||||
plan_id="plan-async-io",
|
||||
fragments=fetch_fragments(backends, request),
|
||||
budget=ContextBudget(max_tokens=4096, reserved_tokens=512),
|
||||
strategy="arce" # Use comprehensive strategy
|
||||
)
|
||||
|
||||
# 3. Inspect assembled context
|
||||
print(f"Fragments: {len(payload.fragments)}")
|
||||
print(f"Tokens: {payload.total_tokens} / {payload.budget.available_tokens}")
|
||||
print(f"Budget used: {payload.budget_used:.1%}")
|
||||
print(f"Strategies: {payload.strategies_used}")
|
||||
|
||||
# 4. Use context in plan execution
|
||||
plan = Plan(
|
||||
title="Implement async I/O",
|
||||
context_payload=payload,
|
||||
context_hash=payload.context_hash
|
||||
)
|
||||
```
|
||||
|
||||
**Result**: LM receives focused context on async I/O patterns, related decisions, and performance considerations.
|
||||
|
||||
### Example 2: Debugging a Performance Issue
|
||||
|
||||
**Scenario**: Investigate slow database queries.
|
||||
|
||||
**Context Assembly**:
|
||||
|
||||
```python
|
||||
# 1. Create context request focused on database code
|
||||
request = ContextRequest(
|
||||
focus_nodes=["project://myapp/src/database.py"],
|
||||
keywords=["query", "performance", "slow", "index"],
|
||||
breadth=3, # Broader search for related code
|
||||
depth=2, # Less deep (focus on structure)
|
||||
resource_types=["source_file", "decision", "test"],
|
||||
detail_level=2, # Less detail to fit more context
|
||||
temporal_window="30d" # Include recent changes
|
||||
)
|
||||
|
||||
# 2. Assemble with temporal strategy
|
||||
payload = pipeline.assemble(
|
||||
plan_id="plan-debug-perf",
|
||||
fragments=fetch_fragments(backends, request),
|
||||
budget=ContextBudget(max_tokens=4096, reserved_tokens=512),
|
||||
strategy="temporal-archaeology" # Include historical context
|
||||
)
|
||||
|
||||
# 3. Analyze context
|
||||
hot_fragments = [f for f in payload.fragments if f.tier == "hot"]
|
||||
recent_fragments = sorted(
|
||||
payload.fragments,
|
||||
key=lambda f: f.created_at,
|
||||
reverse=True
|
||||
)[:5]
|
||||
|
||||
print(f"Hot tier fragments: {len(hot_fragments)}")
|
||||
print(f"Recent changes: {[f.uko_node for f in recent_fragments]}")
|
||||
```
|
||||
|
||||
**Result**: LM receives context on database code, recent changes, and historical decisions about performance.
|
||||
|
||||
### Example 3: Code Review with Context
|
||||
|
||||
**Scenario**: Review a pull request with full context.
|
||||
|
||||
**Context Assembly**:
|
||||
|
||||
```python
|
||||
# 1. Get changed files from PR
|
||||
changed_files = [
|
||||
"project://myapp/src/auth.py",
|
||||
"project://myapp/src/security.py",
|
||||
"project://myapp/tests/test_auth.py"
|
||||
]
|
||||
|
||||
# 2. Create context request
|
||||
request = ContextRequest(
|
||||
focus_nodes=changed_files,
|
||||
breadth=1, # Narrow search (focus on changed files)
|
||||
depth=4, # Deeper (understand full context)
|
||||
resource_types=["source_file", "decision", "test"],
|
||||
detail_level=5, # Higher detail for review
|
||||
strategy_hints=["breadth-depth-navigator"] # Use graph traversal
|
||||
)
|
||||
|
||||
# 3. Assemble context
|
||||
payload = pipeline.assemble(
|
||||
plan_id="plan-review-pr",
|
||||
fragments=fetch_fragments(backends, request),
|
||||
budget=ContextBudget(max_tokens=8192, reserved_tokens=512),
|
||||
strategy="breadth-depth-navigator"
|
||||
)
|
||||
|
||||
# 4. Generate review context
|
||||
review_context = {
|
||||
"changed_files": changed_files,
|
||||
"context_fragments": len(payload.fragments),
|
||||
"context_tokens": payload.total_tokens,
|
||||
"related_decisions": [
|
||||
f for f in payload.fragments
|
||||
if "decision" in f.metadata.get("resource_type", "")
|
||||
],
|
||||
"related_tests": [
|
||||
f for f in payload.fragments
|
||||
if "test" in f.uko_node
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Result**: LM receives comprehensive context on changed files, related code, decisions, and tests for thorough review.
|
||||
|
||||
### Example 4: Multi-level Plan Hierarchy
|
||||
|
||||
**Scenario**: Execute a complex plan with multiple subplans.
|
||||
|
||||
**Context Assembly**:
|
||||
|
||||
```python
|
||||
# Parent plan context
|
||||
parent_request = ContextRequest(
|
||||
focus_nodes=["project://myapp"],
|
||||
breadth=2,
|
||||
depth=2,
|
||||
detail_level=2
|
||||
)
|
||||
|
||||
parent_payload = pipeline.assemble(
|
||||
plan_id="plan-refactor",
|
||||
fragments=fetch_fragments(backends, parent_request),
|
||||
budget=ContextBudget(max_tokens=4096, reserved_tokens=512),
|
||||
strategy="arce"
|
||||
)
|
||||
|
||||
# Subplan 1: Refactor auth module
|
||||
subplan1_request = ContextRequest(
|
||||
focus_nodes=["project://myapp/src/auth.py"],
|
||||
parent_context=parent_payload,
|
||||
inherit_strategy="skeleton", # Compress parent
|
||||
breadth=2,
|
||||
depth=3,
|
||||
detail_level=4
|
||||
)
|
||||
|
||||
subplan1_payload = pipeline.assemble(
|
||||
plan_id="plan-refactor-auth",
|
||||
fragments=fetch_fragments(backends, subplan1_request),
|
||||
budget=ContextBudget(max_tokens=3584, reserved_tokens=512),
|
||||
strategy="breadth-depth-navigator"
|
||||
)
|
||||
|
||||
# Subplan 2: Refactor database module
|
||||
subplan2_request = ContextRequest(
|
||||
focus_nodes=["project://myapp/src/database.py"],
|
||||
parent_context=parent_payload,
|
||||
inherit_strategy="skeleton",
|
||||
breadth=2,
|
||||
depth=3,
|
||||
detail_level=4
|
||||
)
|
||||
|
||||
subplan2_payload = pipeline.assemble(
|
||||
plan_id="plan-refactor-db",
|
||||
fragments=fetch_fragments(backends, subplan2_request),
|
||||
budget=ContextBudget(max_tokens=3584, reserved_tokens=512),
|
||||
strategy="breadth-depth-navigator"
|
||||
)
|
||||
|
||||
# Execute hierarchy
|
||||
execute_plan(parent_plan, parent_payload)
|
||||
execute_plan(subplan1, subplan1_payload)
|
||||
execute_plan(subplan2, subplan2_payload)
|
||||
```
|
||||
|
||||
**Result**: Parent plan gets broad context; subplans get specialized context with parent context compressed for efficiency.
|
||||
|
||||
## Conclusion
|
||||
|
||||
The ACMS provides a powerful, flexible system for managing context in cleveragents-core. By understanding the architecture, strategies, and best practices, you can:
|
||||
|
||||
- **Assemble relevant context** efficiently and deterministically
|
||||
- **Respect token budgets** while maximizing information density
|
||||
- **Implement custom strategies** for specialized use cases
|
||||
- **Optimize performance** through careful budget allocation
|
||||
- **Integrate seamlessly** with plan execution
|
||||
|
||||
For more information, see:
|
||||
- [Context Strategies Reference](../reference/context_strategies_reference.md)
|
||||
- [ACMS Pipeline Reference](../reference/acms_pipeline_reference.md)
|
||||
- [ACMS v1 Context Assembly Pipeline](../reference/acms.md)
|
||||
- [Context Strategy Registry](../reference/context_strategies.md)
|
||||
@@ -0,0 +1,760 @@
|
||||
# ACMS Pipeline Reference
|
||||
|
||||
Complete reference for the ACMS Pipeline components, their interactions, data flow, configuration, and monitoring.
|
||||
|
||||
## Pipeline Architecture
|
||||
|
||||
The ACMS pipeline implements a 10-component architecture across three phases:
|
||||
|
||||
```
|
||||
Phase 1: Strategy Orchestration
|
||||
├── StrategySelector
|
||||
├── BudgetAllocator
|
||||
└── StrategyExecutor
|
||||
|
||||
Phase 2: Fragment Fusion
|
||||
├── FragmentDeduplicator
|
||||
├── DetailDepthResolver
|
||||
├── FragmentScorer
|
||||
├── BudgetPacker
|
||||
└── FragmentOrderer
|
||||
|
||||
Phase 3: Context Finalization
|
||||
├── PreambleGenerator
|
||||
└── SkeletonCompressor
|
||||
```
|
||||
|
||||
## Component Reference
|
||||
|
||||
### Phase 1: Strategy Orchestration
|
||||
|
||||
#### StrategySelector
|
||||
|
||||
**Purpose**: Determine which strategies can handle the request.
|
||||
|
||||
**Input**:
|
||||
- `strategies`: List of registered strategies
|
||||
- `request`: ContextRequest with focus nodes, keywords, etc.
|
||||
- `backends`: Available backends (TextBackend, VectorBackend, etc.)
|
||||
|
||||
**Output**:
|
||||
- `candidates`: List of (strategy, confidence) tuples, sorted by confidence descending
|
||||
|
||||
**Process**:
|
||||
1. Poll each strategy with `can_handle(request, backends)`
|
||||
2. Collect confidence scores (0.0-1.0)
|
||||
3. Filter strategies with confidence >= threshold (default 0.0)
|
||||
4. Sort by confidence descending
|
||||
5. Return top candidates
|
||||
|
||||
**Configuration**:
|
||||
```toml
|
||||
[context.strategies]
|
||||
selector_threshold = 0.0
|
||||
max_candidates = 10
|
||||
```
|
||||
|
||||
**Example**:
|
||||
```python
|
||||
selector = StrategySelector()
|
||||
candidates = selector.select(
|
||||
strategies=[simple_keyword, semantic_embedding, breadth_depth],
|
||||
request=context_request,
|
||||
backends=backend_set
|
||||
)
|
||||
# Returns: [(semantic_embedding, 0.95), (breadth_depth, 0.85), ...]
|
||||
```
|
||||
|
||||
#### BudgetAllocator
|
||||
|
||||
**Purpose**: Distribute token budget among selected strategies.
|
||||
|
||||
**Input**:
|
||||
- `candidates`: List of (strategy, confidence) tuples
|
||||
- `total_budget`: Available tokens for context
|
||||
- `request`: ContextRequest with budget hints
|
||||
|
||||
**Output**:
|
||||
- `allocations`: Dict mapping strategy -> allocated tokens
|
||||
|
||||
**Allocation Strategies**:
|
||||
|
||||
1. **Proportional** (default):
|
||||
```
|
||||
allocation[s] = total_budget * confidence[s] / sum(confidences)
|
||||
```
|
||||
|
||||
2. **Equal**:
|
||||
```
|
||||
allocation[s] = total_budget / len(candidates)
|
||||
```
|
||||
|
||||
3. **Priority**:
|
||||
```
|
||||
Sort by confidence, allocate 50% of remaining to each
|
||||
```
|
||||
|
||||
**Configuration**:
|
||||
```toml
|
||||
[context.strategies]
|
||||
allocator_strategy = "proportional"
|
||||
allocator_min_budget = 100
|
||||
```
|
||||
|
||||
**Example**:
|
||||
```python
|
||||
allocator = BudgetAllocator()
|
||||
allocations = allocator.allocate(
|
||||
candidates=[(semantic_embedding, 0.95), (breadth_depth, 0.85)],
|
||||
total_budget=3584,
|
||||
request=context_request
|
||||
)
|
||||
# Returns: {semantic_embedding: 1900, breadth_depth: 1684}
|
||||
```
|
||||
|
||||
#### StrategyExecutor
|
||||
|
||||
**Purpose**: Execute strategies in parallel with timeout and circuit breaker.
|
||||
|
||||
**Input**:
|
||||
- `allocations`: Dict mapping strategy -> allocated tokens
|
||||
- `request`: ContextRequest
|
||||
- `backends`: Available backends
|
||||
- `plan_context`: Current plan context
|
||||
|
||||
**Output**:
|
||||
- `results`: List of StrategyResult objects
|
||||
|
||||
**Features**:
|
||||
- Parallel execution with configurable workers
|
||||
- Per-strategy timeout (default 30s)
|
||||
- Circuit breaker after N failures
|
||||
- Graceful degradation on timeout
|
||||
|
||||
**Configuration**:
|
||||
```toml
|
||||
[context.strategies]
|
||||
executor_max_workers = 4
|
||||
executor_timeout_seconds = 30
|
||||
executor_circuit_breaker_threshold = 3
|
||||
executor_circuit_breaker_reset_timeout = 60
|
||||
```
|
||||
|
||||
**Example**:
|
||||
```python
|
||||
executor = StrategyExecutor(max_workers=4, timeout_seconds=30)
|
||||
results = executor.execute(
|
||||
allocations={semantic_embedding: 1900, breadth_depth: 1684},
|
||||
request=context_request,
|
||||
backends=backend_set,
|
||||
plan_context=plan_context
|
||||
)
|
||||
# Returns: [StrategyResult(...), StrategyResult(...)]
|
||||
```
|
||||
|
||||
**StrategyResult**:
|
||||
```python
|
||||
@dataclass
|
||||
class StrategyResult:
|
||||
strategy_name: str
|
||||
fragments: tuple[ContextFragment, ...]
|
||||
total_fragments: int
|
||||
tokens_used: int
|
||||
execution_time_ms: float
|
||||
errors: tuple[str, ...]
|
||||
stats: dict[str, Any]
|
||||
```
|
||||
|
||||
### Phase 2: Fragment Fusion
|
||||
|
||||
#### FragmentDeduplicator
|
||||
|
||||
**Purpose**: Remove duplicate fragments based on UKO node and content hash.
|
||||
|
||||
**Input**:
|
||||
- `fragments`: List of ContextFragment objects
|
||||
- `strategy`: Deduplication strategy ("highest_relevance", "first_seen", "most_recent")
|
||||
|
||||
**Output**:
|
||||
- `deduplicated`: List of unique fragments
|
||||
|
||||
**Deduplication Rules**:
|
||||
- Same `uko_node` + same content hash = duplicate
|
||||
- Keep fragment with highest relevance score (default)
|
||||
- Merge provenance from all duplicates
|
||||
|
||||
**Configuration**:
|
||||
```toml
|
||||
[context.strategies]
|
||||
deduplicator_strategy = "highest_relevance"
|
||||
deduplicator_merge_provenance = true
|
||||
```
|
||||
|
||||
**Example**:
|
||||
```python
|
||||
deduplicator = FragmentDeduplicator()
|
||||
deduplicated = deduplicator.deduplicate(
|
||||
fragments=[frag1, frag2, frag1_duplicate],
|
||||
strategy="highest_relevance"
|
||||
)
|
||||
# Returns: [frag1 (with merged provenance), frag2]
|
||||
```
|
||||
|
||||
#### DetailDepthResolver
|
||||
|
||||
**Purpose**: Resolve appropriate detail depth for each fragment.
|
||||
|
||||
**Input**:
|
||||
- `fragments`: List of ContextFragment objects
|
||||
- `budget`: ContextBudget
|
||||
- `request`: ContextRequest with desired detail level
|
||||
|
||||
**Output**:
|
||||
- `resolved`: List of fragments with adjusted detail_depth
|
||||
|
||||
**Resolution Logic**:
|
||||
1. Start with requested detail level
|
||||
2. Adjust based on token budget
|
||||
3. Respect fragment's max depth
|
||||
4. Prefer higher depth for hot tier
|
||||
|
||||
**Configuration**:
|
||||
```toml
|
||||
[context.strategies]
|
||||
resolver_default_depth = 3
|
||||
resolver_hot_tier_boost = 2
|
||||
resolver_budget_aware = true
|
||||
```
|
||||
|
||||
**Example**:
|
||||
```python
|
||||
resolver = DetailDepthResolver()
|
||||
resolved = resolver.resolve(
|
||||
fragments=[frag1, frag2],
|
||||
budget=budget,
|
||||
request=context_request
|
||||
)
|
||||
# Returns: fragments with adjusted detail_depth
|
||||
```
|
||||
|
||||
#### FragmentScorer
|
||||
|
||||
**Purpose**: Score fragments based on multiple factors.
|
||||
|
||||
**Input**:
|
||||
- `fragments`: List of ContextFragment objects
|
||||
- `plan_context`: Current plan context
|
||||
- `request`: ContextRequest
|
||||
|
||||
**Output**:
|
||||
- `scored`: List of (fragment, score) tuples
|
||||
|
||||
**Scoring Factors**:
|
||||
- Relevance score (from strategy): 40%
|
||||
- Tier priority (hot > warm > cold): 30%
|
||||
- Recency (created_at): 20%
|
||||
- Plan context alignment: 10%
|
||||
|
||||
**Configuration**:
|
||||
```toml
|
||||
[context.strategies]
|
||||
scorer_relevance_weight = 0.4
|
||||
scorer_tier_weight = 0.3
|
||||
scorer_recency_weight = 0.2
|
||||
scorer_plan_weight = 0.1
|
||||
```
|
||||
|
||||
**Example**:
|
||||
```python
|
||||
scorer = FragmentScorer()
|
||||
scored = scorer.score(
|
||||
fragments=[frag1, frag2],
|
||||
plan_context=plan_context,
|
||||
request=context_request
|
||||
)
|
||||
# Returns: [(frag1, 0.92), (frag2, 0.78)]
|
||||
```
|
||||
|
||||
#### BudgetPacker
|
||||
|
||||
**Purpose**: Select fragments to fit within token budget.
|
||||
|
||||
**Input**:
|
||||
- `scored_fragments`: List of (fragment, score) tuples
|
||||
- `budget`: ContextBudget
|
||||
|
||||
**Output**:
|
||||
- `packed`: List of selected fragments
|
||||
|
||||
**Packing Algorithm**:
|
||||
1. Sort fragments by score (descending)
|
||||
2. Respect tier ordering (hot → warm → cold)
|
||||
3. Greedily add fragments until budget exhausted
|
||||
4. Early termination when budget full
|
||||
|
||||
**Configuration**:
|
||||
```toml
|
||||
[context.strategies]
|
||||
packer_tier_priority = ["hot", "warm", "cold"]
|
||||
packer_greedy = true
|
||||
```
|
||||
|
||||
**Example**:
|
||||
```python
|
||||
packer = BudgetPacker()
|
||||
packed = packer.pack(
|
||||
scored_fragments=[(frag1, 0.92), (frag2, 0.78)],
|
||||
budget=budget
|
||||
)
|
||||
# Returns: [frag1, frag2] (total tokens <= budget.available_tokens)
|
||||
```
|
||||
|
||||
#### FragmentOrderer
|
||||
|
||||
**Purpose**: Determine final fragment order in payload.
|
||||
|
||||
**Input**:
|
||||
- `fragments`: List of ContextFragment objects
|
||||
- `strategy`: Ordering strategy ("relevance", "recency", "tier-relevance", "custom")
|
||||
|
||||
**Output**:
|
||||
- `ordered`: List of fragments in final order
|
||||
|
||||
**Ordering Strategies**:
|
||||
- **Relevance**: By relevance_score (descending)
|
||||
- **Recency**: By created_at (descending)
|
||||
- **Tier-Relevance**: By tier (hot > warm > cold), then relevance
|
||||
- **Custom**: User-defined ordering
|
||||
|
||||
**Configuration**:
|
||||
```toml
|
||||
[context.strategies]
|
||||
orderer_strategy = "tier-relevance"
|
||||
```
|
||||
|
||||
**Example**:
|
||||
```python
|
||||
orderer = FragmentOrderer()
|
||||
ordered = orderer.order(
|
||||
fragments=[frag1, frag2],
|
||||
strategy="tier-relevance"
|
||||
)
|
||||
# Returns: [hot_frag, warm_frag1, warm_frag2, cold_frag]
|
||||
```
|
||||
|
||||
### Phase 3: Context Finalization
|
||||
|
||||
#### PreambleGenerator
|
||||
|
||||
**Purpose**: Generate optional summary of assembled context.
|
||||
|
||||
**Input**:
|
||||
- `payload`: ContextPayload (before finalization)
|
||||
- `strategies_used`: Tuple of strategy names
|
||||
- `budget_used`: Fraction of budget consumed
|
||||
|
||||
**Output**:
|
||||
- `preamble`: String summary of context
|
||||
|
||||
**Preamble Contents**:
|
||||
- Number of fragments and sources
|
||||
- Token usage and budget utilization
|
||||
- Strategies used
|
||||
- Key topics covered
|
||||
- Temporal range
|
||||
|
||||
**Configuration**:
|
||||
```toml
|
||||
[context.strategies]
|
||||
preamble_enabled = true
|
||||
preamble_include_stats = true
|
||||
preamble_max_length = 500
|
||||
```
|
||||
|
||||
**Example**:
|
||||
```python
|
||||
generator = PreambleGenerator()
|
||||
preamble = generator.generate(
|
||||
payload=payload,
|
||||
strategies_used=["semantic-embedding"],
|
||||
budget_used=0.57
|
||||
)
|
||||
# Returns: "Context includes 5 fragments from 3 sources..."
|
||||
```
|
||||
|
||||
#### SkeletonCompressor
|
||||
|
||||
**Purpose**: Compress context for child plans while preserving critical information.
|
||||
|
||||
**Input**:
|
||||
- `parent_context`: Parent ContextPayload
|
||||
- `child_focus`: List of focus nodes for child plan
|
||||
- `skeleton_budget`: Token budget for compressed context
|
||||
|
||||
**Output**:
|
||||
- `compressed`: Compressed ContextPayload for child plan
|
||||
|
||||
**Compression Strategy**:
|
||||
1. Identify critical fragments for child focus
|
||||
2. Remove redundant details
|
||||
3. Preserve decision context
|
||||
4. Maintain provenance
|
||||
|
||||
**Configuration**:
|
||||
```toml
|
||||
[context.strategies]
|
||||
compressor_enabled = true
|
||||
compressor_preserve_decisions = true
|
||||
compressor_preserve_hot_tier = true
|
||||
```
|
||||
|
||||
**Example**:
|
||||
```python
|
||||
compressor = SkeletonCompressor()
|
||||
compressed = compressor.compress(
|
||||
parent_context=parent_payload,
|
||||
child_focus=["project://myapp/src/main.py"],
|
||||
skeleton_budget=1024
|
||||
)
|
||||
# Returns: compressed ContextPayload for child plan
|
||||
```
|
||||
|
||||
## Data Flow
|
||||
|
||||
### Complete Pipeline Flow
|
||||
|
||||
```
|
||||
ContextRequest
|
||||
↓
|
||||
StrategySelector
|
||||
↓ (candidates: [(strategy, confidence), ...])
|
||||
BudgetAllocator
|
||||
↓ (allocations: {strategy: budget, ...})
|
||||
StrategyExecutor
|
||||
↓ (results: [StrategyResult, ...])
|
||||
Merge Results
|
||||
↓ (fragments: [ContextFragment, ...])
|
||||
FragmentDeduplicator
|
||||
↓ (deduplicated: [ContextFragment, ...])
|
||||
DetailDepthResolver
|
||||
↓ (resolved: [ContextFragment, ...])
|
||||
FragmentScorer
|
||||
↓ (scored: [(ContextFragment, score), ...])
|
||||
BudgetPacker
|
||||
↓ (packed: [ContextFragment, ...])
|
||||
FragmentOrderer
|
||||
↓ (ordered: [ContextFragment, ...])
|
||||
PreambleGenerator
|
||||
↓ (preamble: str)
|
||||
SkeletonCompressor (optional)
|
||||
↓ (compressed: ContextPayload)
|
||||
ContextPayload
|
||||
```
|
||||
|
||||
### Example Data Structures
|
||||
|
||||
**ContextRequest**:
|
||||
```python
|
||||
{
|
||||
"focus_nodes": ["project://myapp/src/main.py"],
|
||||
"breadth": 2,
|
||||
"depth": 3,
|
||||
"keywords": ["async", "io"],
|
||||
"resource_types": ["source_file", "decision"],
|
||||
"detail_level": 3,
|
||||
"temporal_window": "7d",
|
||||
"strategy_hints": ["semantic-embedding"]
|
||||
}
|
||||
```
|
||||
|
||||
**StrategyResult**:
|
||||
```python
|
||||
{
|
||||
"strategy_name": "semantic-embedding",
|
||||
"fragments": [
|
||||
ContextFragment(...),
|
||||
ContextFragment(...),
|
||||
...
|
||||
],
|
||||
"total_fragments": 45,
|
||||
"tokens_used": 2048,
|
||||
"execution_time_ms": 234,
|
||||
"errors": [],
|
||||
"stats": {
|
||||
"similarity_scores": [0.95, 0.87, ...],
|
||||
"backend_queries": 3,
|
||||
"cache_hits": 2
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**ContextPayload**:
|
||||
```python
|
||||
{
|
||||
"payload_id": "01ARZ3NDEKTSV4RRFFQ69G5FAV",
|
||||
"plan_id": "plan-1",
|
||||
"fragments": [
|
||||
ContextFragment(...),
|
||||
ContextFragment(...),
|
||||
...
|
||||
],
|
||||
"total_tokens": 2048,
|
||||
"budget": {
|
||||
"max_tokens": 4096,
|
||||
"reserved_tokens": 512,
|
||||
"available_tokens": 3584
|
||||
},
|
||||
"budget_used": 0.57,
|
||||
"strategies_used": ["semantic-embedding"],
|
||||
"context_hash": "abc123...",
|
||||
"preamble": "Context includes 5 fragments...",
|
||||
"provenance_map": {
|
||||
"fragment-id-1": {...},
|
||||
"fragment-id-2": {...},
|
||||
...
|
||||
},
|
||||
"assembled_at": "2024-04-19T14:30:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration and Tuning
|
||||
|
||||
### Global Configuration
|
||||
|
||||
```toml
|
||||
[context]
|
||||
max_tokens = 4096
|
||||
reserved_tokens = 512
|
||||
|
||||
[context.strategies]
|
||||
enabled = ["simple-keyword", "semantic-embedding", "breadth-depth-navigator"]
|
||||
default_strategy = "arce"
|
||||
|
||||
[context.strategies.simple-keyword]
|
||||
enabled = true
|
||||
timeout_seconds = 10
|
||||
max_fragments = 50
|
||||
|
||||
[context.strategies.semantic-embedding]
|
||||
enabled = true
|
||||
timeout_seconds = 20
|
||||
max_fragments = 100
|
||||
|
||||
[context.strategies.breadth-depth-navigator]
|
||||
enabled = true
|
||||
timeout_seconds = 30
|
||||
max_fragments = 150
|
||||
|
||||
[context.strategies.arce]
|
||||
enabled = true
|
||||
timeout_seconds = 45
|
||||
max_fragments = 200
|
||||
text_budget_fraction = 0.4
|
||||
vector_budget_fraction = 0.4
|
||||
graph_budget_fraction = 0.2
|
||||
```
|
||||
|
||||
### Per-Component Tuning
|
||||
|
||||
#### StrategySelector Tuning
|
||||
|
||||
```toml
|
||||
[context.strategies]
|
||||
selector_threshold = 0.0 # Minimum confidence to select
|
||||
max_candidates = 10 # Maximum strategies to execute
|
||||
```
|
||||
|
||||
**Tuning Tips**:
|
||||
- Increase `selector_threshold` to filter low-confidence strategies
|
||||
- Decrease `max_candidates` to reduce execution time
|
||||
|
||||
#### BudgetAllocator Tuning
|
||||
|
||||
```toml
|
||||
[context.strategies]
|
||||
allocator_strategy = "proportional" # "proportional", "equal", "priority"
|
||||
allocator_min_budget = 100
|
||||
```
|
||||
|
||||
**Tuning Tips**:
|
||||
- Use "proportional" for quality-aware allocation
|
||||
- Use "equal" for fair distribution
|
||||
- Use "priority" for greedy allocation
|
||||
|
||||
#### StrategyExecutor Tuning
|
||||
|
||||
```toml
|
||||
[context.strategies]
|
||||
executor_max_workers = 4
|
||||
executor_timeout_seconds = 30
|
||||
executor_circuit_breaker_threshold = 3
|
||||
executor_circuit_breaker_reset_timeout = 60
|
||||
```
|
||||
|
||||
**Tuning Tips**:
|
||||
- Increase `max_workers` for parallel execution (up to CPU cores)
|
||||
- Increase `timeout_seconds` for complex strategies
|
||||
- Adjust `circuit_breaker_threshold` for fault tolerance
|
||||
|
||||
#### FragmentScorer Tuning
|
||||
|
||||
```toml
|
||||
[context.strategies]
|
||||
scorer_relevance_weight = 0.4
|
||||
scorer_tier_weight = 0.3
|
||||
scorer_recency_weight = 0.2
|
||||
scorer_plan_weight = 0.1
|
||||
```
|
||||
|
||||
**Tuning Tips**:
|
||||
- Increase `relevance_weight` for quality-focused assembly
|
||||
- Increase `tier_weight` for tier-aware assembly
|
||||
- Increase `recency_weight` for recent-focused assembly
|
||||
|
||||
## Monitoring and Metrics
|
||||
|
||||
### Key Metrics
|
||||
|
||||
| Metric | Description | Target |
|
||||
|--------|-------------|--------|
|
||||
| `assembly_time_ms` | Total pipeline execution time | < 1000ms |
|
||||
| `fragments_selected` | Number of fragments in payload | 5-50 |
|
||||
| `tokens_used` | Total tokens in payload | < available_tokens |
|
||||
| `budget_used` | Fraction of budget consumed | 0.5-0.9 |
|
||||
| `avg_relevance` | Average relevance score | > 0.7 |
|
||||
| `strategy_success_rate` | Fraction of successful strategies | > 0.8 |
|
||||
| `dedup_ratio` | Fraction of duplicates removed | 0.0-0.3 |
|
||||
|
||||
### Logging
|
||||
|
||||
Enable debug logging:
|
||||
|
||||
```python
|
||||
import logging
|
||||
|
||||
logging.getLogger("cleveragents.acms").setLevel(logging.DEBUG)
|
||||
```
|
||||
|
||||
### Metrics Collection
|
||||
|
||||
```python
|
||||
from cleveragents.application.services.acms_service import ACMSPipeline
|
||||
|
||||
pipeline = ACMSPipeline()
|
||||
payload = pipeline.assemble(plan_id, fragments, budget)
|
||||
|
||||
# Collect metrics
|
||||
metrics = {
|
||||
"payload_id": payload.payload_id,
|
||||
"plan_id": payload.plan_id,
|
||||
"total_tokens": payload.total_tokens,
|
||||
"budget_used": payload.budget_used,
|
||||
"fragments_count": len(payload.fragments),
|
||||
"strategies_used": payload.strategies_used,
|
||||
"avg_relevance": sum(f.relevance_score for f in payload.fragments) / len(payload.fragments),
|
||||
"tier_distribution": {
|
||||
"hot": sum(1 for f in payload.fragments if f.tier == "hot"),
|
||||
"warm": sum(1 for f in payload.fragments if f.tier == "warm"),
|
||||
"cold": sum(1 for f in payload.fragments if f.tier == "cold"),
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### Strategy Selection Optimization
|
||||
|
||||
```python
|
||||
# Good: Filter low-confidence strategies
|
||||
candidates = [
|
||||
(s, conf) for s, conf in candidates if conf >= 0.7
|
||||
]
|
||||
|
||||
# Avoid: Execute all strategies
|
||||
candidates = all_strategies
|
||||
```
|
||||
|
||||
### Budget Allocation Optimization
|
||||
|
||||
```python
|
||||
# Good: Proportional allocation
|
||||
allocations = allocator.allocate(
|
||||
candidates=high_confidence,
|
||||
total_budget=3584,
|
||||
strategy="proportional"
|
||||
)
|
||||
|
||||
# Avoid: Equal allocation
|
||||
allocations = {s: 3584 // len(strategies) for s in strategies}
|
||||
```
|
||||
|
||||
### Execution Optimization
|
||||
|
||||
```python
|
||||
# Good: Parallel execution with reasonable timeout
|
||||
executor = StrategyExecutor(max_workers=4, timeout_seconds=30)
|
||||
|
||||
# Avoid: Sequential execution or excessive timeout
|
||||
executor = StrategyExecutor(max_workers=1, timeout_seconds=300)
|
||||
```
|
||||
|
||||
### Fragment Deduplication Optimization
|
||||
|
||||
```python
|
||||
# Good: Deduplicate early
|
||||
deduplicated = deduplicator.deduplicate(fragments)
|
||||
scored = scorer.score(deduplicated, plan_context)
|
||||
|
||||
# Avoid: Deduplicate after scoring
|
||||
scored = scorer.score(fragments, plan_context)
|
||||
deduplicated = deduplicator.deduplicate(scored)
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Slow Pipeline Execution
|
||||
|
||||
**Problem**: Pipeline takes > 1 second.
|
||||
|
||||
**Solution**:
|
||||
1. Check `executor_timeout_seconds` - reduce if too high
|
||||
2. Check `executor_max_workers` - increase if too low
|
||||
3. Check strategy complexity - use simpler strategies
|
||||
4. Check fragment count - reduce `max_fragments`
|
||||
|
||||
### Low Quality Context
|
||||
|
||||
**Problem**: Assembled context is not relevant.
|
||||
|
||||
**Solution**:
|
||||
1. Increase `selector_threshold` to filter low-confidence strategies
|
||||
2. Use higher-quality strategy (e.g., ARCE)
|
||||
3. Increase `scorer_relevance_weight` for quality focus
|
||||
4. Adjust strategy-specific parameters
|
||||
|
||||
### Out of Memory
|
||||
|
||||
**Problem**: Pipeline consumes too much memory.
|
||||
|
||||
**Solution**:
|
||||
1. Reduce `max_fragments` limit
|
||||
2. Reduce `executor_max_workers` for parallel execution
|
||||
3. Enable fragment streaming
|
||||
4. Use simpler strategies
|
||||
|
||||
### Budget Exceeded
|
||||
|
||||
**Problem**: Assembled context exceeds budget.
|
||||
|
||||
**Solution**:
|
||||
1. Check `BudgetPacker` implementation
|
||||
2. Reduce `max_fragments` limit
|
||||
3. Increase `reserved_tokens` to reduce available budget
|
||||
4. Enable detail depth reduction
|
||||
|
||||
## See Also
|
||||
|
||||
- [Context Management Deep Dive](../guides/context_management_deep_dive.md)
|
||||
- [Context Strategies Reference](./context_strategies_reference.md)
|
||||
- [ACMS v1 Context Assembly Pipeline](./acms.md)
|
||||
- [Context Strategy Registry](./context_strategies.md)
|
||||
@@ -0,0 +1,750 @@
|
||||
# Context Strategies Reference
|
||||
|
||||
Complete reference for all context strategies in the ACMS, including configuration options, performance characteristics, and use case recommendations.
|
||||
|
||||
## Strategy Overview
|
||||
|
||||
| Strategy | Quality | Speed | Coverage | Backends | Best For |
|
||||
|----------|---------|-------|----------|----------|----------|
|
||||
| Simple Keyword | 0.3 | ⚡⚡⚡ | Narrow | Text | Quick searches, fallback |
|
||||
| Semantic Embedding | 0.6 | ⚡⚡ | Broad | Vector | Semantic similarity |
|
||||
| Breadth-Depth Navigator | 0.85 | ⚡ | Very Broad | Graph | Comprehensive context |
|
||||
| ARCE | 0.95 | 🐢 | Comprehensive | All | Production use |
|
||||
| Temporal Archaeology | 0.5 | 🐢 | Historical | Graph + Temporal | Historical context |
|
||||
| Plan-Decision Context | 0.7 | ⚡ | Hierarchical | Temporal + Graph | Plan coordination |
|
||||
|
||||
## Simple Keyword Strategy
|
||||
|
||||
### Overview
|
||||
|
||||
The Simple Keyword Strategy performs text-based keyword search using the TextBackend. It's the fastest strategy and serves as a fallback when other backends are unavailable.
|
||||
|
||||
### Quality Score
|
||||
|
||||
**0.3** (baseline)
|
||||
|
||||
### Backend Requirements
|
||||
|
||||
- **Required**: TextBackend
|
||||
- **Optional**: None
|
||||
|
||||
### How It Works
|
||||
|
||||
1. Extract keywords from the ContextRequest
|
||||
2. Query TextBackend using keyword search
|
||||
3. Rank results by match frequency and relevance
|
||||
4. Pack greedily into token budget
|
||||
|
||||
### Configuration
|
||||
|
||||
```toml
|
||||
[context.strategies.simple-keyword]
|
||||
enabled = true
|
||||
timeout_seconds = 10
|
||||
max_fragments = 50
|
||||
keyword_boost_factor = 1.5
|
||||
```
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
|--------|------|---------|-------------|
|
||||
| `enabled` | bool | true | Enable this strategy |
|
||||
| `timeout_seconds` | int | 10 | Per-strategy timeout |
|
||||
| `max_fragments` | int | 50 | Maximum fragments returned |
|
||||
| `keyword_boost_factor` | float | 1.5 | Boost for exact keyword matches |
|
||||
|
||||
### Performance Characteristics
|
||||
|
||||
- **Execution Time**: 50-200ms (typical)
|
||||
- **Memory Usage**: Low (streaming results)
|
||||
- **Scalability**: Excellent (linear with keyword count)
|
||||
- **Parallelization**: Not applicable (single-threaded)
|
||||
|
||||
### Use Cases
|
||||
|
||||
- Quick searches with clear keywords
|
||||
- Projects with good text indexing
|
||||
- Fallback when other backends unavailable
|
||||
- Real-time context assembly with tight latency budgets
|
||||
|
||||
### Example Usage
|
||||
|
||||
```python
|
||||
from cleveragents.application.services.acms_service import ACMSPipeline
|
||||
|
||||
pipeline = ACMSPipeline()
|
||||
payload = pipeline.assemble(
|
||||
plan_id="plan-1",
|
||||
fragments=fragments,
|
||||
budget=ContextBudget(max_tokens=4096, reserved_tokens=512),
|
||||
strategy="simple-keyword"
|
||||
)
|
||||
```
|
||||
|
||||
### Limitations
|
||||
|
||||
- Limited to exact keyword matches
|
||||
- No semantic understanding
|
||||
- Cannot traverse relationships
|
||||
- Requires good text indexing
|
||||
|
||||
## Semantic Embedding Strategy
|
||||
|
||||
### Overview
|
||||
|
||||
The Semantic Embedding Strategy uses vector similarity search to find semantically related context. It uses character-frequency embeddings as a v1 approximation.
|
||||
|
||||
### Quality Score
|
||||
|
||||
**0.6** (good)
|
||||
|
||||
### Backend Requirements
|
||||
|
||||
- **Required**: VectorBackend
|
||||
- **Optional**: None
|
||||
|
||||
### How It Works
|
||||
|
||||
1. Embed the ContextRequest using character-frequency model
|
||||
2. Query VectorBackend for similar embeddings
|
||||
3. Rank by cosine similarity
|
||||
4. Pack budget-aware results
|
||||
|
||||
### Configuration
|
||||
|
||||
```toml
|
||||
[context.strategies.semantic-embedding]
|
||||
enabled = true
|
||||
timeout_seconds = 20
|
||||
max_fragments = 100
|
||||
similarity_threshold = 0.5
|
||||
embedding_model = "character-frequency-v1"
|
||||
```
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
|--------|------|---------|-------------|
|
||||
| `enabled` | bool | true | Enable this strategy |
|
||||
| `timeout_seconds` | int | 20 | Per-strategy timeout |
|
||||
| `max_fragments` | int | 100 | Maximum fragments returned |
|
||||
| `similarity_threshold` | float | 0.5 | Minimum similarity score (0.0-1.0) |
|
||||
| `embedding_model` | str | "character-frequency-v1" | Embedding model to use |
|
||||
|
||||
### Performance Characteristics
|
||||
|
||||
- **Execution Time**: 100-500ms (typical)
|
||||
- **Memory Usage**: Medium (embedding cache)
|
||||
- **Scalability**: Good (logarithmic with vector index size)
|
||||
- **Parallelization**: Supported (multiple similarity searches)
|
||||
|
||||
### Use Cases
|
||||
|
||||
- Semantic similarity searches
|
||||
- Conceptual relationships
|
||||
- Cross-domain context discovery
|
||||
- Finding related code patterns
|
||||
|
||||
### Example Usage
|
||||
|
||||
```python
|
||||
from cleveragents.domain.models.core.context_fragment import ContextRequest
|
||||
|
||||
request = ContextRequest(
|
||||
focus_nodes=["project://myapp/src/main.py"],
|
||||
keywords=["async", "io"]
|
||||
)
|
||||
|
||||
payload = pipeline.assemble(
|
||||
plan_id="plan-1",
|
||||
fragments=fragments,
|
||||
budget=ContextBudget(max_tokens=4096, reserved_tokens=512),
|
||||
strategy="semantic-embedding"
|
||||
)
|
||||
```
|
||||
|
||||
### Limitations
|
||||
|
||||
- v1 uses character-frequency embeddings (not true semantic)
|
||||
- Requires VectorBackend
|
||||
- Cannot traverse relationships
|
||||
- Sensitive to embedding quality
|
||||
|
||||
### Future Improvements
|
||||
|
||||
- Integration with real embedding models (e.g., OpenAI, Anthropic)
|
||||
- Fine-tuned embeddings for code
|
||||
- Hybrid semantic-keyword search
|
||||
|
||||
## Breadth-Depth Navigator Strategy
|
||||
|
||||
### Overview
|
||||
|
||||
The Breadth-Depth Navigator Strategy traverses the knowledge graph to find related context. It explores outward (breadth) and downward (depth) from focus nodes.
|
||||
|
||||
### Quality Score
|
||||
|
||||
**0.85** (excellent)
|
||||
|
||||
### Backend Requirements
|
||||
|
||||
- **Required**: GraphBackend
|
||||
- **Optional**: None
|
||||
|
||||
### How It Works
|
||||
|
||||
1. Start from focus nodes in ContextRequest
|
||||
2. Traverse graph outward by breadth hops
|
||||
3. Traverse downward by depth hops
|
||||
4. Collect all reachable nodes
|
||||
5. Rank by distance and relevance
|
||||
6. Pack into budget
|
||||
|
||||
### Configuration
|
||||
|
||||
```toml
|
||||
[context.strategies.breadth-depth-navigator]
|
||||
enabled = true
|
||||
timeout_seconds = 30
|
||||
max_fragments = 150
|
||||
default_breadth = 2
|
||||
default_depth = 3
|
||||
distance_decay = 0.8
|
||||
```
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
|--------|------|---------|-------------|
|
||||
| `enabled` | bool | true | Enable this strategy |
|
||||
| `timeout_seconds` | int | 30 | Per-strategy timeout |
|
||||
| `max_fragments` | int | 150 | Maximum fragments returned |
|
||||
| `default_breadth` | int | 2 | Default breadth hops |
|
||||
| `default_depth` | int | 3 | Default depth hops |
|
||||
| `distance_decay` | float | 0.8 | Decay factor per hop |
|
||||
|
||||
### Performance Characteristics
|
||||
|
||||
- **Execution Time**: 200-1000ms (typical)
|
||||
- **Memory Usage**: Medium (graph traversal state)
|
||||
- **Scalability**: Good (exponential with breadth/depth)
|
||||
- **Parallelization**: Supported (parallel hop traversal)
|
||||
|
||||
### Use Cases
|
||||
|
||||
- Exploring related code and decisions
|
||||
- Understanding dependencies
|
||||
- Comprehensive context assembly
|
||||
- Finding transitive relationships
|
||||
|
||||
### Example Usage
|
||||
|
||||
```python
|
||||
request = ContextRequest(
|
||||
focus_nodes=["project://myapp/src/main.py"],
|
||||
breadth=2,
|
||||
depth=3
|
||||
)
|
||||
|
||||
payload = pipeline.assemble(
|
||||
plan_id="plan-1",
|
||||
fragments=fragments,
|
||||
budget=ContextBudget(max_tokens=4096, reserved_tokens=512),
|
||||
strategy="breadth-depth-navigator"
|
||||
)
|
||||
```
|
||||
|
||||
### Limitations
|
||||
|
||||
- Requires GraphBackend
|
||||
- Can be slow with large graphs
|
||||
- Exponential complexity with breadth/depth
|
||||
- May include irrelevant distant nodes
|
||||
|
||||
### Optimization Tips
|
||||
|
||||
- Reduce breadth/depth for faster execution
|
||||
- Use distance decay to prioritize nearby nodes
|
||||
- Filter by resource type to reduce graph size
|
||||
- Increase timeout for large graphs
|
||||
|
||||
## ARCE Strategy (Advanced Retrieval with Context Enrichment)
|
||||
|
||||
### Overview
|
||||
|
||||
ARCE is the most comprehensive strategy, combining text search, vector similarity, and graph traversal. It's the recommended strategy for production use cases.
|
||||
|
||||
### Quality Score
|
||||
|
||||
**0.95** (highest)
|
||||
|
||||
### Backend Requirements
|
||||
|
||||
- **Required**: TextBackend, VectorBackend, GraphBackend
|
||||
- **Optional**: None
|
||||
|
||||
### How It Works
|
||||
|
||||
1. **Phase 1 (40% budget)**: Text search using keywords
|
||||
2. **Phase 2 (40% budget)**: Vector similarity search
|
||||
3. **Phase 3 (20% budget)**: Graph traversal from results
|
||||
4. Merge and deduplicate results
|
||||
5. Rank by combined score
|
||||
6. Pack into budget
|
||||
|
||||
### Configuration
|
||||
|
||||
```toml
|
||||
[context.strategies.arce]
|
||||
enabled = true
|
||||
timeout_seconds = 45
|
||||
max_fragments = 200
|
||||
text_budget_fraction = 0.4
|
||||
vector_budget_fraction = 0.4
|
||||
graph_budget_fraction = 0.2
|
||||
dedup_strategy = "highest_relevance"
|
||||
```
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
|--------|------|---------|-------------|
|
||||
| `enabled` | bool | true | Enable this strategy |
|
||||
| `timeout_seconds` | int | 45 | Per-strategy timeout |
|
||||
| `max_fragments` | int | 200 | Maximum fragments returned |
|
||||
| `text_budget_fraction` | float | 0.4 | Budget for text search |
|
||||
| `vector_budget_fraction` | float | 0.4 | Budget for vector search |
|
||||
| `graph_budget_fraction` | float | 0.2 | Budget for graph traversal |
|
||||
| `dedup_strategy` | str | "highest_relevance" | Deduplication strategy |
|
||||
|
||||
### Performance Characteristics
|
||||
|
||||
- **Execution Time**: 500-2000ms (typical)
|
||||
- **Memory Usage**: High (multiple result sets)
|
||||
- **Scalability**: Good (parallel phases)
|
||||
- **Parallelization**: Excellent (3 phases in parallel)
|
||||
|
||||
### Use Cases
|
||||
|
||||
- Comprehensive context assembly
|
||||
- Multi-modal queries
|
||||
- Production use cases
|
||||
- High-quality context requirements
|
||||
|
||||
### Example Usage
|
||||
|
||||
```python
|
||||
request = ContextRequest(
|
||||
focus_nodes=["project://myapp/src/main.py"],
|
||||
keywords=["async", "io"],
|
||||
breadth=2
|
||||
)
|
||||
|
||||
payload = pipeline.assemble(
|
||||
plan_id="plan-1",
|
||||
fragments=fragments,
|
||||
budget=ContextBudget(max_tokens=4096, reserved_tokens=512),
|
||||
strategy="arce"
|
||||
)
|
||||
```
|
||||
|
||||
### Limitations
|
||||
|
||||
- Requires all three backends
|
||||
- Slower than single-backend strategies
|
||||
- Higher memory usage
|
||||
- May return too many fragments
|
||||
|
||||
### Optimization Tips
|
||||
|
||||
- Adjust budget fractions based on query type
|
||||
- Increase timeout for complex queries
|
||||
- Use deduplication to reduce redundancy
|
||||
- Filter by resource type to reduce results
|
||||
|
||||
## Temporal Archaeology Strategy
|
||||
|
||||
### Overview
|
||||
|
||||
The Temporal Archaeology Strategy retrieves historical context from the cold tier and traverses relationships from historical nodes.
|
||||
|
||||
### Quality Score
|
||||
|
||||
**0.5** (moderate)
|
||||
|
||||
### Backend Requirements
|
||||
|
||||
- **Required**: GraphBackend, TemporalBackend (cold tier)
|
||||
- **Optional**: None
|
||||
|
||||
### How It Works
|
||||
|
||||
1. Query TemporalBackend for historical nodes
|
||||
2. Filter by temporal window
|
||||
3. Traverse graph from historical nodes
|
||||
4. Collect related current nodes
|
||||
5. Rank by recency and relevance
|
||||
6. Pack into budget
|
||||
|
||||
### Configuration
|
||||
|
||||
```toml
|
||||
[context.strategies.temporal-archaeology]
|
||||
enabled = false
|
||||
timeout_seconds = 60
|
||||
max_fragments = 100
|
||||
default_temporal_window = "7d"
|
||||
include_current_context = true
|
||||
```
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
|--------|------|---------|-------------|
|
||||
| `enabled` | bool | false | Enable this strategy |
|
||||
| `timeout_seconds` | int | 60 | Per-strategy timeout |
|
||||
| `max_fragments` | int | 100 | Maximum fragments returned |
|
||||
| `default_temporal_window` | str | "7d" | Default time window |
|
||||
| `include_current_context` | bool | true | Include current context |
|
||||
|
||||
### Performance Characteristics
|
||||
|
||||
- **Execution Time**: 1000-5000ms (typical)
|
||||
- **Memory Usage**: High (temporal queries)
|
||||
- **Scalability**: Fair (depends on cold tier size)
|
||||
- **Parallelization**: Limited (sequential phases)
|
||||
|
||||
### Use Cases
|
||||
|
||||
- Understanding historical context
|
||||
- Decision archaeology
|
||||
- Long-term project evolution
|
||||
- Regression analysis
|
||||
|
||||
### Example Usage
|
||||
|
||||
```python
|
||||
request = ContextRequest(
|
||||
focus_nodes=["project://myapp/src/main.py"],
|
||||
temporal_window="30d"
|
||||
)
|
||||
|
||||
payload = pipeline.assemble(
|
||||
plan_id="plan-1",
|
||||
fragments=fragments,
|
||||
budget=ContextBudget(max_tokens=4096, reserved_tokens=512),
|
||||
strategy="temporal-archaeology"
|
||||
)
|
||||
```
|
||||
|
||||
### Limitations
|
||||
|
||||
- Requires cold tier (not always available)
|
||||
- Slow execution
|
||||
- May include outdated information
|
||||
- Limited to historical data
|
||||
|
||||
### Temporal Window Format
|
||||
|
||||
- `"1d"` - Last 1 day
|
||||
- `"7d"` - Last 7 days
|
||||
- `"30d"` - Last 30 days
|
||||
- `"90d"` - Last 90 days
|
||||
- `"1y"` - Last 1 year
|
||||
- `"all"` - All history
|
||||
|
||||
## Plan-Decision Context Strategy
|
||||
|
||||
### Overview
|
||||
|
||||
The Plan-Decision Context Strategy walks the plan hierarchy to retrieve decision records and related context.
|
||||
|
||||
### Quality Score
|
||||
|
||||
**0.7** (good)
|
||||
|
||||
### Backend Requirements
|
||||
|
||||
- **Required**: TemporalBackend (warm/cold), GraphBackend
|
||||
- **Optional**: None
|
||||
|
||||
### How It Works
|
||||
|
||||
1. Walk parent and ancestor plan hierarchy
|
||||
2. Retrieve decision records from warm/cold tiers
|
||||
3. Traverse graph from decisions
|
||||
4. Collect related context
|
||||
5. Rank by plan proximity and relevance
|
||||
6. Pack into budget
|
||||
|
||||
### Configuration
|
||||
|
||||
```toml
|
||||
[context.strategies.plan-decision-context]
|
||||
enabled = true
|
||||
timeout_seconds = 30
|
||||
max_fragments = 100
|
||||
include_ancestor_decisions = true
|
||||
max_ancestor_depth = 5
|
||||
```
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
|--------|------|---------|-------------|
|
||||
| `enabled` | bool | true | Enable this strategy |
|
||||
| `timeout_seconds` | int | 30 | Per-strategy timeout |
|
||||
| `max_fragments` | int | 100 | Maximum fragments returned |
|
||||
| `include_ancestor_decisions` | bool | true | Include ancestor decisions |
|
||||
| `max_ancestor_depth` | int | 5 | Maximum ancestor levels |
|
||||
|
||||
### Performance Characteristics
|
||||
|
||||
- **Execution Time**: 200-800ms (typical)
|
||||
- **Memory Usage**: Medium (plan hierarchy)
|
||||
- **Scalability**: Good (linear with plan depth)
|
||||
- **Parallelization**: Supported (parallel ancestor traversal)
|
||||
|
||||
### Use Cases
|
||||
|
||||
- Understanding plan context
|
||||
- Decision inheritance
|
||||
- Multi-level plan coordination
|
||||
- Plan dependency analysis
|
||||
|
||||
### Example Usage
|
||||
|
||||
```python
|
||||
request = ContextRequest(
|
||||
focus_nodes=["project://myapp/src/main.py"]
|
||||
)
|
||||
|
||||
payload = pipeline.assemble(
|
||||
plan_id="plan-1",
|
||||
fragments=fragments,
|
||||
budget=ContextBudget(max_tokens=4096, reserved_tokens=512),
|
||||
strategy="plan-decision-context"
|
||||
)
|
||||
```
|
||||
|
||||
### Limitations
|
||||
|
||||
- Requires plan hierarchy
|
||||
- Limited to decision context
|
||||
- May miss non-decision context
|
||||
- Depends on plan structure
|
||||
|
||||
## Strategy Selection Guide
|
||||
|
||||
### When to Use Each Strategy
|
||||
|
||||
#### Simple Keyword
|
||||
- ✅ Quick searches with clear keywords
|
||||
- ✅ Fallback when other backends unavailable
|
||||
- ✅ Real-time context with tight latency budgets
|
||||
- ❌ Semantic understanding needed
|
||||
- ❌ Relationship traversal needed
|
||||
|
||||
#### Semantic Embedding
|
||||
- ✅ Semantic similarity searches
|
||||
- ✅ Conceptual relationships
|
||||
- ✅ Cross-domain discovery
|
||||
- ❌ Exact keyword matching needed
|
||||
- ❌ Relationship traversal needed
|
||||
|
||||
#### Breadth-Depth Navigator
|
||||
- ✅ Exploring related code
|
||||
- ✅ Understanding dependencies
|
||||
- ✅ Comprehensive context
|
||||
- ❌ Quick searches needed
|
||||
- ❌ Historical context needed
|
||||
|
||||
#### ARCE
|
||||
- ✅ Comprehensive context assembly
|
||||
- ✅ Multi-modal queries
|
||||
- ✅ Production use cases
|
||||
- ❌ Quick searches needed
|
||||
- ❌ Limited backends available
|
||||
|
||||
#### Temporal Archaeology
|
||||
- ✅ Historical context
|
||||
- ✅ Decision archaeology
|
||||
- ✅ Long-term evolution
|
||||
- ❌ Current context needed
|
||||
- ❌ Quick searches needed
|
||||
|
||||
#### Plan-Decision Context
|
||||
- ✅ Plan coordination
|
||||
- ✅ Decision inheritance
|
||||
- ✅ Multi-level plans
|
||||
- ❌ Non-decision context needed
|
||||
- ❌ No plan hierarchy
|
||||
|
||||
### Fallback Chain
|
||||
|
||||
When a strategy fails, the system falls back to simpler strategies:
|
||||
|
||||
```
|
||||
ARCE (0.95)
|
||||
↓ (if unavailable)
|
||||
Breadth-Depth Navigator (0.85)
|
||||
↓ (if unavailable)
|
||||
Semantic Embedding (0.6)
|
||||
↓ (if unavailable)
|
||||
Simple Keyword (0.3)
|
||||
```
|
||||
|
||||
## Performance Comparison
|
||||
|
||||
### Execution Time
|
||||
|
||||
```
|
||||
Simple Keyword: ████ 50-200ms
|
||||
Semantic Embedding: ██████████ 100-500ms
|
||||
Breadth-Depth: ███████████████ 200-1000ms
|
||||
Plan-Decision: ██████████ 200-800ms
|
||||
ARCE: ████████████████████ 500-2000ms
|
||||
Temporal Archaeology: ████████████████████████ 1000-5000ms
|
||||
```
|
||||
|
||||
### Memory Usage
|
||||
|
||||
```
|
||||
Simple Keyword: ██ Low
|
||||
Semantic Embedding: ████ Medium
|
||||
Breadth-Depth: ████ Medium
|
||||
Plan-Decision: ████ Medium
|
||||
ARCE: ██████ High
|
||||
Temporal Archaeology: ██████ High
|
||||
```
|
||||
|
||||
### Coverage
|
||||
|
||||
```
|
||||
Simple Keyword: ██ Narrow
|
||||
Temporal Archaeology: ███ Moderate
|
||||
Semantic Embedding: ████ Broad
|
||||
Plan-Decision: ████ Hierarchical
|
||||
Breadth-Depth: █████ Very Broad
|
||||
ARCE: ██████ Comprehensive
|
||||
```
|
||||
|
||||
## Configuration Best Practices
|
||||
|
||||
### Global Configuration
|
||||
|
||||
```toml
|
||||
[context.strategies]
|
||||
enabled = ["simple-keyword", "semantic-embedding", "breadth-depth-navigator"]
|
||||
default_strategy = "arce"
|
||||
fallback_chain = ["arce", "breadth-depth-navigator", "semantic-embedding", "simple-keyword"]
|
||||
|
||||
[context.strategies.simple-keyword]
|
||||
enabled = true
|
||||
timeout_seconds = 10
|
||||
max_fragments = 50
|
||||
|
||||
[context.strategies.semantic-embedding]
|
||||
enabled = true
|
||||
timeout_seconds = 20
|
||||
max_fragments = 100
|
||||
|
||||
[context.strategies.breadth-depth-navigator]
|
||||
enabled = true
|
||||
timeout_seconds = 30
|
||||
max_fragments = 150
|
||||
|
||||
[context.strategies.arce]
|
||||
enabled = true
|
||||
timeout_seconds = 45
|
||||
max_fragments = 200
|
||||
|
||||
[context.strategies.plan-decision-context]
|
||||
enabled = true
|
||||
timeout_seconds = 30
|
||||
max_fragments = 100
|
||||
```
|
||||
|
||||
### Per-Project Overrides
|
||||
|
||||
```bash
|
||||
# Set strategies for a project
|
||||
agents project context set \
|
||||
--strategy simple-keyword \
|
||||
--strategy semantic-embedding \
|
||||
--strategy breadth-depth-navigator
|
||||
|
||||
# View current strategies
|
||||
agents project context list
|
||||
```
|
||||
|
||||
## Monitoring and Metrics
|
||||
|
||||
### Key Metrics
|
||||
|
||||
- **Execution Time**: Strategy execution wall-clock time
|
||||
- **Fragment Count**: Number of fragments returned
|
||||
- **Token Usage**: Total tokens in assembled context
|
||||
- **Budget Utilization**: Percentage of budget used
|
||||
- **Relevance Score**: Average relevance of fragments
|
||||
- **Tier Distribution**: Hot/warm/cold fragment counts
|
||||
|
||||
### Logging
|
||||
|
||||
Enable debug logging to monitor strategy execution:
|
||||
|
||||
```python
|
||||
import logging
|
||||
|
||||
logging.getLogger("cleveragents.acms").setLevel(logging.DEBUG)
|
||||
```
|
||||
|
||||
### Example Metrics Output
|
||||
|
||||
```
|
||||
Strategy: semantic-embedding
|
||||
Execution Time: 234ms
|
||||
Fragments: 12
|
||||
Tokens: 2048
|
||||
Budget Used: 57%
|
||||
Avg Relevance: 0.82
|
||||
Tier Distribution: hot=2, warm=8, cold=2
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Strategy Not Selected
|
||||
|
||||
**Problem**: Expected strategy not selected.
|
||||
|
||||
**Solution**:
|
||||
1. Check strategy is enabled in configuration
|
||||
2. Verify `can_handle()` returns confidence > 0
|
||||
3. Check required backends are available
|
||||
4. Review strategy selection logs
|
||||
|
||||
### Slow Execution
|
||||
|
||||
**Problem**: Strategy takes too long.
|
||||
|
||||
**Solution**:
|
||||
1. Reduce `max_fragments` limit
|
||||
2. Decrease `breadth` and `depth` parameters
|
||||
3. Increase `timeout_seconds` if appropriate
|
||||
4. Switch to faster strategy
|
||||
|
||||
### Low Quality Results
|
||||
|
||||
**Problem**: Assembled context is not relevant.
|
||||
|
||||
**Solution**:
|
||||
1. Try higher-quality strategy (e.g., ARCE)
|
||||
2. Adjust `similarity_threshold` for semantic strategy
|
||||
3. Increase `breadth` and `depth` for navigator
|
||||
4. Provide better keywords in request
|
||||
|
||||
### Out of Memory
|
||||
|
||||
**Problem**: Strategy consumes too much memory.
|
||||
|
||||
**Solution**:
|
||||
1. Reduce `max_fragments` limit
|
||||
2. Switch to lower-memory strategy
|
||||
3. Reduce `breadth` and `depth` parameters
|
||||
4. Enable fragment streaming
|
||||
|
||||
## See Also
|
||||
|
||||
- [Context Management Deep Dive](../guides/context_management_deep_dive.md)
|
||||
- [ACMS Pipeline Reference](./acms_pipeline_reference.md)
|
||||
- [ACMS v1 Context Assembly Pipeline](./acms.md)
|
||||
- [Context Strategy Registry](./context_strategies.md)
|
||||
@@ -24,8 +24,6 @@ nav:
|
||||
- AI Providers: api/providers.md
|
||||
- TUI: api/tui.md
|
||||
- ACMS / UKO: api/acms.md
|
||||
- Guides:
|
||||
- Configuration Reference: guides/configuration-reference.md
|
||||
- Modules:
|
||||
- Shell Safety: modules/shell-safety.md
|
||||
- UKO Provenance Tracking: modules/uko-provenance.md
|
||||
|
||||
Reference in New Issue
Block a user