Agents
Subagents
Spawn child agents from tools — private conversations, send/reply bridges, and parent monologue integration.
Subagents let a parent agent delegate work to another registered agent via LLM tools. Each spawn gets its own conversation and standard mesh (ingestion, processor, egress). Messages flow through bridge actors wired by config — no seeded state.
Mental model
| Tool | When | What it does |
|---|---|---|
Spawn (spawn_<agent>) | First contact with a subagent | Creates conversation, agent, join, bridge instances. Returns subagentConversationId. |
send_message_to_agent | After spawn | Emits agent.subagent.message.send → send bridge posts to subagent conversation as system. |
send_message_to_agent never creates conversations.
Bootstrap
Spawnable agents are frozen at runtime build. For each subagent type K:
- Register
subagentSendBridge__KandsubagentReplyBridge__K(option 2 — per agent at bootstrap). - Register spawn toolchain from
createToolchainFromAgent("K", ...). - Parent includes
createSubagentMessagingToolchain()when it can delegate.
const researcher = createToolchainFromAgent("researcher", {
agents: expandedAgents,
});
export default defineRuntime()
.events({ ...conversationEvents, ...agentEvents, ...subagentEvents })
.actors(() => ({
...researcher.bridgeActors,
}))
.agents(() => ({
butler: defineAgent({
tools: [
createSubagentMessagingToolchain(),
researcher.spawnToolchain,
],
}),
researcher: defineAgent({ model: "north-default" }),
}));Flow
flowchart LR
P[Parent monologue]
SC[Subagent conversation]
SM[Subagent monologue]
P -->|spawn tool| SC
P -->|send_message_to_agent| E[agent.subagent.message.send]
E --> SB[Send bridge]
SB -->|system post| SC
SC -->|ingestion| SM
SM -->|processor| SM
SC -->|non-system message| RB[Reply bridge]
RB -->|system post| PEvents
agent.subagent.message.send
{
subagentConversationId: string;
message: string;
}Send bridge filters on config.subagentConversationId === payload.subagentConversationId.
Bridge config
Send bridge (one instance per spawn):
{ subagentConversationId: string; systemParticipantId: string }Reply bridge (one instance per spawn):
{
subagentConversationId: string;
parentMonologueId: string;
parentSystemParticipantId: string;
}Runtime durable queuing applies when filters match — no custom queue state.