SDK のサブエージェント
サブエージェントを定義して呼び出し、コンテキストを分離し、タスクを並列実行し、Claude Agent SDK アプリケーションで特殊な指示を適用します。
サブエージェントは、メインエージェントが生成できる個別のエージェントインスタンスで、焦点を絞ったサブタスクを処理します。 サブエージェントを使用して、焦点を絞ったサブタスクのコンテキストを分離し、複数の分析を並列実行し、メインエージェントのプロンプトを肥大化させずに特殊な指示を適用します。
このガイドでは、agents パラメータを使用して SDK でサブエージェントを定義および使用する方法について説明します。
概要
サブエージェントは 3 つの方法で作成できます。
- プログラム的に:
query()オプションのagentsパラメータを使用します(TypeScript、Python) - ファイルシステムベース:
.claude/agents/ディレクトリ内のマークダウンファイルとしてエージェントを定義します(ファイルとしてサブエージェントを定義するを参照) - 組み込みの汎用: Claude は、何も定義することなく、Agent ツールを介して組み込みの
general-purposeサブエージェントをいつでも呼び出すことができます
このガイドでは、SDK アプリケーションに推奨されるプログラム的なアプローチに焦点を当てています。
サブエージェントを定義する場合、Claude は各サブエージェントの description フィールドに基づいて、それらを呼び出すかどうかを判断します。サブエージェントをいつ使用すべきかを説明する明確な説明を書いてください。Claude は自動的に適切なタスクを委譲します。プロンプトでサブエージェントを名前で明示的にリクエストすることもできます(例えば、「code-reviewer エージェントを使用して...」)。
サブエージェントを使用する利点
コンテキスト分離
各サブエージェントは独自の新しい会話で実行されます。中間的なツール呼び出しと結果はサブエージェント内に留まり、最終メッセージだけが親に返されます。サブエージェントが継承するものを参照して、サブエージェントのコンテキストに正確に何が含まれているかを確認してください。
例: research-assistant サブエージェントは、そのコンテンツがメイン会話に蓄積されることなく、数十のファイルを探索できます。親は、サブエージェントが読んだすべてのファイルではなく、簡潔なサマリーを受け取ります。
並列化
複数のサブエージェントを同時に実行でき、複雑なワークフローを劇的に高速化します。
例: コードレビュー中に、style-checker、security-scanner、test-coverage サブエージェントを同時に実行でき、レビュー時間を数分から数秒に短縮できます。
特殊な指示と知識
各サブエージェントは、特定の専門知識、ベストプラクティス、制約を備えたカスタマイズされたシステムプロンプトを持つことができます。
例: database-migration サブエージェントは、SQL ベストプラクティス、ロールバック戦略、データ整合性チェックに関する詳細な知識を持つことができます。これらはメインエージェントの指示では不要なノイズになります。
ツール制限
サブエージェントは特定のツールに制限でき、意図しないアクションのリスクを軽減します。
例: doc-reviewer サブエージェントは Read と Grep ツールのみにアクセスでき、ドキュメントファイルを分析できますが、誤って変更することはありません。
サブエージェントの作成
プログラム的な定義(推奨)
agents パラメータを使用してコード内でサブエージェントを直接定義します。この例では、読み取り専用アクセスを持つコードレビュアーとコマンドを実行できるテストランナーの 2 つのサブエージェントを作成します。Claude がサブエージェントを Agent ツール経由で呼び出すため、Agent ツールを allowedTools に含める必要があります。
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 for subagent invocation
allowed_tools=["Read", "Grep", "Glob", "Agent"],
agents={
"code-reviewer": AgentDefinition(
# description tells Claude when to use this subagent
description="Expert code review specialist. Use for quality, security, and maintainability reviews.",
# prompt defines the subagent's behavior and expertise
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
Be thorough but concise in your feedback.""",
# tools restricts what the subagent can do (read-only here)
tools=["Read", "Grep", "Glob"],
# model overrides the default model for this subagent
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.
Focus on:
- Running test commands
- Analyzing test output
- Identifying failing tests
- Suggesting fixes for failures""",
# Bash access lets this subagent run test commands
tools=["Bash", "Read", "Grep"],
),
},
),
):
if hasattr(message, "result"):
print(message.result)
asyncio.run(main())
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "Review the authentication module for security issues",
options: {
// Agent tool is required for subagent invocation
allowedTools: ["Read", "Grep", "Glob", "Agent"],
agents: {
"code-reviewer": {
// description tells Claude when to use this subagent
description:
"Expert code review specialist. Use for quality, security, and maintainability reviews.",
// prompt defines the subagent's behavior and expertise
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
Be thorough but concise in your feedback.`,
// tools restricts what the subagent can do (read-only here)
tools: ["Read", "Grep", "Glob"],
// model overrides the default model for this subagent
model: "sonnet"
},
"test-runner": {
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.
Focus on:
- Running test commands
- Analyzing test output
- Identifying failing tests
- Suggesting fixes for failures`,
// Bash access lets this subagent run test commands
tools: ["Bash", "Read", "Grep"]
}
}
}
})) {
if ("result" in message) console.log(message.result);
}
AgentDefinition 設定
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
description |
string |
はい | このエージェントをいつ使用するかについての自然言語説明 |
prompt |
string |
はい | エージェントの役割と動作を定義するシステムプロンプト |
tools |
string[] |
いいえ | 許可されたツール名の配列。省略した場合、すべてのツールを継承します |
disallowedTools |
string[] |
いいえ | エージェントのツールセットから削除するツール名の配列 |
model |
string |
いいえ | このエージェントのモデルオーバーライド。'sonnet'、'opus'、'haiku'、'inherit' などのエイリアス、または完全なモデル ID を受け入れます。省略した場合、メインモデルがデフォルトになります |
skills |
string[] |
いいえ | スタートアップ時にエージェントのコンテキストにプリロードするスキル名のリスト。リストされていないスキルは Skill ツール経由で呼び出し可能なままです |
memory |
'user' | 'project' | 'local' |
いいえ | このエージェントのメモリソース |
mcpServers |
(string | object)[] |
いいえ | このエージェントが利用可能な MCP サーバー(名前またはインライン設定) |
maxTurns |
number |
いいえ | エージェントが停止する前の最大 agentic ターン数 |
background |
boolean |
いいえ | 呼び出されたときにこのエージェントをノンブロッキングバックグラウンドタスクとして実行します |
effort |
'low' | 'medium' | 'high' | 'xhigh' | 'max' | number |
いいえ | このエージェントの推論努力レベル |
permissionMode |
PermissionMode |
いいえ | このエージェント内のツール実行のパーミッションモード |
Python SDK では、これらのフィールド名は wire フォーマットに一致するように camelCase を使用します。詳細については、AgentDefinition リファレンスを参照してください。
サブエージェントは独自のサブエージェントを生成することはできません。サブエージェントの tools 配列に Agent を含めないでください。
ファイルシステムベースの定義(代替)
.claude/agents/ ディレクトリ内のマークダウンファイルとしてサブエージェントを定義することもできます。このアプローチの詳細については、Claude Code サブエージェントドキュメントを参照してください。プログラム的に定義されたエージェントは、同じ名前のファイルシステムベースのエージェントより優先されます。
カスタムサブエージェントを定義しなくても、Agent が allowedTools にある場合、Claude は組み込みの general-purpose サブエージェントを生成できます。これは、特殊なエージェントを作成せずに研究または探索タスクを委譲するのに便利です。
サブエージェントが継承するもの
サブエージェントのコンテキストウィンドウは新しく開始されます(親の会話なし)が、空ではありません。親からサブエージェントへの唯一のチャネルは Agent ツールのプロンプト文字列なので、サブエージェントが必要とするファイルパス、エラーメッセージ、または決定をそのプロンプトに直接含めてください。
| サブエージェントが受け取るもの | サブエージェントが受け取らないもの |
|---|---|
独自のシステムプロンプト(AgentDefinition.prompt)と Agent ツールのプロンプト |
親の会話履歴またはツール結果 |
プロジェクト CLAUDE.md(settingSources 経由でロード) |
プリロードされたスキルコンテンツ(AgentDefinition.skills にリストされている場合を除く) |
ツール定義(親から継承、または tools のサブセット) |
親のシステムプロンプト |
親はサブエージェントの最終メッセージを Agent ツール結果として逐語的に受け取りますが、独自の応答で要約する場合があります。サブエージェント出力を逐語的にユーザー向けの応答で保持するには、メイン query() 呼び出しに渡すプロンプトまたは systemPrompt オプションに指示を含めてください。
サブエージェントの呼び出し
自動呼び出し
Claude は、タスクと各サブエージェントの description に基づいて、サブエージェントをいつ呼び出すかを自動的に決定します。例えば、説明が「クエリチューニング用のパフォーマンス最適化スペシャリスト」である performance-optimizer サブエージェントを定義した場合、プロンプトでクエリの最適化について言及すると、Claude はそれを呼び出します。
Claude がタスクを正しいサブエージェントにマッチングできるように、明確で具体的な説明を書いてください。
明示的な呼び出し
Claude が特定のサブエージェントを使用することを保証するには、プロンプトで名前を言及してください。
"Use the code-reviewer agent to check the authentication module"
これは自動マッチングをバイパスし、名前付きサブエージェントを直接呼び出します。
動的エージェント設定
実行時の条件に基づいて、エージェント定義を動的に作成できます。この例では、異なる厳密性レベルを持つセキュリティレビュアーを作成し、厳密なレビューにはより強力なモデルを使用します。
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, AgentDefinition
# Factory function that returns an AgentDefinition
# This pattern lets you customize agents based on runtime conditions
def create_security_agent(security_level: str) -> AgentDefinition:
is_strict = security_level == "strict"
return AgentDefinition(
description="Security code reviewer",
# Customize the prompt based on strictness level
prompt=f"You are a {'strict' if is_strict else 'balanced'} security reviewer...",
tools=["Read", "Grep", "Glob"],
# Key insight: use a more capable model for high-stakes reviews
model="opus" if is_strict else "sonnet",
)
async def main():
# The agent is created at query time, so each request can use different settings
async for message in query(
prompt="Review this PR for security issues",
options=ClaudeAgentOptions(
allowed_tools=["Read", "Grep", "Glob", "Agent"],
agents={
# Call the factory with your desired configuration
"security-reviewer": create_security_agent("strict")
},
),
):
if hasattr(message, "result"):
print(message.result)
asyncio.run(main())
import { query, type AgentDefinition } from "@anthropic-ai/claude-agent-sdk";
// Factory function that returns an AgentDefinition
// This pattern lets you customize agents based on runtime conditions
function createSecurityAgent(securityLevel: "basic" | "strict"): AgentDefinition {
const isStrict = securityLevel === "strict";
return {
description: "Security code reviewer",
// Customize the prompt based on strictness level
prompt: `You are a ${isStrict ? "strict" : "balanced"} security reviewer...`,
tools: ["Read", "Grep", "Glob"],
// Key insight: use a more capable model for high-stakes reviews
model: isStrict ? "opus" : "sonnet"
};
}
// The agent is created at query time, so each request can use different settings
for await (const message of query({
prompt: "Review this PR for security issues",
options: {
allowedTools: ["Read", "Grep", "Glob", "Agent"],
agents: {
// Call the factory with your desired configuration
"security-reviewer": createSecurityAgent("strict")
}
}
})) {
if ("result" in message) console.log(message.result);
}
サブエージェント呼び出しの検出
サブエージェントは Agent ツール経由で呼び出されます。サブエージェントが呼び出されたときを検出するには、name が "Agent" である tool_use ブロックをチェックしてください。サブエージェントのコンテキスト内からのメッセージには parent_tool_use_id フィールドが含まれます。
ツール名は Claude Code v2.1.63 で "Task" から "Agent" に変更されました。現在の SDK リリースは tool_use ブロックで "Agent" を出力しますが、system:init ツールリストと result.permission_denials[].tool_name では引き続き "Task" を使用します。SDK バージョン全体での互換性を確保するために、block.name で両方の値をチェックしてください。
この例は、ストリーミングされたメッセージを反復処理し、サブエージェントが呼び出されたときと、その後のメッセージがそのサブエージェントの実行コンテキスト内から発信されたときをログに記録します。
メッセージ構造は SDK 間で異なります。Python では、コンテンツブロックは message.content 経由で直接アクセスされます。TypeScript では、SDKAssistantMessage が Claude API メッセージをラップするため、コンテンツは message.message.content 経由でアクセスされます。
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, AgentDefinition
async def main():
async for message in query(
prompt="Use the code-reviewer agent to review this codebase",
options=ClaudeAgentOptions(
allowed_tools=["Read", "Glob", "Grep", "Agent"],
agents={
"code-reviewer": AgentDefinition(
description="Expert code reviewer.",
prompt="Analyze code quality and suggest improvements.",
tools=["Read", "Glob", "Grep"],
)
},
),
):
# Check for subagent invocation. Match both names: older SDK
# versions emitted "Task", current versions emit "Agent".
if hasattr(message, "content") and message.content:
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')}")
# Check if this message is from within a subagent's context
if hasattr(message, "parent_tool_use_id") and message.parent_tool_use_id:
print(" (running inside subagent)")
if hasattr(message, "result"):
print(message.result)
asyncio.run(main())
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "Use the code-reviewer agent to review this codebase",
options: {
allowedTools: ["Read", "Glob", "Grep", "Agent"],
agents: {
"code-reviewer": {
description: "Expert code reviewer.",
prompt: "Analyze code quality and suggest improvements.",
tools: ["Read", "Glob", "Grep"]
}
}
}
})) {
const msg = message as any;
// Check for subagent invocation. Match both names: older SDK versions
// emitted "Task", current versions emit "Agent".
for (const block of msg.message?.content ?? []) {
if (block.type === "tool_use" && (block.name === "Task" || block.name === "Agent")) {
console.log(`Subagent invoked: ${block.input.subagent_type}`);
}
}
// Check if this message is from within a subagent's context
if (msg.parent_tool_use_id) {
console.log(" (running inside subagent)");
}
if ("result" in message) {
console.log(message.result);
}
}
サブエージェントの再開
サブエージェントを再開して、中断したところから続行できます。再開されたサブエージェントは、以前のすべてのツール呼び出し、結果、推論を含む完全な会話履歴を保持します。サブエージェントは新しく開始するのではなく、停止したところから正確に再開します。
サブエージェントが完了すると、Claude は Agent ツール結果でエージェント ID を受け取ります。サブエージェントをプログラム的に再開するには:
- セッション ID をキャプチャする: 最初のクエリ中にメッセージから
session_idを抽出します - エージェント ID を抽出する: メッセージコンテンツから
agentIdを解析します - セッションを再開する: 2 番目のクエリのオプションで
resume: sessionIdを渡し、プロンプトにエージェント ID を含めます
サブエージェントのトランスクリプトにアクセスするには、同じセッションを再開する必要があります。各 query() 呼び出しはデフォルトで新しいセッションを開始するため、同じセッションで続行するには resume: sessionId を渡してください。
カスタムエージェント(組み込みエージェントではない)を使用している場合は、両方のクエリで agents パラメータに同じエージェント定義を渡す必要もあります。
以下の例は、このフローを示しています。最初のクエリはサブエージェントを実行してセッション ID とエージェント ID をキャプチャし、2 番目のクエリはセッションを再開して、最初の分析からのコンテキストが必要なフォローアップ質問をします。
import { query, type SDKMessage } from "@anthropic-ai/claude-agent-sdk";
// Helper to extract agentId from message content
// Stringify to avoid traversing different block types (TextBlock, ToolResultBlock, etc.)
function extractAgentId(message: SDKMessage): string | undefined {
if (!("message" in message)) return undefined;
// Stringify the content so we can search it without traversing nested blocks
const content = JSON.stringify(message.message.content);
const match = content.match(/agentId:\s*([a-f0-9-]+)/);
return match?.[1];
}
let agentId: string | undefined;
let sessionId: string | undefined;
// First invocation - use the Explore agent to find API endpoints
for await (const message of query({
prompt: "Use the Explore agent to find all API endpoints in this codebase",
options: { allowedTools: ["Read", "Grep", "Glob", "Agent"] }
})) {
// Capture session_id from ResultMessage (needed to resume this session)
if ("session_id" in message) sessionId = message.session_id;
// Search message content for the agentId (appears in Agent tool results)
const extractedId = extractAgentId(message);
if (extractedId) agentId = extractedId;
// Print the final result
if ("result" in message) console.log(message.result);
}
// Second invocation - resume and ask follow-up
if (agentId && sessionId) {
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);
}
}
import asyncio
import json
import re
from claude_agent_sdk import query, ClaudeAgentOptions
def extract_agent_id(text: str) -> str | None:
"""Extract agentId from Agent tool result text."""
match = re.search(r"agentId:\s*([a-f0-9-]+)", text)
return match.group(1) if match else None
async def main():
agent_id = None
session_id = None
# First invocation - use the Explore agent to find API endpoints
async for message in query(
prompt="Use the Explore agent to find all API endpoints in this codebase",
options=ClaudeAgentOptions(allowed_tools=["Read", "Grep", "Glob", "Agent"]),
):
# Capture session_id from ResultMessage (needed to resume this session)
if hasattr(message, "session_id"):
session_id = message.session_id
# Search message content for the agentId (appears in Agent tool results)
if hasattr(message, "content"):
# Stringify the content so we can search it without traversing nested blocks
content_str = json.dumps(message.content, default=str)
extracted = extract_agent_id(content_str)
if extracted:
agent_id = extracted
# Print the final result
if hasattr(message, "result"):
print(message.result)
# Second invocation - resume and ask follow-up
if agent_id and session_id:
async for message in query(
prompt=f"Resume agent {agent_id} and list the top 3 most complex endpoints",
options=ClaudeAgentOptions(
allowed_tools=["Read", "Grep", "Glob", "Agent"], resume=session_id
),
):
if hasattr(message, "result"):
print(message.result)
asyncio.run(main())
サブエージェントのトランスクリプトはメイン会話とは独立して永続化されます。
- メイン会話の圧縮: メイン会話が圧縮されると、サブエージェントのトランスクリプトは影響を受けません。これらは別のファイルに保存されます。
- セッション永続化: サブエージェントのトランスクリプトはセッション内で永続化されます。同じセッションを再開することで、Claude Code を再起動した後にサブエージェントを再開できます。
- 自動クリーンアップ: トランスクリプトは
cleanupPeriodDays設定に基づいてクリーンアップされます(デフォルト:30 日)。
ツール制限
サブエージェントは tools フィールド経由で制限されたツールアクセスを持つことができます。
- フィールドを省略: エージェントは利用可能なすべてのツールを継承します(デフォルト)
- ツールを指定: エージェントはリストされたツールのみを使用できます
この例では、コードを検査できるが、ファイルを変更したりコマンドを実行したりできない読み取り専用分析エージェントを作成します。
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, AgentDefinition
async def main():
async for message in query(
prompt="Analyze the architecture of this codebase",
options=ClaudeAgentOptions(
allowed_tools=["Read", "Grep", "Glob", "Agent"],
agents={
"code-analyzer": AgentDefinition(
description="Static code analysis and architecture review",
prompt="""You are a code architecture analyst. Analyze code structure,
identify patterns, and suggest improvements without making changes.""",
# Read-only tools: no Edit, Write, or Bash access
tools=["Read", "Grep", "Glob"],
)
},
),
):
if hasattr(message, "result"):
print(message.result)
asyncio.run(main())
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "Analyze the architecture of this codebase",
options: {
allowedTools: ["Read", "Grep", "Glob", "Agent"],
agents: {
"code-analyzer": {
description: "Static code analysis and architecture review",
prompt: `You are a code architecture analyst. Analyze code structure,
identify patterns, and suggest improvements without making changes.`,
// Read-only tools: no Edit, Write, or Bash access
tools: ["Read", "Grep", "Glob"]
}
}
}
})) {
if ("result" in message) console.log(message.result);
}
一般的なツール組み合わせ
| ユースケース | ツール | 説明 |
|---|---|---|
| 読み取り専用分析 | Read、Grep、Glob |
コードを検査できますが、変更または実行はできません |
| テスト実行 | Bash、Read、Grep |
コマンドを実行し、出力を分析できます |
| コード変更 | Read、Edit、Write、Grep、Glob |
コマンド実行なしで完全な読み取り/書き込みアクセス |
| 完全アクセス | すべてのツール | 親からすべてのツールを継承します(tools フィールドを省略) |
トラブルシューティング
Claude がサブエージェントに委譲していない
Claude がサブエージェントに委譲する代わりにタスクを直接完了する場合:
- Agent ツールを含める: サブエージェントは Agent ツール経由で呼び出されるため、
allowedToolsに含める必要があります - 明示的なプロンプトを使用する: プロンプトでサブエージェントを名前で言及します(例えば、「code-reviewer エージェントを使用して...」)
- 明確な説明を書く: サブエージェントをいつ使用すべきかを正確に説明し、Claude がタスクを適切にマッチングできるようにします
ファイルシステムベースのエージェントが読み込まれていない
.claude/agents/ で定義されたエージェントはスタートアップ時にのみ読み込まれます。Claude Code の実行中に新しいエージェントファイルを作成した場合、セッションを再起動して読み込んでください。
Windows:長いプロンプトの失敗
Windows では、非常に長いプロンプトを持つサブエージェントは、コマンドライン長の制限(8191 文字)により失敗する場合があります。プロンプトを簡潔に保つか、複雑な指示にはファイルシステムベースのエージェントを使用してください。
関連ドキュメント
- Claude Code サブエージェント:ファイルシステムベースの定義を含む包括的なサブエージェントドキュメント
- SDK 概要:Claude Agent SDK の開始方法