Reference

Config schema — ~/.agentproto/config.json

The CLI's global config file. Location: $AGENTPROTO_HOME/config.json (defaults to ~/.agentproto/config.json). Created lazily — absent until first agentproto config set or agentproto adapters install.

Read/write via agentproto config:

agentproto config show
agentproto config get adapters
agentproto config set daemon.port 18791

Full shape

{
  // Runtime adapters loaded by `agentproto run-swarm`. Each entry is an
  // npm package id resolvable from the cli's install location OR the
  // user's cwd. Loaded in array order; last write wins on duplicate
  // adapter kinds.
  "adapters": [
    "@guilde/agentproto-bridge",
    "@acme/agentproto-slack"
  ],

  // Slug → package-name aliases for `agentproto install
  // runtime-profile/<slug>`. Without an alias, the verb defaults to
  // `@agentproto/runtime-profile-<slug>`.
  "profileAliases": {
    "guilde": "@guilde/runtime-profile-guilde"
  },

  // npm packages the `corpus` CLI scans for AIP-10 starter presets.
  // Each must declare `package.json#agentproto-corpus-preset` matching
  // the agentproto/corpus-preset/v1 schema. Defaults to just
  // ["@agentproto/corpus-presets"] when omitted.
  "corpusPresetPackages": [
    "@agentproto/corpus-presets",
    "@vendor/corpus-presets"
  ],

  // Daemon-mode options. Read by `agentproto daemon` and
  // `agentproto serve` when launched without explicit flags.
  "daemon": {
    "port": 18791,
    "bind": "127.0.0.1",
    "allowedOrigins": [
      "https://guilde.work"
    ],
    "turnStallAfterMs": 300000
  },

  // End-to-end pairing over an untrusted rendezvous broker. Read by
  // `agentproto serve` / `pair offer`. See concepts/pairing.md.
  "pairing": {
    // Rendezvous broker WS URL used by `pair offer` and by autoconnect on
    // boot. Mirrors tunnel.host. Three states:
    //   - absent  → offers fall back to the hosted default,
    //               wss://rdv.agentproto.sh/v1 (the broker relays only
    //               ciphertext — see concepts/pairing.md).
    //   - a URL   → route through that broker (self-hosted or otherwise).
    //   - ""      → explicit opt-out: no default, `pair offer` requires
    //               an explicit --rendezvous.
    "rendezvous": "wss://rendezvous.example/v1",
    // Whether the daemon opens standing rendezvous connections for every
    // persisted pairing on boot (so a paired client can reconnect anytime).
    // Mirrors tunnel.autoconnect. Default true when a rendezvous is set.
    "autoconnect": true,
    // Web pair page for `pair offer --qr` (the offer rides in its URL
    // fragment). A template with {fp} in the HOSTNAME (the daemon
    // fingerprint) for one browser origin per daemon, or a plain http(s) URL
    // (one shared origin). Absent → https://{fp}.agentproto.cloud/pair.
    // `--pair-page` overrides it.
    // See concepts/pairing.md ("The phone pair page").
    "pairPage": "https://{fp}.pair.example.com/pair"
  },

  // Global and per-adapter defaults auto-applied to every `agent_start`
  // spawn (CLI, MCP, or HTTP). See "defaults" below.
  "defaults": {
    "skills": ["review-checklist"],
    "options": { "verbose": true },
    "adapters": {
      "hermes": {
        "skills": ["hermes-only-skill"],
        "options": { "model": "z-ai/glm-5.2" },
        "auth": { "mode": "api-key" }
      }
    },
    "defaultRoleDepthCutoff": 1,
    "maxGrantableDelegation": 2,
    "langfuseTracing": false,
    "traceRedactor": "secrets"
  },

  // Generic ACP agents — any CLI that speaks the Agent Client Protocol,
  // connectable with zero adapter code. Keyed by adapter slug; shadows a
  // curated ACP_CATALOG entry of the same slug. Managed via
  // `agentproto acp add|ls|rm`. See "acpAgents" below.
  "acpAgents": {
    "my-agent": {
      "bin": "my-agent",
      "bin_args": ["acp"],
      "resumable": true,
      "install_hint": "npm i -g my-agent"
    }
  },

  // Where `agentproto worktree new` creates worktrees + whether the daemon
  // isolates spawned agents into one. See "worktrees" below.
  "worktrees": {
    "root": "~/.agentproto/worktrees",
    "isolation": "on-request",
    "provisionConcurrency": 2,
    "provisionConcurrencyByRepo": { "~/code/big-monorepo": 1 },
    "provisionLoadFactor": 0
  },

  // Spawn-time policy for `agent_start` (dedupe, attach). See "spawn" below.
  "spawn": {
    "dedupe": "always",
    "attach": "always"
  },

  // Provenance policy — the opt-in `gh` PATH shim. See "provenance" below.
  "provenance": {
    "wrapGh": false
  },

  // Named terminal/TUI launch presets for `agentproto sessions terminal
  // --preset <name>`. See "terminalPresets" below.
  "terminalPresets": {
    "terra": { "argv": ["bash", "-l"], "env": { "TERM": "xterm-256color" } }
  },

  // Session-presence + transcript-storage policy. See "sessions" below.
  "sessions": {
    "attentionDelaySec": 60,
    "eventsDir": "~/.agentproto/sessions"
  },

  // Feature toggles. See "features" below.
  "features": {
    "pty": true,
    "llmEndpoint": false
  },

  // Model-role overrides — which model each built-in job uses.
  // Each key is a dotted role name; the value is a model id string or
  // { model, route?, profile? }. See "models" below.
  "models": {
    "review.small": "claude-sonnet-5-5",
    "review.large": "claude-opus-5-5",
    "review.pr": "openrouter/z-ai/glm-5.3-flash",
    "judge.session": "claude-sonnet-5-5"
  },

  // Jev (TypeSafe System One) judge configuration for the session steward.
  // See "jev" below.
  "jev": {
    "apiKey": "...",
    "model": "jev-latest",
    "baseUrl": "https://api.typesafe.ai/v1/systemone"
  }
}

