Expand description
Configuration: precedence, then validate-at-startup.
Precedence, top wins: built-in default < config FILE < env var < CLI flag.
Everything is env-settable (12-factor). The optional
declarative file ([file] — YAML or JSON, --config/AGENTD_CONFIG)
carries only verbose structural config (MCP-server inventory, declared
subscriptions, A2A peers, limits, model/log knobs) and never secrets —
those stay env/flag only. The whole config is validated before any side
effect — a bad config exits 2 in milliseconds, not after an LLM
round-trip.
Module layout: [file] (the config document: format detection, the typed
ConfigFile shape, the JSON Schema), yaml (the hand-rolled YAML-subset
reader), paths (schema-derived path bindings: AGENTD_<PATH> env names
and --<path> flags for every config-file path), [watch] (the inotify
reload trigger).
Modules§
- directives
- Colon-fence directives in operator-authored text — the
:::type{attrs}…:::container syntax (the MyST / remark-directive / ChatGPT subset), so an instruction can CARRY the machinery it describes: - envfile
.envfiles (--env <FILE>, repeatable): a dependency-free dotenv subset.- file
- The declarative config file + its JSON Schema.
- paths
- Schema-derived path bindings: every path in the config-file schema is
also settable as an env var and as a generic
--<path>flag, with names derived mechanically from the path — so a re-defined parameter set needs no per-field plumbing here. - prompt
- Interactive entry for missing secrets (
--prompt-missing). - templates
- Subagent templates: compile the
subagents.templatessection at boot, resolving each template to its tier (flat worker vs instance-tier child) and validating everything that can be judged before params exist. - v2
- The agentd settings document — one nested document (YAML or JSON;
several files merge in order) whose every path is also
AGENTD_<PATH>/AGENT_<PATH>/<PATH>and--<path>. This module holds the typedSettings, its JSON Schema (schema::schema), the load pipeline (files → env → flags → typed → validated), the flat alias table (--instruction,--intelligence,--model,--mcp, …), theagentd --instruction Xsugar, schema detection, and the reload partition (which paths only a restart can change). - yaml
- A hand-rolled YAML subset reader for config files →
serde_json::Value.
Structs§
- A2aPeer
Spec - A declared A2A peer: a name and a client transport endpoint to reach a
remote A2A agent (or the on-node gateway that forwards into the mesh).
a2a.delegatelooks a peer up here and runs the A2A client againstendpoint, which ishttps://host[:port](loopbackhttp://for dev) orunix:/pathfor a co-located peer. No secrets live here. Serializable so it travels in the spawn payload to subagents, exactly likemcp_servers. - AAuth
Settings - AAuth agent-identity settings. Serde-serializable so it rides the spawn
payload verbatim, giving one identity per process tree. The struct is always
defined rather than feature-gated, so the payload plumbing compiles the same
either way; the CLI flags that populate it require
--features aauthat validation. - Auth
Spec - The runtime shape of a unified
auth:credential provider. Every credential input stays a{{secret:…}}template, so this struct rides the spawn payload and appears in logs without ever carrying a live credential.kindis one ofstatic/oauth2/aws/spiffe. - Config
- The fully-resolved, validated configuration.
- Diag
- A reload diagnostic.
Warnis advisory (a restart-only field merely present in the file — it works, it just pins you to restart-to-change);Erroris fatal to the reload (it differs on a live reload, or the reloadable subset is internally inconsistent).--validate-configreports both; the reload path aborts on anyError. - McpOauth
Spec - The runtime shape of an MCP server’s OAuth 2.1 client-credentials config.
Serializable so it rides the spawn payload verbatim;
client_secretstays a{{secret:…}}template and is resolved only at token-fetch time. - McpServer
Spec - A declared MCP server. Serializable because it travels in the subagent spawn payload as the child’s scoped server subset.
Enums§
- A2aEndpoint
- The client transport an
A2aPeerSpecendpoint resolves to. Parsed once (scheme-validated at startup), then the A2A client dials it.vsock:CID:PORTrequires both forms of a cid+port (no wildcard — a client dials a concrete peer, unlike the--serve-mcplisten form which may wildcard). - Config
Error - What
load()can short-circuit with.Help/Version/Capabilitiesare not errors (exit 0);Usageis a validation or parse failure (exit 2).Capabilitiescarries the pretty-printed manifest JSON — the side-effect-free admission probe (agentd --capabilities), short-circuited before run-required validation so it succeeds even with no instruction, which is what lets agentctl probe an image that has no run config yet. - Diag
Level - Mode
- Execution mode. There is one supervisor loop; the mode only chooses the predicate that decides when it is finished.
- Serve
Target - Where
--serve-mcpbinds the served self-MCP.Stdiois the implicit default (no--serve-mcp). The sole transport isHttp—https://HOST:PORT(TLS, the control plane) orhttp://LOOPBACK:PORT(plaintext, loopback-only dev/tests). - Swap
Policy - Model hot-swap policy (
--model-swap/AGENTD_MODEL_SWAP): what an in-flight run does when a reload changes themodelunder it. An endpoint repoint that leaves the model unchanged is ALWAYS finish-on-old and invisible, whatever this policy says — nothing about the turn changed. DefaultFinishOnOld. Serialized into theControlMsg::SwapIntelframe so the child applies the same policy the supervisor was configured with.
Constants§
- LOCAL_
CONFIG_ NAMES - The local rung: a machine-specific overlay that is expected to be git-ignored, so a checkout can be pointed at a dev endpoint without the change ever being committable by accident.
- PROJECT_
CONFIG_ NAMES - The project rung, in the working directory. The dotted spellings are the original discovery names and stay valid: they shipped, and silently ignoring one would break the setups that adopted it.
- RESTART_
ONLY_ FIELDS - The names of the restart-only fields. A live reload whose new-vs-running
diff touches ANY of these is rejected with
reason="restart_required"; whether that becomes a pod restart is agentctl’s policy. They also drive the “restart-only field set in the file” warning. - USER_
CONFIG_ NAMES - One rung of the discovery chain: the spellings that name the SAME logical
file. Two spellings because
.ymland.yamlare both idiomatic and guessing wrong should not mean silence — a config file the tool ignores is the worst outcome of the three.
Functions§
- discovered_
chain - The whole discovery chain, LOWEST precedence first: the user rung, then the project rung, then the local overlay. Every rung that has a file contributes one, and they merge in that order — so a user default is overridden by the project’s config and that by a machine-local overlay, with flags and environment still on top of all three.
- is_
mcp_ endpoint - Does
sname a remote MCP endpoint? True for the Streamable HTTP schemes agentd dials. - mcp_
endpoint_ scheme_ ok - Whether an MCP-server endpoint scheme is admissible:
https://, or a loopbackhttp://for dev. Socket schemes (unix:,vsock:) and non-loopback plaintext are rejected. This gate runs BEFORE the reusable crate’sMcpEndpoint::parse, which is more permissive, so that a config-file server — which never goes throughis_mcp_endpointor CLI parsing — is held to the same HTTPS-only rule as a flag. - parse_
duration - Parse
600s,5m,2h,30d,2w,500ms, or a bare integer (seconds). Days and weeks exist because retention, dunning, and cadence windows are naturally written in them —30dreads,720hgets checked with a calculator. - present_
in - Which of
namesexist indir, in order. - user_
config_ dir - The user rung’s directory:
$XDG_CONFIG_HOME/agentd, else~/.config/agentd.Nonewhen neither variable is set — a daemon with no HOME (a scratch container, a systemd unit without one) simply has no user rung rather than resolving a path relative to nothing.