Skip to content

Appendix B · Configuration Keys Index ​

Every knob Agentao reads — environment variables first, then on-disk JSON. All of them are optional unless marked required.

B.1 Environment variables ​

LLM credentials ​

LLM_PROVIDER selects a provider prefix (default OPENAI). The remaining three keys are read as {PROVIDER}_API_KEY, {PROVIDER}_BASE_URL, {PROVIDER}_MODEL.

KeyRequiredDefaultNotes
LLM_PROVIDER—OPENAIPicks the {PROVIDER}_* prefix. Any upper-case name works (e.g. DEEPSEEK, ANTHROPIC, GEMINI)
{PROVIDER}_API_KEYyes—Constructor api_key= overrides
{PROVIDER}_BASE_URLyes—Constructor base_url= overrides. An OpenAI-compatible endpoint by default; the API root (https://api.anthropic.com) when {PROVIDER}_API_FORMAT=anthropic-messages
{PROVIDER}_MODELyes—Constructor model= overrides. Runtime-swappable via agent.set_model()
{PROVIDER}_API_FORMAT—openai-completionsThe wire protocol spoken to that block's endpoint (0.5.0): openai-completions, anthropic-messages (Anthropic's Messages API) or openai-responses (OpenAI's Responses API, 0.5.3). Never inferred from the URL, the provider name or the model name; an unknown value raises at startup. /provider reads the target block's value, so a switch between blocks on different protocols changes the wire too; sub-agents are built on the parent's current one. On anthropic-messages, LLM_TEMPERATURE is not sent and extended thinking is turned on through LLM_EXTRA_BODY. Equivalent to the constructor api_format=. Full notes: docs/reference/configuration.md §2

Fail-fast rule: LLMClient.__init__ raises ValueError at startup if any of {PROVIDER}_API_KEY, {PROVIDER}_BASE_URL, or {PROVIDER}_MODEL is absent and was not supplied via the constructor. The /provider listing and switching commands apply the same gate — all three must be set for a provider to appear in the list or be switchable.

Global runtime ​

KeyDefaultMeaning
LLM_TEMPERATUREunsetSampling temperature (0.0–2.0). Unset = not sent; the provider's default applies (0.5.7; was 0.2). Malformed value raises at startup
LLM_MAX_TOKENSunsetHard cap on LLM completion tokens per call. Malformed value raises at startup
LLM_EXTRA_BODYunsetJSON object forwarded verbatim to the LLM .create() as the SDK's extra_body — the escape hatch for reasoning_effort / top_p / seed / response_format / provider-specific fields. Equivalent to the constructor extra_body=. Example: LLM_EXTRA_BODY='{"reasoning_effort":"high"}'. Unlike the two above, a malformed or valid-but-non-object value is warned and skipped (not fatal); empty/whitespace is treated as unset (silent). Logged with credential keys redacted
LLM_PROMPT_CACHEoffExplicit prompt-cache breakpoints (0.4.26): anthropic, or off / empty / unset. When on, each agent-turn request carries at most 3 Anthropic-style cache_control markers — system message, last tool definition, end of stable history. Opt-in, never inferred from a base URL or model name: set it only for an endpoint you have verified forwards the key. An unknown value raises at startup. Equivalent to the constructor prompt_cache=. What to verify on the endpoint first: docs/reference/configuration.md §2
LLM_PROMPT_CACHE_TTL5mRetention hint for those markers: 5m or 1h. Unread — validation included — while LLM_PROMPT_CACHE is off. Equivalent to the constructor prompt_cache_ttl=
AGENTAO_CONTEXT_TOKENS200000Context budget; triggers compression when exceeded
AGENTAO_WORKING_DIRECTORY—Override working directory at startup (alternative to constructor working_directory=)
AGENTAO_SCRUB_CHILD_ENVonWhether shell and MCP child processes inherit agentao's own provider credentials. Default drops HARNESS_ENV_KEYS (OPENAI_API_KEY, ANTHROPIC_API_KEY, GEMINI_API_KEY, LLM_EXTRA_BODY, …), {LLM_PROVIDER}_API_KEY, and any variable whose value is a key agentao has used this process (after /provider, set_provider(), or an api_key= read from your own variable; values under 16 characters are not matched) from the child env. Set to 0/false/no/off to restore full inheritance — needed to run agentao run, or any provider-calling script, from inside the agent's own shell. Only agentao's keys are dropped; AWS_*, GITHUB_TOKEN, DATABASE_URL are untouched. See capabilities/process.py::build_child_env

Third-party keys consumed by built-in tools ​

KeyConsumed byPurpose
GITHUB_TOKENSkill catalog fetcherHigher-rate GitHub API access
BOCHA_API_KEYweb_search toolUse Bocha Search API instead of DuckDuckGo. If absent, the tool falls back to DuckDuckGo automatically.

MCP servers and custom tools typically read their own env keys — those are defined in your .agentao/mcp.json or your custom-tool code, not here.

B.2 Precedence order ​

For every setting: constructor argument > environment variable > on-disk JSON > hard-coded default.

On-disk JSON layering varies by surface:

  • sandbox.json — user-scope only. A <cwd>/.agentao/sandbox.json is ignored with a warning (a checked-in or agent-written {"enabled": false} would switch the sandbox off).
  • mcp.json — both files are loaded; user wins on name collision and the project entry is add-only (it may declare new server names but cannot override a user-scope name; collisions warn and skip).
  • permissions.json — user-scope only. A <cwd>/.agentao/permissions.json is intentionally not loaded (a checked-in {"tool": "*", "action": "allow"} would defeat the user policy on first match). Mode preset rules run last (or first in full-access / plan, where they cannot be overridden).
  • memory.db — project and user stores are read independently; both are visible to the prompt renderer. Project does not override user.
  • acp.json, settings.json, skills_config.json, AGENTAO.md — project-only; no merge.

B.3 On-disk JSON files ​

JSON config files live in an .agentao/ directory (project at <working_directory>/.agentao/, user at ~/.agentao/); the project-level AGENTAO.md lives at the project root. Per-surface precedence is described in B.2. Any file may be absent.

FileScopeSectionPurpose
mcp.jsonproject (add-only) + user5.3MCP servers (stdio / Streamable HTTP / SSE)
permissions.jsonuser only (project file is ignored)5.4Per-tool permission rules
sandbox.jsonuser only (project file is ignored)6.2Shell sandbox profile selection
acp.jsonproject only3.2ACP subagent registry (when Agentao runs as client)
settings.jsonproject only6.6Persisted permission mode, builtin-agents flag, replay block
skills_config.jsonproject only5.2Disabled-skills list (managed via /skills disable)
AGENTAO.md (else AGENTS.md)project only5.6Project-specific instructions, prepended to system prompt; AGENTS.md is read only when AGENTAO.md is absent
memory.dbproject + user5.5SQLite-backed persistent memory (not JSON; listed for completeness)

B.3.1 mcp.json ​

json
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "."],
      "env": { "LOG_LEVEL": "info" },
      "trust": false,
      "timeout": 30
    },
    "remote": {
      "type": "sse",
      "url": "https://api.example.com/sse",
      "headers": { "Authorization": "Bearer $API_TOKEN" },
      "timeout": 60
    }
  }
}