Keys

adapters: string[]

npm packages with an agentproto/adapter/v1 manifest. The CLI walks this list at every run-swarm invocation, reads each adapter's manifest, dynamic-imports declared adapter factories, and registers them.

Managed via agentproto adapters — the verb renamed from plugins in 0.20.0. Direct edit is fine — the verb is convenience.

profileAliases: Record<string, string>

Maps a runtime-profile slug to an npm package name. Lets you install third-party profiles without typing the full package name:

# Without alias:
agentproto install runtime-profile/guilde \
  --package @guilde/runtime-profile-guilde

# With alias above:
agentproto install runtime-profile/guilde

The default resolver (@agentproto/runtime-profile-<slug>) still applies when no alias matches.

corpusPresetPackages: string[]

Only consumed by the corpus binary (@agentproto/corpus-cli). Each listed package must declare package.json#agentproto-corpus-preset listing its starter presets. corpus init <slug> resolves against the merged set. corpus init --list enumerates everything visible.

daemon: object

Defaults for agentproto daemon and agentproto serve:

FieldTypeMeaning
portnumberListen port (default 18790).
bindstringBind address (default 127.0.0.1 — loopback-only).
allowedOriginsstring[]CORS allow-list for browser callers of the daemon API.
authTokenstringStable bearer token for /mcp, /events, /conversations*, and the heartbeat tick route — survives restarts, unlike the per-boot runtime.json token. Overridden inline by agentproto serve --auth-token <token>. Loopback callers with no X-Forwarded-For header are still exempt. Unset ⇒ those routes stay open.
turnStallAfterMsnumberTurn-liveness watchdog threshold in ms. When a busy agent-cli session has had no adapter activity for longer than this, the daemon stamps stalledSinceMs on the descriptor and emits session:stalled. If the turn has produced no output or usage at all since its prompt (a provider silently retrying, e.g. a swallowed 429), the descriptor also gets lastTurnErrorMessage: "no output since prompt — provider retrying?". Detection-only — never auto-kills. Default on at 5 minutes (300000). Set to 0 or a negative value to disable. Env override: AGENTPROTO_TURN_STALL_AFTER_MS.

Verb flags override config; config overrides hard-coded defaults.

defaults: object

