מדריך קלוד קוד בעברית

תיעוד 140

תת-סוכנים ב-SDK

הגדר והפעל תת-סוכנים כדי לבודד הקשר, להריץ משימות במקביל, ולהחיל הוראות ייעודיות ביישומי Claude Agent SDK שלך.

תת-סוכנים הם מופעי סוכן נפרדים שהסוכן הראשי שלך יכול להפעיל כדי לטפל במשימות משנה ממוקדות. השתמש בהם כדי לבודד הקשר, להריץ מספר ניתוחים במקביל, ולהחיל הוראות ייעודיות מבלי להעמיס על ההנחיה של הסוכן הראשי.

#סקירה כללית

באפשרותך ליצור תת-סוכנים בשלוש דרכים:

  • באופן תכנותי: השתמש בפרמטר agents באפשרויות של query(). ראה את הפניות התיעוד של TypeScript ושל Python
  • מבוסס מערכת קבצים: הגדר סוכנים כקובצי markdown בספריות .claude/agents/. ראה הגדרת תת-סוכנים כקבצים
  • כללי מובנה (Built-in general-purpose): Claude יכול להפעיל את תת-הסוכן המובנה general-purpose בכל עת באמצעות הכלי Agent מבלי שתגדיר דבר

מדריך זה מתמקד בגישה התכנותית, שהיא המומלצת עבור יישומי SDK.

#יתרונות השימוש בתת-סוכנים

מכיוון שתת-סוכנים הם מופעי סוכן נפרדים, האצלת עבודה אליהם מעניקה לך ארבעה יתרונות:

  • בידוד הקשר (Context isolation): כל תת-סוכן רץ בשיחה משלו, שמתחילה מחדש אלא אם תת-הסוכן הוא פיצול (fork). בכל מקרה, קריאות ביניים לכלים ותוצאותיהן נשארות בתוך תת-הסוכן, ורק ההודעה הסופית שלו חוזרת אל ההורה. תת-סוכן research-assistant יכול לחקור עשרות קבצים מבלי שאף חלק מתוכן זה יצטבר בשיחה הראשית. ההורה מקבל סיכום תמציתי, ולא כל קובץ שתת-הסוכן קרא. ראה מה תת-סוכנים יורשים כדי לראות בדיוק מה נמצא בהקשר של תת-הסוכן.
  • מקביליות (Parallelization): מספר תת-סוכנים יכולים לרוץ בו-זמנית, כך שמשימות משנה בלתי תלויות מסתיימות בזמן של האיטית שבהן ולא בסכום הזמנים של כולן. במהלך סקירת קוד, תוכל להריץ את תת-הסוכנים style-checker, security-scanner ו-test-coverage בו-זמנית במקום בזה אחר זה.
  • הוראות וידע ייעודיים: לכל תת-סוכן יכולה להיות הנחיית מערכת מותאמת אישית עם מומחיות ספציפית, שיטות עבודה מומלצות ואילוצים. לתת-סוכן database-migration יכול להיות ידע מפורט על שיטות עבודה מומלצות ב-SQL, אסטרטגיות שחזור לאחור (rollback) ובדיקות תקינות נתונים, שיהוו רעש מיותר בהוראות של הסוכן הראשי.
  • הגבלות כלים (Tool restrictions): ניתן להגביל תת-סוכנים לכלים ספציפיים, מה שמפחית את הסיכון לפעולות לא רצויות. לתת-סוכן doc-reviewer עשויה להיות גישה רק לכלים Read ו-Grep, מה שמבטיח שהוא יוכל לנתח אך לעולם לא לשנות בטעות את קובצי התיעוד שלך.

#יצירת תת-סוכנים

#הגדרה תכנותית (מומלץ)

הגדר תת-סוכנים ישירות בקוד שלך באמצעות הפרמטר agents. Claude מפעיל תת-סוכנים באמצעות הכלי Agent.

רוב הדוגמאות בדף זה מדפיסות רק את התוצאה הסופית. כדי לאשר ש-Claude האציל משימה לתת-סוכן במקום לענות ישירות, ראה זיהוי הפעלת תת-סוכן.

