Expand description
The supervisor↔subagent control protocol.
A minimal JSON-RPC sibling — not literal MCP (no initialize
handshake) — carried length-framed (4-byte prefix, crate::json::frame)
over the child’s stdio pipes, so payloads that contain newlines
(instructions, context seeds, distilled results) survive. Two directions:
ControlMsg flows down (supervisor→child), AgentMsg flows up.
The control reader inside the child runs on a thread separate from the
agentic loop, so Ping/Pong liveness survives a long in-flight tool or
model call: if the reader shared the loop’s thread, a slow model call would
read as a hung child and the supervisor would reap a healthy process. This
module is just the wire types; the spawn mechanics are supervisor/spawn.rs,
the child side subagent/control.rs.
Structs§
- Intel
Active - Which endpoint is serving the child’s intelligence, for
AgentMsg::IntelHealth. The bounded structural identity ONLY — the list index and the transport scheme (unix/vsock/https) — never the URL, cid, host, or any credential, matching what theagentd://intelligenceresource redacts. An index plus a scheme is enough to tell operators which configured endpoint is live without putting an address into logs or events. - Intel
Config - Limits
- Seed
Message - A single seed message — a minimal {role, content} pair. Roles mirror the
loop’s:
system|user|assistant|tool. - Spawn
Payload - Everything a subagent needs to run, minted by the supervisor. The child
takes none of these fields from its own request —
depthin particular is derived by the supervisor from the caller’s handle, so a child cannot claim a shallower depth to buy itself more levels of delegation. - Swap
Intel - The intelligence config the child rebuilds its client from on a hot-swap:
the endpoint-list URI, the default endpoint-1 credential, the model, and the
swap policy — exactly the parts
IntelConfigcarries plus the policy. Boxed inControlMsgto keep the enum small, asSpawnPayloadis. - Telemetry
- The correlation block stamped into the child’s logs, so every line a subtree emits can be joined back to the run and to its position in the tree.
- Turn
Result - A finished turn.
messagesis the transcript DELTA — only the assistant and tool messages appended during this turn, in order — which the supervisor concatenates onto the context it already holds. Sending a delta rather than the whole transcript keeps the frame bounded as a conversation grows. - Turn
Spec - The turn worker’s input: everything the child needs to run exactly one turn — the system prompt, the context slice, the tool definitions and which of them round-trip to the supervisor, the output schema, and the knobs. The worker holds no state of its own between turns; whatever it needs is here.
Enums§
- Agent
Msg - Control
Msg - Role
- The child’s role: which driver the child process runs after spawn.
- Turn
Kind - What kind of turn a
Role::Turnworker runs.
Constants§
- ALLOWED_
TOOLS_ ROLE - The reserved
SeedMessage::rolethat carries a child’s tool allow-list —subagent.run’stools:narrowing, which is how scope narrows monotonically down the tree. Minted by the supervisor withSpawnPayload::narrow_tools, enforced by the child incrate::agentloop::runner::Session::prepare, which filters its assembled catalogue AND its dispatch against it. - SUBAGENT_
ENV - The environment variable the supervisor sets on the child so its
maintakes the subagent path instead of re-parsing CLI config.
Functions§
- parse_
allowed_ tools - Parse an allow-list marker’s body (a JSON array of registry patterns:
*, an exact name,prefix*). An unreadable body narrows to NOTHING rather than to everything — a grant that cannot be read is not a grant (fail closed).