Global and per-adapter defaults auto-applied to every agent_start spawn (CLI sessions start/run, MCP start_agent_session, or the HTTP API) — introduced in 0.5.0.

FieldTypeMeaning
skillsstring[]Global skills folded into every spawn's options.skills.
optionsRecord<string, boolean|number|string>Global options merged into every spawn.
adaptersRecord<string, { skills?, options?, auth? }>Per-adapter overrides, keyed by adapter slug (e.g. "hermes").
auth (per-adapter){ mode?: "subscription" | "api-key", token?: string, apiKey?: string, provider?: string }Per-adapter billing-auth defaults merged at spawn time.
defaultRoleDepthCutoffnumberSpawn depth at/above which a session defaults to executor instead of supervisor (default 1).
maxGrantableDelegationnumberTrust-boundary cap on how much delegation a supervisor can grant a child.
langfuseTracingbooleanOpt in to per-session Langfuse tracing by default.
traceRedactorstringRedactor slug (e.g. "secrets") applied to traced session content.
agentPromptInterruptbooleanDefault interrupt behaviour for agent_prompt / message_parent calls that omit the interrupt field. false (the default) queues the prompt behind any in-flight turn. true cancels the in-flight turn and redirects the session onto the new prompt immediately. An explicit interrupt: true|false on a single call always overrides this default. For message_parent this only requests an interrupt — whether it may cut the parent's turn is messaging.agentInterrupt.
contextContinuity{ mode?, warnAtPct?, compactAtPct?, continueFreshAtPct?, hardStopAtPct?, handoffAtQuotaRemaining? }Context-window policy (handoff guide). handoffAtQuotaRemaining (number ≥ 0, unset = off) emits a session:handoff-suggested event, once per quota window, when the session's Anthropic auth profile reports that many requests or fewer remaining. A raw remaining count (no limit is available to make a percentage); only sessions with an access profile are watched. It only suggests — it never switches harness.
messaging{ allowSiblings?: boolean, agentInterrupt?: "allow" | "deny", pendingPromptStaleMinutes?: number }Inter-session messaging policy (sessions → Messages between sessions). allowSiblings (default false) lets message_send / message_reply reach a sibling session. agentInterrupt (default "deny") decides whether a session sender's urgency: "interrupt" may cancel the recipient's turn; when denied it's delivered as steer and the result reports it. Human (HTTP/CLI) senders always keep interrupt. pendingPromptStaleMinutes (default 5) is how long a prompt may sit queued behind a mid-turn session before it is flagged stale in session_list / session_recap (pendingPrompts) and its sender is told via a notice message.

Merge precedence (low → high): defaults.options < defaults.adapters.<slug>.options < the explicit options passed at spawn time. For skills, an explicit skills array at spawn time replaces the union of defaults.skills and defaults.adapters.<slug>.skills rather than merging with it. Adapters with no declared skills option treat the resolved skills list as a no-op.

acpAgents: Record<string, object>

Generic ACP agents — any CLI that already speaks the Agent Client Protocol, connectable with zero adapter code. Keyed by adapter slug; each value is a spawn recipe. A config entry shadows a curated ACP_CATALOG entry of the same slug, and both lose to a real @agentproto/adapter-<slug> npm package (resolution order: npm → config → catalog). Managed via agentproto acp; direct edit is fine.

FieldTypeMeaning
binstring (required)Executable to spawn (e.g. "gemini").
bin_argsstring[]Extra argv, e.g. ["--experimental-acp"].
namestringDisplay name. Default: the slug.
descriptionstringOne-line summary shown in acp ls.
envRecord<string, string>Always-on environment variables for the spawn.
resumablebooleanAdvertise resumable + native-resume continuation.
models{ default?, allowed? }Known model ids (informational hint).
install_hintstringShown by acp ls when the bin is missing from PATH.

A malformed entry (no string bin) is dropped on load with a warning rather than failing the whole config. See concepts/adapters.md.

worktrees: object

Where agentproto worktree new provisions new git worktrees, and the daemon's policy for isolating spawned agent sessions into one.

