# ADR-024: Configuration System

**Status:** Accepted  
**Date:** 2026-02-16  
**Supersedes:** None  
**Author(s):** Jeffrey Phillips Freeman <Jeffrey.Freeman@CleverThis.com>  
**Approver(s):** Jeffrey Phillips Freeman <Jeffrey.Freeman@CleverThis.com>

## Context

CleverAgents has a large number of configurable settings — output format, log level, sandbox strategy, context budgets, provider credentials, index backends, and more. These settings must be manageable through multiple channels (CLI flags, environment variables, configuration files) with a clear precedence order. Entity definitions (actors, tools, skills, actions, resource types) also need a configuration format. The system needs a configuration architecture that supports hierarchical keys, project-scoped overrides, environment variable interpolation, and a clean separation between global system settings and entity definitions.

## Decision

CleverAgents uses a **dual-format configuration system**: **TOML** for global system configuration (managed via `agents config` CLI) with **dot-path hierarchical keys**, and **YAML** for entity configuration files (actors, tools, skills, actions, resource types, automation profiles, context views). A five-tier resolution chain determines the effective value for each setting: CLI flag > environment variable > project-scoped config > global config file > built-in default.

## Design

### Global Configuration (TOML)

The global configuration file (default: `~/.cleveragents/config.toml`) stores system-wide settings. Keys use dot-separated hierarchical names:

```
core.format = "rich"
core.log.level = "FATAL"
index.text.backend = "tantivy"
sandbox.strategy = "git_worktree"
provider.openai.api-key = "sk-..."
```

The hierarchy maps to TOML's native table structure:

```toml
[core]
format = "rich"

[core.log]
level = "FATAL"

[index.text]
backend = "tantivy"
```

Both inline dot notation and nested table notation are valid and can be mixed.

### Key Groups

Configuration keys are organized into groups:

| Group | Scope | Examples |
|-------|-------|---------|
| `core.*` | Core system settings | `core.format`, `core.log.level`, `core.namespace`, `core.automation-profile` |
| `server.*` | Server mode | `server.url`, `server.token`, `server.sync.auto` |
| `actor.*` | Actor defaults | `actor.default.strategy`, `actor.default.execution` |
| `plan.*` | Plan execution | `plan.concurrency`, `plan.budget.per-plan`, `plan.tool.max-calls-per-step` |
| `sandbox.*` | Sandbox and checkpointing | `sandbox.strategy`, `sandbox.checkpoint.enabled` |
| `index.*` | Code intelligence | `index.text.backend`, `index.vector.backend`, `index.embedding.provider` |
| `context.*` | Context management | `context.hot.max-tokens`, `context.strategies.enabled`, `context.pipeline.*` |
| `provider.*` | LLM provider credentials | `provider.openai.api-key`, `provider.anthropic.api-key` |

### Resolution Chain

For any configuration value, the effective value is determined by:

```
CLI flag > environment variable > project-scoped config > global config file > built-in default
```

Environment variables use the `CLEVERAGENTS_` prefix (e.g., `CLEVERAGENTS_FORMAT` for `core.format`). Provider credentials use standard names (e.g., `OPENAI_API_KEY` for `provider.openai.api-key`) for ecosystem compatibility.

### Project-Scoped Configuration

Many keys are **project-scopable** — they can be overridden at the project level via `agents project config set`. Project-scoped values take precedence over the global config but are overridden by CLI flags and environment variables. Key project-scopable settings: `sandbox.strategy`, `sandbox.checkpoint.enabled`, `plan.concurrency`, `core.automation-profile`, and all `context.*` keys.

### Entity Configuration (YAML)

All entity definitions use YAML as the canonical format:

- Actors: Graph structure, LLM config, skills, context view policy.
- Tools: Input/output schemas, capability metadata, resource bindings.
- Skills: Tool references, includes, MCP servers, builtins.
- Actions: Description, definition of done, actors, inputs schema.
- Resource types: Type schema, sandbox strategy.
- Automation profiles: Threshold values, safety flags.

Entity YAML files support `${ENV_VAR}` syntax for environment variable interpolation.