דוגמה זו יוצרת שני תת-סוכנים: סוקר קוד עם גישת קריאה בלבד, ומריץ בדיקות שיכול לבצע פקודות.

#Python

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(
            
# Auto-approve these tools
            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())

#TypeScript

import { query } from "@anthropic-ai/claude-agent-sdk";

for await (const message of query({
  prompt: "Review the authentication module for security issues",
  options: {
    // Auto-approve these tools
    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

שדהטיפוסנדרשתיאור
descriptionstringכןתיאור בשפה טבעית המציין מתי להשתמש בסוכן זה
promptstringכןהנחיית המערכת של הסוכן המגדירה את תפקידו והתנהגותו
toolsstring[]לאמערך של שמות כלים מורשים. אם הושמט, יורש כל כלי שזמין לתת-סוכנים
disallowedToolsstring[]לאמערך של שמות כלים להסרה מסט הכלים של הסוכן. מתקבלות גם תבניות ברמת שרת MCP: התבנית mcp__server או mcp__server__* מסירה כל כלי מאותו שרת, והתבנית mcp__* מסירה כל כלי MCP מכל שרת
modelstringלאדריסת מודל עבור סוכן זה. מקבל כינוי כגון 'fable', 'opus', 'sonnet', 'haiku', 'inherit', או מזהה מודל מלא. הערך 'inherit' משתמש במודל הראשי. כאשר משמיטים אותו, Claude Code בוחר את המודל לפי סדר עדיפות מודל תת-הסוכן
skillsstring[]לארשימה של שמות מיומנויות לטעינה מראש אל תוך ההקשר של הסוכן בעת ההפעלה. מיומנויות שלא נכללו ברשימה נשארות ניתנות להפעלה באמצעות הכלי Skill
memory'user' | 'project' | 'local'לאמקור הזיכרון עבור סוכן זה
mcpServers(string | object)[]לאשרתי MCP הזמינים לסוכן זה, לפי שם או תצורה מוטבעת
initialPromptstringלאנשלח אוטומטית כתור המשתמש הראשון כאשר סוכן זה רץ כסוכן השרשור הראשי. מנוטרל כאשר הסוכן מופעל כתת-סוכן
maxTurnsnumberלאמספר מרבי של תורות סוכן לפני שהסוכן עוצר. כאשר הסוכן מגיע למגבלה, Claude Code מחזיר את הפלט שלו כשהוא מסומן כחלקי, ובאפשרותך לחדש את פעולת הסוכן כדי להמשיך. הסימון כחלקי דורש את Claude Code בגרסה v2.1.246 ומעלה
backgroundbooleanלאהרץ סוכן זה כמשימת רקע שאינה חוסמת בעת הפעלתו
effort'low' | 'medium' | 'high' | 'xhigh' | 'max' | numberלארמת מאמץ החשיבה עבור סוכן זה
permissionModePermissionModeלאמצב הרשאות להרצת כלים בתוך סוכן זה

ב-Python SDK, שמות שדות המורכבים ממספר מילים, כגון disallowedTools ו-mcpServers, שומרים על איות ב-camelCase כדי להתאים למבנה המועבר ברשת, במקום לעקוב אחר מוסכמת snake_case של Python. ראה את הפניית התיעוד של AgentDefinition לפרטים נוספים.

תת-סוכנים רצים ברקע כברירת מחדל. קריאה לכלי Agent המשמיטה את הקלט run_in_background מפעילה תת-סוכן ברקע, ו-Claude מגדיר run_in_background: false כאשר הוא זקוק לתוצאה לפני שימשיך. הגדר את השדה background כ-true כדי לאלץ הרצה ברקע עבור סוכן ספציפי ללא תלות במה ש-Claude מבקש. לפני Claude Code בגרסה v2.1.198, ברירת המחדל להרצה ברקע נפרסה בהדרגה, וקריאה לכלי Agent שהשמיטה את run_in_background יכלה להריץ את תת-הסוכן באופן סינכרוני.

תת-סוכנים יכולים גם להפעיל תת-סוכנים משלהם. כדי להגביל את עומק הקינון, את מספר תת-הסוכנים שרצים בו-זמנית, ואת הסכום שהשאילתה מוציאה, ראה הגבלת עומק תת-סוכנים, ריצה מקבילית ועלויות.

#הגדרה מבוססת מערכת קבצים (חלופה)

באפשרותך גם להגדיר תת-סוכנים כקובצי markdown בספריות .claude/agents/. ראה את תיעוד תת-הסוכנים של Claude Code לפרטים על גישה זו. סוכנים המוגדרים באופן תכנותי מקבלים עדיפות על פני סוכנים מבוססי מערכת קבצים בעלי אותו שם.

הערה: כאשר Claude קורא לכלי Agent ללא subagent_type, הוא מקבל את תת-הסוכן המובנה general-purpose, ש-Claude יכול להפעיל גם כאשר אינך מגדיר אף סוכן משלך. הגדרת CLAUDE_AGENT_SDK_DISABLE_BUILTIN_AGENTS=1 מסירה את ברירת המחדל הזו, וקריאה כזו תיכשל עם השגיאה subagent_type is required.

#מה תת-סוכנים יורשים

אלא אם תת-הסוכן הוא פיצול (fork), חלון ההקשר שלו מתחיל מחדש, ללא שיחת ההורה, אך אינו ריק. התוכן היחיד שאתה מעביר מההורה לתת-הסוכן הוא מחרוזת ההנחיה של הכלי Agent, לכן כלול כל נתיב קובץ, הודעת שגיאה או החלטה שתת-הסוכן זקוק להם ישירות בתוך הנחיה זו.

תת-סוכן שיש לו את הכלי SendMessage מתחיל עם רשימה של שאר הסוכנים בעלי השם שרצים בסשן, כך שהוא יודע לאילו שמות הוא יכול לשלוח הודעות. Claude Code מוסיף את הרשימה לתור הראשון של תת-הסוכן באופן אוטומטי. פיצול (fork) אינו מקבל את הרשימה מכיוון שהוא יורש את שיחת ההורה במקום זאת.

תת-סוכן יורש גם את תצורת החשיבה המורחבת (extended thinking) של הסשן הראשי.

הטבלה שלהלן מפרטת מה מכיל ההקשר של תת-סוכן שאינו פיצול וממה הוא נמנע.

תת-הסוכן מקבלתת-הסוכן אינו מקבל
הנחיית מערכת משלו (AgentDefinition.prompt) ואת ההנחיה של הכלי Agentהיסטוריית השיחה או תוצאות הכלים של ההורה
קובץ CLAUDE.md של הפרויקט (נטען באמצעות settingSources)תוכן מיומנויות (skills) שנטען מראש, אלא אם צוין ב-AgentDefinition.skills
הגדרות כלים (מורשות מההורה או תת-הקבוצה המוגדרת ב-tools, מסוננות להרצות רקע)הנחיית המערכת של ההורה

הערה: ההורה מקבל את ההודעה הסופית של תת-הסוכן כתוצאה של הכלי Agent, אך עשוי לסכם אותה בתגובה שלו. כדי לשמור על פלט תת-הסוכן מילה במילה בתגובה המוצגת למשתמש, כלול הוראה לעשות זאת בהנחיה או באפשרות systemPrompt שאתה מעביר לקריאה הראשית של query().

בגרסה v2.1.210 ואילך, Claude Code סורק את ההודעה הסופית לאיתור תבניות בעלות מבנה של הוראות לפני שההורה קורא אותה. הסריקה מתייחסת לשלושה סוגי תבניות באופן שונה:

  • חיקוי תגי בקרה (Control-tag imitation): Claude Code מנטרל במקום תג שרק סביבת ההרצה פולטת, כגון בלוק <system-reminder>. הוא מכניס לוכסן שמאלי (backslash) אחרי סוגר הזווית הפותח ואינו מוחק דבר.
  • אזכורים של תצורת הרשאות: Claude Code משאיר התייחסויות לתצורת הרשאות, כגון .claude/settings.json, bypassPermissions, או --dangerously-skip-permissions, כפי שנכתבו.
  • סמני תור (Turn markers): שורה שמתחילה ב-Human: או ב-Assistant: מקבלת לוכסן שמאלי לפני הנקודתיים, כדי שההודעה לא תוכל לחקות גבול של תור בשיחה.

עבור התאמה של תג בקרה או תצורת הרשאות, Claude Code מוסיף בתחילה שורת סימון [harness: ...] המציינת את התבניות שהותאמו. התאמה של סמן תור אינה מוסיפה את שורת הסימון. אלו השינויים היחידים שהסריקה מבצעת: היא לעולם אינה מסירה או מנסחת מחדש את הטקסט של תת-הסוכן.

שגיאת API שמסיימת את תת-הסוכן מוקדם מהצפוי, כגון מגבלת קצב (rate limit), לעולם אינה נמסרת כתוצאה שלו. ראה שגיאות API בתת-סוכנים להתנהגות בחזית וברקע.

#הפעלת תת-סוכנים

#הפעלה אוטומטית

Claude מחליט אוטומטית מתי להפעיל תת-סוכנים על סמך המשימה וה-description של כל תת-סוכן. לדוגמה, אם תגדיר תת-סוכן performance-optimizer עם התיאור "Performance optimization specialist for query tuning", Claude יפעיל אותו כאשר ההנחיה שלך תזכיר ייעול שאילתות.

כתוב תיאורים ברורים וספציפיים כדי ש-Claude יוכל להתאים משימות לתת-הסוכן הנכון.

#הפעלה מפורשת

כדי להבטיח ש-Claude ישתמש בתת-סוכן ספציפי, ציין אותו בשמו בהנחיה שלך:

"Use the code-reviewer agent to check the authentication module"

פעולה זו עוקפת את ההתאמה האוטומטית ומפעילה ישירות את תת-הסוכן בעל השם.

#תצורת סוכן דינמית

באפשרותך ליצור הגדרות סוכן באופן דינמי על סמך תנאים בזמן ריצה. דוגמה זו יוצרת סוקר אבטחה עם רמות קפדנות שונות, תוך שימוש במודל בעל יכולות גבוהות יותר עבור סקירות קפדניות.

#Python

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())

#TypeScript

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);
}

#זיהוי הפעלת תת-סוכן

Claude מפעיל תת-סוכנים באמצעות הכלי Agent. כדי לזהות מתי תת-סוכן מופעל, בדוק אם יש בלוקי tool_use שבהם name הוא "Agent". הודעות מתוך ההקשר של תת-סוכן כוללות שדה parent_tool_use_id.

הערה: הכלי מופיע כ-"Agent" בבלוקי tool_use, אך כ-"Task" ברשימת הכלים של system:init. לפני Claude Code בגרסה v2.1.63, בלוקי tool_use כינו אותו גם "Task". כדי להבטיח שהזיהוי ימשיך לפעול בכל גרסאות ה-SDK, התאם את שני הערכים ב-block.name.

מבנה ההודעה שונה בין ספריות ה-SDK. ב-Python, הגישה לבלוקי התוכן נעשית ישירות דרך message.content. ב-TypeScript, האובייקט SDKAssistantMessage עוטף את הודעת ה-API של Claude, ולכן הגישה לתוכן היא דרך message.message.content.

דוגמה זו עוברת על הודעות המוזרמות, מתעדת ביומן מתי תת-סוכן מופעל ומתי הודעות עוקבות מגיעות מתוך הקשר ההרצה של אותו תת-סוכן.

#Python

import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, AgentDefinition, ToolUseBlock


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 isinstance(block, ToolUseBlock) 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())