FieldTypeMeaning
rootstringAbsolute path new worktrees are created under (layout <root>/<repoName>/<slug>). Resolution order: --root flag > AGENTPROTO_WORKTREES_ROOT env > this field > the hardcoded default ~/.agentproto/worktrees.
isolation"always" | "on-request" | "never"Policy for agent_start's worktree field. on-request (default) isolates only when a spawn passes worktree; always isolates every root spawn whose cwd is inside a git repo (a spawn made through an orchestrator inherits its parent's tree; a cwd outside any repo spawns plain); never turns it off and rejects an explicit worktree rather than silently ignoring it. Resolution order: AGENTPROTO_WORKTREES_ISOLATION env > this field > the default on-request. The worktree is not auto-removed on session exit — reclaim it with agentproto worktree rm|archive|gc.
provisionConcurrencyinteger >= 0Daemon-wide cap on concurrently running heavy provisioning phases (depsCmd, cloneGlobs/copyGlobs, worktree.setup hooks). Excess agent_start({worktree}) spawns wait in a FIFO queue (fair across callers) and show provisioning: { state: "queued", position }. 0 disables the cap. Default 2. Resolution order: AGENTPROTO_WORKTREES_PROVISION_CONCURRENCY env > this field > the default. Hot-applied: a change takes effect on the next provisioning without a daemon restart. git worktree add and the other cheap steps are never queued.
provisionConcurrencyByRepoobjectExtra per-repo cap, { "<repo path or directory name>": cap } (~/ expands; a bare name matches the repo's directory name). Applies in addition to provisionConcurrency, never looser than it. Invalid entries are ignored.
provisionLoadFactornumberOptional load guard. When > 0, a queued provisioning is not admitted while the 1-minute load average exceeds cores x provisionLoadFactor, unless nothing is running (an idle scheduler always admits one, so a permanently loaded host cannot deadlock). Default 0 (off).

spawn: object

Daemon-side policy for agent_start spawns.

FieldTypeMeaning
attach"always" | "on-request"Whether a spawn auto-attaches to its caller as parent lineage. "always" (default) nests a child under the spawning session whenever the identity is derivable; "on-request" disables auto-attribution unless the caller opts in. Resolution order: AGENTPROTO_SPAWN_ATTACH env > this field > "always". A per-call attach: false opts out.
dedupe"always" | "on-request"Implicit idempotency-key policy. "always" (default) derives a key from the spawn's label + a hash of the initial prompt when no explicit idempotencyKey is given; "on-request" disables implicit derivation. Resolution order: AGENTPROTO_SPAWN_DEDUPE env > this field > "always". A per-call dedupe: false opts out.

provenance: object

Daemon-side provenance policy — the opt-in gh PATH shim.

FieldTypeMeaning
wrapGhbooleanWhen true, every agent session the daemon spawns gets a shim directory prepended to its PATH so any gh pr create it — or an adapter subprocess shelling out (claude-code, codex, …) — runs has a deterministic 🤖 @agentproto-bot provenance footer (session id, adapter, model, workspace) appended to the created PR's body, matching the footer the cloud runner stamps. The tool stamps, never the model; commit messages are never touched. Stamping is cosmetic — a failure never fails the underlying gh. Resolution order: AGENTPROTO_PROVENANCE_WRAP_GH env > this field > default false (off).

terminalPresets: Record<string, object>

User-defined named terminal/TUI launch recipes for agentproto sessions terminal --preset <name> — local-only, never packaged in shared adapter manifests or defaults.

FieldTypeMeaning
argvstring[]Command + args to spawn. When provided, sessions terminal can be used without -- <argv...>.
envRecord<string, string>Extra environment variables layered on top of the daemon's inherited process.env.
cwdstringWorking directory for the PTY session. Relative paths resolve against the CLI's cwd.
workspacestringWorkspace slug used for cwd fallback when cwd is omitted.
namestringStable session name passed to the registry.
labelstringHuman-readable label surfaced in session listings.

sessions: object

Session-presence and transcript-storage policy.

FieldTypeMeaning
attentionDelaySecnumberHow long (seconds) a session stays shown as running after its last turn ends before the dashboard settles it into attention/quiet. Absent ⇒ 60. Env override: AGENTPROTO_SESSIONS_ATTENTION_DELAY_SEC.
eventsDirstringRoot directory the daemon stores per-session transcripts under: each session's events.jsonl (and a terminal session's terminal.jsonl) lives at <eventsDir>/<sessionId>/events.jsonl. Every writer and reader (the transcript writer, GET /sessions/:id/events, sessions export, tool-call/usage logs) resolves through this single key. Relative paths resolve against the home directory. Absent ⇒ the hardcoded default ~/.agentproto/sessions — zero behaviour change out of the box. Takes effect on daemon restart; existing transcripts are not moved. Spawn responses (agent_start descriptor) carry the resolved absolute path of the current session's events.jsonl as descriptor.eventsPath.

