Config Reference

All agent configuration lives in a single agent.toml file in the project root. Generate it interactively with ai init, then tune by hand. Sensitive values (API keys) must always use ${ENV_VAR} references — inline secrets are rejected at load time.

Security: Fields agent.model.api_key and any [[agent.model.fallback_chain]] api_key must be ${ENV_VAR} references. Literal secrets are rejected with an error.

[agent]

Top-level agent identity and system prompt.

FieldTypeDefaultDescription
namestringRequired. Human-readable agent name (used in AgentCard and logs)
descriptionstring""Short description of the agent's purpose (exposed via A2A AgentCard)
system_promptstring""Base system prompt. Skill fragments are appended at serve time. Bare $name is never expanded — use ${VAR} only for API keys

[agent.model]

Primary model selection and optional fallback chain.

FieldTypeDefaultDescription
providerstring"anthropic" (uses anthropic-sdk-go) or "openai-compat" (any OpenAI-compatible endpoint)
modelstringModel ID, e.g. "claude-sonnet-4-6", "gpt-5-mini", "llama3" (Ollama), "mistral" (vLLM/Fireworks)
api_keystring""Must be ${ENV_VAR}. E.g. ${ANTHROPIC_API_KEY}
base_urlstring""For openai-compat: endpoint URL (e.g. http://localhost:11434/v1)
max_response_tokensint8192Maximum tokens per model response

Ordered list of fallback models. Tried in sequence if the primary model fails or hits the cost circuit breaker.

FieldTypeDefaultDescription
providerstring"anthropic" or "openai-compat"
modelstringFallback model ID
base_urlstring""For openai-compat fallbacks
api_keystring""Must be ${ENV_VAR} if set
[[agent.model.fallback_chain]]
provider = "openai-compat"
model    = "llama3"
base_url = "${OLLAMA_URL}"

[[agent.model.fallback_chain]]
provider = "anthropic"
model    = "claude-haiku-4-5-20251001"
api_key  = "${ANTHROPIC_API_KEY}"

[agent.budget]

Resource limits and context pressure thresholds for each session.

FieldTypeDefaultDescription
max_turnsint10Maximum agent turns per session before aborting
max_tokens_per_sessionint0Max total tokens (input + output) per session. 0 = unlimited
max_usd_per_sessionfloat0.0Cost circuit breaker in USD per session. 0.0 = unlimited
context_warn_ratiofloat0.70Context fill ratio that triggers a warning log (0.0–1.0)
context_compact_ratiofloat0.80Context fill ratio that triggers automatic compaction
context_abort_ratiofloat0.95Context fill ratio that triggers session abort to prevent truncation

[agent.memory]

Session persistence and semantic memory backends.

FieldTypeDefaultDescription
session_storestring"inmemory"Session state backend: "file", "redis", or "inmemory"
semantic_memoryboolfalseEnable semantic memory sidecar (port 8092) for cross-session recall
trace_graphboolfalseWrite execution traces (turn-by-turn) to the graph DB for replay and evaluation

[agent.graph]

Connection to a graph database backend (Neo4j Aura or local Cypherlite).

FieldTypeDefaultDescription
uristring""Neo4j/Cypherlite connection URI, e.g. "neo4j+s://demo.neo4jlabs.com:7687"
usernamestring""Graph DB username
passwordstring""Must be ${ENV_VAR}. E.g. ${NEO4J_PASSWORD}
databasestring""Graph database name. Empty = driver default
Note: When uri is non-empty, ai serve exposes the schema via GET /api/graph/schema in the web console.

[agent.toolbox]

MCP tool server connection. Start mcp-toolbox with ai sidecar mcp-toolbox --config toolbox.yaml — it supports 48 database sources out of the box including Neo4j, PostgreSQL, MySQL, MongoDB, Redis, BigQuery, Snowflake, Cassandra, Elasticsearch, and more. See ai sidecar and the toolbox.yaml reference below.

FieldTypeDefaultDescription
endpointstring""MCP server SSE URL, e.g. "http://localhost:15001/mcp/sse"
transportstring"sse""sse" for HTTP/SSE (multi-session); "stdio" for subprocess / single-client
sidecar_configstring""Path to toolbox YAML file. If set, ai serve auto-starts mcp-toolbox as a sidecar

toolbox.yaml

Separate config file consumed by mcp-toolbox (not agent.toml). Defines database sources and the Cypher / SQL tools the agent can call.

Supported source kinds (48 total)

CategorySources
Graphneo4j, dgraph
Documentmongodb, firestore, couchbase, elasticsearch
Relationalpostgres, mysql, mariadb, mssql, oracle, sqlite, cockroachdb, tidb, yugabytedb, clickhouse, trino, singlestore, oceanbase, firebird, mindsdb
Key-value / Cacheredis, valkey, cassandra, bigtable
Cloud analyticsbigquery, spanner, snowflake, looker, cloud-gda, dataplex, dataproc
Google Cloud SQLalloydb-pg, cloud-sql-mysql, cloud-sql-pg, cloud-sql-mssql
Othercloud-healthcare, cloud-logging-admin, cloud-monitoring, http

Minimal Neo4j example

sources:
  my_graph:
    kind: neo4j
    uri:      "${NEO4J_URI}"
    username: "${NEO4J_USERNAME}"
    password: "${NEO4J_PASSWORD}"
    database: "${NEO4J_DATABASE}"

tools:
  search_companies:
    source:      my_graph
    description: "Find companies by name (case-insensitive partial match)"
    parameters:
      - name: query
        type: string
        description: "Company name fragment"
    statement: |
      MATCH (c:Company)
      WHERE toLower(c.name) CONTAINS toLower($query)
      RETURN c.name AS name LIMIT 10

toolsets:
  default:
    - search_companies

Minimal PostgreSQL example

sources:
  my_db:
    kind: postgres
    host:     "${PG_HOST}"
    port:     5432
    database: "${PG_DATABASE}"
    user:     "${PG_USER}"
    password: "${PG_PASSWORD}"

tools:
  list_orders:
    source:      my_db
    description: "List recent orders for a customer"
    parameters:
      - name: customer_id
        type: integer
        description: "Customer ID"
    statement: |
      SELECT id, status, total FROM orders
      WHERE customer_id = $customer_id
      ORDER BY created_at DESC LIMIT 20

Start the server: ai sidecar mcp-toolbox --config toolbox.yaml --port 15001

Connect the agent: set [agent.toolbox] endpoint = "http://localhost:15001/mcp/sse"

[[agent.tools]]

Explicit tool entries that supplement toolbox-discovered tools. Repeated table.

FieldTypeDefaultDescription
namestringTool name (must match a tool registered in the tool registry)
descriptionstring""Optional override for the tool's description shown to the model

[agent.tool_context]

Layered tool context management. Controls how many tool schemas are injected per turn and which strategies are active.

FieldTypeDefaultDescription
group_thresholdint0Tool count above which list_tools meta-tool is injected. 0 = runtime default of 20; -1 = disable
max_schemas_per_turnint8Maximum full tool schemas injected per turn
tool_selectorstring""Fast model ID for pre-filtering tools before the main model call. Empty = disabled
tool_embedderstring""Embedding model for semantic tool retrieval. Empty = disabled

[agent.skills]

List of skills to load at serve time. Each skill contributes system prompt fragments and tool requirements.

FieldTypeDefaultDescription
skills[]string[]Skill names or GitHub refs, e.g. ["graph-search", "memory-recall"]

[agent.a2a]

Inbound Agent-to-Agent (A2A) protocol server configuration.

FieldTypeDefaultDescription
enabledbooltrueEnable the inbound A2A HTTP server
portint8080Port for the A2A server to listen on
endpointstring""Outbound URL for task handoff to another agent (used by StepHandoff)
max_requests_per_minuteint0Rate limit per principal per sliding minute window. 0 = unlimited
max_concurrent_tasksint0Max non-terminal tasks per principal. 0 = unlimited

[agent.a2a.auth]

Authentication mode for inbound A2A requests.

FieldTypeDefaultDescription
modestring"bearer"Auth mode: "bearer" for static token, "google" for Google ID token (OIDC) validation
audiencestring""Expected token audience for "google" mode — usually the Cloud Run service URL

Example — Google ID token auth for a Cloud Run service:

[agent.a2a.auth]
mode     = "google"
audience = "https://my-agent-abc123-uc.a.run.app"

[agent.a2a.card]

AgentCard metadata served at GET /.well-known/agent.json. Conforms to A2A protocol v0.3.

FieldTypeDefaultDescription
urlstring""Public URL of the agent service (e.g. Cloud Run service URL). Auto-detected on Cloud Run via K_SERVICE metadata
protocol_versionstring"0.3"A2A protocol version advertised in the card

Use ai show --card --validate to check that all required fields are populated before registering with Gemini Enterprise.

[agent.deploy.cloudrun]

Persistent Cloud Run deployment settings. Values here become defaults for ai deploy --target cloudrun; CLI flags always override.

FieldTypeDefaultDescription
projectstring""GCP project ID; env: GOOGLE_CLOUD_PROJECT
regionstring"us-central1"GCP region; env: GOOGLE_CLOUD_REGION
service_accountstring""Service account email for the Cloud Run service identity
allow_unauthenticatedboolfalseAllow public (unauthenticated) traffic. When false, Cloud Run requires a Google ID token
secrets[]string[]Secret Manager mounts: ["ENV_VAR=projects/P/secrets/S/versions/latest"]

Example:

[agent.deploy.cloudrun]
project              = "my-gcp-project"
region               = "us-central1"
allow_unauthenticated = true
secrets              = [
  "ANTHROPIC_API_KEY=projects/my-gcp-project/secrets/anthropic-key/versions/latest",
]

[agent.mcp_server]

Outward-facing MCP server surface — exposes agent skills as MCP prompts to Claude Desktop, Cursor, and other MCP hosts.

FieldTypeDefaultDescription
enabledboolfalseEnable the outward MCP server
transportstring"http""stdio" (single host, e.g. Claude Desktop) or "http" (dual transport: Streamable HTTP at POST /mcp (preferred) + legacy SSE at GET /sse)
portint8081Port for the MCP HTTP server

[agent.security]

Authentication and prompt injection protection.

FieldTypeDefaultDescription
require_authboolfalseRequire Bearer token auth on all A2A endpoints
injection_detectionboolfalseScan incoming messages and tool results for prompt injection patterns
require_human_approvalboolfalseRequire human approval for irreversible (R_DESTROY) tool calls
require_human_approval_except[]string[]Glob patterns (path.Match syntax) for tools exempt from the approval gate. Wildcard "*" is not permitted

When require_auth = true, all A2A requests must include Authorization: Bearer <token>. Task ownership is enforced — clients can only access tasks they created.

[agent.sandbox]

Secure code execution sandbox. Registers execute_js, execute_python, and execute_shell MCP tools when enabled.

FieldTypeDefaultDescription
enableboolfalseRegister sandbox MCP tools at serve time
require_human_approval[]string[]Glob patterns for tools requiring approval before execution, e.g. ["execute_shell", "delete_*"]
firecracker_pool_sizeint2Number of pre-warmed Firecracker VMs
shell_backendstring"auto""firecracker" (microVM, linux/amd64+KVM), "nsjail" (linux, no KVM), or "auto" (Firecracker if /dev/kvm present, nsjail otherwise)
python_timeout_secint30Execution timeout for execute_python
js_timeout_secint10Execution timeout for execute_js
shell_timeout_secint60Execution timeout for execute_shell

[agent.tool_trust]

Override automatic trust classification for specific tools. Trust levels range from T4 (schema-meta, highest trust) to T9 (untrusted, lowest trust).

FieldTypeDefaultDescription
overridesmap[string]int{}Maps tool name substrings to trust levels 4–9. Auto-classification is used for unmatched tools
[agent.tool_trust.overrides]
"my_internal_api__" = 6   # T6: allowlisted external API
"scraped_content"   = 8   # T8: web content

[agent.tool_reversibility]

Override automatic reversibility classification for specific tools.

FieldTypeDefaultDescription
overridesmap[string]int{}Maps tool name substrings to reversibility levels 0–2. Auto-classification is used for unmatched tools
Levels: 0 = R_READ (safe, no side effects), 1 = R_WRITE (reversible side effects), 2 = R_DESTROY (irreversible — triggers approval gate when require_human_approval is true).

These tools are always classified as shown, regardless of overrides. Use overrides to change the classification for your deployment.

Tool nameClassificationDescription
delete_*R_DESTROYAny tool matching the delete_ prefix
drop_*R_DESTROYAny tool matching the drop_ prefix
execute_shellR_DESTROYShell execution
http_requestR_DESTROYArbitrary HTTP writes
send_*, email_*R_DESTROYMessaging and notification tools
deploy_*, ai_deployR_DESTROYDeployment tools
write_cypherR_DESTROYGeneric Cypher write fallback — always approval-gated
write_*, create_*, update_*R_WRITEReversible write operations
read_cypherR_READGeneric read-only Cypher query — never gated
(everything else)R_READDefault when no pattern matches
[agent.tool_reversibility.overrides]
"my_safe_shell" = 0   # treat as safe even though name matches R_DESTROY
"read_api"      = 2   # this read-looking tool has irreversible side effects

[agent.intent_router]

Intent-based routing. Classifies user intent before the first LLM call and restricts tool visibility to the matched route.

FieldTypeDefaultDescription
classify_modelstring""Model ID for lightweight intent classification. Empty = routing disabled

Ordered list of intent routes. A route with intent = "default" acts as the fallback when no other intent matches.

FieldTypeDefaultDescription
intentstringIntent label returned by the classifier. "default" = fallback route
agentstring""Optional A2A endpoint URL for sub-agent handoff
tools[]string[]Allowlist of tool names visible for this intent. Empty = all tools
[agent.intent_router]
classify_model = "claude-haiku-4-5-20251001"

[[agent.intent_router.route]]
intent = "research"
tools  = ["search_companies", "get_company_details"]

[[agent.intent_router.route]]
intent = "billing"
agent  = "http://billing-agent:8080"

[[agent.intent_router.route]]
intent = "default"

[[agent.tool_guard]]

Before/after guards for tool calls. Repeated table — add one section per guard rule.

FieldTypeDefaultDescription
toolstringGlob pattern (path.Match syntax) matching tool names to guard
beforestring""Tool to call before the guarded tool. If it returns an error, the guarded tool is blocked
afterstring""Tool to call after the guarded tool. Always runs (defer semantics)
[[agent.tool_guard]]
tool   = "delete_*"
before = "human_approval"

[[agent.tool_guard]]
tool  = "write_file"
after = "audit_log"

[agent.honesty]

Calibrated uncertainty and identity acknowledgement behaviours injected into the system prompt.

FieldTypeDefaultDescription
calibrated_uncertaintybooltrueAdds uncertainty guidance to the system prompt ("when data is incomplete, say so")
identity_acknowledgementbooltrueAdds AI identity line to the system prompt
data_freshness_notestring""Operator note about data freshness appended to system prompt. Empty = no note

Full Example

A complete annotated agent.toml:

# agent.toml — complete example

[agent]
name         = "companies-researcher"
description  = "Research companies using the knowledge graph"
system_prompt = """
You are a research agent. Use available tools to answer questions about companies.
Prefer targeted lookups over broad queries. Cite your sources.
"""

[agent.model]
provider            = "anthropic"
model               = "claude-sonnet-4-6"
api_key             = "${ANTHROPIC_API_KEY}"
max_response_tokens = 8192

[[agent.model.fallback_chain]]
provider = "openai-compat"
model    = "llama3"
base_url = "${OLLAMA_URL}"

[agent.budget]
max_turns              = 15
max_tokens_per_session = 0        # 0 = unlimited
max_usd_per_session    = 0.50
context_warn_ratio     = 0.70
context_compact_ratio  = 0.80
context_abort_ratio    = 0.95

[agent.memory]
session_store   = "file"     # file | redis | inmemory
semantic_memory = true
trace_graph     = true       # write execution traces to graph DB

[agent.graph]
uri      = "neo4j+s://demo.neo4jlabs.com:7687"
username = "companies2"
password = "${NEO4J_PASSWORD}"
database = "companies2"

[agent.toolbox]
endpoint       = "http://localhost:15000/mcp/sse"
transport      = "http"         # stdio | http
sidecar_config = "toolbox.yaml" # auto-start mcp-toolbox

[agent.tool_context]
group_threshold     = 20
max_schemas_per_turn = 8
tool_selector       = "claude-haiku-4-5-20251001"

[agent.skills]
skills = ["graph-search", "memory-recall"]

[agent.a2a]
enabled                = true
port                   = 8080
max_requests_per_minute = 60
max_concurrent_tasks   = 5

[agent.mcp_server]
enabled    = true
transport  = "http"       # stdio | http (dual: POST /mcp + GET /sse)
port       = 8081

[agent.security]
require_auth                = true
injection_detection         = true
require_human_approval      = true
require_human_approval_except = ["safe_read_*"]

[agent.sandbox]
enable        = true
shell_backend = "auto"

[agent.honesty]
calibrated_uncertainty   = true
identity_acknowledgement = true
data_freshness_note      = "query results may reflect data as of last nightly sync"

[agent.intent_router]
classify_model = "claude-haiku-4-5-20251001"

[[agent.intent_router.route]]
intent = "research"
tools  = ["search_companies", "get_company_details"]

[[agent.intent_router.route]]
intent = "default"

[[agent.tool_guard]]
tool   = "delete_*"
before = "human_approval"