### CLI Management

```
agents config set <key> <value>     # Set a global config value
agents config get <key>             # Get the effective value
agents config list [pattern]        # List keys (supports glob, e.g., `index.*`)
```

### Convention Over Configuration

Default behavior requires zero configuration. The system ships with sensible defaults for every key. For entity registration commands, the YAML configuration file is the complete definition (no CLI overrides required). For runtime commands (e.g., `plan use`), CLI flags may override entity defaults.

## Constraints

- Every configuration key must have a built-in default. The system must function with an empty configuration file.
- Environment variables for CleverAgents settings must use the `CLEVERAGENTS_` prefix (except provider credentials which use standard names).
- The resolution chain order (CLI > env > project > global > default) is fixed and cannot be overridden.
- Entity YAML files must validate completely before registration. Partially valid configurations must never be applied.
- Provider credential keys (containing `api-key`, `token`, etc.) must not be logged or displayed in plain text by any command.
- The `agents config list` command must support glob patterns for filtering by key group.

## Consequences

### Positive
- Dot-path hierarchical keys provide a familiar, git-config-like experience.
- The dual-format approach uses each format where it's strongest: TOML for flat key-value settings, YAML for complex entity structures.
- The five-tier resolution chain provides maximum flexibility while ensuring predictable precedence.
- Project-scoped overrides enable different teams or codebases to have different configurations without modifying the global config.
- Zero-configuration defaults ensure the system works out of the box.

### Negative
- Two configuration formats (TOML + YAML) increase the cognitive load for users who must learn both.
- The five-tier resolution chain can make it difficult to determine which level is providing a given effective value.
- Project-scoped configuration adds another layer of indirection to an already complex resolution chain.

### Risks
- Conflicting settings across tiers may produce confusing behavior. The `agents config get` command must show which tier provides the effective value.
- Environment variable interpolation in YAML files (`${ENV_VAR}`) could expose sensitive values if YAML files are committed to version control.
- Large numbers of configuration keys could make the system feel over-configured and intimidating to new users.

## Alternatives Considered

**YAML for everything (no TOML)** — YAML can represent the same data but is more verbose for simple key-value settings. TOML's native table structure maps more naturally to dot-path hierarchical keys. Python 3.13's `tomllib` provides stdlib TOML support.

**Single configuration file (no project-scoped overrides)** — Would require per-project configuration in separate files or environment variables, losing the benefit of project-level defaults that apply automatically to all plans targeting that project.

## Compliance

- **Resolution chain tests**: Tests verify that each tier in the chain correctly overrides lower-priority tiers.
- **Default completeness tests**: Tests verify that every declared configuration key has a built-in default and that the system starts successfully with an empty config file.
- **YAML validation tests**: Tests verify that entity YAML files are validated completely and that invalid configurations are rejected with actionable error messages.
- **Credential safety tests**: Tests verify that provider credential keys are masked in `agents config list` output and never appear in log output.
- **Environment interpolation tests**: Tests verify that `${ENV_VAR}` syntax is correctly resolved in YAML entity files.

## Related ADRs

| ADR | Title | Relationship |
|-----|-------|-------------|
| [ADR-004](ADR-004-data-validation.md) | Data Validation | Pydantic Settings validates and loads configuration values |
| [ADR-005](ADR-005-technical-stack.md) | Technical Stack | TOML and YAML are the chosen configuration file formats |
| [ADR-009](ADR-009-project-model.md) | Project Model | Projects define project-scoped configuration overrides in the resolution chain |
| [ADR-017](ADR-017-automation-profiles.md) | Automation Profiles | Automation profiles are selected and configured through the configuration system |

## Acceptance

### Votes For

| Voter | Comment |
|-------|---------|
| Jeffrey Phillips Freeman <Jeffrey.Freeman@CleverThis.com> | Dual-format configuration with a five-tier resolution chain covers all override scenarios cleanly |

**Total: 1**

### Votes Against

| Voter | Comment |
|-------|---------|

**Total: 0**

### Abstentions

| Voter | Comment |
|-------|---------|

**Total: 0**
