config.toml
Complete AGH config.toml schema, defaults, valid values, merge behavior, and annotated examples.
- Audience
- Operators running durable agent work
- Focus
- Configuration guidance shaped for scanability, day-two clarity, and operator context.
config.toml is the main AGH runtime desired-state file. AGH loads the built-in defaults, then
overlays global and workspace files when they exist. The daemon only treats a change as runtime
truth after ConfigApplyService advances the active generation and writes a config_apply_records
audit row.
| File | Scope | Loaded when |
|---|---|---|
$AGH_HOME/config.toml | Global | Every config load. Defaults to ~/.agh/config.toml. |
$AGH_HOME/mcp.json | Global MCP sidecar | After global TOML. |
<workspace>/.agh/config.toml | Workspace overlay | Only when a workspace root is resolved for the session or command. |
<workspace>/.agh/mcp.json | Workspace MCP sidecar | After workspace TOML. |
Unknown TOML keys are errors. Sandbox profiles are implemented under [sandboxes.<name>]; the old
Use only [sandboxes.<name>] for session execution boundaries.
Quick Reference
| Section | Purpose | Default |
|---|---|---|
[daemon] | Unix domain socket path for CLI and UDS API traffic. | socket = "$AGH_HOME/daemon.sock" |
[daemon.reload_timeouts] | Live reload timeout budgets for provider, MCP, and bridge subsystem applies. | providers 5s, MCP 10s, bridges 30s |
[http] | HTTP and SSE bind address. | host = "localhost", port = 2123 |
[defaults] | Default agent, provider, and sandbox resolution. | agent = "general", provider = "", sandbox = "" |
[limits] | Daemon-level concurrently running agent cap. | max_concurrent_agents = 20 |
[session.limits] | Session-scoped wall-clock timeout. | timeout = "0s" |
[session.supervision] | Runtime activity heartbeat, progress, warning, and inactivity timeout controls. | heartbeat 30 seconds, progress 10 minutes, warning 15 minutes, timeout 30 minutes |
[agents.soul] | Optional SOUL.md parsing, body limits, and compact projection budget. | enabled, 32 KiB body, 2 KiB compact projection |
[agents.heartbeat] | Optional HEARTBEAT.md policy bounds, wake cadence/limits, and health timing. | enabled, 32 KiB body, 5 min/30 min intervals, 25 wakes per cycle, 168 h retention |
[permissions] | Default permission mode. | mode = "approve-all" |
[tools] | Tool registry lifecycle, hosted MCP enablement, and result budget defaults. | enabled, hosted MCP enabled, 256 KiB result default |
[tools.hosted_mcp] | Hosted MCP session bind nonce lifecycle. | 30 seconds |
[tools.policy] | External tool source defaults, approval timeout, and trusted sources. | external tools disabled, 120 second approval timeout, no trusted sources |
[[mcp_servers]] | Top-level MCP servers passed to agents. | empty list |
[providers.<name>] | Built-in provider override or custom provider definition. | empty map plus built-ins |
[model_catalog.sources.models_dev] | models.dev enrichment source (cross-provider). | enabled, https://models.dev/api.json, 24 h TTL, 10 s timeout |
[sandboxes.<name>] | Local or provider-backed execution sandbox profiles. | local backend when no profile is selected |
[observability] | Event summary retention and global byte cap. | enabled, 7 days, 1 GiB |
[observability.transcripts] | Transcript segment sizing and per-session cap. | enabled, 1 MiB segments, 256 MiB per session |
[log] | Structured log level and daemon-owned rotation. | level = "info", 10 MiB, 5 backups, 30 days, compression off |
[memory] | Persistent memory runtime and global memory directory. | enabled, $AGH_HOME/memory |
[memory.controller] | Hybrid write controller mode, latency, and fallback op. | hybrid, 300 ms, noop |
[memory.controller.llm] | Controller LLM tiebreaker. | enabled, anthropic/claude-haiku-4, 250 ms, top_k 5 |
[memory.controller.policy] | Content/rate caps and allowed write origins. | 4096 chars, 60 writes/min, all canonical origins |
[memory.recall] | Deterministic recall: top-K, weights, freshness, signal queue. | top-K 5, raw 50, weighted fusion |
[memory.decisions] | Decision WAL retention and per-row body cap. | 90 days, audit summary on, 64 KiB body cap |
[memory.extractor] | Post-message extractor and bounded queue. | enabled, post_message mode, capacity 1, coalesce 16 |
[memory.dream] | Dreaming runtime, gates, and scoring. | enabled, agent dreaming-curator, 24 h, 3 sessions, 30 min ticker |
[memory.session] | Forensic session ledger materialization, archive, and unbound partition. | jsonl, $AGH_HOME/sessions, 24 h grace, 30-day cold archive, _unbound partition |
[memory.daily] | Daily-log retention and rotation. | 1 MiB, 5000 lines, 7-day window, 30-day cold archive, sweep at 03:00 |
[memory.file] | Curated memory file body limits. | 200 lines, 25 KiB |
[memory.provider] | Active memory provider selection and circuit breaker. | bundled local, 2 s timeout, 5 failures, 30 s cooldown |
[memory.workspace] | Workspace identity file location and auto-creation. | <workspace>/.agh/workspace.toml, auto-create on first touch |
[skills] | Skill discovery, polling, disable list, and marketplace trust gates. | enabled, poll every 3 seconds |
[skills.marketplace] | Skill registry override. | unset |
[extensions.marketplace] | Extension registry override. | unset |
[automation] | Automation scheduler defaults. | enabled, UTC, 5 concurrent jobs |
[[automation.jobs]] | Scheduled automation jobs. | empty list |
[[automation.triggers]] | Event-driven automation triggers. | empty list |
[autonomy.coordinator] | Coordinator session bootstrap for workspace-scoped task runs. | disabled, agent coordinator, TTL 2 hours, 5 children, 1 coordinator + 5 sessions per workspace |
[task.orchestration] | Bounds for run summaries, context bundles, scheduler health, and max-runtime. | 4 KiB summaries, 8 KiB context, prior 5/recent 50 events, spawn fail limit 5 |
[task.orchestration.profile] | Defaults and gates for task execution profiles. | inherit coordinator/worker/sandbox; provider override + sandbox none allowed |
[task.orchestration.review] | Defaults and bounds for the post-terminal review gate. | policy none, max rounds 3, max attempts 2, timeout 20m, failure block_task |
[task.recovery] | Gates agent access to task-run force recovery verbs. | agents may force release, force fail, and retry |
[[hooks.declarations]] | Config-defined runtime hooks. | empty list |
[network] | Experimental AGH network runtime. | enabled, channel default |
Load And Merge Order
| Order | Source | Merge behavior |
|---|---|---|
| 1 | Built-in defaults | Base config. |
| 2 | $AGH_HOME/config.toml | Scalar fields replace defaults. TOML MCP and provider MCP entries merge by name. |
| 3 | $AGH_HOME/mcp.json | Same-name MCP servers replace the whole server object. |
| 4 | <workspace>/.agh/config.toml | Workspace overlay applies over global config. |
| 5 | <workspace>/.agh/mcp.json | Same-name MCP servers replace the whole server object after workspace TOML. |
| 6 | Path normalization and validation | ~ is expanded for daemon.socket and memory.global_dir; invalid values fail startup. |
TOML [[mcp_servers]] entries merge fields by name: non-empty command, non-empty args, and
new env keys overlay the existing server. JSON sidecars replace same-name servers as whole
objects.
Daemon boot uses the home config for boot-time daemon settings. The general config loader applies global and workspace MCP sidecars for session and runtime resolution.
Complete Annotated Example
# ~/.agh/config.toml
[daemon]
# Path to the Unix domain socket used by AGH CLI commands.
socket = "~/.agh/daemon.sock"
[daemon.reload_timeouts]
# Provider runtime reload budget. Valid range: 1s to 60s.
providers = "5s"
# MCP runtime reload budget. Valid range: 1s to 60s.
mcp = "10s"
# Bridge runtime reload budget. Valid range: 1s to 300s.
bridges = "30s"
[http]
# HTTP/SSE API bind address.
host = "localhost"
port = 2123
[defaults]
# Agent name used when a command or API request does not specify one.
agent = "general"
# Provider used by AGENT.md files that omit provider.
provider = "claude"
# Sandbox profile used when a workspace does not set sandbox_ref.
sandbox = "local"
[limits]
# Positive daemon-wide agent concurrency bound.
max_concurrent_agents = 20
[session.limits]
# 0 means no configured wall-clock timeout. Use Go durations such as "30m" or "2h".
timeout = "0s"
[session.supervision]
# Short heartbeats update durable liveness only. They are not persisted as session events.
activity_heartbeat_interval = "30s"
# 0 disables periodic progress events.
progress_notify_interval = "10m"
# 0 disables inactivity warnings.
inactivity_warning_after = "15m"
# 0 disables inactivity timeout.
inactivity_timeout = "30m"
# Grace period after cooperative prompt cancel before AGH stops the session as timeout.
timeout_cancel_grace = "30s"
[agents.soul]
# Disabling pauses prompt injection but keeps inspect/validate/write/delete/history/rollback available.
enabled = true
# Hard cap for SOUL.md body bytes after normalization.
max_body_bytes = 32768
# Compact /agent/context projection budget. Must be <= max_body_bytes.
context_projection_bytes = 2048
[agents.heartbeat]
# Disabling pauses wake decisions but keeps managed authoring available for repair.
enabled = true
# Bounded HEARTBEAT.md body size (snapshot uses normalized body).
max_body_bytes = 32768
# Compact projection budget for status surfaces.
context_projection_bytes = 4096
# Hard floor for authored preferences.min_interval. Files below this are clamped.
min_interval = "5m"
# Default cadence baseline used when authored files omit min_interval.
default_interval = "30m"
# Cooldown between wakes for a single session.
wake_cooldown = "1m"
# Maximum scheduler-cycle wakes across the daemon.
max_wakes_per_cycle = 25
# When true, wake only sessions in active runtime state.
active_session_only = true
# When true, authored active_hours/quiet_windows preferences are honored within bounds.
allow_active_hours_preferences = true
# Retention for agent_heartbeat_wake_events audit rows. Minimum 1h.
wake_event_retention = "168h"
# Idle age before metadata-only presence is treated as stale for wake eligibility.
session_health_stale_after = "2m"
# Minimum interval between session.health.update.after hook fires for the same session.
session_health_hook_min_interval = "1m"
[permissions]
# Valid values: deny-all, approve-reads, approve-all.
mode = "approve-all"
[tools]
# Disables registry dispatch and hosted MCP exposure when false.
enabled = true
# Enables AGH-hosted local MCP projection for session-visible tools.
hosted_mcp_enabled = true
# Default result cap for tool descriptors that do not set a smaller cap.
default_max_result_bytes = 262144
[tools.hosted_mcp]
# Non-secret launch correlation nonce lifetime before UDS peer binding.
bind_nonce_ttl_seconds = 30
[tools.policy]
# Valid values: disabled, ask, enabled.
external_default = "disabled"
# Bounded wait for daemon-mediated approval flows.
approval_timeout_seconds = 120
# External read-only sources trusted for approve-reads. Entries use kind:owner.
trusted_sources = []
[[mcp_servers]]
name = "filesystem"
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "/Users/you/work"]
env = { LOG_LEVEL = "info" }
[[mcp_servers]]
name = "remote-docs"
transport = "sse"
url = "https://mcp.example.com/sse"
[mcp_servers.auth]
type = "oauth2_pkce"
issuer_url = "https://auth.example.com"
client_id = "agh-desktop"
client_secret_ref = "env:REMOTE_DOCS_MCP_CLIENT_SECRET"
scopes = ["mcp.read", "mcp.write"]
[providers.claude]
# Overrides the built-in Claude provider command and records native auth diagnostics.
command = "npx -y @agentclientprotocol/claude-agent-acp@latest"
auth_mode = "native_cli"
auth_status_command = "claude auth status"
auth_login_command = "claude auth login"
[providers.claude.models]
# Pre-session catalog defaults consumed by the daemon-owned model catalog.
default = "claude-sonnet-4-6"
[[providers.claude.models.curated]]
id = "claude-sonnet-4-6"
display_name = "Claude Sonnet 4.6"
[[providers.claude.models.curated]]
id = "claude-haiku-4-5"
display_name = "Claude Haiku 4.5"
[model_catalog.sources.models_dev]
# Optional models.dev enrichment source for catalog metadata.
enabled = true
endpoint = "https://models.dev/api.json"
ttl = "24h"
timeout = "10s"
[[providers.claude.mcp_servers]]
name = "github"
command = "npx"
args = ["-y", "@modelcontextprotocol/server-github"]
secret_env = { GITHUB_TOKEN = "env:GITHUB_TOKEN" }
[sandboxes.local]
backend = "local"
sync_mode = "none"
persistence = "reuse"
runtime_root = "~"
[sandboxes.daytona-dev]
backend = "daytona"
sync_mode = "session-bidirectional"
persistence = "reuse"
runtime_root = "/home/daytona/workspace"
[sandboxes.daytona-dev.env]
NODE_ENV = "development"
[sandboxes.daytona-dev.network]
allow_public_ingress = false
allow_outbound = true
allow_list = ["api.example.test"]
deny_list = ["metadata.google.internal"]
[sandboxes.daytona-dev.daytona]
api_url = "https://app.daytona.io/api"
target = "team-default"
snapshot = "snap-agent-base"
image = "ubuntu:24.04"
class = "cpu-2"
auto_stop = "30m"
auto_archive = "24h"
[observability]
enabled = true
retention_days = 7
max_global_bytes = 1073741824
[observability.transcripts]
enabled = true
segment_bytes = 1048576
max_bytes_per_session = 268435456
[log]
level = "info"
max_size_mb = 10
max_backups = 5
max_age_days = 30
compress_backups = false
[memory]
enabled = true
global_dir = "~/.agh/memory"
[memory.controller]
mode = "hybrid" # hybrid | rules | llm
max_latency = "300ms"
default_op_on_fail = "noop"
[memory.controller.llm]
enabled = true
model = "anthropic/claude-haiku-4"
top_k = 5
prompt_version = "v1"
timeout = "250ms"
max_tokens_out = 256
[memory.controller.policy]
max_content_chars = 4096
max_writes_per_min = 60
allow_origins = ["cli", "http", "uds", "tool", "extractor", "dreaming", "file", "provider"]
[memory.recall]
top_k = 5
raw_candidates = 50
fusion = "weighted"
include_already_surfaced = false
include_system = false
[memory.recall.weights]
bm25_unicode = 0.55
bm25_trigram = 0.20
recency = 0.15
recall_signal = 0.10
[memory.recall.freshness]
banner_after_days = 1
[memory.recall.signals]
queue_capacity = 256
worker_retry_max = 3
metrics_enabled = true
[memory.decisions]
prune_after_applied_days = 90
keep_audit_summary = true
max_post_content_bytes = 65536
[memory.extractor]
enabled = true
mode = "post_message"
throttle_turns = 1
deadline = "60s"
sandbox_inbox_only = true
inbox_path = "$AGH_HOME/memory/_inbox"
dlq_path = "$AGH_HOME/memory/_system/extractor/failures"
model = ""
[memory.extractor.queue]
capacity = 1
coalesce_max = 16
[memory.dream]
enabled = true
agent = "dreaming-curator"
min_hours = 24
min_sessions = 3
debounce = "10m"
prompt_version = "v1"
check_interval = "30m"
[memory.dream.gates]
min_unpromoted = 5
min_recall_count = 2
min_score = 0.75
[memory.dream.scoring]
recency_half_life_days = 14
[memory.dream.scoring.weights]
frequency = 0.30
relevance = 0.35
recency = 0.20
freshness = 0.15
[memory.session]
ledger_format = "jsonl"
ledger_root = "$AGH_HOME/sessions"
events_purge_grace = "24h"
cold_archive_days = 30
hard_delete_days = 0
max_archive_bytes = 10737418240
unbound_partition = "_unbound"
[memory.daily]
max_bytes = 1048576
max_lines = 5000
rotate_format = "{date}.{seq}.md"
dreaming_window = 7
cold_archive_days = 30
hard_delete_days = 0
max_archive_bytes = 1073741824
sweep_hour = 3
archive_path = "_system/archive"
[memory.file]
max_lines = 200
max_bytes = 25600
[memory.provider]
name = "" # empty = bundled local provider
timeout = "2s"
failure_threshold = 5
cooldown = "30s"
[memory.workspace]
toml_path = "<workspace>/.agh/workspace.toml" # informational; not configurable
auto_create = true
[skills]
enabled = true
disabled_skills = ["experimental-skill"]
poll_interval = "3s"
allowed_marketplace_mcp = ["clawhub:@team/search-skill"]
allowed_marketplace_hooks = ["clawhub:@team/format-hook"]
[skills.marketplace]
registry = "clawhub"
base_url = "https://registry.example.com"
[extensions.marketplace]
registry = "github"
base_url = "https://api.github.com"
[automation]
enabled = true
timezone = "UTC"
max_concurrent_jobs = 5
default_fire_limit = { max = 12, window = "1h" }
[[automation.jobs]]
scope = "workspace"
name = "daily-doc-check"
agent = "docs"
workspace = "workspace-id-or-path"
prompt = "Review changed docs and report stale links."
enabled = true
fire_limit = { max = 2, window = "24h" }
[automation.jobs.schedule]
mode = "cron"
expr = "0 9 * * 1-5"
[automation.jobs.retry]
strategy = "backoff"
max_retries = 3
base_delay = "2s"
[[automation.triggers]]
scope = "workspace"
workspace = "workspace-id-or-path"
name = "failed-session-summary"
agent = "general"
prompt = "Summarize why session {{ index .Data \"session_id\" }} stopped."
event = "session.stopped"
enabled = true
[automation.triggers.filter]
kind = "session.stopped"
data.stop_reason = "error"
[autonomy.coordinator]
# Disabled by default. When enabled, a workspace-scoped coordinated task run may start
# one coordinator session for that workspace after publish, start, approval, or an
# equivalent execution boundary enqueues the run.
enabled = false
agent_name = "coordinator"
# Optional provider/model overrides. Empty values fall through to agent/provider defaults.
provider = ""
model = ""
default_ttl = "2h"
max_children = 5
max_active_sessions_per_workspace = 5
[task.orchestration]
# Bounds for task summaries, context bundles, scheduler health, and max-runtime watchdog.
summary_max_bytes = 4096
context_body_max_bytes = 8192
context_prior_attempts = 5
context_recent_events = 50
spawn_failure_limit = 5
scheduler_bad_tick_threshold = 6
scheduler_bad_tick_cooldown = "5m"
# Zero disables the per-task max-runtime watchdog default. Tasks may still set a per-task override.
default_max_runtime = "0s"
[task.orchestration.profile]
# Defaults that apply when a task does not persist its own execution profile.
default_coordinator_mode = "inherit"
default_worker_mode = "inherit"
default_sandbox_mode = "inherit"
# Gate task-level provider/model overrides on the profile.
allow_task_provider_override = true
# Gate task-level sandbox = "none" selections.
allow_task_sandbox_none = true
[task.orchestration.review]
# Defaults for the post-terminal review gate. See the review-gate docs for end-to-end behavior.
default_policy = "none"
max_rounds = 3
max_review_attempts = 2
timeout = "20m"
rapid_terminal_window = "2m"
rapid_terminal_limit = 3
missing_work_max_items = 20
missing_work_item_max_bytes = 512
reason_max_bytes = 2048
review_text_max_bytes = 12000
next_round_guidance_max_bytes = 4096
failure_policy = "block_task"
[task.recovery]
# When true, agent identities may use force release, force fail, retry, and bulk recovery surfaces.
# Set false to reserve those verbs for non-agent operator identities.
allow_agent_force = true
[[hooks.declarations]]
name = "record-session-start"
event = "session.post_create"
mode = "async"
required = false
priority = 500
timeout = "5s"
command = "printf"
args = ["session started\n"]
env = { HOOK_LOG = "1" }
[hooks.declarations.matcher]
agent_name = "general"
[network]
enabled = true
default_channel = "default"
port = -1
max_payload = 1048576
greet_interval = 30
max_replay_age = 300
max_queue_depth = 100[daemon]
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
socket | string path | $AGH_HOME/daemon.sock | Non-empty path. ~ is expanded. | Unix domain socket used by CLI IPC and the UDS API server. |
[http]
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
host | string | localhost | Non-empty host or bind address. | HTTP/SSE server host. |
port | integer | 2123 | 1 through 65535 | HTTP/SSE server port. |
[defaults]
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
agent | string | general | Non-empty agent name. | Agent selected when a command or API request omits an agent. |
provider | string | empty | Built-in provider name or configured provider key. | Provider selected when an AGENT.md omits provider. Empty is valid until an agent without provider is resolved. |
[limits]
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
max_concurrent_agents | integer | 20 | Positive integer. | Daemon-wide cap for concurrently running agent subprocesses. |
[session.limits]
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
timeout | duration | 0s | Zero or positive Go duration. | Session-level wall-clock timeout. Zero means no configured wall-clock timeout. |
[session.supervision]
Session supervision keeps long-running prompts observable without turning every heartbeat into a stored event. AGH updates session metadata on short heartbeats and only writes durable events for lower-frequency progress, warnings, and timeout classification.
This timeout is based on inactivity, not total runtime. A prompt can run for hours as long as AGH continues to observe runtime activity or controlled waiting heartbeats.
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
activity_heartbeat_interval | duration | 30s | Positive Go duration. | Cadence for metadata-only activity heartbeats while a prompt is waiting on ACP/provider work. |
progress_notify_interval | duration | 10m | Zero or positive Go duration. | Cadence for persisted runtime_progress events. Zero disables periodic progress events. |
inactivity_warning_after | duration | 15m | Zero or positive Go duration. | Idle age before AGH emits one runtime_warning. Zero disables the warning. |
inactivity_timeout | duration | 30m | Zero or positive Go duration. | Idle age before AGH cancels the prompt cooperatively. Zero disables inactivity timeout. |
timeout_cancel_grace | duration | 30s | Positive Go duration. | Grace period after timeout cancel before AGH stops the session with stop reason timeout. |
[agents.soul]
[agents.soul] controls the optional SOUL.md authored persona artifact. Config owns body
limits, compact projection budget, and the enabled toggle. SOUL.md cannot redefine any of
these keys, and forbidden operational fields in SOUL.md are rejected. See
Agent Soul.
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
enabled | boolean | true | true or false | When false, AGH stops injecting Soul into prompts and /agent/context but keeps inspect/validate/write/delete/history/rollback available. |
max_body_bytes | integer | 32768 | Positive integer. | Maximum normalized SOUL.md body size. Files beyond this fail validation with oversized_body. |
context_projection_bytes | integer | 2048 | Positive integer; must be <= max_body_bytes. | Compact /agent/context.soul projection budget. |
Workspace overlay merges scalar fields predictably; setting any key zero-clamps to the validated positive value or fails with a typed validation error. Disabling at runtime does not clear stored snapshots; managed authoring keeps working so operators can repair a broken file.
[agents.heartbeat]
[agents.heartbeat] controls the optional HEARTBEAT.md advisory wake policy and the runtime
health/wake-audit subsystem. Config owns cadence, rate limits, retention, and stale thresholds;
authored files express bounded preferences only. See
Agent Heartbeat.
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
enabled | boolean | true | true or false | When false, AGH disables wake decisions but keeps managed authoring available so operators can repair a broken policy. |
max_body_bytes | integer | 32768 | Positive integer; capped at the runtime hard limit. | Maximum normalized HEARTBEAT.md body size; oversized files fail validation. |
context_projection_bytes | integer | 4096 | Positive integer; must be <= max_body_bytes. | Compact projection budget for status responses. |
min_interval | duration | 5m | Positive Go duration; must be <= default_interval. | Hard floor for authored preferences.min_interval. Files below this are clamped with heartbeat_preference_clamped. |
default_interval | duration | 30m | Positive Go duration. | Default cadence baseline used when authored files omit min_interval. |
wake_cooldown | duration | 1m | Positive Go duration. | Cooldown between wakes targeting the same session. |
max_wakes_per_cycle | integer | 25 | Positive integer. | Daemon-wide cap on wakes per scheduler cycle. Excess wakes return heartbeat_rate_limited. |
active_session_only | boolean | true | true or false | When true, only sessions reported as active and attachable are wake-eligible. |
allow_active_hours_preferences | boolean | true | true or false | When false, authored active_hours/quiet_windows are ignored with heartbeat_preference_ignored. |
wake_event_retention | duration | 168h | Positive Go duration; minimum 1h. | Retention for agent_heartbeat_wake_events audit rows. Cleanup runs at boot and during scheduler maintenance cycles. |
session_health_stale_after | duration | 2m | Positive Go duration. | Idle age before metadata-only presence becomes stale for wake eligibility. |
session_health_hook_min_interval | duration | 1m | Positive Go duration. | Minimum interval between session.health.update.after hook fires for the same session; metadata-only touches are coalesced. |
[agents.heartbeat] does not own task-run lease heartbeat (task_runs + ClaimNextRun +
HeartbeatRunLease), [session.supervision] activity heartbeat, or AGH Network [network]
greet presence. Those four authorities remain independent.
HEARTBEAT.md snapshot digest covers the normalized body, canonical frontmatter JSON, and a
canonical digest of the resolved [agents.heartbeat] config subset. Editing any field that
affects parsing, preference resolution, eligibility, retention, or coalescing invalidates the
digest and triggers a fresh resolution at the next wake decision.
[permissions]
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
mode | string | approve-all | deny-all, approve-reads, approve-all | Default permission policy used when an agent definition does not override permissions. |
[tools]
Tool registry configuration is loaded before runtime policy and dispatch consume it. These keys only
establish defaults and parse-time guardrails; dispatch still revalidates visibility, permission,
availability, hooks, and approval state per call. When enabled = true, the runtime injects the
agh__bootstrap and agh__catalog discovery toolsets for every agent unless effective policy
denies them, and a startup prompt section teaches the search → info → invoke loop.
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
enabled | boolean | true | true or false. | When false, disables AGH-owned registry dispatch and hosted MCP exposure. |
hosted_mcp_enabled | boolean | true | true or false. | Allows AGH to expose the local hosted MCP proxy for session-visible tools. |
default_max_result_bytes | integer | 262144 | 0 through 16777216. | Result cap used when a descriptor does not specify a smaller limit. |
[tools.hosted_mcp]
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
bind_nonce_ttl_seconds | integer | 30 | 1 through 300 seconds. | Lifetime for the non-secret hosted MCP bind nonce before UDS peer binding. |
[tools.policy]
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
external_default | string | disabled | disabled, ask, enabled. | Default executable policy for extension, MCP, and dynamic tools before explicit tool/source grants. |
approval_timeout_seconds | integer | 120 | 1 through 600 seconds. | Maximum wait for daemon-mediated approval flows. |
trusted_sources | string array | [] | mcp:<server> or extension:<name>. | External read-only sources trusted for approve-reads; MCP entries must reference configured MCP servers. |
trusted_sources does not store credentials. Remote MCP OAuth tokens remain in the MCP auth store,
and hosted MCP bind nonces are transient session launch state.
[[mcp_servers]]
Top-level MCP servers are merged with provider, agent, and skill MCP servers during session startup. They can point at local stdio processes or remote HTTP/SSE MCP endpoints.
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
name | string | required | Non-empty after trimming. | Stable server key used for merge and replacement. |
transport | string | inferred | stdio, http, sse. | Transport kind. Command servers default to stdio; URL servers default to http. |
command | string | required for stdio | Non-empty command. | Executable command for a local stdio MCP server. Invalid for remote transports. |
url | string URL | required for remote | Absolute URL. | Remote MCP endpoint for http or sse transports. Invalid for stdio. |
auth | object | empty | OAuth 2.1 PKCE settings. | Remote auth metadata and client settings. Invalid for stdio. |
args | string array | empty | Strings. | Process arguments passed to the command. |
env | string map | empty | String keys and values. | Literal environment values passed to the MCP server. AGH does not perform shell expansion. |
secret_env | string map | empty | env:NAME or vault:mcp/<server>/env/<KEY> refs. | Secret environment bindings for stdio servers. Values are resolved at launch and redacted from diagnostics. |
OAuth-enabled remote servers store only metadata in config. Token material is kept in the AGH
Vault as encrypted refs and is exposed through API, settings, CLI, logs, and the agent-callable
agh__mcp_status / agh__mcp_auth_status tools only as redacted status. Login/logout happen on
CLI and HTTP. These are operator-only management flows.
auth field | Type | Required | Description |
|---|---|---|---|
type | string | yes | Must be oauth2_pkce. |
client_id | string | yes | OAuth client ID. |
client_secret_ref | string | no | env:NAME or vault:mcp/<server>/oauth/client-secret ref containing the client secret, when required. |
issuer_url | string URL | conditional | Issuer for OAuth metadata discovery. |
metadata_url | string URL | conditional | Explicit OAuth authorization-server metadata URL. |
authorization_url | string URL | conditional | Direct authorization endpoint. Pair with token_url. |
token_url | string URL | conditional | Direct token endpoint. Pair with authorization_url. |
revocation_url | string URL | no | Optional endpoint used by agh mcp auth logout. |
scopes | string array | no | Requested OAuth scopes. |
Configure one of metadata_url, issuer_url, or both authorization_url and token_url, then
authenticate with:
agh mcp auth login remote-docs
agh mcp auth status remote-docs
agh mcp auth status remote-docs --refresh
agh mcp auth logout remote-docsAgents can read the same redacted status from inside a session through agh__mcp_status or
agh__mcp_auth_status. These tools never trigger an OAuth browser flow; missing or expired
authentication is repaired through the operator login/logout commands above. Auth-blocked MCP
tools are omitted from callable discovery while status/probe output explains the repair path.
[providers.<name>]
Provider keys override built-ins with the same name or create a custom provider. Built-ins are
claude, codex, gemini, opencode, copilot, cursor, kiro, blackbox, cline,
goose, hermes, junie, kimi-cli, openclaw, openhands, qoder, qwen-code, pi,
openrouter, zai, moonshot, vercel-ai-gateway, xai, minimax, mistral, and groq.
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
command | string | Built-in command or empty for custom providers. | Required after built-in plus override resolution. | ACP launch command for this provider. |
display_name | string | Built-in label or empty. | Any string. | Operator-facing label shown in settings and provider pickers. |
models | table | Built-in defaults or empty. | Nested model config block (see below). | Pre-session model defaults, curated metadata, and optional discovery wiring. |
harness | string | acp unless a built-in sets pi_acp. | acp, pi_acp. | Launch strategy. pi_acp routes the provider through Pi's ACP adapter. |
runtime_provider | string | Provider key. | Harness-specific provider id. | Downstream provider id used by Pi and other harnesses. |
transport | string | empty. | Harness-specific string. | Optional Pi models override transport/API family. |
base_url | string | empty. | URL string. | Optional Pi models override base URL for custom gateways. |
auth_mode | string | bound_secret only when credential slots are configured; otherwise native_cli. | native_cli, bound_secret, none. | Declares whether auth belongs to the provider CLI, AGH secret binding, or no auth. |
none_security | string | local_transport. | local_transport, external_identity, public_readonly. | Safety rationale required for auth_mode = "none". |
env_policy | string | filtered. | filtered, isolated. | Controls which daemon environment variables the provider subprocess inherits. |
home_policy | string | operator. | operator, isolated. | Controls whether native CLI state comes from the operator home or an AGH provider home. |
auth_status_command | string | empty. | Shell-style command string. | Optional status probe run by agh provider auth status <provider>. |
auth_login_command | string | empty unless a built-in provider defines one. | Shell-style command string. | Optional login command surfaced by agh provider auth login <provider>; isolated homes print the required environment prefix. |
session_mcp | boolean | true unless a provider disables it. | true, false. | Enables AGH session MCP injection for providers that support it. |
credential_slots | array | empty. | See below. | Bound secret refs injected into provider subprocess environment variables at launch. |
mcp_servers | array of MCP server objects | empty. | Same shape as [[mcp_servers]]. | Provider-specific MCP servers merged after top-level config and before agent MCP servers. |
The flat keys default_model, supported_models, and supports_reasoning_effort are no longer
accepted. Config that still sets them is rejected with a deterministic hard-cut error citing the
exact path. Move every value into [providers.<id>.models] below.
Provider and model aliases are small and explicit. Provider aliases such as claude-code,
ai-gateway, vercel, kimi, glm, x.ai, grok, open-code, and qwen resolve to the
canonical provider ID before config is applied. Provider-scoped model aliases such as sonnet,
opus, haiku, gpt5, mini, kimi, glm, grok, and qwen resolve to the concrete model ID
for the selected provider. Runtime diagnostics, session metadata, and model catalog rows use the
canonical resolved value.
The old providers.<id>.aliases config key was removed for v1. Reference providers by canonical
name only; config files that set aliases = [...] under a provider are rejected during load.
auth_mode = "none" means No auth required and is only valid when the provider needs no AGH or
provider-owned credential. Set none_security to state why that is safe: local-only transport,
external identity enforcement, or public read-only access. No-auth providers cannot define
credential_slots, auth_status_command, or auth_login_command; those keys are rejected during
config validation.
[providers.<id>.models]
Pre-session model defaults and curated metadata are owned by the daemon-owned model catalog. The
catalog merges builtin defaults, the operator config, the optional models.dev enrichment source,
live provider discovery sources, and extension model sources, and exposes the result through HTTP,
UDS, CLI, the OpenAI-compatible projection, the Host API, and the web. Active ACP configOptions
continue to govern model and reasoning controls inside a running session, so curated entries are
metadata, never an allowlist.
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
models.default | string | Built-in default or empty. | Any non-blank model id. | Model used when an agent omits model. Free-form: it does not need to appear in models.curated. |
models.curated | array | empty. | See entry fields below. | Curated model entries projected as config rows. Not an allowlist; manual model ids stay valid. |
models.curated[].id | string | required per entry. | Unique provider model id. | Provider model identifier sent to the runtime. |
models.curated[].display_name | string | empty. | Any string. | Optional human label. |
models.curated[].context_window | integer | empty. | Positive integer. | Context window in tokens. |
models.curated[].max_input_tokens | integer | empty. | Positive integer. | Maximum input tokens. |
models.curated[].max_output_tokens | integer | empty. | Positive integer. | Maximum output tokens. |
models.curated[].supports_tools | boolean | empty. | true, false. | Whether the model supports tool calls. |
models.curated[].supports_reasoning | boolean | empty. | true, false. | Whether the model supports reasoning effort. |
models.curated[].reasoning_efforts | array | empty. | Subset of minimal, low, medium, high, xhigh. Blanks rejected. | Allowed reasoning levels for this model. |
models.curated[].default_reasoning_effort | string | empty. | Member of reasoning_efforts when both are set. | Per-model default reasoning level. Must appear in reasoning_efforts when both are set. |
models.curated[].cost_input_per_million | number | empty. | Non-negative number. | Display-only input cost per million tokens. |
models.curated[].cost_output_per_million | number | empty. | Non-negative number. | Display-only output cost per million tokens. |
models.discovery.enabled | boolean | false unless a built-in opts in. | true, false. | Enables the side-effect-free model discovery adapter for this provider. |
models.discovery.command | string | empty. | Shell-style command string. | Side-effect-free discovery command. Mutually exclusive with endpoint unless the adapter documents both. |
models.discovery.endpoint | string | empty. | Absolute HTTP(S) URL. | Side-effect-free discovery endpoint URL. Mutually exclusive with command unless the adapter documents both. |
models.discovery.timeout | string | model catalog source timeout. | Positive duration (10s, 45s, 2m). | Per-discovery timeout. |
Discovery adapters use the resolved provider auth, env, and home policy. Discovery never creates an ACP session; if discovery is unavailable or fails, the catalog records source status and falls back to stale or lower-priority rows. Session creation never depends on a successful discovery refresh.
OpenClaw, Hermes, and Pi only register a live provider source when models.discovery.enabled = true and either command or endpoint is set; with no discovery wiring, those providers stay
on builtin/config rows plus the optional models.dev enrichment.
Top-level [model_catalog.sources.models_dev] controls the cross-provider models.dev enrichment
source documented in the next section.
env_policy = "filtered" preserves ordinary operator context such as PATH, HOME, and locale
while stripping secret-shaped daemon variables before launch. env_policy = "isolated" starts from
a small operational allowlist and then adds only AGH session metadata, provider-home variables, and
explicit bound_secret slots. home_policy = "operator" lets native CLIs reuse existing login
state. home_policy = "isolated" creates $AGH_HOME/providers/<provider> with private
permissions, sets PROVIDER_HOME, XDG directories, and known provider-specific home variables such
as CLAUDE_CONFIG_DIR, CODEX_HOME, and OPENCODE_CONFIG_DIR.
Credential slots use this shape:
[providers.openrouter]
auth_mode = "bound_secret"
[[providers.openrouter.credential_slots]]
name = "api_key"
target_env = "OPENROUTER_API_KEY"
secret_ref = "vault:providers/openrouter/api-key"
kind = "api_key"
required = truesecret_ref supports env:NAME for operator-managed environment variables and
vault:providers/<provider>/<slot> for AGH-managed encrypted provider credentials written through
the settings API, agh vault, or web provider editor. The vault: form accepts lowercase
provider/slot identifiers only, with letters, numbers, hyphens, underscores, or dots; arbitrary
vault paths are not valid provider credential refs.
The slot required flag is enforced at session start for both env: and vault: refs.
credential_slots are valid only when auth_mode = "bound_secret". Direct ACP built-ins and the
direct pi provider use native_cli by default and do not preflight provider API keys. Pi-backed
API-key wrappers such as OpenRouter, z.ai, Moonshot/Kimi, Vercel AI Gateway, xAI, MiniMax, Mistral,
and Groq default to AGH-managed bound_secret slots while AGH runs Pi under the hood.
| Built-in | Harness | Runtime provider | models.default | Auth mode | Credential target |
|---|---|---|---|---|---|
claude | acp | claude | claude-sonnet-4-6 | native_cli | provider login |
codex | acp | codex | gpt-5.4 | native_cli | provider login |
gemini | acp | gemini | gemini-3.1-pro-preview | native_cli | provider login |
opencode | acp | opencode | none | native_cli | provider login |
copilot | acp | copilot | none | native_cli | provider login |
cursor | acp | cursor | none | native_cli | provider login |
kiro | acp | kiro | none | native_cli | provider login |
blackbox | acp | blackbox | none | native_cli | provider login |
cline | acp | cline | none | native_cli | provider login |
goose | acp | goose | none | native_cli | provider login |
hermes | acp | hermes | none | native_cli | provider login |
junie | acp | junie | none | native_cli | provider login |
kimi-cli | acp | kimi-cli | none | native_cli | provider login |
openclaw | acp | openclaw | none | native_cli | provider login |
openhands | acp | openhands | none | native_cli | provider login |
qoder | acp | qoder | none | native_cli | provider login |
qwen-code | acp | qwen-code | qwen3.6-plus | native_cli | provider login |
pi | pi_acp | anthropic | claude-opus-4-7 | native_cli | Pi /login |
openrouter | pi_acp | openrouter | openai/gpt-5.4 | bound_secret | OPENROUTER_API_KEY |
zai | pi_acp | zai | glm-4.6 | bound_secret | ZAI_API_KEY |
moonshot | pi_acp | kimi-coding | kimi-k2-thinking | bound_secret | KIMI_API_KEY |
vercel-ai-gateway | pi_acp | vercel-ai-gateway | anthropic/claude-opus-4-7 | bound_secret | AI_GATEWAY_API_KEY |
xai | pi_acp | xai | grok-4-fast-non-reasoning | bound_secret | XAI_API_KEY |
minimax | pi_acp | minimax | MiniMax-M2.1 | bound_secret | MINIMAX_API_KEY |
mistral | pi_acp | mistral | devstral-medium-latest | bound_secret | MISTRAL_API_KEY |
groq | pi_acp | groq | openai/gpt-oss-120b | bound_secret | GROQ_API_KEY |
[model_catalog.sources.models_dev]
The models.dev enrichment source feeds catalog metadata such as token windows, tool support, and
reasoning hints. It is cross-provider, daemon-owned, and never proves account-level availability.
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
enabled | boolean | true | true, false | Toggles the models.dev source. When false, the source still appears in status but performs no outbound calls. |
endpoint | string | https://models.dev/api.json | Absolute HTTP(S) URL. | Endpoint queried for the cross-provider model index. Must be HTTP(S) when set. |
ttl | duration | 24h | Positive Go duration. | Cache lifetime before catalog rows are flagged stale and a refresh is scheduled. |
timeout | duration | 10s | Positive Go duration. | Per-call HTTP timeout for the source. The HTTP client always uses an explicit deadline (no shared http.DefaultClient). |
[model_catalog.sources.models_dev]
enabled = true
endpoint = "https://models.dev/api.json"
ttl = "24h"
timeout = "10s"models.dev rows write provider-scoped status: a single models.dev refresh records one
(source_id="models_dev", provider_id) status row per AGH provider mapped, never a global
empty-provider sentinel. Disabled sources still expose status but skip outbound calls. Refresh
lifetime is daemon-owned: requests trigger refreshes but the daemon detaches the work, applies an
explicit deadline, and joins outstanding refresh workers during shutdown.
Live provider discovery is configured per provider through [providers.<id>.models.discovery].
Discovery refresh is serialized per provider_id before any subprocess or provider-home work, and
concurrent refresh requests for the same provider coalesce behind the in-flight refresh.
[observability]
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
enabled | boolean | true | true or false | Enables global event summary and health observation paths. |
retention_days | integer | 7 | Zero or positive. | Retention window for global event summaries, token stats, and permission logs. 0 keeps history. |
max_global_bytes | integer | 1073741824 | Positive integer. | Size cap for global observability storage. |
[observability.transcripts]
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
enabled | boolean | true | true or false | Enables transcript capture from persisted session events. |
segment_bytes | integer | 1048576 | Positive integer. | Segment size for transcript retention. |
max_bytes_per_session | integer | 268435456 | Positive integer. | Per-session transcript byte cap. |
[log]
The daemon writes structured logs to $AGH_HOME/logs/agh.log. Rotation is owned by the daemon's
LogSink, so operators do not need an external logrotate rule for the default file.
Changing any [log] key is restart-required in v1. The daemon applies the new rotation
writer on the next start.
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
level | string | info | debug, info, warn, error | Structured daemon log level. |
max_size_mb | integer | 10 | Positive integer. | Rotate agh.log when the active file would exceed this size. |
max_backups | integer | 5 | Zero or positive integer. | Maximum rotated backups to keep. 0 disables backup count retention. |
max_age_days | integer | 30 | Zero or positive integer. | Delete backups older than this many days. 0 disables age retention. |
compress_backups | boolean | false | true or false | Compress rotated backups with gzip after rotation. |
[memory]
The [memory] tree is the Memory v2 runtime configuration. Memory v2 is the only memory subsystem;
there is no [memory.v2] enabled flag and no parallel compatibility namespace. Disabling
[memory] enabled short-circuits prompt assembly, the controller, recall, dreaming, the extractor,
and the bundled local provider.
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
enabled | boolean | true | true or false | Master switch for the Memory v2 runtime. |
global_dir | string path | $AGH_HOME/memory | Non-empty path when set. ~ is expanded. | Global memory directory. Blank overlays are ignored and keep the previous value. |
[memory.controller]
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
mode | string | hybrid | hybrid, rules, llm | Controller decision mode. hybrid runs the rule-first lexical/entity logic with an LLM tiebreaker. |
max_latency | duration | 300ms | Positive Go duration. | Maximum end-to-end controller latency before fall-back behavior triggers. |
default_op_on_fail | string | noop | noop, reject | Decision op used when the controller fails or its deadline is exceeded. |
[memory.controller.llm]
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
enabled | boolean | true | true or false | Enables the LLM tiebreaker for ambiguous rule traces. |
model | string | anthropic/claude-haiku-4 | Non-empty model identifier. | Model used by the controller tiebreaker. |
top_k | integer | 5 | Positive integer. | Candidates passed to the entity-slot tiebreaker. |
prompt_version | string | v1 | Non-empty pinned version. | Prompt template version pinned in decisions for replay fidelity. |
timeout | duration | 250ms | Positive Go duration. | LLM call deadline before fall-through to the rule trace. |
max_tokens_out | integer | 256 | Positive integer. | Output cap for the tiebreaker call. |
[memory.controller.policy]
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
max_content_chars | integer | 4096 | Positive integer. | Hard cap on candidate body length. |
max_writes_per_min | integer | 60 | Positive integer. | Per-workspace write rate limit before the controller starts rejecting candidates. |
allow_origins | string array | ["cli","http","uds","tool","extractor","dreaming","file","provider"] | Subset of canonical origins. | Origins permitted to submit candidates. Empty rejects every write. |
[memory.recall]
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
top_k | integer | 5 | Positive integer. | Top-K curated entries packaged per recall response. |
raw_candidates | integer | 50 | Positive integer. | Raw candidate pool before scoring/shadowing. |
fusion | string | weighted | weighted, rrf | Score fusion strategy. rrf is reserved for slice 3. |
include_already_surfaced | boolean | false | true or false | Includes entries already surfaced this session. |
include_system | boolean | false | true or false | Includes _system/ artifacts in recall (operator-only). |
[memory.recall.weights]
Weights are blended into the recall score. Defaults sum to 1.0.
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
bm25_unicode | float | 0.55 | 0.0–1.0 | BM25 score from the unicode FTS5 index. |
bm25_trigram | float | 0.20 | 0.0–1.0 | BM25 score from the trigram FTS5 index. |
recency | float | 0.15 | 0.0–1.0 | Time-decay factor. |
recall_signal | float | 0.10 | 0.0–1.0 | Live recall-signal feedback factor. |
[memory.recall.freshness]
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
banner_after_days | integer | 1 | Positive integer. | Adds a "verify before asserting" banner to entries older than this. |
[memory.recall.signals]
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
queue_capacity | integer | 256 | Positive integer. | Bounded channel for recall-signal updates. Oldest drops on overflow. |
worker_retry_max | integer | 3 | Positive integer. | Per-update retries before emitting memory.recall.signal_update_failed. |
metrics_enabled | boolean | true | true or false | Emits recall-signal metrics for observability. |
[memory.decisions]
WAL retention controls. Pruned rows are replaced by a redaction-safe summary so audit history survives.
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
prune_after_applied_days | integer | 90 | Positive integer. | Decisions with applied_at older than this are pruned after a memory.decisions.audit_summarized event. |
keep_audit_summary | boolean | true | true or false | Emits the audit-summary event before pruning. |
max_post_content_bytes | integer | 65536 | Positive integer. | Per-row body cap. Oversized rows store a content-hash reference instead. |
[memory.extractor]
The extractor consumes the session.message_persisted hook and writes structured proposals via the
controller. inbox_path and dlq_path are validation-locked to the canonical AGH-managed
locations.
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
enabled | boolean | true | true or false | Enables the extractor runtime. |
mode | string | post_message | post_message | Extraction mode. AGH currently supports only post-message extraction. |
throttle_turns | integer | 1 | Positive integer. | Minimum same-session queued turns to coalesce before launching another extraction; drain flushes pending content. |
deadline | duration | 60s | Positive Go duration. | Per-extraction deadline before the runtime drops the candidate. |
sandbox_inbox_only | boolean | true | true or false | Restricts extractor writes to _inbox/ until the controller accepts them. |
inbox_path | string | $AGH_HOME/memory/_inbox | Daemon-managed. | Read-only display field; the daemon manages the inbox path. |
dlq_path | string | $AGH_HOME/memory/_system/extractor/failures | Daemon-managed. | Read-only display field; the daemon manages the DLQ path. |
model | string | empty | Empty or model id. | Optional model override for the extractor child session. Empty uses the agent/provider default. |
[memory.extractor.queue]
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
capacity | integer | 1 | Positive integer. | Maximum concurrent provider-backed extractor child sessions; additional sessions wait without losing queued turns. |
coalesce_max | integer | 16 | Positive integer greater than or equal to throttle_turns. | Maximum coalesced turns when consecutive triggers arrive while the extractor is busy. |
[memory.dream]
If enabled = false, the remaining dream validation is skipped.
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
enabled | boolean | true | true or false | Enables the dreaming runtime and the Trigger-dream action. |
agent | string | dreaming-curator | Non-empty when enabled. | Dedicated curator agent. Does not inherit [defaults].agent. |
min_hours | float | 24 | Positive number. | Time-gate threshold before another successful run. |
min_sessions | integer | 3 | Positive integer. | Sessions-gate threshold (completed sessions since last run). |
debounce | duration | 10m | Positive Go duration. | Debounce window for triggers fed by session.post_stop. |
prompt_version | string | v1 | Non-empty pinned version. | Prompt template version pinned to dreaming sessions for replay fidelity. |
check_interval | duration | 30m | Positive Go duration. | Background ticker interval. |
[memory.dream.gates]
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
min_unpromoted | integer | 5 | Positive integer. | Minimum unpromoted candidates with sufficient signal. |
min_recall_count | integer | 2 | Positive integer. | Minimum recall hits per candidate before it qualifies. |
min_score | float | 0.75 | 0.0–1.0 | Minimum scored value for a candidate to clear the signal gate. |
[memory.dream.scoring]
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
recency_half_life_days | integer | 14 | Positive integer. | Half-life applied to recall recency in the dreaming score. |
[memory.dream.scoring.weights]
Defaults sum to 1.0 across the four factors.
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
frequency | float | 0.30 | 0.0–1.0 | Weight of recall frequency. |
relevance | float | 0.35 | 0.0–1.0 | Weight of BM25 relevance. |
recency | float | 0.20 | 0.0–1.0 | Weight of recency decay. |
freshness | float | 0.15 | 0.0–1.0 | Penalty weight for stale, never-promoted entries. |
[memory.session]
Forensic ledger materialization. The materializer writes one read-only ledger.jsonl
under <ledger_root>/<workspace_id>/<session_id>/. Sessions without a workspace use
<unbound_partition> instead of a workspace_id segment.
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
ledger_format | string | jsonl | jsonl | Forensic ledger format. |
ledger_root | string | $AGH_HOME/sessions | Daemon-managed. | Ledger root. Read-only; daemon-managed path. |
events_purge_grace | duration | 24h | Positive Go duration. | Time after materialization before live events.db rows are purged. |
cold_archive_days | integer | 30 | Zero or positive. | Cold-archive window for ledger.jsonl. 0 keeps ledgers in-place. |
hard_delete_days | integer | 0 | Zero or positive. | 0 keeps ledgers forever; explicit prune via CLI. |
max_archive_bytes | integer | 10737418240 | Positive integer. | Safety-valve cap on the cold-archive store. |
unbound_partition | string | _unbound | Daemon-managed. | Partition used for sessions without a workspace_id. |
[memory.daily]
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
max_bytes | integer | 1048576 | Positive integer. | Per-day daily-log byte cap before rotation. |
max_lines | integer | 5000 | Positive integer. | Per-day daily-log line cap before rotation. |
rotate_format | string | {date}.{seq}.md | Daemon-managed. | Rotation filename format. Read-only. |
dreaming_window | integer | 7 | Positive integer. | Days the dreaming curator reads from daily logs. |
cold_archive_days | integer | 30 | Zero or positive. | Cold-archive window for rotated daily logs. |
hard_delete_days | integer | 0 | Zero or positive. | 0 keeps daily logs forever; explicit prune via CLI. |
max_archive_bytes | integer | 1073741824 | Positive integer. | Safety-valve cap on the daily archive. |
sweep_hour | integer | 3 | 0–23 | Local hour for daily housekeeping sweep. |
archive_path | string | _system/archive | Daemon-managed. | Archive subdirectory under each scope's _system/. |
[memory.file]
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
max_lines | integer | 200 | Positive integer. | Cap for MEMORY.md lines included in the frozen prompt snapshot. |
max_bytes | integer | 25600 | Positive integer. | Cap for MEMORY.md bytes included in the frozen prompt snapshot. |
[memory.provider]
name = "" selects the bundled local provider. Setting a configured provider name routes runtime
calls through the registered MemoryProvider while keeping the local provider as a circuit-breaker
fallback (see Extensions).
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
name | string | empty | Empty or registered name. | Active provider. Empty falls back to the bundled local provider. |
timeout | duration | 2s | Positive Go duration. | Per-method deadline before fail-open to the bundled local provider. |
failure_threshold | integer | 5 | Positive integer. | Consecutive failures before the circuit opens. |
cooldown | duration | 30s | Positive Go duration. | How long the circuit stays open before retry. |
[memory.workspace]
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
toml_path | string | <workspace>/.agh/workspace.toml | Daemon-managed. | Read-only display field. Workspace identity always lives at this path. |
auto_create | boolean | true | true/false | Auto-create <workspace>/.agh/workspace.toml on first daemon touch of a new workspace. |
[skills]
If enabled = false, skill polling and marketplace validation are skipped.
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
enabled | boolean | true | true or false | Enables skill catalog discovery and polling. |
disabled_skills | string array | empty | Skill names. | Replaces the disabled-skill list in overlays. |
poll_interval | duration | 3s | Positive Go duration. | Filesystem poll interval for skill catalog refresh. |
allowed_marketplace_mcp | string array | empty | Marketplace slug, registry:slug, or verified hash. | Trust allowlist for MCP servers declared by marketplace skills. |
allowed_marketplace_hooks | string array | empty | Marketplace slug, registry:slug, or verified hash. | Trust allowlist for hooks declared by marketplace skills. |
[skills.marketplace]
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
registry | string | empty | Empty or clawhub. Required when base_url is set. | Skill marketplace registry adapter. |
base_url | string URL | empty | Empty or http or https URL with host. | Registry base URL override. |
[extensions.marketplace]
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
registry | string | empty | Empty or github. Required when base_url is set. | Extension marketplace registry adapter. |
base_url | string URL | empty | Empty or http or https URL with host. | Registry base URL override. http is accepted but logs a warning. |
[automation]
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
enabled | boolean | true | true or false | Enables config-defined automation jobs and triggers. |
timezone | string | UTC | IANA timezone loadable by Go, such as UTC or America/Sao_Paulo. | Schedule timezone for automation. |
max_concurrent_jobs | integer | 5 | Positive integer. | Global automation concurrency cap. |
default_fire_limit | object | { max = 12, window = "1h" } | max positive, window positive Go duration. | Default rolling fire limit copied into jobs and triggers that omit their own limit. |
[[automation.jobs]]
Jobs are appended by overlays; they do not replace earlier jobs with the same name.
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
scope | string | required | global or workspace | Binding scope. |
name | string | required | Non-empty. | Job name. |
agent | string | required unless task is configured | Non-empty. | Agent that handles the scheduled prompt. |
workspace | string | required when scope = "workspace", empty when scope = "global" | Workspace ID or root accepted by the automation resolver. | Workspace binding. |
prompt | string | required unless task is configured | Non-empty. | Prompt submitted when the job fires. |
schedule.mode | string | required | cron, every, at | Schedule mode. |
schedule.expr | string | empty | Required only for cron; standard five-field cron. | Cron expression. |
schedule.interval | string | empty | Required only for every; positive Go duration. | Repeating interval. |
schedule.time | string | empty | Required only for at; RFC3339 timestamp. | One-shot fire time. |
task.title | string | empty | Any string. | Task title when the job materializes a task instead of starting an agent session. |
task.description | string | empty | Any string. | Task description. |
task.owner | object | empty | Task ownership object. | Owner metadata validated by the task package. |
task.network_channel | string | empty | Valid network channel. | Network channel attached to generated tasks. |
enabled | boolean | true | true or false | Enables this job. |
retry.strategy | string | none | none or backoff | Retry behavior. Must be none when task is configured. |
retry.max_retries | integer | 0 | 0 for none; positive for backoff. | Maximum retry count. |
retry.base_delay | string | empty | Empty for none; positive Go duration for backoff. | Base backoff delay. |
fire_limit | object | [automation].default_fire_limit | max positive, window positive Go duration. | Per-job fire limit. |
[[automation.triggers]]
Triggers are appended by overlays; they do not replace earlier triggers with the same name.
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
scope | string | required | global or workspace | Binding scope. |
name | string | required | Non-empty. | Trigger name. |
agent | string | required | Non-empty. | Agent that handles the trigger prompt. |
workspace | string | required when scope = "workspace", empty when scope = "global" | Workspace ID or root accepted by the automation resolver. | Workspace binding. |
prompt | string | required | Valid Go template over the activation envelope. | Prompt submitted when the trigger fires. |
event | string | required | Non-empty; webhook has extra requirements. | Event name. |
filter | string map | empty | Keys kind, scope, workspace_id, source, or data.<field>; values non-empty. | Activation-envelope filter. |
enabled | boolean | true | true or false | Enables this trigger. |
retry.strategy | string | none | none or backoff | Retry behavior. |
retry.max_retries | integer | 0 | 0 for none; positive for backoff. | Maximum retry count. |
retry.base_delay | string | empty | Empty for none; positive Go duration for backoff. | Base backoff delay. |
fire_limit | object | [automation].default_fire_limit | max positive, window positive Go duration. | Per-trigger fire limit. |
endpoint_slug | string | empty | Required when event = "webhook"; empty otherwise. | Webhook endpoint slug. |
webhook_secret_ref | string | empty | Required when event = "webhook"; must be env:NAME or vault:automation/...; empty otherwise. | Secret ref used to validate webhook requests. |
See Vault for the CLI, HTTP, UDS, web, and session-scoped surfaces that store and inspect encrypted AGH-managed secret refs.
[autonomy.coordinator]
Coordinator config controls whether AGH may start a workspace coordinator when executable task-run work is enqueued. Task creation is not executable work. Creating or saving a task does not enqueue a run, create a coordination channel, or spawn a coordinator. Publish, start, approval, and equivalent run-enqueue APIs are the execution boundary.
Coordinator launch only applies to workspace-scoped coordinated runs with a stable
coordination_channel_id. Global runs and intent-only tasks do not start coordinators in the MVP.
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
enabled | boolean | false | true or false | Allows coordinator bootstrap after a coordinated workspace run is enqueued. |
agent_name | string | coordinator | Non-empty when enabled. | Agent definition used for managed coordinator sessions. |
provider | string | empty | Empty or a configured provider key. | Optional provider override for the coordinator agent. |
model | string | empty | Empty or provider-supported model string. | Optional model override. If set, provider or provider default resolution must exist. |
default_ttl | duration | 2h | 1m through 24h. | Lifetime assigned to managed coordinator sessions. |
max_children | integer | 5 | 1 through 5. | Maximum safe-spawn children a coordinator may hold at once. |
max_active_sessions_per_workspace | integer | 5 | Positive integer. | Caps concurrent autonomy-managed sessions (coordinator + spawned workers) per workspace. Coordinator uniqueness is enforced by the daemon singleton check. |
Provider and model resolution is intentionally narrow. The daemon applies:
- Workspace
.agh/config.tomloverride for the resolved workspace. - Global
$AGH_HOME/config.toml. - The bundled/default coordinator agent definition and provider defaults.
Safe-spawn limits still apply after a coordinator starts. Coordinator children inherit the workspace and coordination channel, must use a positive TTL, and can only narrow the coordinator's permission set.
[task.orchestration]
[task.orchestration] controls bounded task orchestration behavior: run summaries, task context
bundles, scheduler health telemetry, the spawn-failure circuit breaker, and the per-task max-runtime
default. The defaults shown below are loaded from internal/config/task_orchestration.go and apply
when neither the global file nor a workspace overlay sets a value.
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
summary_max_bytes | integer | 4096 | Positive integer. | Maximum byte size for stored task-run summary fields used by context, web, CLI, and review surfaces. |
context_body_max_bytes | integer | 8192 | Positive integer. | Maximum byte size for the rendered task context bundle attached to /agent/context. |
context_prior_attempts | integer | 5 | Zero or positive integer. | Maximum prior-attempt summaries included in the task context bundle. |
context_recent_events | integer | 50 | Zero or positive integer. | Maximum recent task events included in the task context bundle. |
spawn_failure_limit | integer | 5 | Positive integer. | Spawn-failure threshold before the per-task spawn circuit breaker opens. |
scheduler_bad_tick_threshold | integer | 6 | Positive integer. | Bad-tick count before the scheduler health watchdog flags a degraded scheduler tick. |
scheduler_bad_tick_cooldown | duration | 5m | Positive Go duration with whole-second precision. | Cooldown between scheduler bad-tick health emissions. |
default_max_runtime | duration | 0s | Zero or positive Go duration up to 24h with whole-second precision. | Default per-task max-runtime watchdog. Zero disables the default; tasks may still set a per-task override. |
[task.orchestration] keys are agent-mutable through the existing config tool surface
(agh config set and the agh__config_* native tools). Workspace overlays apply through the
existing config loader without any special handling.
Config and hook mutation tools return lifecycle truth in their structured payloads. Writes under
hooks.* and extensions.* are persisted as desired state with applied=false,
lifecycle="restart-required", and next_action="restart-daemon"; agents should not treat
those writes as active runtime truth until the daemon restarts.
[task.orchestration.profile]
Defaults and gates that apply when a task does not store its own execution profile, plus the gates that allow or reject task-level provider/sandbox overrides. See Task Execution Profiles for the runtime behavior.
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
default_coordinator_mode | string | inherit | inherit, guided | Coordinator behavior when a task profile does not set coordinator.mode. |
default_worker_mode | string | inherit | inherit | Worker selection mode when a task profile does not set worker.mode. select is allowed only on the per-task profile. |
default_sandbox_mode | string | inherit | inherit, none | Sandbox mode when a task profile does not set sandbox.mode. |
allow_task_provider_override | boolean | true | true or false | When false, task profiles may not set provider/model on coordinator, worker, or review blocks. |
allow_task_sandbox_none | boolean | true | true or false | When false, task profiles may not set sandbox.mode = "none". Required to be true if default_sandbox_mode = "none". |
Profile validation runs in task.Service when a profile is created or updated; the normalized
profile is then stored. Session start loads the persisted profile (or the default inherit profile
when none exists) without re-running validation. Updates and deletes are rejected while the task has
an active run (tasks.current_run_id is set); resolve or release the run before retrying.
Per-task profiles also store sandbox.mode and runtime.mode. sandbox.mode accepts inherit,
none, or ref; ref requires sandbox.sandbox_ref and resolves a named [sandboxes.<name>].
runtime.mode accepts default or evidence. Evidence mode adds runtime evidence guidance and
widens session permissions only when the same profile explicitly selects sandbox.mode = "ref";
inherited or disabled sandbox modes keep the configured permission policy.
[task.orchestration.review]
Defaults and bounds for the post-terminal review gate. These values shape the task.review_policy
defaults and the bounded reviewer evidence enforced by task.Service.RecordRunReview.
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
default_policy | string | none | none, on_success, on_failure, always | Default review trigger policy when a task does not set its own. |
max_rounds | integer | 3 | Positive integer. | Maximum review rounds before the failure policy applies. |
max_review_attempts | integer | 2 | Positive integer. | Maximum reviewer attempts within a single review round before the round counts as exhausted. |
timeout | duration | 20m | Positive Go duration with whole-second precision. | Maximum reviewer think time before the review counts as a timeout. |
rapid_terminal_window | duration | 2m | Positive Go duration with whole-second precision. | Window used by the review circuit breaker to detect rapid shallow attempts. |
rapid_terminal_limit | integer | 3 | Positive integer. | Maximum terminal events within rapid_terminal_window before the review circuit opens. |
missing_work_max_items | integer | 20 | Positive integer. | Maximum missing_work items recorded per rejected verdict. |
missing_work_item_max_bytes | integer | 512 | Positive integer. | Maximum byte size per missing_work item. |
reason_max_bytes | integer | 2048 | Positive integer. | Maximum byte size for the reviewer reason field. |
review_text_max_bytes | integer | 12000 | Positive integer. | Maximum byte size for reviewer free-form review text. |
next_round_guidance_max_bytes | integer | 4096 | Positive integer. | Maximum byte size for the typed next-round guidance attached to continuation runs. |
failure_policy | string | block_task | block_task, fail_task | What happens when review attempts/rounds are exhausted: block the task awaiting operator action, or terminally fail it. |
Workspace overlays may tighten or relax these values per workspace through
<workspace>/.agh/config.toml. Unknown keys still fail validation.
[task.recovery]
[task.recovery] controls who may call the task-run recovery verbs documented in
Task Runs and Leases. The setting
does not change normal token-fenced claim, heartbeat, complete, fail, or release tools.
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
allow_agent_force | boolean | true | true or false | When false, agent identities cannot force release, force fail, retry, or bulk-recover runs. |
Set allow_agent_force = false when recovery should require a non-agent operator identity. The
CLI/API/UDS surfaces then return a deterministic authorization diagnostic for agent callers and
leave the run unchanged.
[[hooks.declarations]]
Config hooks merge by name; a later overlay replaces the whole hook declaration with the same
name.
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
name | string | required | Non-empty. | Hook declaration name. |
event | string | required | Current dot-form hook event. | Event that triggers the hook. |
mode | string | async | sync or async; sync only for sync-eligible events. | Dispatch mode. |
required | boolean | false | true or false; required hooks must be sync. | Whether a hook failure blocks the source operation. |
priority | integer | Config source default 500 when omitted. | Integer. | Ordering priority. |
timeout | duration | 0s; subprocess executor uses 5 seconds when zero. | Non-negative Go duration. | Hook timeout. |
matcher | object | empty | Supported matcher fields listed below. | Narrows hook eligibility. |
command | string | empty | Required for subprocess hooks unless nested executor fields are used. | Subprocess command. |
args | string array | empty | Strings. | Subprocess arguments. |
env | string map | empty | String keys and values. | Explicit hook environment values. |
executor.kind | string | subprocess when a command is present. | subprocess or wasm for user config. native is internal only. | Executor kind. |
executor.command | string | empty | Same as command. | Nested command form. Cannot be mixed with top-level command/args/env. |
executor.args | string array | empty | Strings. | Nested args form. |
executor.env | string map | empty | String keys and values. | Nested env form. |
Supported matcher fields are agent_name, agent_type, workspace_id, workspace_root,
session_type, input_class, acp_event_type, turn_id, tool_name, tool_namespace,
tool_read_only, decision_class, message_role, message_delta_type, compaction_reason, and
compaction_strategy.
Current hook events are:
session.pre_create
session.post_create
session.pre_resume
session.post_resume
session.pre_stop
session.post_stop
input.pre_submit
prompt.post_assemble
event.pre_record
event.post_record
automation.job.pre_fire
automation.job.post_fire
automation.trigger.pre_fire
automation.trigger.post_fire
automation.run.completed
automation.run.failed
agent.pre_start
agent.spawned
agent.crashed
agent.stopped
turn.start
turn.end
message.start
message.delta
message.end
tool.pre_call
tool.post_call
tool.post_error
permission.request
permission.resolved
permission.denied
context.pre_compact
context.post_compact[network]
| Field | Type | Default | Valid values | Description |
|---|---|---|---|---|
enabled | boolean | true | true or false | Enables the embedded AGH network runtime. |
default_channel | string | default | Regex ^[a-z0-9][a-z0-9_-]{0,63}$ | Default network channel for sessions. |
port | integer | -1 | -1 or 1 through 65535 | Network listener port. -1 lets the runtime choose. |
max_payload | integer bytes | 1048576 | Positive integer no greater than 2147483647. | Maximum network payload size. |
greet_interval | integer seconds | 30 | Positive integer seconds. | Peer greeting interval. |
max_replay_age | integer seconds | 300 | Positive integer seconds. | Maximum replay window for network messages. |
max_queue_depth | integer | 100 | Positive integer. | Maximum queued network messages. |
Related Pages
- mcp.json documents JSON sidecars and whole-object replacement.
- AGENT.md documents agent-local
mcp_serversand hooks. - Providers covers
[providers.<id>.models]shape andmodels.discoverydefaults. - Provider Model Catalog explains the catalog projection, OpenAI-compatible endpoint, and extension
model.source. - File Locations lists the exact global and workspace paths.