#TypeScript

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);
  }
}

#חידוש תת-סוכנים

באפשרותך לחדש את פעולתו של תת-סוכן כדי להמשיך מהנקודה שבה עצר במקום להתחיל מחדש. תת-סוכן שחודש שומר על היסטוריית השיחה המלאה שלו, כולל כל הקריאות הקודמות לכלים, התוצאות ותהליכי החשיבה.

כאשר תת-סוכן עוצר בהגעה למגבלת maxTurns שלו, Claude Code מסמן את הפלט בתוצאת הכלי Agent כחלקי, כך ש-Claude יודע שההרצה לא הושלמה.

כאשר תת-סוכן מסיים, תוצאת הכלי Agent כוללת בלוק טקסט המכיל את המחרוזת agentId: <id>. סוכני Explore ו-Plan המובנים מיועדים להרצה חד-פעמית ואינם מחזירים agentId, לכן השתמש בסוכן מותאם אישית או ב-general-purpose כאשר יש צורך בחידוש הפעולה. כדי לחדש פעולת תת-סוכן באופן תכנותי:

  1. לכידת מזהה הסשן: חלץ את session_id מהודעות במהלך השאילתה הראשונה
  2. חילוץ מזהה הסוכן: נתח את agentId מתוך טקסט התוצאה של הכלי Agent
  3. חידוש פעולת הסשן: העבר resume: sessionId באפשרויות השאילתה השנייה, וכלול את מזהה הסוכן בהנחיה שלך. כל קריאה ל-query() מתחילה סשן חדש כברירת מחדל, וחובה לחדש את אותו סשן כדי לגשת לתמליל של תת-הסוכן.

