Courses/Introduction to Subagents/Subagents in the Claude Agent SDK
Advanced and At ScaleLesson 15 of 18

Subagents in the Claude Agent SDK

From Claude Code to Code You Write

Everything so far has been about subagents inside Claude Code. But the same capability is available programmatically through the Claude Agent SDK, so you can build your own applications that spawn subagents. The SDK gives you three ways to define them: programmatically via the agents parameter (recommended for SDK apps), filesystem-based as .claude/agents/*.md (the same files you've been writing), and the built-in general-purpose agent (available without defining anything).

ℹ️

Same concepts, new surface

The benefits carry over exactly: context isolation (each subagent runs in a fresh conversation; only its final message returns), parallelization (multiple subagents run concurrently), specialized instructions, and tool restrictions. If you understood subagents in Claude Code, you already understand them in the SDK.

Defining a Subagent with AgentDefinition

Programmatic subagents are defined in the agents parameter of your query() call, using AgentDefinition. Claude invokes them through the Agent tool, so you include 'Agent' in allowedTools to auto-approve invocations. Here's a code-reviewer subagent with read-only access:

pythonA programmatic subagent. Note 'Agent' in allowed_tools — without it, subagent invocations aren't auto-approved.
from claude_agent_sdk import query, ClaudeAgentOptions, AgentDefinition

async for message in query(
    prompt="Review the authentication module for security issues",
    options=ClaudeAgentOptions(
        allowed_tools=["Read", "Grep", "Glob", "Agent"],
        agents={
            "code-reviewer": AgentDefinition(
                description="Expert code review specialist. Use for security reviews.",
                prompt="You are a code review specialist. Identify security\nvulnerabilities, performance issues, and standards violations.",
                tools=["Read", "Grep", "Glob"],  # read-only
                model="sonnet",
            ),
        },
    ),
):
    if hasattr(message, "result"):
        print(message.result)

The AgentDefinition Fields

FieldRequiredWhat it does
descriptionYesNatural-language description of WHEN to use this agent (drives delegation)
promptYesThe agent's system prompt (its role and behavior)
toolsNoAllowed tool names; if omitted, inherits all tools
disallowedToolsNoTool names to remove from the set
modelNo'sonnet'/'opus'/'haiku'/'inherit' or a full ID; defaults to the main model
skills, memory, mcpServers, maxTurns, background, effort, permissionModeNoAdvanced control (preload skills, persistent memory, scoped MCP, turn caps, etc.)

AgentDefinition mirrors the Markdown frontmatter you already know — description and prompt are required.

⚠️

Two rules to remember

(1) Subagents cannot spawn their own subagents — do NOT include 'Agent' in a subagent's tools array. (2) Programmatically defined agents take precedence over filesystem agents with the same name.

What Crosses the Boundary, and the Task→Agent Rename

A subagent's context starts fresh but isn't empty. The only channel from parent to subagent is the Agent tool's prompt string — so include any file paths, error messages, or decisions the subagent needs directly in that prompt. It DOES receive its own system prompt + the task prompt + project CLAUDE.md + tool definitions; it does NOT receive the parent's conversation history, tool results, or system prompt.

The subagent receivesThe subagent does NOT receive
Its own prompt + the Agent tool's task promptThe parent's conversation history or tool results
Project CLAUDE.mdPreloaded skills (unless listed in 'skills')
Tool definitions (inherited or the 'tools' subset)The parent's system prompt

Same isolation model as Claude Code: fresh context, single prompt channel in, summary out.

Task → Agent (v2.1.63)

The tool that spawns subagents was renamed from 'Task' to 'Agent' in Claude Code v2.1.63. Current SDK releases emit 'Agent' in tool_use blocks but still use 'Task' in some places (the init tools list, permission denials). When detecting subagent invocations, check for BOTH 'Agent' and 'Task' for compatibility.

Next

You can define subagents in code. Next: running them in parallel vs sequence — and what to reach for when you need dozens or hundreds of agents (the Workflow tool).

Key Takeaways

  • The Agent SDK exposes subagents three ways: programmatic (agents param + AgentDefinition, recommended), filesystem (.claude/agents/*.md), and the built-in general-purpose agent.
  • AgentDefinition requires description (when to use) and prompt (system prompt); tools, disallowedTools, model, and several advanced fields are optional.
  • Claude invokes subagents via the Agent tool — include 'Agent' in allowedTools to auto-approve invocations.
  • Subagents cannot spawn subagents (don't put 'Agent' in a subagent's tools); programmatic agents take precedence over same-name filesystem agents.
  • The only parent→subagent channel is the Agent tool's prompt string; the subagent gets its prompt + task + project CLAUDE.md + tool defs, but not the parent's history/system prompt.
  • The spawning tool was renamed Task → Agent in v2.1.63; detect invocations by checking for BOTH 'Agent' and 'Task'.

Check Your Understanding

Test what you learned in this lesson.

Q1.In the Agent SDK, how do you define a subagent programmatically?

Q2.Why must you include 'Agent' in allowedTools when using SDK subagents?

Q3.What is the ONLY channel of information from a parent to its subagent?

Q4.When detecting subagent invocations across SDK versions, what should you check for?

Practice This Lesson