features: object

Daemon feature toggles. All fields are optional; defaults are conservative (off / informational) so upgrades don't change behaviour.

FieldTypeMeaning
ptybooleanInformational hint that PTY support is desired. The daemon still detects node-pty's presence at runtime.
llmEndpointbooleanEnable the local @agentproto/llm-endpoint proxy sidecar. When true, the daemon registers the llm-endpoint route and exposes the llm_endpoint_* MCP tools. Default false — opt-in because the sidecar spawns a child process and binds an extra port.

models: Record<string, string | object>

Model-role overrides — which model each built-in automated job uses. Each key is a dotted role name; the value is either a bare model id string or { model: string, route?: string, profile?: string }.

Precedence (highest to lowest): explicit run input → the repo's agentproto.json models → this daemon config → built-in default. Read the resolved table and its sources with config_get models or the read-only model_roles MCP tool.

Built-in roles and their defaults:

RoleDefaultDescription
review.smallclaude-sonnet-5-5Reviewer for a small residual (repo-maintenance review step).
review.largeclaude-opus-5-5Reviewer for a large residual and the retry reviewer.
review.propenrouter/z-ai/glm-5.3-flashCI pull-request reviewer.
judge.sessionclaude-sonnet-5-5Session-steward agent judge.

Override a role:

agentproto config set models.review.small claude-haiku-5
agentproto config set models.judge.session claude-opus-5-5

An id unknown to the model catalog is warned about at set time but accepted. A AGENT.md step may reference a role with model: role:<name>, resolved before adapter selection.

jev: object

Configuration for the Jev (TypeSafe System One) judge backend used by the session steward. All fields are optional.

FieldTypeMeaning
apiKeystringJev judge API key. Read before the JEV_API_KEY env var, so the key can live in agentproto's own config rather than a workspace env file. Not writable via config_set; hand-edit ~/.agentproto/config.json (mode 0600 recommended for this field).
modelstringJev model id. Default "jev-latest". Writable via config_set jev.model <id>.
baseUrlstringJev endpoint override. Default https://api.typesafe.ai/v1/systemone. Writable via config_set jev.baseUrl <url>.

tunnel: object

Outbound tunnel defaults read by agentproto serve (and the managed agentproto daemon) when --connect is not passed explicitly.

FieldTypeMeaning
hoststringWebSocket URL of the tunnel host. When set with autoconnect: true, the daemon connects on boot.
tokenstringBearer token used before falling back to credentials.json. Required for e2e: true.
autoconnectbooleanConnect the tunnel automatically on daemon start.
e2ebooleanOpt into end-to-end encryption of the tunnel. Requires token.

profiles: Record<string, object> and activeProfile: string

Named connection bundles. profiles.<name> shallow-overrides the top-level daemon/tunnel/features blocks when selected; activeProfile selects a profile by default when --profile is not passed. Missing fields fall through to the top-level config, so a profile typically only declares tunnel.host + tunnel.token.

{
  "activeProfile": "prod",
  "profiles": {
    "prod": {
      "tunnel": { "host": "wss://tunnel.example/connect", "token": "apt_…" },
      "daemon": { "port": 18791 }
    }
  }
}

Explicit --profile <name> is fatal if the profile does not exist; activeProfile pointing at a missing profile only warns and falls back to the top-level config.

Permissions

Mode 0600 is NOT enforced for config.json — unlike credentials.json, this file doesn't carry secrets. Plugin names, ports, and alias maps are not sensitive.

Versioning

The config file is unversioned today. New keys may appear in any minor release of the CLI; unknown keys are tolerated and preserved across reads/writes. Removed keys are still readable but are no-ops. See ../../../VERSIONING.md for the broader policy.