Skip to main content

agent_spawn

Dynamic sub-agent creation and management. One action, eight modes. The LLM sees a single Agent tool; the modes are dispatched from params.

PropertyValue
Module idagent_spawn
Action count1 (agent_spawn.agent → tool name Agent)
Typeshared (per-app), per-session task tracking
Permissionsagent.spawn, agent.monitor, agent.control

Design notes

  • One tool, eight modes - the LLM mostly calls Agent(prompt=...); coordinators use the hidden params for monitoring + control.
  • Background by default - wait=false is the default; multiple Agent calls in one turn run concurrently via asyncio.gather (the action is in _READ_ONLY_ACTIONS).
  • Module sharing - memory, web, lsp, filesystem, shell modules are shared with sub-agents (same instance, same cwd, same _read_files set, same memory store). Other modules get fresh instances. (.)
  • Universal directives - the runner injects a mandatory prefix before every specialist's system prompt: "Be FAST, no filler, go straight to tool calls, return only key findings." Sub-agents never create tasks or set goals.
  • Cancellation propagation - aborting the parent session cancels every running sub-agent and emits an agent_cancel event per agent.

The single Agent action - 8 modes

Visible params:

ParamTypeDefaultDescription
promptstringnullThe task. Must be self-contained - the sub-agent cannot see the parent's conversation.
descriptionstring""Short label shown in the UI (e.g. "Search API endpoints").
waitboolfalseBlock until the agent finishes.
specialiststring | nullnullPredefined agent id from agents[] (e.g. web_researcher, writer). Required so the coordinator can dispatch to the right specialist instead of a generic worker.

Hidden params:

ParamTypeDescription
agent_idstringReference an existing agent - check status, wait, cancel, reassign.
agent_idslist[string]Wait for multiple agents. Empty list = wait for all running.
cancelboolCancel a running agent (requires agent_id).
reassignstringNew task for a failed / cancelled agent (requires agent_id).
list_agentsboolList all agents with their status.
system_promptstringCustom system prompt for ad-hoc agents.
max_turnsintDefault 100, max 10000.
timeoutfloatDefault 3600.0 s, max 7200 s.

Mode 1 - Spawn background (default)

Agent(prompt="Find all API endpoints in the repo")
# returns: {agent_id, status: "running", started_at}

Multiple parallel calls in one turn execute via asyncio.gather.

Mode 2 - Spawn and wait

Agent(prompt="Summarize README.md", wait=true)

Blocks until completion, returns the agent's result.

Mode 3 - Check status

Agent(agent_id="abc123")
# returns: {agent_id, status, duration_seconds, tool_calls_count, preview}

status: running / completed / failed / cancelled.

Mode 4 - Wait for one

Agent(agent_id="abc123", wait=true)

Mode 5 - Wait for many

Agent(agent_ids=["abc123", "def456"])    # specific set
Agent(agent_ids=[]) # all currently running

Returns results in the same order as agent_ids.

Mode 6 - Cancel

Agent(agent_id="abc123", cancel=true)

Cancels the asyncio task and emits agent_cancel.

Mode 7 - Reassign

Agent(agent_id="abc123", reassign="Try a different approach: ...")

Respawns a failed / cancelled agent with a new task.

Mode 8 - List

Agent(list_agents=true)

Returns all agents for the current session with their status.

Specialist agents

A specialist: name selects a preconfigured system prompt + tool allow-list. Declared under agents: with role: specialist (or any role other than coordinator).

agents:
- id: explore
role: specialist
brain: { ... }
modules:
- {filesystem: [read, grep, glob]} # only these 3 actions
- {shell: [bash]} # full module
- {memory: [remember]} # single action
system_prompt: |
You are an exploration specialist. Find and summarise code.

The modules: list supports two formats:

  • modules: [filesystem, shell] - full access.
  • modules: [{filesystem: [read, grep, glob]}] - restrict to specific actions.

Parsed → action_filter dict → passed to build_index(action_filter=...). The LLM schema then contains only the allowed tools.

Pool configuration (coordinators)

agents:
- id: coordinator
role: coordinator
brain: { ... }
pool:
max_workers: 5 # max concurrent sub-agents [1, 100], default 3
progress: true # relay specialist progress events back, default false
auto_retry: 1 # automatic retries on transient failures [0, 5], default 0

When the pool is full, additional Agent calls wait until a slot frees up.

Socket.IO events

Sub-agent lifecycle is streamed to the client via agent_event (emitted by _notify_bg_relay in ).

EventFieldsWhen
spawn_agentagent_id, specialist, taskAgent launched.
agent_progressagent_id, duration_seconds, tool_calls_count, previewMid-run heartbeat.
agent_resultagent_id, result_summary, error?Completed or failed.
agent_cancelagent_id, reason, duration_secondsCancelled (manual or session abort).

Session cleanup

cleanup_session(session_id) runs automatically on session abort or end:

  1. Cancels every pending asyncio task for running agents.
  2. Emits agent_cancel events per agent (reason: session_aborted).
  3. Orphaned tool calls in the parent session receive synthetic "interrupted": true results on resume.

Wired into the abort flow at abort_session - kills the agent turn, shell tasks, sub-agents, watchers; injects synthetic interrupted: true results for orphaned tool calls on session resume.

Cross-references