Field reference:

FieldTypeNotes
typestringTransport selector: "stdio" / "http" / "sse" (aliases "streamable-http" / "streamable_http" fold to "http"). Omitted → inferred: command = stdio, bare url = Streamable HTTP
commandstringstdio server — mutually exclusive with url
argsstring[]stdio args
envobjectexpanded ($VAR / ${VAR})
cwdstringstdio subprocess cwd
urlstringURL-transport server URL (Streamable HTTP or SSE)
headersobjectURL-transport request headers ($VAR expanded)
trustboolSkip confirmation prompt for tools from this server. When true, the server's ToolAnnotations (readOnlyHint, destructiveHint) are also consulted; destructiveHint=true re-introduces confirmation for that op. Hints are ignored entirely when trust is false.
timeoutnumber (s) or {startup, request}A number bounds connecting and the handshake (default 60). request bounds each tool call (no default)

All three MCP transports are supported: stdio, Streamable HTTP, and SSE. A bare url defaults to Streamable HTTP; set "type": "sse" for a legacy SSE endpoint.

B.3.2 permissions.json ​

json
{
  "rules": [
    { "tool": "run_shell_command", "args": { "command": "^git " }, "action": "allow" },
    { "tool": "run_shell_command", "args": { "command": "rm\\s+-rf" }, "action": "deny" },
    { "tool": "write_file", "action": "ask" },
    {
      "tool": "web_fetch",
      "domain": { "allowlist": [".github.com"], "url_arg": "url" },
      "action": "allow"
    }
  ],
  "shell": { "dialect": "powershell" }
}