הערה: בעת שימוש בסוכן מותאם אישית, העבר את אותה הגדרת סוכן בפרמטר agents עבור שתי השאילתות.

הדוגמה שלהלן מגדירה סוכן מותאם אישית בשם endpoint-finder. השאילתה הראשונה מריצה אותו ולוכדת את מזהה הסשן ואת מזהה הסוכן מתוצאת הכלי Agent, ולאחר מכן השאילתה השנייה מחדשת את הסשן כדי לשאול שאלת המשך הדורשת הקשר מניתוח המידע הראשוני.

#Python

import asyncio
import re
from claude_agent_sdk import query, ClaudeAgentOptions, AgentDefinition, ToolResultBlock

AGENTS = {
    "endpoint-finder": AgentDefinition(
        description="Locates and catalogs API endpoints in a codebase.",
        prompt="You find and document API endpoints. Report each endpoint's path, method, and handler.",
        tools=["Read", "Grep", "Glob"],
    )
}


def extract_agent_id(block: ToolResultBlock) -> str | None:
    """Extract agentId from an Agent tool result's text content."""
    parts = block.content if isinstance(block.content, list) else [{"text": block.content}]
    for part in parts:
        if match := re.search(r"agentId:\s*([\w-]+)", part.get("text") or ""):
            return match.group(1)
    return None


