49. Agent configuration environment variable convention
Date: 2026-06-16
Status
Accepted
Context
Agents need behavioral knobs — settings that tune how they work without changing the agent definition itself. Issue #2333 surfaced a concrete case: the review agent should let repo owners set a minimum severity threshold for reported findings. More knobs will follow for other agents.
The harness already delivers environment variables into the sandbox via .env files with expand: true (ADR 0024), and pre/post scripts read env vars from runner_env (ADR 0045). The infrastructure for carrying configuration exists. What is missing is a naming convention that establishes a consistent pattern for every agent going forward.
This ADR covers only agent configuration env vars — behavioral knobs that tune agent behavior. It does not retroactively rename existing context vars (event data like GITHUB_PR_URL, ISSUE_NUMBER) or infrastructure vars (tokens, paths, credentials). Those remain as they are.
Decision
Agent configuration environment variables follow a single convention:
Naming
{AGENT}_{SETTING_NAME}{AGENT}is the agent's name in uppercase, derived from the harness filename:REVIEW,CODE,TRIAGE,FIX,PRIORITIZE,RETRO, etc.{SETTING_NAME}isSCREAMING_SNAKE_CASEdescribing the setting.- Examples:
REVIEW_SEVERITY_THRESHOLD,CODE_MAX_FILE_SIZE,REVIEW_POST_INLINE,TRIAGE_SKIP_DUPLICATE_CHECK. - A setting that applies to multiple agents gets separate vars per agent (e.g.,
CODE_MAX_FILE_SIZEandREVIEW_MAX_FILE_SIZE), keeping each agent's configuration independent.
The agent name prefix prevents collisions when multiple agents share an execution environment or when env files are sourced together. Existing context vars (e.g., PRIOR_REVIEW_SHA) and credential vars (e.g., GH_TOKEN) already use agent-name prefixes — the {AGENT}_ prefix alone does not distinguish config vars from those. The distinction is by purpose and documentation: config vars are behavioral knobs listed in docs/agents/<agent>.md.
Where config vars live in the harness
Config vars are carried the same way as other agent env vars — no new schema fields are needed. Note: ADR 0055 introduces a unified env: key with runner/sandbox sub-maps that replaces runner_env and manual .env files. The delivery mechanism below still works but is deprecated in favor of env.runner and env.sandbox.
The .env file and runner_env serve different audiences: the .env file delivers vars into the sandbox for the agent at inference time, while runner_env makes vars available to pre/post scripts on the host. A config var needed by both must appear in both places.
For sandbox access (inference time): Add the variable to the agent's
.envfile (e.g.,env/review.env) with${VAR}expansion. The harnesshost_filesentry withexpand: trueresolves the value from the host environment before copying into the sandbox. The agent reads it at runtime.For pre/post scripts (host side): Add the variable to the harness's
runner_envor the forge-specificrunner_envblock. Scripts read it from the environment. This is independent of the.envfile —runner_envcontrols the host-side environment, not the sandbox.For CI workflow injection: The CI workflow sets the value from org secrets, repo variables, or hardcoded defaults. This is the same mechanism used for all other env vars — no change needed.
Defaults
Default values live in the canonical harness (the scaffold's harness/<agent>.yaml). Downstream layers — the org .fullsend repo or a per-repo .fullsend/ — override them via base composition (ADR 0045). Defaults are also documented in docs/agents/<agent>.md so users can discover them without reading harness YAML.
For agent prompts, the agent treats an unset or empty variable the same as "use the default." The .env file's expand: true mechanism resolves unset host vars to an empty string, not an absent var — so agents and scripts must handle both cases.
For pre/post scripts, use standard shell defaulting, which already handles both empty and unset: ${REVIEW_SEVERITY_THRESHOLD:-low}.
Documentation
Each agent's user-facing documentation (docs/agents/<agent>.md) includes a Variables subsection under the existing "Configuration and extension" section:
## Configuration and extension
See [Customizing with AGENTS.md](../guides/user/customizing-with-agents-md.md) and
[Customizing with Skills](../guides/user/customizing-with-skills.md).
### Variables
| Variable | Description | Default | Valid values |
|----------|-------------|---------|--------------|
| `REVIEW_SEVERITY_THRESHOLD` | Minimum severity for reported findings | `low` | `info`, `low`, `medium`, `high`, `critical` |
| `REVIEW_POST_INLINE` | Post inline comments on individual findings | `true` | `true`, `false` |This is the single place a user looks to discover what knobs an agent supports. Every agent doc includes this subsection for consistency — agents that accept no configuration vars state "None" in the section. The agent's system prompt (agents/<agent>.md) references config vars wherever they are naturally needed in the instructions — no prescribed section structure.
Using config vars at inference time
The agent's system prompt references config vars in context where the behavior is conditioned. For example, in the review agent:
## Severity filtering
If `$REVIEW_SEVERITY_THRESHOLD` is set, suppress findings below that level.
The severity order is: info < low < medium < high < critical. Suppressed
findings do not appear in the output — they are dropped entirely, not
downgraded.The agent reads the value from its sandbox environment (e.g., via printenv REVIEW_SEVERITY_THRESHOLD or by referencing it in tool calls) and conditions its behavior accordingly. This is no different from how agents already read $GITHUB_PR_URL or $ISSUE_NUMBER.
Precedence
Config var values follow the existing harness layering from ADR 0045 and ADR 0003: fullsend defaults (scaffold) can be overridden by the org .fullsend repo, which can be overridden by per-repo .fullsend/. This layering already applies to .env files and runner_env — config vars inherit it for free.
Consequences
No runner changes required. The convention uses existing env var delivery mechanisms (
host_fileswithexpand: true,runner_env, CI workflowenv:). Agents start accepting config vars immediately by documenting them and referencing them in their prompts and scripts.Discoverability is centralized. Users check
docs/agents/<agent>.mdto see what knobs an agent supports. Agent authors document new config vars there when adding them.Collision-free by convention. The
{AGENT}_prefix scopes config vars to the agent that owns them.Agent system prompts stay flexible. There is no required section structure for how
agents/<agent>.mdreferences config vars. Agent authors place references where they make sense in the prompt flow.Each new config var may require updates in several places:
- Agent
.envfile (sandbox delivery) - Harness
runner_env(host-side script access) - Agent system prompt (behavioral conditioning)
- Pre/post scripts (host-side logic)
docs/agents/<agent>.md(user documentation)
Not every var needs all five — a var used only at inference time skips 2 and 4; a var used only in scripts skips 1 and 3.
- Agent
