Three Spawning Approaches
1. Static Spawning
The coordinator always spawns the same set of subagents in a known pattern. Used for repeatable, well-defined workflows.
# Customer support resolution — always follows this pattern
coordinator_prompt = """
When handling a customer issue, always:
1. Spawn a customer lookup subagent (gets customer profile and history)
2. Spawn an order lookup subagent (gets relevant order details)
3. Spawn a policy check subagent (determines what resolution is available)
4. Based on results, spawn one of: refund_agent, replacement_agent, or escalation_agent
"""
The coordinator knows at design time which subagents exist and when to spawn each.
2. Dynamic Spawning
The coordinator discovers what needs to be done and spawns subagents accordingly. Used for open-ended investigation where the right approach depends on what’s found.
coordinator_prompt = """
Investigate this codebase to identify all test coverage gaps.
You may spawn specialized subagents as needed to:
- Analyze specific modules that look complex
- Deep-dive into areas with suspected coverage gaps
- Verify findings that seem contradictory
Spawn whatever specialized subagents will give you the most complete picture.
"""
The coordinator might spawn 3 subagents for a simple codebase, or 15 for a complex one.
3. The Explore Subagent Pattern
A specialized pattern for verbose discovery tasks. Instead of running discovery in the coordinator context (which fills it quickly), delegate discovery to an Explore subagent that returns only a structured summary.
Without Explore subagent:
Coordinator explores files → context fills with file contents → context overflow
With Explore subagent:
Coordinator spawns Explore(task="map all authentication entry points")
Explore subagent reads all relevant files (in its own isolated context)
Explore subagent returns structured summary: {entry_points: [...], concerns: [...]}
Coordinator context only grows by the size of the summary
# Coordinator spawns an Explore subagent
explore_task = {
"description": "Map the authentication system",
"prompt": """
Explore the codebase and map the authentication system.
Investigate:
- All authentication entry points (HTTP endpoints, API routes)
- Session management approach
- Token validation logic
- Any security concerns observed
Return a structured JSON summary:
{
"entry_points": [{"path": "...", "method": "...", "auth_mechanism": "..."}],
"session_approach": "...",
"token_validation": "...",
"security_concerns": ["...", "..."],
"files_examined": 47
}
Do NOT return file contents — return only your structured analysis.
""",
"allowed_tools": ["file_read", "glob", "grep"]
}
The coordinator’s context grows only by the size of the summary, not by the contents of 47 files.
Handling Spawning Failures
Subagents fail. Networks time out, tools break, LLMs return unexpected outputs. Your spawning pattern needs explicit failure handling:
async def spawn_with_retry(task_input, max_retries=2):
for attempt in range(max_retries + 1):
try:
result = await run_subagent(
task_input["prompt"],
task_input.get("allowed_tools", [])
)
return {"status": "success", "result": result}
except TimeoutError:
if attempt < max_retries:
await asyncio.sleep(2 ** attempt) # exponential backoff
continue
return {
"status": "error",
"error_type": "timeout",
"message": "Subagent timed out after retries",
"partial_result": None
}
except Exception as e:
return {
"status": "error",
"error_type": type(e).__name__,
"message": str(e),
"partial_result": None
}
Return structured error results to the coordinator — let it decide whether to retry, use an alternative approach, or inform the user.
Key Takeaways
- Static spawning for predictable workflows, dynamic for open-ended investigation
- Explore subagent pattern prevents context exhaustion during verbose discovery
- Explore returns summaries, not raw content — keeps coordinator context manageable
- Handle spawning failures explicitly — return structured errors, let coordinator decide
- Scope subagent tools to minimum necessary for their specific role