async def main():
    agent_id = None
    session_id = None

    
# First invocation - run the endpoint-finder subagent
    try:
        async for message in query(
            prompt="Use the endpoint-finder agent to find all API endpoints in this codebase",
            options=ClaudeAgentOptions(allowed_tools=["Read", "Grep", "Glob", "Agent"], agents=AGENTS),
        ):
            
# Capture session_id from ResultMessage (needed to resume this session)
            if hasattr(message, "session_id"):
                session_id = message.session_id
            
# Search tool results for the agentId trailer
            for block in getattr(message, "content", None) or []:
                if isinstance(block, ToolResultBlock):
                    agent_id = extract_agent_id(block) or agent_id
            
# Print the final result
            if hasattr(message, "result"):
                print(message.result)
    except Exception as error:
        
# A single-shot query() raises after yielding an error result,
        
# so session_id and agent_id have already been captured by the loop above.
        print(f"Session ended with an error: {error}")

    
# 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"], agents=AGENTS, resume=session_id
            ),
        ):
            if hasattr(message, "result"):
                print(message.result)
    else:
        print("No agentId found in the first query, so there is no subagent to resume.")


asyncio.run(main())

#TypeScript

import { query, type SDKMessage } from "@anthropic-ai/claude-agent-sdk";

const agents = {
  "endpoint-finder": {
    description: "Locates and catalogs API endpoints in a codebase.",
    prompt: "You find and document API endpoints. Report each endpoint's path, method, and handler.",
    tools: ["Read", "Grep", "Glob"]
  }
};

