← Schema index / Config Reference
nodes schema (1-150)
Canonical generated docsThis section is generated from
caco config schema --json. The table below preserves the runtime field path, type, required/default markers, and canonical description for every value in this slice.Node definitions — machines in the cluster.
| Field path | Type | Required | Default | Canonical description |
|---|---|---|---|---|
nodes | section | required | Node definitions — machines in the cluster. | |
└ nodes.name | string | required | Unique node identifier. | |
└ nodes.short_name | string | optional | Optional short display name for space-constrained TUI elements. | |
└ nodes.host | string | required | Hostname or IP address. | |
└ nodes.public_host | string | optional | host | Externally advertised cluster host for public/dynamic callers when it differs from private host. |
└ nodes.ssh | map | optional | SSH connection config. | |
└ nodes.ssh.mode | string | optional | openssh | SSH transport mode: openssh/default or tailscale. |
└ nodes.ssh.username | string | optional | SSH username. | |
└ nodes.ssh.port | u16 | optional | SSH port (OpenSSH mode). | |
└ nodes.ssh.key | string | map | optional | SSH key path (string or { path: ... }) for OpenSSH mode. | |
└ nodes.github_ssh_routing | string | optional | auto | GitHub SSH routing for daemon-managed git on this node: auto (respect configured host/port), ssh_over_443, or default_port. |
└ nodes.scp | map | optional | SCP configuration. | |
└ nodes.scp.legacy | bool | optional | false | Pass -O for legacy SCP protocol mode. |
└ nodes.distribute_command | map | optional | Per-node config distribution command override. | |
└ nodes.distribute_command.fetch | string | optional | Shell command to fetch current remote config to stdout. | |
└ nodes.distribute_command.write | string | required | Shell command to write config content from stdin. | |
└ nodes.distribute_command.restart | string | optional | Shell command to restart the daemon. | |
└ nodes.config_strategy | map | optional | Operator-managed config strategy. | |
└ nodes.config_strategy.kind | string | required | Strategy kind: 'aca_share' or 'kubernetes_configmap'. | |
└ nodes.config_strategy.artifact_id | string | required | Identifies the underlying deployment artifact. Nodes sharing the same artifact must use the same artifact_id. | |
└ nodes.config_strategy.aca | map | optional | ACA-specific config (required when kind is aca_share). | |
└ nodes.config_strategy.aca.resource_group | string | required | Azure resource group. | |
└ nodes.config_strategy.aca.storage_account | string | required | Azure Storage account. | |
└ nodes.config_strategy.aca.share_name | string | required | Azure Files share name. | |
└ nodes.config_strategy.aca.path | string | required | Path within the share for the config file. | |
└ nodes.config_strategy.aca.app_name_template | string | optional | Template for ACA app names (supports {node} placeholder). | |
└ nodes.config_strategy.kubernetes | map | optional | Kubernetes-specific config (required when kind is kubernetes_configmap). | |
└ nodes.config_strategy.kubernetes.namespace | string | required | Kubernetes namespace. | |
└ nodes.config_strategy.kubernetes.configmap | string | required | ConfigMap name. | |
└ nodes.config_strategy.kubernetes.key | string | required | Key within the ConfigMap. | |
└ nodes.config_strategy.kubernetes.workload_kind | string | optional | Workload kind to restart (e.g. statefulset, deployment). | |
└ nodes.config_strategy.kubernetes.workload_name | string | optional | Workload name to restart. | |
└ nodes.tls | map | optional | TLS cert/key paths for mTLS. | |
└ nodes.tls.cert | string | required | TLS certificate path. | |
└ nodes.tls.key | string | required | TLS private key path. | |
└ nodes.relay_eligible | bool | optional | false | Whether this static node is eligible to serve as a relay peer for relay-mode dynamic nodes. |
└ nodes.role | string | optional | worker | Capability role: worker or daemon_only. |
└ nodes.concurrency | map | optional | Agent spawn concurrency ceilings for this node. | |
└ nodes.concurrency.global | map | optional | Global ceiling across all profiles. | |
└ nodes.concurrency.global.max_parallel | u32 | required | Maximum live non-terminal agents. | |
└ nodes.concurrency.profile | map[string, map] | optional | Per-profile ceilings keyed by profile name. | |
└ nodes.concurrency.profile.max_parallel | u32 | required | Maximum live non-terminal agents for this profile. | |
└ nodes.tests | map | optional | Queued test ceilings for this node. | |
└ nodes.tests.max_parallel | u32 | optional | 1 | Maximum concurrent test jobs. |
└ nodes.builds | map | optional | Queued build ceilings and managed-worker validation policy for this node. | |
└ nodes.builds.max_parallel | u32 | optional | 1 | Maximum concurrent build jobs. |
└ nodes.builds.node_heavy_max_parallel | u32 | optional | 2 | Shared per-node ceiling on concurrent heavy (cargo/nix) builds across the test AND build queues, incl. queued release/darwin self-builds. Env CACO_NODE_HEAVY_MAX_PARALLEL overrides; 0 disables. |
└ nodes.builds.node_heavy_min_available_memory_mb | u32 | optional | 0 | Host available-memory floor (MiB) below which new heavy ops are refused admission even if a count slot is free (memory-aware admission; covers cross-project load via MemAvailable). Env CACO_NODE_HEAVY_MIN_AVAILABLE_MB overrides; 0 (default) disables -- opt-in, since no fixed MiB default is fleet-safe. Recommended per-node: ~2-3G cargo-only nodes, ~4-6G darwin/swift nodes like ms-mac. |
└ nodes.builds.node_heavy_min_available_memory_pct | u32 | optional | 0 | Host available-memory floor as a PERCENT of total RAM (0-100); when >0 the floor is max(2048 MiB, pct% total RAM), composing with the fixed *_mb floor (larger wins) -- auto-scaling so one setting is safe across small+big nodes. Env CACO_NODE_HEAVY_MIN_AVAILABLE_PCT overrides; 0 (default) disables (opt-in; ~15 a reasonable auto-enable value). |
└ nodes.builds.source_only_workers | bool | optional | false | Refuse compiler/build work from managed-agent direct shells and daemon queues on this node; node/operator calls remain available. |
└ nodes.builds.source_only_exceptions | list[map] | optional | Exact expiring managed-agent exceptions to source-only mode. | |
└ nodes.builds.source_only_exceptions.agent | string | required | Exact agent ID or stable persistent name. | |
└ nodes.builds.source_only_exceptions.command_classes | list[string] | required | Allowed classes: cargo, rustc, nix, caco_test, caco_build, just, make, gradle, emulator, test_runner, platform_build. | |
└ nodes.builds.source_only_exceptions.expires_at | RFC3339 timestamp | required | Exception expiry. | |
└ nodes.builds.source_only_exceptions.max_timeout_secs | u64 | required | Maximum required timeout wrapper in seconds. | |
└ nodes.builds.source_only_exceptions.reason | string | required | Non-empty operator/controller audit reason. | |
└ nodes.agents | map | optional | Node-scoped declarative persistent agents. | |
└ nodes.agents.persistent.<name> | map | optional | Persistent agent declaration keyed by stable name. | |
└ nodes.agents.persistent.<name>.name | string | optional | Stable human-readable agent name (alphanumeric + hyphens, max 32 chars). | |
└ nodes.agents.persistent.<name>.profile | string | list[string] | required | Profile name or ordered list for composite composition. | |
└ nodes.agents.persistent.<name>.preset | string | optional | Preset ID to launch with. | |
└ nodes.agents.persistent.<name>.ahp_host | string | optional | For `ahp` agents: the AHP host (agents.ahp_hosts) the session lives on; optional when the node has exactly one. | |
└ nodes.agents.persistent.<name>.type | string | optional | Explicit agent type when not implied by preset. | |
└ nodes.agents.persistent.<name>.environment | map[string, string] | optional | Non-secret declaration overrides applied after project, preset, and profile env. | |
└ nodes.agents.persistent.<name>.auto_start | bool | optional | true | Whether daemon auto-converges toward a live instance. |
└ nodes.agents.persistent.<name>.restart | string | optional | failure | Restart policy: 'failure' (default), 'always', or 'never'. |
└ nodes.agents.persistent.<name>.restart_backoff_secs | u32 | optional | 30 | Minimum backoff between failed restart attempts. |
└ nodes.agents.persistent.<name>.nodes | list[string] | optional | Node allowlist (project-scoped only). Omit for all nodes. | |
└ nodes.agents.persistent.<name>.cadence | map | optional | Controller idle polling timers. | |
└ nodes.agents.persistent.<name>.cadence.reconcile_interval_secs | u64 | optional | 120 | Idle reconciliation cadence. |
└ nodes.agents.persistent.<name>.cadence.inbox_poll_interval_secs | u64 | optional | 120 | Inbox poll cadence. |
└ nodes.agents.persistent.<name>.cadence.jitter_secs | u64 | optional | 30 | Max random jitter to prevent thundering herd. |
└ nodes.agents.persistent.<name>.cadence.claimed_heartbeat_interval_secs | u64 | optional | 1800 | Claimed-bead heartbeat cadence (PostToolUse hook reminds agents of active claims + goal; 0 disables).. |
└ nodes.agents.persistent.<name>.wait | map | optional | Controller wait mode configuration. | |
└ nodes.agents.persistent.<name>.wait.inbox_delay_secs | u64 | optional | 60 | Minimum delay before inbox wait reads state. |
└ nodes.agents.persistent.<name>.wait.choice_timeout_secs | u64 | optional | Timeout for choice wait mode (null = indefinite). | |
└ nodes.agents.persistent.<name>.model | string | optional | Model to use for this persistent agent (e.g. 'opus', 'sonnet'). Passed as --model. | |
└ nodes.agents.persistent.<name>.provider | string | optional | Provider to use for this persistent agent (e.g. 'openai', 'anthropic', 'google'). | |
└ nodes.agents.persistent.<name>.mcp_policy | string | optional | profile | Final declaration-scoped MCP policy: profile (default) or disabled. |
└ nodes.agents.persistent.<name>.short_name_strategy | map | optional | Strategy for generating a short human-friendly display name at agent creation time. | |
└ nodes.agents.persistent.<name>.short_name_strategy.strategy | string | required | Short-name strategy: adj_noun, template or llm. | |
└ nodes.agents.persistent.<name>.short_name_strategy.template | string | optional | Bounded display template for strategy = template. Placeholders: {adj}, {noun}, {profile}, {bead}, {node}, {n}. Names remain aliases, not identities. | |
└ nodes.agents.persistent.<name>.short_name_strategy.llm | string | optional | Top-level llm alias used when strategy = llm. | |
└ nodes.agents.persistent.<name>.checkout_type | string | optional | worktree | How the agent's working checkout is materialized: worktree (default; a git worktree sharing the canonical.git, fastest startup), clone (a shared clone), full (a 1st-party clone of the real remote), read_only_symlink (observers), or pr_branch (a full-clone whose working branch is an existing GitHub PR head; requires github_integration.enabled,). made worktree the default. |
└ nodes.agents.persistent.<name>.confirm_before_spawn | bool | optional | false | Require operator approval through caco choices before spawning this persistent agent. |
└ nodes.agents.persistent.<name>.confirm_before_spawn_timeout_secs | u64 | optional | 300 | Timeout in seconds for the operator confirmation prompt. |
└ nodes.agents.persistent.<name>.confirm_before_spawn_auto_approve | bool | optional | false | Auto-approve the spawn when the confirmation timeout expires. |
└ nodes.agents.persistent.<name>.all_projects | bool | optional | false | Allow this persistent agent to access all configured projects instead of only its bound project. |
└ nodes.agents.persistent.<name>.goal | string | optional | Default goal/task description for managed launches via this declaration; used when --goal is not passed. | |
└ nodes.agents.persistent.<name>.schedule | map | optional | Schedule configuration for periodic persistent agent launches. | |
└ nodes.agents.persistent.<name>.schedule.cron | string | required | Standard 5-field cron expression. | |
└ nodes.agents.persistent.<name>.schedule.launch_mode | string | optional | restart-or-recreate | Launch mode: recreate, restart, or restart-or-recreate. |
└ nodes.agents.persistent.<name>.pane_error_detection | bool | optional | false | Enable tmux pane content scanning for fatal error detection. Overrides agent_defaults. Default false. |
└ nodes.agents.persistent.<name>.project | string | optional | Explicit project binding for node-scoped persistent agents. When set, this project is used for checkout, bead visibility, and profile resolution instead of the first configured project. | |
└ nodes.agents.persistent.<name>.depends_on_node | string | optional | Cross-node reachability dependency: defer launch until the named remote node is reachable per PeerReachabilityMap. When omitted, no gate is applied. | |
└ nodes.agents.persistent.<name>.friend_projects | list[friend_project] | optional | Per-declaration friend project overlay; entries can narrow or disable inherited friends. | |
└ nodes.agents.persistent.<name>.friend_projects.project | string | required | Target project name. | |
└ nodes.agents.persistent.<name>.friend_projects.branch | string | optional | Target branch; omitted means the friend project's default_branch. Mutually exclusive with revision. | |
└ nodes.agents.persistent.<name>.friend_projects.revision | string | optional | Pinned git revision. Mutually exclusive with branch. | |
└ nodes.agents.persistent.<name>.friend_projects.permissions | list[string] | optional | [checkout_read] | Granted operations: checkout_read, checkout_write, beads_read, beads_create, beads_update, beads_claim, beads_close, beads_dispatch. |
└ nodes.agents.persistent.<name>.friend_projects.materialize | bool | optional | false | Materialize a real friend checkout cloned from the friend project's remote; omitted means a virtual friend with no checkout. |
└ nodes.agents.persistent.<name>.friend_projects.enabled | bool | optional | true | Set false in a narrower layer to disable an inherited friend. |
└ nodes.agents.heartbeat | map | optional | Node-local managed-agent heartbeat defaults and per-agent overrides. | |
└ nodes.agents.heartbeat.enabled | bool | optional | false | Enable local daemon-owned managed-agent heartbeat delivery for this scope. Defaults to false for safe rollout. |
└ nodes.agents.heartbeat.selector | string | optional | persistent | Agent selector for this scope: all, persistent, workers, or none. |
└ nodes.agents.heartbeat.interval_secs | u64 | optional | 300 | Base heartbeat cadence in seconds. |
└ nodes.agents.heartbeat.jitter_secs | u64 | optional | 0 | Optional jitter in seconds; must not exceed interval_secs. |
└ nodes.agents.heartbeat.max_backoff_secs | u64 | optional | 300 | Optional delivery-failure backoff ceiling in seconds; must be at least interval_secs. |
└ nodes.agents.heartbeat.allow_runtime_opt_out | bool | optional | true | Allow runtime/profile code to decline heartbeats even when config enables them. |
└ nodes.agents.heartbeat.conditions | list[string] | optional | Optional OR timer gates: claimed_beads (owned unfinished claims), unmerged_prs (linked open PRs), pending_inbox (visible unread messages). Inherits when omitted; [] is unconditional. Runtime on never bypasses conditions. | |
└ nodes.agents.heartbeat.overrides | map[string, map] | optional | Per-agent overrides keyed by persistent declaration name, composed profile, or concrete agent id. | |
└ nodes.agents.heartbeat.overrides.<agent> | map | optional | One per-agent heartbeat override; inherits unspecified fields from the surrounding scope. | |
└ nodes.agents.heartbeat.overrides.<agent>.enabled | bool | optional | Enable or disable heartbeat for this agent. | |
└ nodes.agents.heartbeat.overrides.<agent>.selector | string | optional | Optional selector override: all, persistent, workers, or none. | |
└ nodes.agents.heartbeat.overrides.<agent>.interval_secs | u64 | optional | Override base heartbeat cadence in seconds. | |
└ nodes.agents.heartbeat.overrides.<agent>.jitter_secs | u64 | optional | Override jitter in seconds; must not exceed interval_secs when both are set. | |
└ nodes.agents.heartbeat.overrides.<agent>.max_backoff_secs | u64 | optional | Override delivery-failure backoff ceiling in seconds. | |
└ nodes.agents.heartbeat.overrides.<agent>.allow_runtime_opt_out | bool | optional | Override runtime opt-out permission for this agent. | |
└ nodes.agents.heartbeat.overrides.<agent>.conditions | list[string] | optional | Replace inherited OR timer gates (claimed_beads, unmerged_prs, pending_inbox); [] restores unconditional delivery. | |
└ nodes.agents.message_delivery | map | optional | Node-local managed-agent message-delivery cadence defaults and per-agent overrides (wake vs batch). | |
└ nodes.agents.message_delivery.enabled | bool | optional | false | Enable local daemon-owned managed-agent message-delivery batching for this scope. Defaults to false (immediate wake) for safe rollout. |
└ nodes.agents.message_delivery.selector | string | optional | all | Agent selector for this scope: all, persistent, workers, or none. |
└ nodes.agents.message_delivery.default_mode | string | optional | immediate | Wake mode for a message with no explicit wake flag: immediate (wake now) or batch (defer to next heartbeat). |
└ nodes.agents.message_delivery.always_wake_kinds | list[string] | optional | Message kinds that always wake regardless of mode (e.g. lifecycle, system). | |
└ nodes.agents.message_delivery.allow_runtime_opt_out | bool | optional | true | Allow runtime/profile code to decline batching even when config enables it. |
└ nodes.agents.message_delivery.batch_flush_interval_secs | u64 | optional | Optional shorter dedicated cadence in seconds for surfacing deferred (batched) messages via a coalesced summary wake, instead of waiting for the full heartbeat. A flush with no pending messages costs zero model turns. | |
└ nodes.agents.message_delivery.direct_message_wake | bool | optional | true | Operator- or agent-authored direct messages the batch policy would defer instead force one coalesced wake carrying them inline, including for idle, dormant and queue-parked recipients; paused or starting recipients are held until live. Automated notices, broadcast batching and heartbeat intervals are unchanged. false restores pure batching of direct messages. |
└ nodes.agents.message_delivery.overrides | map[string, map] | optional | Per-agent overrides keyed by persistent declaration name or concrete agent id. | |
└ nodes.agents.message_delivery.overrides.<agent> | map | optional | One per-agent message-delivery override; inherits unspecified fields from the surrounding scope. | |
└ nodes.agents.message_delivery.overrides.<agent>.enabled | bool | optional | Enable or disable message-delivery batching for this agent. | |
└ nodes.agents.message_delivery.overrides.<agent>.selector | string | optional | Optional selector override: all, persistent, workers, or none. | |
└ nodes.agents.message_delivery.overrides.<agent>.default_mode | string | optional | Override wake mode: immediate or batch. | |
└ nodes.agents.message_delivery.overrides.<agent>.always_wake_kinds | list[string] | optional | Override always-wake message kinds. | |
└ nodes.agents.message_delivery.overrides.<agent>.allow_runtime_opt_out | bool | optional | Override runtime opt-out permission for this agent. | |
└ nodes.agents.message_delivery.overrides.<agent>.batch_flush_interval_secs | u64 | optional | Override the dedicated batch-flush cadence in seconds. | |
└ nodes.agents.message_delivery.overrides.<agent>.direct_message_wake | bool | optional | Override the direct-message wake for this agent. | |
└ nodes.agents.paratenic | map | optional | Node-local Paratenic AHP client settings for pi-paratenic agents. | |
└ nodes.agents.paratenic.apply_to_pi | bool | optional | false | Route ordinary managed Pi delivery through an exact schema-v2 Paratenic binding first, with normal Pi fallback when evidence is absent or stale. |
└ nodes.agents.paratenic.url | string | required | ws://127.0.0.1:7788/ahp | Paratenic AHP WebSocket endpoint including /ahp. |
└ nodes.agents.paratenic.token_file | string | required | ~/.config/paratenic/token | Owner-private Paratenic bearer-token file. |
└ nodes.agents.paratenic.backend_socket | string | required | ~/.local/state/paratenic/backend.sock | Owner-private Paratenic backend registration socket. |
└ nodes.agents.paratenic.extension_path | string | required | Reviewed Paratenic Pi extension loaded by managed Pi. | |
└ nodes.agents.paratenic.registration_timeout_secs | u64 | optional | 30 | Legacy registration timeout exported for runtime compatibility; not a launch or resume gate. |
└ nodes.agents.paratenic.dispatch_timeout_secs | u64 | optional | 30 | Maximum AHP dispatch/acceptance wait. |
└ nodes.agents.pi_daemon | map | optional | Node-local standalone Pi SDK host client settings for pi-daemon logical agents (pico-daemon is a migration alias). | |
└ nodes.agents.pi_daemon.socket_path | string | required | Owner-local Unix socket exposed by the separately supervised standalone pi-daemon host. | |
└ nodes.agents.pi_daemon.binary | string | optional | pi-daemon | Standalone pi-daemon executable path/name. |
└ nodes.agents.pi_daemon.state_dir | string | optional | $CACOPHONY_DIR/pi-daemon | Standalone host state directory. |
└ nodes.agents.pi_daemon.agent_dir | string | optional | Pi auth/model directory; omitted uses Pi's default. | |
└ nodes.agents.pi_daemon.allow_root | string | optional | $CACOPHONY_DIR/agents | Canonical workload root allowed by the standalone host. |