obsidian/wiki/agent-sdk/subagents.md
2026-04-17 13:16:15 +01:00

8 KiB

title aliases tags sources created updated
Subagents in the SDK
subagents
sdk-subagents
agent-spawning
agent-sdk
subagents
parallelization
context-isolation
python
typescript
raw/Subagents in the SDK.md
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 Agent in a subagent's tools.

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 description field
  • 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:

  1. Capture session_id from ResultMessage during first query
  2. Parse agentId from message content (appears in Agent tool results)
  3. Pass resume: sessionId in second query's options
  4. 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

  • Agent tool must be in allowedTools — subagents are invoked through it
  • Subagents cannot spawn sub-subagents (no Agent in subagent's tools)
  • Context isolation means only the final message returns to parent — include all needed context in the Agent tool prompt
  • description field 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

Sources