// Stringify content to search for agentId without traversing nested block types
function extractAgentId(message: SDKMessage): string | undefined {
  if (message.type !== "assistant" && message.type !== "user") return undefined;
  const content = JSON.stringify(message.message.content);
  const match = content.match(/agentId:\s*([\w-]+)/);
  return match?.[1];
}

let agentId: string | undefined;
let sessionId: string | undefined;

// First invocation - run the endpoint-finder subagent
try {
  for await (const message of query({
    prompt: "Use the endpoint-finder agent to find all API endpoints in this codebase",
    options: { allowedTools: ["Read", "Grep", "Glob", "Agent"], agents }
  })) {
    // 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);
  }
} catch (error) {
  // A single-shot query() throws after yielding an error result,
  // so sessionId and agentId have already been captured by the loop above.
  console.error(`Session ended with an error: ${error}`);
}

// 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"], agents, resume: sessionId }
  })) {
    if ("result" in message) console.log(message.result);
  }
} else {
  console.log("No agentId found in the first query, so there is no subagent to resume.");
}

תמלילי תת-סוכנים נשמרים בקבצים נפרדים ונשארים ללא תלות בשיחה הראשית. ראה חידוש תת-סוכנים ב-Claude Code עבור התנהגות דחיסה (compaction) ותקופת הניקוי cleanupPeriodDays.

#הגבלות כלים

השתמש בשדה tools כדי להגביל את מה שתת-סוכן יכול לעשות:

  • השמטת tools: תת-הסוכן מקבל כל כלי שזמין לתת-סוכנים
  • ציון רשימת כלים: תת-הסוכן מקבל רק אותם. לדוגמה, סוקר קוד שלעולם אינו אמור לערוך קבצים מקבל ["Read", "Grep", "Glob"]

כלי שאינך כולל אינו נמצא בסשן של תת-הסוכן כלל: Claude עובד בלעדיו, ללא בקשת הרשאה וללא שגיאה.

דוגמה זו יוצרת סוכן ניתוח לקריאה בלבד שיכול לבחון קוד אך אינו יכול לשנות קבצים או להריץ פקודות.

#Python

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())

#TypeScript

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)

#הגבלת עומק תת-סוכנים, ריצה מקבילית ועלויות

הערה: סעיף זה מתאר את TypeScript SDK בגרסה v0.3.219 ואת Python SDK בגרסה v0.2.127 ואילך, המהדורות הכוללות את Claude Code בגרסה v2.1.219 ואילך. במהדורות קודמות, חלק ממגבלות אלו חסרות או מוגדרות עם ברירות מחדל שונות, לכן שדרג לפני שאתה מסתמך עליהן להגבלת הרצה. תיעוד משתני הסביבה ו-תורות ותקציב מתעדים את גרסת Claude Code שהוסיפה כל משתנה ואת אכיפת תקרת ההוצאות על תת-סוכנים.

Claude מחליט בעצמו מתי להפעיל תת-סוכן וכמה להפעיל. כל תת-סוכן מבצע בקשות API משלו, הנחשבות לחלק מ-total_cost_usd של השאילתה, ותת-סוכן יכול להפעיל תת-סוכנים משלו, כך שהנחיה אחת עלולה לצמוח לעץ של סוכנים.

באפשרותך להגביל צמיחה זו בשלוש דרכים: עומק הקינון של תת-הסוכנים, כמה מהם רצים בו-זמנית, וכמה כל השאילתה מוציאה. הגדר את מגבלות העומק והמקביליות כמשתני סביבה באמצעות האפשרות env, ואת מגבלת ההוצאה כאפשרות שאילתה:

מגבלההגדרה באמצעותברירת מחדלמה Claude Code עושה בהגעה למגבלה
עומקCLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH3 שכבות של תת-סוכנים מתחת לסוכן הראשי שלך. הערך 1 מונע מתת-הסוכנים שלך להפעיל תת-סוכנים משלהםמשאיר תת-סוכן בשכבה התחתונה ללא יכולת להפעיל סוכנים נוספים, כך שהוא מבצע את העבודה שהואצלה לו בעצמו. ראה תת-סוכנים מקוננים
מקביליותCLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS20 תת-סוכנים הרצים בו-זמנית, בספירת כל תת-סוכן ש-Claude מפעיל באמצעות הכלי Agentמסרב להפעיל תת-סוכן נוסף ומחזיר Concurrent subagent limit reached, עד שמספר הסוכנים הרצים יורד מתחת למגבלה. סשנים שבהם ultracode פעיל אינם מסורבים לעולם. ראה מגבלת תת-סוכנים מקביליים
עלותmaxBudgetUsd ב-TypeScript, או max_budget_usd ב-Pythonללא מגבלה. מושווה מול total_cost_usd, כך שבקשות של תת-סוכנים נספרותאוכף את התקרה בשלוש דרכים: מסרב להפעיל תת-סוכנים נוספים ומחזיר Budget limit reached, עוצר תת-סוכנים ברקע שעדיין רצים, ומסיים את השאילתה עם תת-סוג תוצאה error_max_budget_usd. ראה תורות ותקציב

שתי ספריות ה-SDK מתייחסות לאפשרות env באופן שונה: ה-TypeScript SDK מחליף באמצעותה את סביבת תהליך המשנה (subprocess environment), לכן פרוס לתוכה את process.env כדי לשמור על משתנים כמו PATH, בעוד ש-Python SDK ממזג אותה אל תוך הסביבה שירש. דוגמה זו מבטלת קינון, מאפשרת לכל היותר חמישה תת-סוכנים בו-זמנית, ועוצרת את השאילתה ברגע שההוצאה המשוערת מגיעה ל-5 דולר:

#Python

import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage


async def main():
    try:
        async for message in query(
            prompt="Audit every service in this repo for unhandled promise rejections",
            options=ClaudeAgentOptions(
                allowed_tools=["Read", "Grep", "Glob", "Agent"],
                
# env is merged on top of the inherited environment
                env={
                    "CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH": "1",
                    "CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS": "5",
                },
                max_budget_usd=5.0,
            ),
        ):
            if isinstance(message, ResultMessage):
                print(f"{message.subtype}: ${message.total_cost_usd}")
    except Exception as error:
        
# A single-shot query() raises after yielding an error result,
        
# so the budget-capped result has already been printed above.
        print(f"Session ended with an error: {error}")


asyncio.run(main())

#TypeScript

import { query } from "@anthropic-ai/claude-agent-sdk";

try {
  for await (const message of query({
    prompt: "Audit every service in this repo for unhandled promise rejections",
    options: {
      allowedTools: ["Read", "Grep", "Glob", "Agent"],
      // env replaces the subprocess environment, so spread process.env to keep PATH
      env: {
        ...process.env,
        CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH: "1",
        CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS: "5",
      },
      maxBudgetUsd: 5,
    },
  })) {
    if (message.type === "result") {
      console.log(`${message.subtype}: $${message.total_cost_usd}`);
    }
  }
} catch (error) {
  // A single-shot query() throws after yielding an error result,
  // so the budget-capped result has already been logged above.
  console.error(`Session ended with an error: ${error}`);
}

מה שתראה תלוי באיזו מגבלה, אם בכלל, השאילתה מגיעה אליה:

  • מתחת לתקרת ההוצאה: אתה רואה success ואת העלות המשוערת.
  • בתקרת ההוצאה: אתה רואה error_max_budget_usd עם עלות של 5 או יותר, ולאחר מכן מופעל מטפל השגיאות שלך.
  • במגבלת המקביליות: אתה רואה בלוק tool_result בזרם ההודעות הנושא את Concurrent subagent limit reached. Claude מקבל את אותו בלוק כתוצאה של הכלי Agent.

#הרצת Opus 5 עם תת-סוכנים

