8 KiB
| title | aliases | tags | sources | created | updated | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Subagents in the SDK |
|
|
|
2026-04-17 | 2026-04-17 |
Subagents in the SDK
Subagents are separate agent instances spawned by a main agent to handle focused subtasks. Core use cases: context isolation, parallel execution, specialized instructions, and tool restriction.
Three Ways to Create Subagents
| Method | When to use |
|---|---|
Programmatic (agents param in query()) |
Recommended for SDK apps — full control, dynamic config |
Filesystem-based (.claude/agents/*.md) |
Static definitions, loaded at startup |
Built-in general-purpose |
Available automatically when Agent is in allowedTools — no definition needed |
Programmatic agents take precedence over filesystem agents with the same name.
Benefits
Context Isolation
Each subagent runs in a fresh conversation. Only the final message returns to the parent — not intermediate tool calls or reasoning. Parent receives a concise summary, not every file the subagent read.
Parallelization
Multiple subagents run concurrently. Example: style-checker, security-scanner, and test-coverage can run simultaneously during a code review.
Specialized Instructions
Each subagent has its own system prompt with domain-specific knowledge — without bloating the main agent's prompt.
Tool Restrictions
Limit subagents to specific tools. A doc-reviewer with only Read + Grep can analyze but never modify files.
AgentDefinition Fields
| Field | Type | Required | Notes |
|---|---|---|---|
description |
string | Yes | Tells Claude when to use this subagent — write clearly |
prompt |
string | Yes | Subagent's system prompt |
tools |
string[] | No | If omitted, inherits all parent tools |
model |
sonnet|opus|haiku|inherit |
No | Defaults to main model |
skills |
string[] | No | Skills available to this subagent |
memory |
user|project|local |
No | Python only |
mcpServers |
array | No | MCP servers by name or inline config |
Important: Subagents cannot spawn their own subagents — never include
Agentin a subagent'stools.
Python Example
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, AgentDefinition
async def main():
async for message in query(
prompt="Review the authentication module for security issues",
options=ClaudeAgentOptions(
# Agent tool is required — Claude invokes subagents through it
allowed_tools=["Read", "Grep", "Glob", "Agent"],
agents={
"code-reviewer": AgentDefinition(
description="Expert code review specialist. Use for quality, security, and maintainability reviews.",
prompt="""You are a code review specialist with expertise in security, performance, and best practices.
When reviewing code:
- Identify security vulnerabilities
- Check for performance issues
- Verify adherence to coding standards
- Suggest specific improvements""",
tools=["Read", "Grep", "Glob"], # read-only
model="sonnet",
),
"test-runner": AgentDefinition(
description="Runs and analyzes test suites. Use for test execution and coverage analysis.",
prompt="You are a test execution specialist. Run tests and provide clear analysis of results.",
tools=["Bash", "Read", "Grep"],
),
},
),
):
if hasattr(message, "result"):
print(message.result)
asyncio.run(main())
What Subagents Inherit
| Receives | Does NOT receive |
|---|---|
| Own system prompt + Agent tool prompt | Parent's conversation history or tool results |
| Project CLAUDE.md | Skills (unless listed in AgentDefinition.skills) |
| Tool definitions (parent's or restricted subset) | Parent's system prompt |
The only channel from parent → subagent is the Agent tool's prompt string. Include file paths, error messages, or decisions directly in that prompt.
Invocation
- Automatic: Claude matches tasks to subagents based on
descriptionfield - Explicit: Mention by name in prompt —
"Use the code-reviewer agent to check auth module"
Dynamic Agent Configuration
Factory pattern for runtime customization:
def create_security_agent(security_level: str) -> AgentDefinition:
is_strict = security_level == "strict"
return AgentDefinition(
description="Security code reviewer",
prompt=f"You are a {'strict' if is_strict else 'balanced'} security reviewer...",
tools=["Read", "Grep", "Glob"],
model="opus" if is_strict else "sonnet", # more capable model for high-stakes
)
Detecting Subagent Invocation
Subagents are invoked via the Agent tool. Detect by checking tool_use blocks where name is "Agent" (or "Task" for SDK < v2.1.63). Messages from inside a subagent include parent_tool_use_id.
for block in message.content:
if getattr(block, "type", None) == "tool_use" and block.name in ("Task", "Agent"):
print(f"Subagent invoked: {block.input.get('subagent_type')}")
if hasattr(message, "parent_tool_use_id") and message.parent_tool_use_id:
print(" (running inside subagent)")
Resuming Subagents
Resumed subagents retain full conversation history. Flow:
- Capture
session_idfromResultMessageduring first query - Parse
agentIdfrom message content (appears in Agent tool results) - Pass
resume: sessionIdin second query's options - Include agent ID in prompt
// Resume example (TypeScript)
for await (const message of query({
prompt: `Resume agent ${agentId} and list the top 3 most complex endpoints`,
options: { allowedTools: ["Read", "Grep", "Glob", "Agent"], resume: sessionId }
})) {
if ("result" in message) console.log(message.result);
}
Transcripts persist independently of the main conversation and are cleaned up after cleanupPeriodDays (default: 30 days).
Common Tool Combinations
| Use case | Tools |
|---|---|
| Read-only analysis | Read, Grep, Glob |
| Test execution | Bash, Read, Grep |
| Code modification | Read, Edit, Write, Grep, Glob |
| Full access | Omit tools field |
Troubleshooting
| Problem | Fix |
|---|---|
| Claude not delegating to subagents | Add Agent to allowedTools; use explicit name in prompt; write clearer description |
| Filesystem agents not loading | Restart session — agents are loaded at startup only |
| Windows long prompt failures | Keep prompts concise (<8191 chars) or use filesystem-based agents |
Key Takeaways
Agenttool must be inallowedTools— subagents are invoked through it- Subagents cannot spawn sub-subagents (no
Agentin subagent'stools) - Context isolation means only the final message returns to parent — include all needed context in the Agent tool prompt
descriptionfield drives automatic delegation — write it carefully- Dynamic factory functions enable runtime customization (different models per security level, etc.)
- Tool name changed from
"Task"→"Agent"in v2.1.63 — check both for compatibility
Related Articles
- wiki/agent-sdk/agent-loop — how turns, tool execution, and context management work
- wiki/agent-sdk/configure-permissions — permission modes and subagent inheritance
- wiki/agent-sdk/agent-skills-plugins — loading skills into subagents
- wiki/agent-sdk/hosting-production — multi-agent deployment patterns
- wiki/agent-sdk/sdk-hooks — intercept tool calls including Agent tool invocations
Sources
- Subagents in the SDK — official Anthropic docs