Two top-level keys, rules and shell. Anything else is a named error rather than an ignored key.

Rule fields:

FieldTypeRequiredNotes
toolstringyesTool name; matched as a regex via re.fullmatch (use "*" for wildcard)
argsobjectnoMap of <arg_name> → regex; all entries must re.search-match for the rule to fire
domainobjectnoURL-tools only (web_fetch); keys url_arg (default "url"), allowlist, blocklist. Patterns starting with . do suffix matching (e.g. .github.com matches api.github.com); otherwise exact match
actionstringyes"allow" | "deny" | "ask" (case-insensitive)

Shell block (new in 0.4.22, user scope, Windows only):

KeyTypeRequiredNotes
dialectstringno"posix" | "cmd" | "powershell" — the syntax the interpreter reads. This is what the command floor scans with and what the prompt's shell guidance speaks. On its own it is enough: {"dialect": "powershell"} is the ordinary way to turn PowerShell on
pathstringnoabsolute path to a specific interpreter. Requires dialect — path alone is an error, because nothing can infer the syntax from a filename

{"dialect": "powershell"} discovers pwsh.exe, else powershell.exe, and is an error if neither is installed — never a silent fall back to cmd. Nothing configured leaves Windows on %COMSPEC% /c exactly as before. On macOS and Linux, asking for powershell or cmd is an unsupported-platform error. Full behaviour, including the launch and the encoding: docs/reference/configuration.md §4.

The mode field is not stored in permissions.json — it lives in settings.json (B.3.5) and is changed at runtime via /permissions. Modes: read-only, workspace-write, full-access, plan (lowercase-hyphen; plan is internal).

Evaluation order:

  • read-only / workspace-write: [user rules] → [active mode preset] — first match wins. In read-only this applies only to tools whose is_read_only is True; any other tool is denied before a rule is consulted.
  • full-access / plan: [active mode preset] → [user rules] — presets cannot be overridden.
  • No match → falls back to the tool's own requires_confirmation attribute.

Project-scope <cwd>/.agentao/permissions.json is not loaded — see B.2.

B.3.3 sandbox.json ​

~/.agentao/sandbox.json:

json
{
  "enabled": true,
  "platform": "darwin",
  "default_profile": "workspace-write",
  "rules": [],
  "profiles_dir": "~/.agentao/sandbox-profiles",
  "workspace_root": null
}

Built-in profiles: readonly, workspace-write-no-network, workspace-write. Fail-closed: a missing profile file raises SandboxMisconfiguredError; the shell tool refuses to run.

B.3.4 acp.json ​

Only consumed when Agentao itself is an ACP client: the CLI's /acp command (CLI · /acp) or a host's ACPManager (3.4). Project-level only (<project>/.agentao/acp.json). Servers sit under a top-level servers object, not mcpServers. Safe to omit for most integrations.

Per-server keys under servers.{name}:

KeyTypeDefaultNotes
commandstring—Required
argslist[str]—Required
envdict—Required; $VAR / ${VAR} expanded
cwdstring—Required; relative paths resolve against project root
autoStartbooltrueRead by ACPManager.start_all(). The CLI never auto-starts. Registry entries are written with false
startupTimeoutMsint10000Wait for the initialize answer. Never less than 30 s in effect. Registry entries are written with 120000
requestTimeoutMsint60000Per-request timeout. Also bounds one CLI /acp send turn
maxRecoverableRestartsint3Cap for auto-restarts after recoverable subprocess deaths; reset on first successful turn
capabilitiesdict{}
descriptionstring""
nonInteractivePolicy{"mode": "reject_all" | "accept_all"}{"mode": "reject_all"}Structured object (Week 3). Legacy bare-string form is rejected at config load time — see Appendix E.

B.3.5 settings.json ​

Project-local runtime settings. Read from <working_directory>/.agentao/settings.json. Carries persisted permission mode, the built-in-agents opt-in, the background-wake switch, and the replay block.

json
{
  "mode": "workspace-write",
  "agents": {
    "enable_builtin": false
  },
  "background_agents": {
    "auto_wake": true
  },
  "replay": {
    "enabled": false,
    "max_instances": 20,
    "capture_flags": {
      "capture_llm_delta": true,
      "capture_full_llm_io": false,
      "capture_tool_result_full": false,
      "capture_plugin_hook_output_full": false
    }
  }
}

Top-level keys:

KeyTypeDefaultNotes
modestring"workspace-write" (when key absent)Last-known permission mode used for restoration paths and /permissions inspection. Allowed: "read-only", "workspace-write", "full-access". ("plan" is internal — set by the /plan flow, never written by users.)
agents.enable_builtinboolfalseEnables the built-in sub-agent set. Legacy top-level alias enable_builtin_agents (bool) is still honored.
background_agents.auto_wakebooltrue (when key absent)Interactive CLI only. When a background sub-agent's update is queued while the CLI waits at an empty prompt, run one turn automatically so the update is read without typing continue. Not while you are typing, with images staged, or in plan mode; pauses after 3 wakes in a row until you submit a line. false turns it off; any other value is reported and read as true.

Replay keys:

KeyTypeDefaultNotes
replay.enabledboolfalseEnables recording for future sessions. /replay on and /replay off write this value.
replay.max_instancesint20Retention cap under .agentao/replays/; does not affect .agentao/sessions/. true / false, a non-number or a value below 1 is ignored (20 is used, and agentao doctor reports an error); a numeric string or a fraction is converted, with a doctor warning.
replay.capture_flags.capture_llm_deltabooltrueRecords messages newly added by each LLM call.
replay.capture_flags.capture_full_llm_ioboolfalseDeep capture of full LLM inputs/outputs; treat as sensitive.
replay.capture_flags.capture_tool_result_fullboolfalseDeep capture of full tool results beyond the normal replay truncation policy.
replay.capture_flags.capture_plugin_hook_output_fullboolfalseDeep capture of plugin hook output.

Malformed settings.json falls back to safe defaults instead of blocking startup.

B.4 Constructor parameters that shadow these ​

Every env var and JSON key above has a Python equivalent on Agentao(...):

JSON / envConstructor
{PROVIDER}_API_KEYapi_key=
{PROVIDER}_BASE_URLbase_url=
{PROVIDER}_MODELmodel=
{PROVIDER}_API_FORMATapi_format=
AGENTAO_WORKING_DIRECTORYworking_directory=
AGENTAO_CONTEXT_TOKENSmax_context_tokens=
mcp.jsonextra_mcp_servers= (merged on top of file)
permissions.jsonpermission_engine=
sandbox.jsonno direct arg — policy is read at tool-call time
settings.json replay blockno direct arg — use /replay on/off or edit the file

Constructor always wins. Useful for SaaS hosts that inject per-tenant settings without touching env.


→ Appendix D · Error codes