Claude Opus 5 מאציל משימות לתת-סוכנים בקלות רבה יותר מדגמים קודמים, לכן מגבלות העומק, המקביליות וההוצאה חשובות במיוחד בשאילתות המריצות את Opus 5. מדריך ההנחיות של Opus 5 כולל הוראת האצלה שבאפשרותך להוסיף לכל הנחיה. השאלה אם Claude Code מוסיף הוראה משלו תלויה באיזו הנחיית מערכת אתה משתמש:

  • הגדרה מראש (preset) של claude_code: כאשר המודל הוא Opus 5, Claude Code מוסיף שורה להנחיית המערכת שלו המורה ל-Claude לא לקרוא לכלי Agent אלא אם התבקש לעשות זאת. הכלי Agent נשאר זמין.
  • הנחיה מותאמת אישית, או ללא systemPrompt: Claude Code אינו בונה את הנחיית המערכת שלו, ולכן שורה זו נעדרת. הוסף את הוראת ההאצלה ממדריך ההנחיות להנחיה שלך.

כל אחת מההוראות רק מכוונת את Claude, לכן הגדר גם את המגבלות. Claude Code אוכף אותן ללא קשר לאופן שבו Claude מחליט להאציל משימות.

#הגדלת היקף העבודה באמצעות תהליכי עבודה דינמיים

תת-סוכנים מתאימים היטב למספר קטן של משימות מואצלות בכל תור. עבור הרצות שמתאמות בין עשרות עד מאות סוכנים, השתמש בכלי Workflow, אשר מעביר את התיאום לסקריפט שסביבת ההרצה מפעילה מחוץ להקשר השיחה. ראה תהליכי עבודה דינמיים כדי לראות כיצד תהליכי עבודה נבדלים מהאצלה לתת-סוכנים מתור לתור.

הכלי Workflow זמין ב-TypeScript Agent SDK בגרסה v0.3.149 ואילך. כלול את Workflow ב-allowedTools כדי לאשר אוטומטית הרצות של תהליכי עבודה. סכמות הקלט והפלט של הכלי מפורטות ב-הפניית התיעוד של TypeScript.

#פתרון בעיות

#Claude אינו מאציל משימות לתת-סוכנים

אם Claude משלים משימות ישירות במקום להאציל אותן לתת-הסוכן שלך:

  • השתמש בהנחיה מפורשת: ציין את תת-הסוכן בשמו בהנחיה שלך, לדוגמה "Use the code-reviewer agent to..."
  • כתוב תיאור ברור: הסבר בדיוק מתי להשתמש בתת-הסוכן כדי ש-Claude יוכל להתאים משימות בצורה נכונה

#סוכנים מבוססי מערכת קבצים אינם נטענים

Claude Code עוקב אחר ~/.claude/agents/ ו-.claude/agents/ ומזהה קובץ סוכן חדש או ערוך תוך שניות בודדות, ללא צורך בהפעלה מחדש. אם הגדרה אינה מופיעה לעולם, בדוק את הסיבות הבאות:

  • ספריית agents חדשה: רכיב המעקב מכסה רק ספריות שהיו קיימות כאשר הסשן התחיל, ולכן הקובץ הראשון בספרייה חדשה דורש הפעלה מחדש של הסשן. זוהי הסיבה הנפוצה ביותר.
  • frontmatter לא תקין או name כפול: בדוק את ה-YAML של הקובץ, והאם סוכן קיים כבר משתמש ב-name זה.
  • --disable-slash-commands: סשנים שהופעלו עם דגל זה אינם עוקבים אחר ספריות אלו ותמיד דורשים הפעלה מחדש כדי לטעון קבצים חדשים.
  • קובץ תחת ספרייה שנוספה: Claude Code טוען את .claude/agents/ מספריות שנוספו עם האפשרות add_dirs (ב-Python) או additionalDirectories (ב-TypeScript), או דרך --add-dir או /add-dir ב-CLI, אך אינו עוקב אחריהן, ולכן קובץ חדש או ערוך שם דורש הפעלה מחדש של הסשן.
  • סוכן תכנותי בעל אותו שם: פרמטר agents המועבר ל-query() דורס סוכן ממערכת הקבצים בעל אותו שם.

עבור מבנה הקובץ, ראה כיצד לכתוב קובצי תת-סוכנים.

#תיעוד קשור