7d74be68aa
CI / lint (pull_request) Successful in 14s
CI / benchmark-publish (pull_request) Has been skipped
CI / quality (pull_request) Successful in 28s
CI / typecheck (pull_request) Successful in 33s
CI / build (pull_request) Successful in 14s
CI / security (pull_request) Successful in 35s
CI / unit_tests (pull_request) Successful in 2m52s
CI / docker (pull_request) Successful in 39s
CI / integration_tests (pull_request) Successful in 3m53s
CI / coverage (pull_request) Successful in 3m42s
CI / lint (push) Successful in 13s
CI / quality (push) Successful in 16s
CI / build (push) Successful in 16s
CI / security (push) Successful in 29s
CI / typecheck (push) Successful in 32s
CI / benchmark-regression (push) Has been skipped
CI / unit_tests (push) Successful in 1m53s
CI / docker (push) Successful in 53s
CI / integration_tests (push) Successful in 2m49s
CI / coverage (push) Successful in 3m50s
CI / benchmark-publish (push) Successful in 13m7s
CI / benchmark-regression (pull_request) Successful in 28m12s
Add --project flag to config set, config get, and config list CLI commands, enabling per-project configuration overrides stored under [project."<name>"] TOML tables in the global config file. Project-scoped resolution slots between environment variable and global levels in the ConfigService resolution chain. config list --project shows only overrides for the named project with source annotations. Implementation: - ConfigService: add set_project_value() and get_project_overrides() methods for TOML-backed project-scoped persistence and retrieval - CLI config commands: wire --project flag through set, get, and list subcommands; project-scoped list filters to overrides only - Database persistence: project-scoped config stored as alternative backend for projects not using TOML - Documentation: update docs/reference/config_resolution.md with project-scopable key lists, CLI examples, precedence diagram, and non-scopable key rejection behavior Tests: - Behave: 12 BDD scenarios in features/config_project_scope.feature covering set/get/list, precedence over global defaults, and non-scopable key rejection - Robot: 5 integration smoke tests in robot/config_project_scope.robot for end-to-end project-scoped round-trip verification - ASV: benchmarks/config_project_scope_bench.py measuring resolution overhead with project scope active All nox quality gates pass: lint, typecheck, unit_tests (7522 scenarios), integration_tests (Config Project Scope suite passed), and coverage at 98% line rate (threshold 97%). Closes #259
231 lines
7.0 KiB
Markdown
231 lines
7.0 KiB
Markdown
# Configuration Resolution
|
|
|
|
CleverAgents resolves every configuration value through a **5-level precedence
|
|
chain**. The first level that supplies a non-`None` value wins.
|
|
|
|
## Resolution Order
|
|
|
|
| Priority | Source | Example |
|
|
|----------|--------|---------|
|
|
| 1 (highest) | **CLI flag** | `--format json`, `--data-dir /tmp` |
|
|
| 2 | **Environment variable** | `CLEVERAGENTS_CORE_LOG_LEVEL=WARNING` |
|
|
| 3 | **Project-scoped config** | `[project."myapp"]` table in TOML |
|
|
| 4 | **Global config file** | `~/.cleveragents/config.toml` |
|
|
| 5 (lowest) | **Built-in default** | Hardcoded in key registry |
|
|
|
|
```
|
|
$ export CLEVERAGENTS_CORE_LOG_LEVEL=WARNING
|
|
$ agents config set core.log_level DEBUG # writes to global config
|
|
$ agents config get core.log_level
|
|
# -> WARNING (env var at priority 2 beats global config at priority 4)
|
|
```
|
|
|
|
## Key Format
|
|
|
|
Keys use hierarchical dot-separated names. The segment before the first dot is
|
|
the **group**; everything after it is the **key name** within that group.
|
|
|
|
```
|
|
core.log.level
|
|
plan.budget.per-plan
|
|
provider.openai.api-key
|
|
```
|
|
|
|
Environment variable mapping follows the pattern
|
|
`CLEVERAGENTS_<GROUP>_<KEY>` with dots and hyphens replaced by underscores and
|
|
all characters uppercased:
|
|
|
|
- `core.log.level` → `CLEVERAGENTS_CORE_LOG_LEVEL`
|
|
- `plan.budget.per-plan` → `CLEVERAGENTS_PLAN_BUDGET_PER_PLAN`
|
|
|
|
**Exception:** `provider.*` credential keys use standard provider env vars
|
|
(see [Provider Credentials](#provider-credentials)).
|
|
|
|
## Configuration Groups
|
|
|
|
| Group | Keys | Scope | Description |
|
|
|-------|------|-------|-------------|
|
|
| `core.*` | 14 | Mixed | Core system settings — logging, data dirs, database, runtime env |
|
|
| `server.*` | 4 | Global only | Server mode — bind host, port, TLS, workers |
|
|
| `actor.*` | 5 | Mixed | Actor defaults — timeout, retry, concurrency |
|
|
| `plan.*` | 8 | Mixed | Plan execution — budget, retries, auto-apply, timeout |
|
|
| `sandbox.*` | 5 | Mixed | Sandbox and checkpointing — strategy, cleanup, max age |
|
|
| `index.*` | 12 | Mixed | Code intelligence and indexing — backend, embedding model, dimensions |
|
|
| `context.*` | 43 | **All project-scopable** | Context tier defaults — token limits, file caps, inclusion rules |
|
|
| `provider.*` | 11 | Global only | LLM provider credentials and model defaults |
|
|
| `skills.*` | 1 | Project-scopable | Agent Skills discovery paths |
|
|
|
|
**Total: 103 registered keys.**
|
|
|
|
## Project-Scopable Keys
|
|
|
|
Keys marked as project-scopable can be overridden per-project in the
|
|
`[project."<name>"]` TOML table. When a project name is active, the resolver
|
|
checks this table at priority 3 before falling back to the global value.
|
|
|
|
**Fully project-scopable groups:**
|
|
|
|
- `context.*` — all 43 keys
|
|
|
|
**Partially project-scopable groups:**
|
|
|
|
- `core.*` — `automation-profile`
|
|
- `plan.*` — `concurrency`, `max-child-depth`, `budget.per-plan`
|
|
- `sandbox.*` — `strategy`, `checkpoint.enabled`
|
|
- `skills.*` — `agent_skills_paths`
|
|
|
|
**Never project-scopable:**
|
|
|
|
- `server.*` — applies globally to the running process
|
|
- `provider.*` — credentials are always global
|
|
- `actor.*` — actor defaults are global
|
|
- `index.*` — index backends are global
|
|
|
|
### Setting project overrides
|
|
|
|
Use the `--project` flag on `config set` to store a value under the
|
|
project-scoped TOML table:
|
|
|
|
```bash
|
|
agents config set core.automation-profile manual --project my-project
|
|
agents config set plan.concurrency 16 --project my-project
|
|
```
|
|
|
|
### Reading project-scoped values
|
|
|
|
When `--project` is provided, the resolver checks the project table at
|
|
priority 3 between environment variables and the global config file:
|
|
|
|
```bash
|
|
agents config get core.automation-profile --project my-project
|
|
```
|
|
|
|
### Listing project overrides only
|
|
|
|
`config list --project <name>` shows **only** the keys that have been
|
|
explicitly overridden for that project — not the full resolved view:
|
|
|
|
```bash
|
|
agents config list --project my-project
|
|
```
|
|
|
|
### Non-scopable key rejection
|
|
|
|
Attempting to set a non-project-scopable key (e.g. `core.data-dir`) via
|
|
`--project` raises an error:
|
|
|
|
```bash
|
|
$ agents config set core.data-dir /tmp --project my-project
|
|
Error: Key 'core.data-dir' is not project-scopable.
|
|
```
|
|
|
|
## CLI Commands
|
|
|
|
### `agents config set`
|
|
|
|
```
|
|
agents config set <key> <value> [--project <name>]
|
|
```
|
|
|
|
Writes a value to the global config file (or to the project-scoped table when
|
|
`--project` is supplied). The value is coerced to the key's registered type.
|
|
|
|
### `agents config get`
|
|
|
|
```
|
|
agents config get <key> [--verbose] [--project <name>]
|
|
```
|
|
|
|
| Flag | Effect |
|
|
|------|--------|
|
|
| `--verbose` | Print the full resolution chain showing every level |
|
|
| `--project` | Resolve as if inside the named project |
|
|
|
|
Verbose output example:
|
|
|
|
```
|
|
$ agents config get core.log.level --verbose
|
|
Key: core.log.level
|
|
Value: INFO
|
|
Source: default
|
|
|
|
Resolution chain (highest → lowest):
|
|
cli_flag → (not set)
|
|
env_var → (not set) [CLEVERAGENTS_CORE_LOG_LEVEL]
|
|
project → (not set)
|
|
global → (not set) [~/.cleveragents/config.toml]
|
|
default → INFO ← active
|
|
```
|
|
|
|
### `agents config list`
|
|
|
|
```
|
|
agents config list [pattern] [--filter-values] [--show-secrets] [--project <name>]
|
|
```
|
|
|
|
| Flag | Effect |
|
|
|------|--------|
|
|
| `pattern` | Glob filter on key names (e.g. `core.*`, `plan.budget.*`) |
|
|
| `--filter-values` | Only show keys whose resolved value differs from the default |
|
|
| `--show-secrets` | Unmask secret values (provider keys are masked by default) |
|
|
| `--project` | Resolve values in the context of the named project |
|
|
|
|
## TOML File Format
|
|
|
|
`~/.cleveragents/config.toml`:
|
|
|
|
```toml
|
|
[core]
|
|
log_level = "DEBUG"
|
|
data_dir = "/var/lib/cleveragents"
|
|
|
|
[plan]
|
|
auto_apply = true
|
|
max_retries = 5
|
|
|
|
[sandbox]
|
|
strategy = "container"
|
|
|
|
[index]
|
|
enabled = true
|
|
backend = "faiss"
|
|
embedding_model = "text-embedding-3-small"
|
|
|
|
# Project-scoped overrides
|
|
[project."myapp"]
|
|
core.log_level = "WARNING"
|
|
plan.auto_apply = false
|
|
context.max_tokens = 64000
|
|
|
|
[project."data-pipeline"]
|
|
plan.budget.per_plan = 2.50
|
|
sandbox.strategy = "git_worktree"
|
|
```
|
|
|
|
Parent directories are created automatically on the first write.
|
|
|
|
## Provider Credentials
|
|
|
|
Provider keys use **standard provider environment variable names**, not the
|
|
`CLEVERAGENTS_*` convention. This avoids requiring users to duplicate
|
|
credentials under a project-specific prefix.
|
|
|
|
| Key | Environment Variable |
|
|
|-----|---------------------|
|
|
| `provider.openai.api-key` | `OPENAI_API_KEY` |
|
|
| `provider.anthropic.api-key` | `ANTHROPIC_API_KEY` |
|
|
| `provider.google.api-key` | `GOOGLE_API_KEY` |
|
|
| `provider.azure.api-key` | `AZURE_OPENAI_API_KEY` |
|
|
| `provider.default-provider` | `CLEVERAGENTS_PROVIDER_DEFAULT_PROVIDER` |
|
|
| `provider.default-model` | `CLEVERAGENTS_PROVIDER_DEFAULT_MODEL` |
|
|
| `provider.temperature` | `CLEVERAGENTS_PROVIDER_TEMPERATURE` |
|
|
|
|
Provider credential values are **masked** in `config list` output by default.
|
|
Use `--show-secrets` to reveal them.
|
|
|
|
## Validation
|
|
|
|
- **Unknown keys** produce an actionable error listing valid keys.
|
|
- **Type mismatches** raise `TypeError` with the expected type and actual value.
|
|
- Boolean coercion accepts `true`/`false`, `1`/`0`, `yes`/`no` (case-insensitive).
|