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

תיעוד 195

הפניה ל-Agent SDK - Python

הפניה מלאה ל-API של Agent SDK בפייתון, כולל כל הפונקציות, הטיפוסים והמחלקות.

#התקנה

התקינו את החבילה בסביבה וירטואלית. בהתקנות Python עדכניות של Debian, Ubuntu ו-Homebrew, הרצה של pip install מול Python של המערכת נכשלת עם error: externally-managed-environment.

python3 -m venv .venv
source .venv/bin/activate
pip install claude-agent-sdk

לגבי uv, Windows PowerShell והגדרת מפתח API, ראו הגדרה במדריך המהיר של Agent SDK.

#בחירה בין query() לבין ClaudeSDKClient

ה-SDK של Python מספק שתי דרכים לקיים אינטראקציה עם Claude Code:

מאפייןquery()ClaudeSDKClient
סשןיוצר סשן חדש כברירת מחדלעושה שימוש חוזר באותו סשן
שיחהחילוף יחידכמה חילופים באותו הקשר
חיבורמנוהל אוטומטיתשליטה ידנית
קלט בזרימה✅ נתמך✅ נתמך
פסיקות❌ לא נתמך✅ נתמך
Hooks✅ נתמך✅ נתמך
כלים מותאמים✅ נתמך✅ נתמך
המשך צ'אטידני דרך continue_conversation או resume✅ אוטומטי
תרחיש שימושמשימות חד-פעמיותשיחות מתמשכות

השתמשו ב-ClaudeSDKClient ליישומים אינטראקטיביים כמו ממשקי צ'אט, או כשהפעולה הבאה תלויה בתשובה של Claude.

#פונקציות

[!NOTE]

בלוקי חתימה וקטעים חשופים של async for או async with בדף הזה הם להמחשה. כדי להריץ אותם, עטפו את הגוף ב-async def main(): ... וקראו ל-asyncio.run(main()).

#query()

יוצר סשן חדש לכל אינטראקציה עם Claude Code כברירת מחדל. מחזיר איטרטור אסינכרוני שמניב הודעות כשהן מגיעות. כל קריאה ל-query() מתחילה מחדש בלי זיכרון של אינטראקציות קודמות, אלא אם מעבירים continue_conversation=True או resume ב-ClaudeAgentOptions. ראו סשנים.

async def query(
    *,
    prompt: str | AsyncIterable[dict[str, Any]],
    options: ClaudeAgentOptions | None = None,
    transport: Transport | None = None
) -> AsyncIterator[Message]

#פרמטרים

פרמטרטיפוסתיאור
promptstr | AsyncIterable[dict]פרומפט הקלט כמחרוזת, או כאיטרבל אסינכרוני למצב זרימה
optionsClaudeAgentOptions | Noneאובייקט הגדרות אופציונלי (ברירת המחדל היא ClaudeAgentOptions() אם הערך הוא None)
transportTransport | Noneתעבורה מותאמת אופציונלית לתקשורת עם תהליך ה-CLI

#ערך מוחזר

מחזיר AsyncIterator[Message] שמניב הודעות מהשיחה.

#דוגמה - עם אפשרויות

import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions


async def main():
    options = ClaudeAgentOptions(
        system_prompt="You are an expert Python developer",
        permission_mode="acceptEdits",
    )

    async for message in query(prompt="Create a Python web server", options=options):
        print(message)


asyncio.run(main())

#tool()

דקורטור להגדרת כלי MCP עם בטיחות טיפוסים.

def tool(
    name: str,
    description: str,
    input_schema: type | dict[str, Any],
    annotations: ToolAnnotations | None = None
) -> Callable[[Callable[[Any], Awaitable[dict[str, Any]]]], SdkMcpTool[Any]]

#פרמטרים

פרמטרטיפוסתיאור
namestrמזהה ייחודי לכלי
descriptionstrתיאור קריא לבני אדם של מה שהכלי עושה
input_schematype | dict[str, Any]סכמה שמגדירה את פרמטרי הקלט של הכלי. ראו אפשרויות לסכמת קלט
annotationsToolAnnotations | Noneהערות כלי MCP אופציונליות שמספקות רמזים התנהגותיים ללקוחות

#אפשרויות לסכמת קלט

  1. מיפוי טיפוסים פשוט (מומלץ):

    {"text": str, "count": int, "enabled": bool}
  2. פורמט JSON Schema (לאימות מורכב):

    {
        "type": "object",
        "properties": {
            "text": {"type": "string"},
            "count": {"type": "integer", "minimum": 0},
        },
        "required": ["text"],
    }
  3. מחלקת TypedDict: סכמה מטיפוס, שמפתחות NotRequired שלה נשארים מחוץ ל-required.

    • Python 3.11 ואילך: ייבאו את TypedDict ואת NotRequired מ-typing.
    • Python 3.10: ב-typing אין NotRequired. ייבאו את TypedDict ואת NotRequired מ-typing_extensions, שה-SDK מתקין ב-Python 3.10.
    from typing import Annotated, Any, NotRequired, TypedDict
    from claude_agent_sdk import tool
    
    
    class ForecastArgs(TypedDict):
        latitude: Annotated[float, "Latitude coordinate"]
        hours: NotRequired[Annotated[int, "How many hours of forecast to return"]]
    
    
    @tool("get_forecast", "Get the hourly forecast for a location", ForecastArgs)
    async def get_forecast(args: dict[str, Any]) -> dict[str, Any]:
        hours = args.get("hours", 12)
        return {"content": [{"type": "text", "text": f"{hours}-hour forecast for {args['latitude']}"}]}

בצורות של מיפוי פשוט ושל TypedDict, עטפו טיפוס ב-Annotated[type, "description"] כדי לקבוע את תיאור השדה.

#ערך מוחזר

פונקציית דקורטור שעוטפת את מימוש הכלי ומחזירה מופע SdkMcpTool.

#דוגמה

from claude_agent_sdk import tool
from typing import Any


@tool("greet", "Greet a user", {"name": str})
async def greet(args: dict[str, Any]) -> dict[str, Any]:
    return {"content": [{"type": "text", "text": f"Hello, {args['name']}!"}]}

#ToolAnnotations

רמזים התנהגותיים לכלי, שמועברים כארגומנט annotations של tool(). ToolAnnotations מרחיב את mcp.types.ToolAnnotations של MCP SDK בשדה maxResultSizeChars, ואפשר לכתוב כל רמז ב-camelCase או ב-snake_case: ToolAnnotations(readOnlyHint=True) ו-ToolAnnotations(read_only_hint=True) שקולים. כדי לקרוא רמז בחזרה מהאובייקט, השתמשו באיות שמצהירה עליו חבילת mcp המותקנת: .readOnlyHint ב-mcp 1.x ו-.read_only_hint ב-2.x, בעוד .maxResultSizeChars עובד בשניהם. אפשר גם להעביר mcp.types.ToolAnnotations רגיל בכל מקום שה-SDK מקבל בו annotations.

שמות snake_case והשדה המטיפוס maxResultSizeChars דורשים Python Agent SDK 0.2.140 ואילך. גרסאות 0.1.31 עד 0.2.139 מייצאות מחדש את mcp.types.ToolAnnotations בלי שינוי. בגרסאות 0.1.55 עד 0.2.139 עדיין אפשר להעביר את maxResultSizeChars כארגומנט מילת מפתח: מחלקת MCP מקבלת שדות נוספים, וה-SDK מעביר את הערך אל Claude Code.

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

שדהטיפוסברירת מחדלתיאור
titlestr | NoneNoneכותרת קריאה לבני אדם לכלי
readOnlyHintbool | NoneFalseאם True, הכלי לא משנה את הסביבה שלו
destructiveHintbool | NoneTrueאם True, הכלי עשוי לבצע עדכונים הרסניים (משמעותי רק כש-readOnlyHint הוא False)
idempotentHintbool | NoneFalseאם True, לקריאות חוזרות עם אותם ארגומנטים אין השפעה נוספת (משמעותי רק כש-readOnlyHint הוא False)
openWorldHintbool | NoneTrueאם True, הכלי מקיים אינטראקציה עם ישויות חיצוניות (לדוגמה, חיפוש באינטרנט). אם False, התחום של הכלי סגור (לדוגמה, כלי זיכרון)
maxResultSizeCharsint | NoneNoneמספר התווים שעד אליו Claude Code שומר את תוצאת הטקסט של הכלי הזה בתוך השיחה, במקום לשמור אותה בקובץ, עד 500,000. תוצאות שמכילות תמונות לא מושפעות. זו הגדרה של Claude Code ולא רמז MCP: ה-SDK שולח אותה ב-_meta של הכלי בתור anthropic/maxResultSizeChars. ראו העלאת המגבלה לכלי מסוים
from claude_agent_sdk import tool, ToolAnnotations
from typing import Any


@tool(
    "search",
    "Search the web",
    {"query": str},
    annotations=ToolAnnotations(readOnlyHint=True, openWorldHint=True),
)
async def search(args: dict[str, Any]) -> dict[str, Any]:
    return {"content": [{"type": "text", "text": f"Results for: {args['query']}"}]}

#create_sdk_mcp_server()

יוצר שרת MCP בתוך התהליך, שרץ בתוך יישום Python שלכם.

def create_sdk_mcp_server(
    name: str,
    version: str = "1.0.0",
    tools: list[SdkMcpTool[Any]] | None = None
) -> McpSdkServerConfig

#פרמטרים

פרמטרטיפוסברירת מחדלתיאור
namestr-מזהה ייחודי לשרת
versionstr"1.0.0"מחרוזת גרסת השרת
toolslist[SdkMcpTool[Any]] | NoneNoneרשימת פונקציות כלים שנוצרו עם הדקורטור @tool

#ערך מוחזר

מחזיר אובייקט McpSdkServerConfig שאפשר להעביר אל ClaudeAgentOptions.mcp_servers.

#דוגמה

from claude_agent_sdk import tool, create_sdk_mcp_server, ClaudeAgentOptions


@tool("add", "Add two numbers", {"a": float, "b": float})
async def add(args):
    return {"content": [{"type": "text", "text": f"Sum: {args['a'] + args['b']}"}]}


@tool("multiply", "Multiply two numbers", {"a": float, "b": float})
async def multiply(args):
    return {"content": [{"type": "text", "text": f"Product: {args['a'] * args['b']}"}]}


calculator = create_sdk_mcp_server(
    name="calculator",
    version="2.0.0",
    tools=[add, multiply],  # Pass decorated functions
)

# Use with Claude
options = ClaudeAgentOptions(
    mcp_servers={"calc": calculator},
    allowed_tools=["mcp__calc__add", "mcp__calc__multiply"],
)

#list_sessions()

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

def list_sessions(
    directory: str | None = None,
    limit: int | None = None,
    offset: int = 0,
    include_worktrees: bool = True
) -> list[SDKSessionInfo]

#פרמטרים

פרמטרטיפוסברירת מחדלתיאור
directorystr | NoneNoneספרייה שעבורה מציגים סשנים. כשמשמיטים, מחזיר סשנים מכל הפרויקטים
limitint | NoneNoneהמספר המרבי של סשנים להחזרה
offsetint0מספר הסשנים לדילוג מתחילת התוצאות הממוינות. השתמשו יחד עם limit לעימוד
include_worktreesboolTrueכש-directory נמצא בתוך מאגר git, כלול סשנים מכל נתיבי ה-worktree

#טיפוס החזרה: SDKSessionInfo

מאפייןטיפוסתיאור
session_idstrמזהה סשן ייחודי
summarystrכותרת תצוגה: כותרת מותאמת, הפרומפט האחרון, סיכום שנוצר אוטומטית, או הפרומפט הראשון
last_modifiedintזמן השינוי האחרון באלפיות שנייה מאז epoch
file_sizeint | Noneגודל קובץ הסשן בבתים (None עבור צדדי אחסון מרוחקים)
custom_titlestr | Noneכותרת הסשן: הכותרת שהמשתמש קבע, או הכותרת שנוצרה אוטומטית כשאף כותרת לא נקבעה
first_promptstr | Noneהפרומפט המשמעותי הראשון של המשתמש בסשן
git_branchstr | Noneענף Git בסוף הסשן
cwdstr | Noneספריית העבודה של הסשן
tagstr | Noneתג סשן שהמשתמש קבע (ראו tag_session())
created_atint | Noneזמן יצירת הסשן באלפיות שנייה מאז epoch

#דוגמה

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

from claude_agent_sdk import list_sessions

for session in list_sessions(directory="/path/to/project", limit=10):
    print(f"{session.summary} ({session.session_id})")

#get_session_messages()

מאחזר הודעות מסשן קודם. סינכרוני. חוזר מיד.

def get_session_messages(
    session_id: str,
    directory: str | None = None,
    limit: int | None = None,
    offset: int = 0
) -> list[SessionMessage]

#פרמטרים

פרמטרטיפוסברירת מחדלתיאור
session_idstrחובהמזהה הסשן שעבורו מאחזרים הודעות
directorystr | NoneNoneספריית הפרויקט לחיפוש. כשמשמיטים, מחפש בכל הפרויקטים
limitint | NoneNoneהמספר המרבי של הודעות להחזרה
offsetint0מספר ההודעות לדילוג מההתחלה

#טיפוס החזרה: SessionMessage

מאפייןטיפוסתיאור
typeLiteral["user", "assistant"]תפקיד ההודעה
uuidstrמזהה הודעה ייחודי
session_idstrמזהה הסשן
messageAnyתוכן ההודעה הגולמי
parent_tool_use_idstr | Noneבהודעות של subagent, המזהה של בלוק השימוש בכלי Agent שיצר אותו. None להודעות של הסשן הראשי ולסשנים ישנים יותר
parent_agent_idstr | Noneלהודעות מ-subagent מקונן, מזהה הסוכן של ה-subagent ההורה. None להודעות של הסשן הראשי, להודעות של subagent ברמה העליונה, ולסשנים ישנים יותר. דורש Python Agent SDK 0.2.140 ואילך

#דוגמה

from claude_agent_sdk import list_sessions, get_session_messages

sessions = list_sessions(limit=1)
if sessions:
    messages = get_session_messages(sessions[0].session_id)
    for msg in messages:
        print(f"[{msg.type}] {msg.uuid}")

#get_session_info()

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

def get_session_info(
    session_id: str,
    directory: str | None = None,
) -> SDKSessionInfo | None

#פרמטרים

פרמטרטיפוסברירת מחדלתיאור
session_idstrחובהUUID של הסשן לחיפוש
directorystr | NoneNoneנתיב ספריית הפרויקט. כשמשמיטים, מחפש בכל ספריות הפרויקטים

מחזיר SDKSessionInfo, או None אם הסשן לא נמצא.

#דוגמה

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

from claude_agent_sdk import get_session_info

info = get_session_info("550e8400-e29b-41d4-a716-446655440000")
if info:
    print(f"{info.summary} (branch: {info.git_branch}, tag: {info.tag})")

#rename_session()

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

def rename_session(
    session_id: str,
    title: str,
    directory: str | None = None,
) -> None

#פרמטרים

פרמטרטיפוסברירת מחדלתיאור
session_idstrחובהUUID של הסשן לשינוי שם
titlestrחובהכותרת חדשה. חייבת להיות לא ריקה אחרי הסרת רווח לבן
directorystr | NoneNoneנתיב ספריית הפרויקט. כשמשמיטים, מחפש בכל ספריות הפרויקטים

מעלה ValueError אם session_id אינו UUID תקין או אם title ריק. מעלה FileNotFoundError אם אי אפשר למצוא את הסשן.

#דוגמה

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

from claude_agent_sdk import list_sessions, rename_session

sessions = list_sessions(directory="/path/to/project", limit=1)
if sessions:
    rename_session(sessions[0].session_id, "Refactor auth module")

#tag_session()

מתייג סשן. העבירו None כדי לנקות את התג. קריאות חוזרות בטוחות. התג האחרון הוא הקובע. סינכרוני.

def tag_session(
    session_id: str,
    tag: str | None,
    directory: str | None = None,
) -> None

#פרמטרים

פרמטרטיפוסברירת מחדלתיאור
session_idstrחובהUUID של הסשן לתיוג
tagstr | Noneחובהמחרוזת תג, או None לניקוי. עובר ניקוי Unicode לפני השמירה
directorystr | NoneNoneנתיב ספריית הפרויקט. כשמשמיטים, מחפש בכל ספריות הפרויקטים

מעלה ValueError אם session_id אינו UUID תקין או אם tag ריק אחרי הניקוי. מעלה FileNotFoundError אם אי אפשר למצוא את הסשן.

#דוגמה

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

from claude_agent_sdk import list_sessions, tag_session

# Tag the most recent session
sessions = list_sessions(directory="/path/to/project", limit=1)
if sessions:
    tag_session(sessions[0].session_id, "needs-review")

# Later: find all sessions with that tag
for session in list_sessions(directory="/path/to/project"):
    if session.tag == "needs-review":
        print(session.summary)

#fork_session()

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

def fork_session(
    session_id: str,
    directory: str | None = None,
    up_to_message_id: str | None = None,
    title: str | None = None,
) -> ForkSessionResult

#פרמטרים

פרמטרסוגברירת מחדלתיאור
session_idstrחובהUUID של הסשן לפיצול
directorystr | NoneNoneנתיב ספריית הפרויקט. כשמושמט, החיפוש מתבצע בכל ספריות הפרויקט
up_to_message_idstr | NoneNoneמעתיק את התמליל עד וכולל ההודעה עם UUID זה, כגון uuid מ-get_session_messages(). כשמושמט, מעתיק את כל התמליל
titlestr | NoneNoneכותרת לפיצול. כשמושמט, ה-SDK גוזר כותרת מהסשן המקורי, ואחריה (fork)

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

fork_session() מעלה:

  • ValueError: session_id או up_to_message_id אינו UUID תקין
  • ValueError: בסשן אין הודעות, או ש-up_to_message_id לא תואם לאף הודעה בתמליל
  • FileNotFoundError: לא ניתן למצוא את הסשן

#דוגמה

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

from claude_agent_sdk import fork_session, list_sessions

sessions = list_sessions(directory="/path/to/project", limit=1)
if sessions:
    forked = fork_session(sessions[0].session_id, title="Try the OAuth approach")
    print(forked.session_id)  # pass as ClaudeAgentOptions(resume=...) to continue the fork

#מחלקות

#ClaudeSDKClient

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

class ClaudeSDKClient:
    def __init__(self, options: ClaudeAgentOptions | None = None, transport: Transport | None = None)
    async def connect(self, prompt: str | AsyncIterable[dict] | None = None) -> None
    async def query(self, prompt: str | AsyncIterable[dict], session_id: str = "default") -> None
    async def receive_messages(self) -> AsyncIterator[Message]
    async def receive_response(self) -> AsyncIterator[Message]
    async def interrupt(self) -> None
    async def set_permission_mode(self, mode: PermissionMode) -> None
    async def set_model(self, model: str | None = None) -> None
    async def rewind_files(self, user_message_id: str) -> None
    async def get_mcp_status(self) -> McpStatusResponse
    async def get_context_usage(self) -> ContextUsageResponse
    async def reconnect_mcp_server(self, server_name: str) -> None
    async def toggle_mcp_server(self, server_name: str, enabled: bool) -> None
    async def stop_task(self, task_id: str) -> None
    async def get_server_info(self) -> dict[str, Any] | None
    async def disconnect(self) -> None

#מתודות

מתודהתיאור
__init__(options)מאתחל את הלקוח עם תצורה אופציונלית
connect(prompt)מתחבר אל Claude עם הנחיה ראשונית אופציונלית או זרם הודעות
query(prompt, session_id)שולח בקשה חדשה במצב הזרמה
receive_messages()מקבל את כל ההודעות מ-Claude כאיטרטור אסינכרוני
receive_response()מקבל הודעות עד וכולל ResultMessage
interrupt()שולח אות פסיקה (עובד רק במצב הזרמה)
set_permission_mode(mode)משנה את מצב ההרשאות של הסשן הנוכחי
set_model(model)משנה את המודל של הסשן הנוכחי. מעבירים None כדי לאפס למודל ברירת המחדל של Claude Code. סשן במצב auto משתנה למצב default אם המודל החדש לא תומך במצב auto
rewind_files(user_message_id)משחזר קבצים למצבם בהודעת המשתמש שצוינה. דורש enable_file_checkpointing=True. ראו נקודות ביקורת של קבצים
get_mcp_status()מקבל את הסטטוס של כל שרתי ה-MCP המוגדרים. מחזיר McpStatusResponse
get_context_usage()מקבל פירוט של שימוש בחלון ההקשר לפי קטגוריה, skill וכלי. כולל את הנתונים ש-/context מציג בסשן אינטראקטיבי. מחזיר ContextUsageResponse. כדי לחשב את הפירוט, Claude Code מבצע כמה בקשות API לספירת טוקנים שלא מופיעות בזרם ההודעות. ראו איך הבקשות האלה מטופלות
reconnect_mcp_server(server_name)מנסה מחדש להתחבר לשרת MCP שנכשל או נותק
toggle_mcp_server(server_name, enabled)מפעיל או משבית שרת MCP באמצע הסשן. השבתת שרת stdio, SSE או HTTP מסירה את הכלים שלו
stop_task(task_id)עוצר משימת רקע שרצה. TaskNotificationMessage עם סטטוס "stopped" מגיע אחרי כן בזרם ההודעות
get_server_info()מקבל את פרטי האתחול של השרת, כולל פקודות זמינות וסגנונות פלט
disconnect()מתנתק מ-Claude

#תמיכה במנהל הקשר

אפשר להשתמש בלקוח כמנהל הקשר אסינכרוני לניהול חיבור אוטומטי:

import asyncio
from claude_agent_sdk import ClaudeSDKClient


async def main():
    async with ClaudeSDKClient() as client:
        await client.query("Hello Claude")
        async for message in client.receive_response():
            print(message)


asyncio.run(main())

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

#דוגמה: המשך שיחה

import asyncio
from claude_agent_sdk import ClaudeSDKClient, AssistantMessage, TextBlock, ResultMessage


async def main():
    async with ClaudeSDKClient() as client:
        # First question
        await client.query("What's the capital of France?")

        # Process response
        async for message in client.receive_response():
            if isinstance(message, AssistantMessage):
                for block in message.content:
                    if isinstance(block, TextBlock):
                        print(f"Claude: {block.text}")

        # Follow-up question - the session retains the previous context
        await client.query("What's the population of that city?")

        async for message in client.receive_response():
            if isinstance(message, AssistantMessage):
                for block in message.content:
                    if isinstance(block, TextBlock):
                        print(f"Claude: {block.text}")

        # Another follow-up - still in the same conversation
        await client.query("What are some famous landmarks there?")

        async for message in client.receive_response():
            if isinstance(message, AssistantMessage):
                for block in message.content:
                    if isinstance(block, TextBlock):
                        print(f"Claude: {block.text}")


asyncio.run(main())

#דוגמה: קלט בזרם עם ClaudeSDKClient

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

import asyncio
from claude_agent_sdk import ClaudeSDKClient


async def message_stream():
    """Assemble the prompt at send time and yield it as one user message."""
    readings = {"Temperature": "25°C", "Humidity": "60%"}
    data = ", ".join(f"{name}: {value}" for name, value in readings.items())
    yield {
        "type": "user",
        "message": {
            "role": "user",
            "content": f"Analyze the following sensor data and describe any patterns you see: {data}",
        },
    }


async def main():
    async with ClaudeSDKClient() as client:
        # Stream input to Claude
        await client.query(message_stream())

        # Process response
        async for message in client.receive_response():
            print(message)

        # Follow-up in same session
        await client.query("Should we be concerned about these readings?")

        async for message in client.receive_response():
            print(message)


asyncio.run(main())

#דוגמה: שימוש בפסיקות

import asyncio
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions, ResultMessage


async def interruptible_task():
    options = ClaudeAgentOptions(allowed_tools=["Bash"], permission_mode="acceptEdits")

    async with ClaudeSDKClient(options=options) as client:
        # Start a long-running task
        await client.query("Count from 1 to 100 slowly, using the bash sleep command")

        # Let it run for a bit
        await asyncio.sleep(2)

        # Interrupt the task
        await client.interrupt()
        print("Task interrupted!")

        # Drain the interrupted task's messages (including its ResultMessage)
        async for message in client.receive_response():
            if isinstance(message, ResultMessage):
                print(f"Interrupted task: terminal_reason={message.terminal_reason!r}")
                # terminal_reason is "aborted_streaming" or "aborted_tools"
                # for interrupted turns

        # Send a new command
        await client.query("Just say hello instead")

        # Now receive the new response
        async for message in client.receive_response():
            if isinstance(message, ResultMessage) and message.subtype == "success":
                print(f"New result: {message.result}")


asyncio.run(interruptible_task())

הערה

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

#דוגמה: בקרת הרשאות מתקדמת

import asyncio
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions
from claude_agent_sdk.types import (
    PermissionResultAllow,
    PermissionResultDeny,
    ToolPermissionContext,
)


async def custom_permission_handler(
    tool_name: str, input_data: dict, context: ToolPermissionContext
) -> PermissionResultAllow | PermissionResultDeny:
    """Custom logic for tool permissions."""

    # Block writes to system directories
    if tool_name == "Write" and input_data.get("file_path", "").startswith("/system/"):
        return PermissionResultDeny(
            message="System directory write not allowed", interrupt=True
        )

    # Redirect sensitive file operations
    if tool_name in ["Write", "Edit"] and "config" in input_data.get("file_path", ""):
        safe_path = f"./sandbox/{input_data['file_path']}"
        return PermissionResultAllow(
            updated_input={**input_data, "file_path": safe_path}
        )

    # Allow everything else
    return PermissionResultAllow(updated_input=input_data)


async def main():
    # Don't also list the gated tools in allowed_tools: allow rules approve calls before can_use_tool runs
    options = ClaudeAgentOptions(can_use_tool=custom_permission_handler)

    async with ClaudeSDKClient(options=options) as client:
        await client.query("Update the system config file")

        async for message in client.receive_response():
            # Will use sandbox path instead
            print(message)


asyncio.run(main())

#טיפוסים

הערה

@dataclass מול TypedDict: ה-SDK הזה משתמש בשני סוגים של טיפוסים. מחלקות שמעוטרות ב-@dataclass (כגון ResultMessage, AgentDefinition, TextBlock) הן מופעי אובייקט בזמן ריצה ותומכות בגישה למאפיינים: msg.result. מחלקות שמוגדרות עם TypedDict (כגון ThinkingConfigEnabled, McpStdioServerConfig, SyncHookJSONOutput) הן מילונים רגילים בזמן ריצה ודורשות גישה לפי מפתח: config["budget_tokens"], ולא config.budget_tokens. תחביר הקריאה ClassName(field=value) עובד לשניהם, אבל רק dataclasses מייצרים אובייקטים עם מאפיינים.

#SdkMcpTool

הגדרה לכלי MCP של ה-SDK שנוצר עם הדקורטור @tool.

@dataclass
class SdkMcpTool(Generic[T]):
    name: str
    description: str
    input_schema: type[T] | dict[str, Any]
    handler: Callable[[T], Awaitable[dict[str, Any]]]
    annotations: ToolAnnotations | None = None
מאפייןסוגתיאור
namestrמזהה ייחודי לכלי
descriptionstrתיאור קריא לאדם
input_schematype[T] | dict[str, Any]סכמה לאימות הקלט
handlerCallable[[T], Awaitable[dict[str, Any]]]פונקציה אסינכרונית שמטפלת בהרצת הכלי
annotationsToolAnnotations | Noneהערות כלי אופציונליות (לדוגמה readOnlyHint, destructiveHint, openWorldHint, maxResultSizeChars)

#Transport

מחלקת בסיס מופשטת למימושי תעבורה מותאמים. משתמשים בזה כדי לתקשר עם תהליך Claude בערוץ מותאם (לדוגמה, חיבור מרוחק במקום subprocess מקומי).

אזהרה

זה API פנימי ברמה נמוכה. הממשק עשוי להשתנות במהדורות עתידיות. מימושים מותאמים חייבים להתעדכן כדי להתאים לכל שינוי בממשק.

from abc import ABC, abstractmethod
from collections.abc import AsyncIterator
from typing import Any


class Transport(ABC):
    @abstractmethod
    async def connect(self) -> None: ...

    @abstractmethod
    async def write(self, data: str) -> None: ...

    @abstractmethod
    def read_messages(self) -> AsyncIterator[dict[str, Any]]: ...

    @abstractmethod
    async def close(self) -> None: ...

    @abstractmethod
    def is_ready(self) -> bool: ...

    @abstractmethod
    async def end_input(self) -> None: ...
מתודהתיאור
connect()מחבר את התעבורה ומכין לתקשורת
write(data)כותב נתונים גולמיים (JSON + newline) לתעבורה
read_messages()איטרטור אסינכרוני שמניב הודעות JSON מפוענחות
close()סוגר את החיבור ומנקה משאבים
is_ready()מחזיר True אם התעבורה יכולה לשלוח ולקבל
end_input()סוגר את זרם הקלט (לדוגמה, סוגר את stdin בתעבורות subprocess)

ייבוא: from claude_agent_sdk import Transport

#ClaudeAgentOptions

מחלקת נתונים (dataclass) להגדרת שאילתות של Claude Code.

@dataclass
class ClaudeAgentOptions:
    tools: list[str] | ToolsPreset | None = None
    allowed_tools: list[str] = field(default_factory=list)
    system_prompt: str | SystemPromptPreset | SystemPromptCustom | SystemPromptFile | None = None
    mcp_servers: dict[str, McpServerConfig] | str | Path = field(default_factory=dict)
    strict_mcp_config: bool = False
    permission_mode: PermissionMode | None = None
    continue_conversation: bool = False
    resume: str | None = None
    session_id: str | None = None
    max_turns: int | None = None
    max_budget_usd: float | None = None
    disallowed_tools: list[str] = field(default_factory=list)
    model: str | None = None
    fallback_model: str | None = None
    betas: list[SdkBeta] = field(default_factory=list)
    output_format: dict[str, Any] | None = None
    permission_prompt_tool_name: str | None = None
    cwd: str | Path | None = None
    cli_path: str | Path | None = None
    settings: str | None = None
    add_dirs: list[str | Path] = field(default_factory=list)
    env: dict[str, str] = field(default_factory=dict)
    extra_args: dict[str, str | None] = field(default_factory=dict)
    max_buffer_size: int | None = None
    debug_stderr: Any = sys.stderr  # Deprecated
    stderr: Callable[[str], None] | None = None
    can_use_tool: CanUseTool | None = None
    hooks: dict[HookEvent, list[HookMatcher]] | None = None
    user: str | None = None
    include_partial_messages: bool = False
    include_hook_events: bool = False
    forward_subagent_text: bool = False
    verbatim_prompts: bool = False
    fork_session: bool = False
    resume_session_at: str | None = None
    resume_drops_turn: str | None = None
    agents: dict[str, AgentDefinition] | None = None
    setting_sources: list[SettingSource] | None = None
    skills: list[str] | Literal["all"] | None = None
    sandbox: SandboxSettings | None = None
    plugins: list[SdkPluginConfig] = field(default_factory=list)
    max_thinking_tokens: int | None = None  # Deprecated: use thinking instead
    thinking: ThinkingConfig | None = None
    effort: EffortLevel | None = None
    enable_file_checkpointing: bool = False
    session_store: SessionStore | None = None
    session_store_flush: SessionStoreFlushMode = "batched"
    load_timeout_ms: int = 60_000
    task_budget: TaskBudget | None = None
תכונהטיפוסברירת מחדלתיאור
toolslist[str] | ToolsPreset | NoneNoneתצורת כלים. השתמש ב-{"type": "preset", "preset": "claude_code"} לכלים ברירת המחדל של Claude Code
allowed_toolslist[str][]כלים לאישור אוטומטי בלי הנחיה, מלבד קריאות מנתיבי רשת. זה לא מגביל את Claude רק לכלים האלה. אם אתה מציין כאן אחד מכלי מעקב המשימות, Claude Code גם מפעיל את ההצטרפות עבור הסשן. כלים אחרים שלא ברשימה עוברים אל permission_mode ו-can_use_tool. השתמש ב-disallowed_tools כדי לחסום כלים. ראה הרשאות
system_promptstr | SystemPromptPreset | SystemPromptCustom | SystemPromptFile | NoneNoneתצורת הנחיית מערכת. העבר מחרוזת להנחיה מותאמת, {"type": "preset", "preset": "claude_code"} להנחיית המערכת של Claude Code עם "append" אופציונלי, {"type": "custom", "prompt": "..."} להנחיה מותאמת שיכולה גם להגדיר "snapshot", או {"type": "file", "path": "..."} כדי לטעון הנחיה גדולה מהדיסק. ראה SystemPromptPreset, SystemPromptCustom, ו-SystemPromptFile
mcp_serversdict[str, McpServerConfig] | str | Path{}תצורות שרתי MCP או נתיב לקובץ תצורה
strict_mcp_configboolFalseכאשר True, השתמש רק בשרתים שהועברו ב-mcp_servers והתעלם מ-.mcp.json של הפרויקט, מהגדרות המשתמש, משרתי MCP שמספקים תוספים, וממחברים של claude.ai. ממופה לדגל CLI --strict-mcp-config
permission_modePermissionMode | NoneNoneמצב הרשאה לשימוש בכלים
continue_conversationboolFalseהמשך את השיחה האחרונה
resumestr | NoneNoneמזהה סשן לחידוש
session_idstr | NoneNoneהשתמש במזהה סשן מסוים במקום מזהה שנוצר אוטומטית. חייב להיות UUID תקין. אי אפשר לשלב עם continue_conversation או resume אלא אם גם fork_session מוגדר
max_turnsint | NoneNoneמספר מרבי של תורות סוכניות
max_budget_usdfloat | NoneNoneעצור את השאילתה כאשר אומדן העלות בצד הלקוח מגיע לערך זה בדולר ארה"ב. האומדן יכול לעבור את הערך הזה, לכן השאר מרווח. נספרת רק ההוצאה של הקריאה עצמה. סכומים ששוחזרו מסשן שחודש לא נספרים. להסתייגויות דיוק ולהתנהגות איפוס, ראה מעקב עלות ושימוש
disallowed_toolslist[str][]כלים לדחייה. שם חשוף כגון "Bash" מסיר את הכלי מההקשר של Claude. כלל ממוקד כגון "Bash(rm *)" משאיר את הכלי זמין ודוחה קריאות תואמות בכל מצב הרשאה, כולל bypassPermissions, עבור הפקודה כפי שנכתבה. ראה הרשאות
enable_file_checkpointingboolFalseהפעל מעקב שינויי קבצים לחזרה אחורה. ראה נקודות ביקורת לקבצים
modelstr | NoneNoneכינוי מודל של Claude או שם מודל מלא. ראה ערכים מקובלים ומזהים ספציפיים לספק
fallback_modelstr | NoneNoneמודל גיבוי לשימוש אם המודל הראשי נכשל. מקבל רשימה מופרדת בפסיקים. להנחיה, ראה בחירת מודל
betaslist[SdkBeta][]תכונות בטא להפעלה. ראה SdkBeta לאפשרויות הזמינות
output_formatdict[str, Any] | NoneNoneתבנית פלט לתשובות מובנות (לדוגמה, {"type": "json_schema", "schema": {...}}). ראה פלטים מובנים לפרטים
permission_prompt_tool_namestr | NoneNoneשם כלי MCP להנחיות הרשאה
cwdstr | Path | NoneNoneספריית העבודה הנוכחית
cli_pathstr | Path | NoneNoneנתיב מותאם לקובץ ההרצה של Claude Code CLI
settingsstr | NoneNoneנתיב לקובץ הגדרות או מחרוזת JSON מוטמעת
add_dirslist[str | Path][]ספריות נוספות ש-Claude יכול לגשת אליהן. ה-SDK מעביר כל רשומה ל-Claude Code בתור --add-dir, ולכן עם מקור ההגדרות project Claude Code גם טוען את הכישורים, הפקודות ותתי הסוכנים של הספרייה
envdict[str, str]{}משתני סביבה שממוזגים מעל סביבת התהליך שעוברת בירושה. ראה משתני סביבה למשתנים שה-CLI הבסיסי קורא, וטיפול בתגובות API איטיות או תקועות למשתנים שקשורים לפסק זמן. הגדר CLAUDE_AGENT_SDK_CLIENT_APP כדי לזהות את האפליקציה שלך בכותרת User-Agent
extra_argsdict[str, str | None]{}ארגומנטים נוספים של CLI להעברה ישירה ל-CLI
max_buffer_sizeint | NoneNoneמספר בתים מרבי בעת אגירת stdout של ה-CLI
debug_stderrAnysys.stderrמיושן: ה-SDK מתעלם מהערך הזה. השתמש בקריאת ה-callback של stderr לפלט stderr של ה-CLI
stderrCallable[[str], None] | NoneNoneפונקציית callback לפלט stderr מה-CLI
can_use_toolCanUseTool | NoneNoneקריאת callback להרשאת כלים, שמופעלת רק כאשר זרימת ההרשאות מגיעה להנחיה. לא מופעלת לקריאות שאושרו אוטומטית על ידי allowed_tools, כללי allow, או permission_mode. כלל allow לא מאשר מראש את הפעולות שאף מצב לא מאשר אוטומטית. ראה CanUseTool לפרטים
hooksdict[HookEvent, list[HookMatcher]] | NoneNoneתצורות hook ליירוט אירועים
userstr | NoneNoneבפלטפורמות POSIX, חשבון המשתמש של מערכת ההפעלה שתחתיו רץ תהליך המשנה של Claude Code. Claude Code שומר את סביבת תהליך האב, כולל HOME, ורץ ב-cwd
include_partial_messagesboolFalseכלול אירועי הזרמה של הודעות חלקיות. כאשר מופעל, הודעות StreamEvent מוחזרות (yield)
include_hook_eventsboolFalseכלול אירועי מחזור חיים של hook בזרם ההודעות כאובייקטי HookEventMessage
forward_subagent_textboolFalseהעבר בלוקי טקסט וחשיבה של תת סוכן בזרם ההודעות. בלי אפשרות זו, Claude Code משמיט את בלוקי הטקסט והחשיבה של תת סוכן שרץ בחזית. לתתי סוכנים מקוננים, לכישורים עם context: fork, ולגרסת Claude Code שכל אחד מהם דורש, ראה מעקב אחרי הודעות תת סוכן. דורש Python Agent SDK 0.2.140 או חדש יותר
verbatim_promptsboolFalseמסור כל הנחיה כפי שנכתבה. ה-SDK שולח כל הודעת משתמש עם client_composed שמוגדר ל-True. ראה client_composed למה ש-Claude Code מדלג בהודעות האלה. השתמש באפשרות זו כאשר טקסט ההנחיה שלך כולל תוכן שמשתמש הקצה לא הקליד. לשליטה לפי תור, השאר אותה כבויה והגדר "client_composed": True על הודעות מוזרמות בודדות. כל עוד האפשרות פועלת, ה-SDK דורס כל ערך client_composed שהגדרת. דורש Python Agent SDK 0.2.158 או חדש יותר ו-Claude Code v2.1.248 או חדש יותר. ה-CLI שמצורף לגרסאות SDK אלה מספק את דרישת Claude Code
fork_sessionboolFalseבעת חידוש עם resume, פצל למזהה סשן חדש במקום להמשיך את הסשן המקורי
resume_session_atstr | NoneNoneבעת חידוש, טען את השיחה רק עד וכולל ההודעה עם UUID זה. השתמש יחד עם resume, ובדרך כלל fork_session, כדי להסתעף מנקודה מוקדמת יותר. דורש Python Agent SDK 0.2.137 או חדש יותר
resume_drops_turnstr | NoneNoneUUID של הנחיית המשתמש שהתור שלה נזרק בקיצור של resume_session_at. כאשר מוגדר, ה-CLI מסרב לחידוש אם הטווח שנזרק מכיל רשומות שלא מיוחסות לתור הזה. דורש Python Agent SDK 0.2.137 או חדש יותר ו-Claude Code v2.1.223 או חדש יותר. ה-CLI שמצורף לגרסאות SDK אלה מספק את דרישת Claude Code
agentsdict[str, AgentDefinition] | NoneNoneתתי סוכנים שמוגדרים באופן תכנותי
pluginslist[SdkPluginConfig][]טען תוספים מותאמים מנתיבים מקומיים. ראה תוספים לפרטים
sandboxSandboxSettings | NoneNoneהגדר התנהגות sandbox באופן תכנותי. ראה הגדרות sandbox לפרטים
setting_sourceslist[SettingSource] | NoneNone (ברירות מחדל של CLI: כל המקורות)שלוט באילו הגדרות מערכת קבצים לטעון. העבר [] כדי להשבית הגדרות משתמש, פרויקט ומקומיות. כאשר skills מוגדר והשדה הזה לא מוגדר, נטענים רק מקורות משתמש ופרויקט. הגדר setting_sources במפורש כדי לשמור הגדרות מקומיות. מדיניות שמנוהלת בנקודת הקצה נטענת בכל מקרה. הגדרות שמנוהלות בשרת נמשכות כאשר הסשן מאמת עם אישור ארגון בתצורה זכאית. לקלטים שנקראים בלי קשר לאפשרות זו, ראה מה settingSources לא שולט
skillslist[str] | Literal["all"] | NoneNoneכישורים שזמינים לסשן. העבר "all" כדי להפעיל כל כישור שהתגלה, או רשימת שמות כישורים. העבר שמות מדויקים בלבד. ה-SDK דוחה שמות פגומים ושמות בצורת תו כללי עם ValueError לפני הפעלת תהליך Claude Code. הבדיקה הזו דורשת Python Agent SDK 0.2.129 או חדש יותר. כאשר מוגדר, ה-SDK מוסיף את כלי Skill ל-allowed_tools אוטומטית. אם אתה גם מעביר tools, כלול "Skill" ברשימה הזו. ראה כישורים
max_thinking_tokensint | NoneNoneמיושן: מספר אסימונים מרבי לבלוקי חשיבה. השתמש ב-thinking במקום
thinkingThinkingConfig | NoneNoneשולט בהתנהגות חשיבה מורחבת. מקבל עדיפות על פני max_thinking_tokens
effortEffortLevel | NoneNoneרמת מאמץ לעומק החשיבה. ראה התאמת רמת המאמץ
session_storeSessionStore | NoneNoneשכפל תמלילי סשן למערכת אחורית חיצונית כדי שמארח אחר יוכל לחדש אותם. ראה שמירת סשנים באחסון חיצוני
session_store_flushLiteral["batched", "eager"]"batched"מתי לרוקן רשומות תמליל משוכפלות אל session_store. "batched" מרוקן פעם אחת לכל תור או כאשר המאגר מתמלא. "eager" מפעיל ריקון ברקע אחרי כל מסגרת. מתעלמים כאשר session_store הוא None
load_timeout_msint60000פסק זמן לכל קריאה עבור session_store.load() ו-list_subkeys() במהלך מימוש החידוש, באלפיות שנייה
task_budgetTaskBudget | NoneNoneתקציב אסימונים בצד ה-API. נשלח בתור output_config.task_budget עם כותרת הבטא task-budgets-2026-03-13. העבר {"total": <int>}.

#טיפול בתגובות API איטיות או תקועות

תהליך המשנה של ה-CLI קורא כמה משתני סביבה ששולטים בפסקי זמן של API ובזיהוי תקיעה. העבר אותם דרך ClaudeAgentOptions.env:

from claude_agent_sdk import ClaudeAgentOptions

options = ClaudeAgentOptions(
    env={
        "API_TIMEOUT_MS": "120000",
        "CLAUDE_CODE_MAX_RETRIES": "2",
        "CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS": "120000",
    },
)
  • API_TIMEOUT_MS: כמה זמן כל ניסיון בקשה יכול להמתין לכותרות התגובה, באלפיות שנייה. זה לא מגביל כמה זמן תגובת הזרמה רצה אחרי שהכותרות מגיעות. ברירת מחדל 600000. חל על הלולאה הראשית ועל כל תתי הסוכנים.

  • CLAUDE_CODE_MAX_RETRIES: מספר מרבי של ניסיונות חוזרים ל-API. ברירת מחדל 10, עם תקרה של 15. כל ניסיון חוזר מקבל חלון API_TIMEOUT_MS משלו.

    להרצות בלי השגחה שצריכות להמתין לאורך תקלות ארוכות יותר, הגדר CLAUDE_CODE_RETRY_WATCHDOG=1: זה מנסה שוב שגיאות קיבולת חולפות בלי הגבלה, וב-Claude Code v2.1.199 או חדש יותר מעלה את ברירת המחדל לשגיאות חולפות אחרות ל-300 ומסיר את התקרה על המשתנה הזה.

  • CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS: שומר תקיעה לתתי סוכנים. כאשר שומר הזרם פועל, ברירת המחדל היא CLAUDE_STREAM_IDLE_TIMEOUT_MS ועוד 5 דקות, שמגיע ל-600000 אלא אם אתה מעלה את המשתנה הזה. כאשר שומר הזרם כבוי, ברירת המחדל היא 600000. לפני v2.1.257, ברירת המחדל הייתה תמיד 600000.

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

  • CLAUDE_ENABLE_STREAM_WATCHDOG עם CLAUDE_STREAM_IDLE_TIMEOUT_MS: שומר זרם שמבטל את הבקשה כאשר הכותרות הגיעו אבל גוף התגובה מפסיק לזרום. השומר פועל כברירת מחדל לכל הספקים. הגדר CLAUDE_ENABLE_STREAM_WATCHDOG=0 כדי להשבית אותו. CLAUDE_STREAM_IDLE_TIMEOUT_MS ברירת המחדל היא 300000 והוא מהודק למינימום הזה. אחרי הביטול, ניסיונות חוזרים אוטומטיים מכסים את מה ש-Claude Code עושה, לפי כמה רחוק התגובה התקדמה.

    בזמן שהשומר ממתין לתגובה ששער מאחורי ANTHROPIC_BASE_URL מחזיק פתוחה עם ping של keep-alive, מארח שמגדיר include_partial_messages ממשיך לקבל הודעות ping מסוג StreamEvent. קרא את המסגרות האלה כסימן חיים, במקום לסיים את הסשן בפסק זמן בגלל שקט. לפני v2.1.257, המסגרות נעצרו 5 דקות אחרי אירוע הזרם האמיתי האחרון.

#OutputFormat

תצורה לאימות פלט מובנה. העבר זאת כ-dict לשדה output_format ב-ClaudeAgentOptions:

# Expected dict shape for output_format
{
    "type": "json_schema",
    "schema": {...},  # Your JSON Schema definition
}
שדהחובהתיאור
typeכןחייב להיות "json_schema" לאימות JSON Schema
schemaכןהגדרת JSON Schema לאימות הפלט

#SystemPromptPreset

תצורה לשימוש בהנחיית המערכת המוגדרת מראש של Claude Code, עם תוספות אופציונליות.

class SystemPromptPreset(TypedDict):
    type: Literal["preset"]
    preset: Literal["claude_code"]
    append: NotRequired[str]
    exclude_dynamic_sections: NotRequired[bool]
    snapshot: NotRequired[bool]
שדהחובהתיאור
typeכןחייב להיות "preset" כדי להשתמש בהנחיית מערכת מוגדרת מראש
presetכןחייב להיות "claude_code" כדי להשתמש בהנחיית המערכת של Claude Code
appendלאהוראות נוספות לצירוף להנחיית המערכת המוגדרת מראש
exclude_dynamic_sectionsלאמעביר הקשר לפי משתמש, כגון מיקום הזיכרון האוטומטי, מהנחיית המערכת אל הודעת המשתמש הראשונה. משפר שימוש חוזר במטמון ההנחיות בין משתמשים ומכונות. ראה שינוי הנחיות מערכת
snapshotלאהגדר ל-False כדי לבנות מחדש את הנחיית המערכת בכל בקשה במקום שימוש חוזר בהנחיה שההפעלה תיעדה בבקשה הראשונה שלה. דורש claude-agent-sdk בגרסה v0.2.153 או חדשה יותר

#SystemPromptCustom

הנחיית מערכת מותאמת בצורת אובייקט, שקולה להעברת מחרוזת כ-system_prompt, ויכולה גם להגדיר snapshot. דורש claude-agent-sdk בגרסה v0.2.153 או חדשה יותר.

class SystemPromptCustom(TypedDict):
    type: Literal["custom"]
    prompt: str
    snapshot: NotRequired[bool]
שדהחובהתיאור
typeכןחייב להיות "custom"
promptכןטקסט הנחיית המערכת. מועבר ל-CLI כארגומנט של שורת פקודה, ולכן חלות מגבלות אורך שורת הפקודה
snapshotלאזהה ל-SystemPromptPreset.snapshot, ומוחל על prompt

#SystemPromptFile

תצורה לטעינת הנחיית מערכת מותאמת מקובץ במקום להעביר אותה כמחרוזת. ה-SDK ממפה זאת לדגל ה-CLI --system-prompt-file. השתמש בצורת הקובץ כשההנחיה גדולה: ה-SDK מעביר מחרוזת system_prompt ב-argv של תהליך המשנה של ה-CLI, והיא כפופה למגבלות אורך שורת הפקודה של מערכת ההפעלה לפני שה-SDK שולח בקשת API כלשהי. ב-Linux ארגומנט יחיד שארוך מכ-128 KB נכשל ביצירת התהליך עם Argument list too long. ב-Windows כל שורת הפקודה מוגבלת לכ-32 KB, ולכן צורת המחרוזת נכשלת בסף נמוך יותר.

class SystemPromptFile(TypedDict):
    type: Literal["file"]
    path: str
שדהחובהתיאור
typeכןחייב להיות "file" כדי לטעון את ההנחיה מהדיסק
pathכןנתיב לקובץ שמכיל את הנחיית המערכת

#SettingSource

שולט מאילו מקורות תצורה מבוססי מערכת קבצים ה-SDK טוען הגדרות.

SettingSource = Literal["user", "project", "local"]
ערךתיאורמיקום
"user"הגדרות משתמש גלובליות~/.claude/settings.json
"project"הגדרות פרויקט משותפות (בבקרת גרסאות).claude/settings.json
"local"הגדרות פרויקט מקומיות, שנכנסות ל-gitignore כש-Claude Code שומר אליהן הגדרה.claude/settings.local.json

#התנהגות ברירת מחדל

כש-setting_sources מושמט או None ו-skills לא מוגדר, query() טוען את אותן הגדרות מערכת קבצים כמו ה-CLI של Claude Code: user, project ו-local. כש-skills מוגדר, שורת setting_sources מתארת את ברירת המחדל הנוכחית. מדיניות שמנוהלת בנקודת הקצה נטענת בכל המקרים. הגדרות שמנוהלות בשרת נשלפות כשההפעלה מבצעת אימות עם אישור ארגון בתצורה זכאית. למידע נוסף, ראה במה settingSources לא שולט.

#למה להשתמש ב-setting_sources

השבתת הגדרות מערכת קבצים:

# Do not load user, project, or local settings from disk
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions


async def main():
    async for message in query(
        prompt="Analyze this code",
        options=ClaudeAgentOptions(
            setting_sources=[]
        ),
    ):
        print(message)


asyncio.run(main())

[!NOTE]

ב-Python SDK 0.1.59 ומוקדם יותר, רשימה ריקה טופלה כמו השמטת האפשרות, ולכן setting_sources=[] לא השבית הגדרות מערכת קבצים. שדרג למהדורה חדשה יותר אם צריך שרשימה ריקה תיכנס לתוקף. ה-TypeScript SDK לא מושפע.

טעינה של מקורות הגדרות ספציפיים בלבד:

# Load only project settings, ignore user and local
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions


async def main():
    async for message in query(
        prompt="Run CI checks",
        options=ClaudeAgentOptions(
            setting_sources=["project"]  # Only .claude/settings.json
        ),
    ):
        print(message)


asyncio.run(main())

יישומים של SDK בלבד:

# Define everything programmatically.
# Pass [] to opt out of filesystem setting sources.
import asyncio
from claude_agent_sdk import AgentDefinition, ClaudeAgentOptions, query


async def main():
    async for message in query(
        prompt="Review this PR",
        options=ClaudeAgentOptions(
            setting_sources=[],
            agents={
                "code-reviewer": AgentDefinition(
                    description="Reviews code changes",
                    prompt="You are a code reviewer. Report issues in the diff.",
                ),
            },
            allowed_tools=["Read", "Grep", "Glob"],
        ),
    ):
        print(message)


asyncio.run(main())

כדי לטעון הוראות פרויקט של CLAUDE.md, כלול "project" ב-setting_sources. ראה שינוי הנחיות מערכת לאופן שבו טעינת CLAUDE.md פועלת יחד עם אפשרויות הנחיית המערכת.

#קדימות הגדרות

כשנטענים כמה מקורות, ההגדרות ממוזגות לפי הקדימות הזו (מהגבוהה לנמוכה):

  1. הגדרות מקומיות (.claude/settings.local.json)
  2. הגדרות פרויקט (.claude/settings.json)
  3. הגדרות משתמש (~/.claude/settings.json)

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

#AgentDefinition

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

@dataclass
class AgentDefinition:
    description: str
    prompt: str
    tools: list[str] | None = None
    disallowedTools: list[str] | None = None
    model: str | None = None
    skills: list[str] | None = None
    memory: Literal["user", "project", "local"] | None = None
    mcpServers: list[str | dict[str, Any]] | None = None
    initialPrompt: str | None = None
    maxTurns: int | None = None
    background: bool | None = None
    effort: EffortLevel | int | None = None
    permissionMode: PermissionMode | None = None
שדהחובהתיאור
descriptionכןתיאור בשפה טבעית של מתי להשתמש בסוכן הזה
promptכןהנחיית המערכת של הסוכן
toolsלאמערך של שמות כלים מותרים. אם מושמט, יורש כל כלי שזמין לסוכני משנה
disallowedToolsלאמערך של שמות כלים להסרה מערכת הכלים של הסוכן. מתקבלות גם תבניות ברמת שרת MCP: mcp__server או mcp__server__* מסיר כל כלי מהשרת הזה, ו-mcp__* מסיר כל כלי MCP מכל שרת
modelלאדריסת מודל לסוכן הזה. מקבל כינוי כגון "sonnet", "opus", "haiku" או "inherit", או מזהה מודל מלא. כשמשמיטים אותו, Claude Code בוחר את המודל בסדר המודל של סוכן משנה
skillsלארשימת שמות skill לטעינה מראש להקשר של הסוכן בהפעלה. skills שלא ברשימה נשארים ניתנים להפעלה דרך כלי ה-Skill
memoryלאמקור זיכרון לסוכן הזה: "user", "project" או "local"
mcpServersלאשרתי MCP שזמינים לסוכן הזה. כל רשומה היא שם שרת או מילון {name: config} מוטמע
initialPromptלאנשלח אוטומטית כתור המשתמש הראשון כשהסוכן הזה רץ כסוכן של השרשור הראשי
maxTurnsלאמספר מרבי של תורות agentic לפני שהסוכן עוצר
backgroundלאהרץ את הסוכן הזה כמשימת רקע לא חוסמת כשהוא מופעל
effortלארמת מאמץ החשיבה לסוכן הזה. מקבל רמה בעלת שם או מספר שלם. ראה EffortLevel
permissionModeלאמצב הרשאה לביצוע כלים בתוך הסוכן הזה. כללי הירושה של סוכן משנה קובעים מתי הוא חל. ראה PermissionMode

[!NOTE]

שמות השדות של AgentDefinition משתמשים ב-camelCase, כגון disallowedTools, permissionMode ו-maxTurns. השמות האלה ממופים ישירות לפורמט ה-wire המשותף עם TypeScript SDK. זה שונה מ-ClaudeAgentOptions, שמשתמש ב-snake_case של Python לשדות המקבילים ברמה העליונה, כגון disallowed_tools ו-permission_mode. מכיוון ש-AgentDefinition הוא dataclass, העברת מילת מפתח ב-snake_case מעלה TypeError בזמן הבנייה.

#PermissionMode

מצבי הרשאה לשליטה בביצוע כלים.

PermissionMode = Literal[
    "default",  # Standard permission behavior
    "acceptEdits",  # Auto-accept file edits
    "plan",  # Planning mode - Claude explores and plans
    "dontAsk",  # Deny anything not pre-approved instead of prompting
    "bypassPermissions",  # Bypass permission checks; explicit ask rules still prompt (use with caution)
    "auto",  # A model classifier reviews actions such as shell commands and network requests
]

#EffortLevel

רמות מאמץ להנחיית עומק החשיבה.

EffortLevel = Literal[
    "low",  # Minimal thinking, fastest responses
    "medium",  # Moderate thinking
    "high",  # Deep reasoning
    "xhigh",  # Extended reasoning; falls back to "high" on models that don't support it
    "max",  # Maximum effort
]

#CanUseTool

כינוי טיפוס לפונקציות callback של הרשאת כלים.

CanUseTool = Callable[
    [str, dict[str, Any], ToolPermissionContext], Awaitable[PermissionResult]
]

ה-callback מקבל:

  • tool_name: שם הכלי שנקרא
  • input_data: פרמטרי הקלט של הכלי
  • context: ToolPermissionContext עם מידע נוסף

מחזיר PermissionResult (PermissionResultAllow או PermissionResultDeny).

ה-callback מחליף את בקשת ההרשאה האינטראקטיבית. ה-SDK קורא ל-can_use_tool כשזרימת הערכת ההרשאות מגיעה לבקשה. קריאות שאושרו באחת מהדרכים האלה רצות בלי קריאה ל-can_use_tool:

  • קריאה שרשומה ב-allowed_tools או כלל allow בהגדרות מאשר
  • קריאה שמצב ההרשאה מאשר, כגון עריכת קובץ במצב acceptEdits

כדי לבדוק את הקריאות האלה, השתמש ב-hook של PreToolUse, שרץ גם עבורן.

כלל allow לא מאשר מראש את הפעולות שאף מצב לא מאשר אוטומטית. ראה איך הרשאות מוערכות לגבי אילו מהן מגיעות ל-callback ומה קורה במצב dontAsk ובמצב auto.

#ToolPermissionContext

מידע הקשר שמועבר ל-callbacks של הרשאת כלים.

@dataclass
class ToolPermissionContext:
    signal: Any | None = None  # Future: abort signal support
    suggestions: list[PermissionUpdate] = field(default_factory=list)
    tool_use_id: str | None = None
    agent_id: str | None = None
    blocked_path: str | None = None
    decision_reason: str | None = None
    title: str | None = None
    display_name: str | None = None
    description: str | None = None
שדהטיפוסתיאור
signalAny | Noneשמור לתמיכה עתידית באות ביטול
suggestionslist[PermissionUpdate]הצעות לעדכון הרשאה מה-CLI. בקשות Bash כוללות הצעה עם היעד localSettings, ולכן החזרתה ב-updated_permissions כותבת את הכלל אל .claude/settings.local.json ושומרת אותו בין הפעלות.
tool_use_idstr | Noneמזהה של קריאת הכלי הספציפית שהבקשה הזו מיועדת לה. תמיד מאוכלס כשהוא מועבר ל-can_use_tool
agent_idstr | Noneמזהה סוכן משנה כשהקריאה מגיעה מסוכן משנה. None עבור הסוכן הראשי
blocked_pathstr | Noneנתיב קובץ שהפעיל את בקשת ההרשאה, כשרלוונטי. לדוגמה, כשפקודת Bash מנסה לגשת לנתיב מחוץ לספריות המותרות
decision_reasonstr | Noneהסיבה שבקשת ההרשאה הזו הופעלה. מועבר מ-permissionDecisionReason של hook מסוג PreToolUse כשה-hook החזיר "ask"
titlestr | Noneמשפט מלא של בקשת ההרשאה, כגון Claude wants to read foo.txt. השתמש בו כטקסט הבקשה העיקרי כשהוא קיים
display_namestr | Noneצירוף שמות עצם קצר לפעולת הכלי, כגון Read file, שמתאים לתוויות כפתורים
descriptionstr | Noneכותרת משנה קריאה לאדם עבור ממשק ההרשאות

#PermissionResult

טיפוס איחוד לתוצאות של callback הרשאה.

PermissionResult = PermissionResultAllow | PermissionResultDeny

#PermissionResultAllow

תוצאה שמציינת שיש לאפשר את קריאת הכלי.

@dataclass
class PermissionResultAllow:
    behavior: Literal["allow"] = "allow"
    updated_input: dict[str, Any] | None = None
    updated_permissions: list[PermissionUpdate] | None = None
שדהטיפוסברירת מחדלתיאור
behaviorLiteral["allow"]"allow"חייב להיות "allow"
updated_inputdict[str, Any] | NoneNoneקלט ששונה לשימוש במקום המקור
updated_permissionslist[PermissionUpdate] | NoneNoneעדכוני הרשאה להחלה

אם מחזירים PermissionResultAllow עם יותר מ-4,096 פריטים ב-updated_permissions, Claude Code מתייחס לתוצאה כלא תקינה ודוחה את קריאת הכלי. כל PermissionUpdate נספר כפריט אחד, וכך גם כל רשומה ברשימת rules או directories שלו. הודעת הדחייה מסתיימת ב-updatedPermissions may hold at most 4096 updates, rules and directories in all. כדי להימנע מהדחייה, החזר 4,096 פריטים או פחות.

#PermissionResultDeny

תוצאה שמציינת שיש לדחות את קריאת הכלי.

@dataclass
class PermissionResultDeny:
    behavior: Literal["deny"] = "deny"
    message: str = ""
    interrupt: bool = False
שדהטיפוסברירת מחדלתיאור
behaviorLiteral["deny"]"deny"חייב להיות "deny"
messagestr""הודעה שמסבירה למה הכלי נדחה
interruptboolFalseהאם לקטוע את הביצוע הנוכחי

#PermissionUpdate

תצורה לעדכון הרשאות באופן תכנותי.

@dataclass
class PermissionUpdate:
    type: Literal[
        "addRules",
        "replaceRules",
        "removeRules",
        "setMode",
        "addDirectories",
        "removeDirectories",
    ]
    rules: list[PermissionRuleValue] | None = None
    behavior: Literal["allow", "deny", "ask"] | None = None
    mode: PermissionMode | None = None
    directories: list[str] | None = None
    destination: (
        Literal["userSettings", "projectSettings", "localSettings", "session"] | None
    ) = None
שדהטיפוסתיאור
typeLiteral[...]סוג פעולת עדכון ההרשאה
ruleslist[PermissionRuleValue] | Noneכללים לפעולות הוספה, החלפה או הסרה
behaviorLiteral["allow", "deny", "ask"] | Noneהתנהגות לפעולות שמבוססות על כללים
modePermissionMode | Noneמצב לפעולת setMode
directorieslist[str] | Noneספריות לפעולות הוספה או הסרה של ספריות
destinationLiteral[...] | Noneהיכן להחיל את עדכון ההרשאה

#PermissionRuleValue

כלל להוספה, להחלפה או להסרה בעדכון הרשאה.

@dataclass
class PermissionRuleValue:
    tool_name: str
    rule_content: str | None = None

#ToolsPreset

תצורת כלים מוגדרת מראש לשימוש בערכת הכלים שברירת המחדל של Claude Code.

class ToolsPreset(TypedDict):
    type: Literal["preset"]
    preset: Literal["claude_code"]

#ThinkingConfig

שולט בהתנהגות החשיבה המורחבת. איחוד של שלוש תצורות:

ThinkingDisplay = Literal["summarized", "omitted"]


class ThinkingConfigAdaptive(TypedDict):
    type: Literal["adaptive"]
    display: NotRequired[ThinkingDisplay]


class ThinkingConfigEnabled(TypedDict):
    type: Literal["enabled"]
    budget_tokens: int
    display: NotRequired[ThinkingDisplay]


class ThinkingConfigDisabled(TypedDict):
    type: Literal["disabled"]


ThinkingConfig = ThinkingConfigAdaptive | ThinkingConfigEnabled | ThinkingConfigDisabled
וריאנטשדותתיאור
adaptivetype, displayClaude מחליט באופן מסתגל מתי לחשוב
enabledtype, budget_tokens, displayהפעלת חשיבה עם תקציב טוקנים מסוים
disabledtypeהשבתת חשיבה

השדה האופציונלי display קובע אם טקסט החשיבה מוחזר כ-"summarized" או כ-"omitted". ב-Claude Opus 4.7 ואילך, ברירת המחדל של ה-API היא "omitted", ולכן יש להגדיר "summarized" כדי לקבל תוכן חשיבה בפלטי ThinkingBlock. Claude Code לא מעביר את ערך display שלך לחלק מהספקים, כמו Amazon Bedrock ו-Agent Platform של Google Cloud. אצל ספקים אלה, Opus 4.7 ואילך מחזירים פלטי ThinkingBlock ריקים גם כשמגדירים את display ל-"summarized".

מכיוון שאלה מחלקות TypedDict, הן מילונים רגילים בזמן ריצה. אפשר לבנות אותן כליטרלים של מילון או לקרוא למחלקה כמו לבנאי. שתי הדרכים מייצרות dict. ניגשים לשדות עם config["budget_tokens"], ולא עם config.budget_tokens:

from claude_agent_sdk import ClaudeAgentOptions, ThinkingConfigEnabled

# Option 1: dict literal (recommended, no import needed)
options = ClaudeAgentOptions(thinking={"type": "enabled", "budget_tokens": 20000})

# Option 2: constructor-style (returns a plain dict)
config = ThinkingConfigEnabled(type="enabled", budget_tokens=20000)
print(config["budget_tokens"])  # 20000
# config.budget_tokens would raise AttributeError

#TaskBudget

תקציב משימה בטוקנים בצד ה-API, בשימוש עם השדה task_budget ב-ClaudeAgentOptions.

class TaskBudget(TypedDict):
    total: int
שדהטיפוסתיאור
totalintתקציב הטוקנים הכולל למשימה

מכיוון שזה TypedDict, מעבירים אותו כמילון רגיל, למשל ClaudeAgentOptions(task_budget={"total": 50000}).

#SdkBeta

טיפוס ליטרל לתכונות בטא של ה-SDK.

SdkBeta = Literal["context-1m-2025-08-07"]

משתמשים בו עם השדה betas ב-ClaudeAgentOptions כדי להפעיל תכונות בטא.

[!WARNING]

ב-Claude API, הבטא context-1m-2025-08-07 הוצאה משימוש עבור Claude Sonnet 4.5 ו-Claude Sonnet 4. אם עדיין מעבירים אותה עם אחד מהמודלים האלה, בקשות שחורגות מחלון ההקשר הרגיל של 200 אלף טוקנים מחזירות שגיאה, ולכן יש להסיר אותה מ-betas. כדי להריץ סשן עם חלון הקשר של מיליון טוקנים, מגדירים את model למודל שרץ עם חלון של מיליון כברירת מחדל, כמו claude-sonnet-5-5 או claude-opus-5-5. עבור מודל שמגיע למיליון רק דרך וריאנט [1m] שלו, מוסיפים את הסיומת למזהה המודל, כמו ב-claude-opus-4-6[1m].

#McpSdkServerConfig

תצורה לשרתי MCP של ה-SDK שנוצרים עם create_sdk_mcp_server().

class McpSdkServerConfig(TypedDict):
    type: Literal["sdk"]
    name: str
    instance: Any  # MCP Server instance

#McpServerConfig

טיפוס איחוד לתצורות שרת MCP.

McpServerConfig = (
    McpStdioServerConfig | McpSSEServerConfig | McpHttpServerConfig | McpSdkServerConfig
)

#McpStdioServerConfig

class McpStdioServerConfig(TypedDict):
    type: NotRequired[Literal["stdio"]]  # Optional for backwards compatibility
    command: str
    args: NotRequired[list[str]]
    env: NotRequired[dict[str, str]]

#McpSSEServerConfig

class McpSSEServerConfig(TypedDict):
    type: Literal["sse"]
    url: str
    headers: NotRequired[dict[str, str]]

#McpHttpServerConfig

class McpHttpServerConfig(TypedDict):
    type: Literal["http"]
    url: str
    headers: NotRequired[dict[str, str]]

#McpServerStatusConfig

התצורה של שרת MCP כפי שמדווחת על ידי get_mcp_status(). זהו האיחוד של כל וריאנטי התעבורה של McpServerConfig, ובנוסף וריאנט claudeai-proxy לפלט בלבד עבור שרתים שמתווכים דרך claude.ai.

McpServerStatusConfig = (
    McpStdioServerConfig
    | McpSSEServerConfig
    | McpHttpServerConfig
    | McpSdkServerConfigStatus
    | McpClaudeAIProxyServerConfig
)

McpSdkServerConfigStatus הוא הצורה הניתנת לסריאליזציה של McpSdkServerConfig, עם השדות type ("sdk") ו-name (str) בלבד. ה-instance שבתוך התהליך מושמט. ל-McpClaudeAIProxyServerConfig יש את השדות type ("claudeai-proxy"), url (str) ו-id (str).

#McpStatusResponse

תשובה מ-ClaudeSDKClient.get_mcp_status(). עוטפת את רשימת סטטוסי השרתים תחת המפתח mcpServers.

class McpStatusResponse(TypedDict):
    mcpServers: list[McpServerStatus]

#McpServerStatus

הסטטוס של שרת MCP מחובר, הכלול ב-McpStatusResponse.

class McpServerStatus(TypedDict):
    name: str
    status: McpServerConnectionStatus  # "connected" | "failed" | "needs-auth" | "pending" | "disabled"
    serverInfo: NotRequired[McpServerInfo]
    error: NotRequired[str]
    config: NotRequired[McpServerStatusConfig]
    scope: NotRequired[str]
    tools: NotRequired[list[McpToolInfo]]
שדהטיפוסתיאור
namestrשם השרת
statusstrאחד מ-"connected", "failed", "needs-auth", "pending" או "disabled"
serverInfodict (אופציונלי)שם השרת והגרסה ({"name": str, "version": str})
errorstr (אופציונלי)הודעת שגיאה אם השרת נכשל בהתחברות
configMcpServerStatusConfig (אופציונלי)תצורת השרת. אותה צורה כמו McpServerConfig (stdio, SSE, HTTP או SDK), ובנוסף וריאנט claudeai-proxy לשרתים שמחוברים דרך claude.ai
scopestr (אופציונלי)היקף התצורה
toolslist (אופציונלי)כלים שמספק השרת, לכל אחד השדות name, description ו-annotations

#ContextUsageResponse

תשובה מ-ClaudeSDKClient.get_context_usage(). התשובה כוללת את המטען ש-Claude Code מציג עבור הפקודה /context בסשן אינטראקטיבי. לצד ספירות הטוקנים, המטען הזה נושא שדות תצוגה כמו color ו-gridRows, ש-Claude Code משתמש בהם כדי לצייר את רשת השימוש של /context.

Claude Code בונה את המטען הזה על ידי שליחת כמה בקשות ל-API של ספירת טוקנים. הבקשות האלה לא מופיעות בזרם ההודעות, ולכן מעקב עלות שקורא את הזרם לא יראה אותן. ב-Anthropic API, ספירת טוקנים לא מחויבת.

class ContextUsageResponse(TypedDict):
    categories: list[ContextUsageCategory]
    totalTokens: int
    maxTokens: int
    rawMaxTokens: int
    percentage: float
    model: str
    isAutoCompactEnabled: bool
    memoryFiles: list[dict[str, Any]]
    mcpTools: list[dict[str, Any]]
    agents: list[dict[str, Any]]
    gridRows: list[list[dict[str, Any]]]
    autoCompactThreshold: NotRequired[int]
    deferredBuiltinTools: NotRequired[list[dict[str, Any]]]
    systemTools: NotRequired[list[dict[str, Any]]]
    systemPromptSections: NotRequired[list[dict[str, Any]]]
    slashCommands: NotRequired[dict[str, Any]]
    skills: NotRequired[dict[str, Any]]  # skill usage with frontmatter breakdown
    messageBreakdown: NotRequired[dict[str, Any]]  # message tokens by type
    apiUsage: NotRequired[dict[str, Any] | None]

כל רשומת ContextUsageCategory נושאת את name, tokens, color ודגל אופציונלי isDeferred. totalTokens הוא שימוש ההקשר הנוכחי של הסשן, ו-maxTokens הוא החלון שלפיו נמדד השימוש. החלון הזה הוא חלון ההקשר של המודל, או חלון הדחיסה האוטומטית הנמוך יותר כשאחד כזה חל, ו-rawMaxTokens נושא את אותו ערך כמו maxTokens. apiUsage מחזיק את השימוש מתשובת ה-API האחרונה, ולא סכום מצטבר לסשן. Claude Code משאיר את המפתחות האופציונליים deferredBuiltinTools, systemTools ו-systemPromptSections לא מוגדרים, ולכן צפוי שהם ייעדרו גם אם הטיפוס מצהיר עליהם.

#SdkPluginConfig

תצורה לטעינת תוספים ב-SDK.

class SdkPluginConfig(TypedDict):
    type: Literal["local"]
    path: str
שדהטיפוסתיאור
typeLiteral["local"]חייב להיות "local" (כרגע נתמכים רק תוספים מקומיים)
pathstrנתיב מוחלט או יחסי לתיקיית התוסף

דוגמה:

plugins = [
    {"type": "local", "path": "./my-plugin"},
    {"type": "local", "path": "/absolute/path/to/plugin"},
]

למידע מלא על יצירה ושימוש בתוספים, ראו Plugins.

#סוגי הודעות

#Message

טיפוס איחוד של כל ההודעות האפשריות.

Message = (
    UserMessage
    | AssistantMessage
    | SystemMessage
    | ResultMessage
    | StreamEvent
    | RateLimitEvent
    | ConversationResetMessage
)

#UserMessage

הודעת קלט של המשתמש.

@dataclass
class UserMessage:
    content: str | list[ContentBlock]
    uuid: str | None = None
    parent_tool_use_id: str | None = None
    tool_use_result: dict[str, Any] | None = None
    origin: MessageOrigin | None = None
שדהטיפוסתיאור
contentstr | list[ContentBlock]תוכן ההודעה כטקסט או כבלוקי תוכן
uuidstr | Noneמזהה ייחודי של ההודעה
parent_tool_use_idstr | Noneמזהה שימוש בכלי אם ההודעה היא תשובת תוצאת כלי
tool_use_resultdict[str, Any] | Noneנתוני תוצאת הכלי, אם רלוונטי
originMessageOrigin | Noneמקור ההודעה, מאוכלס בתורות שהוזרקו כמו התראות משימה והודעות עמיתים. None כשה-CLI לא ייחס אותה. דורש Python Agent SDK 0.2.137 או מאוחר יותר

ה-SDK מעביר את tool_use_result מה-CLI בלי שינוי. עבור כלי בשרת MCP חיצוני שהתוצאה שלו מכילה בלוקי resource_link, למילון יש מפתח resourceLinks שמחזיק רשימת מילונים עם המפתחות של טיפוס TypeScript SDKMcpResourceLink. Claude מקבל כל קישור כשורת טקסט בתוצאת הכלי. כדי להציג את הקבצים שהשרת החזיר, קוראים את resourceLinks במקום לנתח את הטקסט הזה. המפתח resourceLinks דורש Python Agent SDK 0.2.150 או מאוחר יותר ו-Claude Code v2.1.257 או מאוחר יותר. ה-CLI שמצורף לגרסת ה-SDK הזו עומד בדרישת Claude Code.

ה-CLI משמיט את המפתח כשאין קישורים בתוצאה, וגם בתוצאות מסוכני משנה. ה-CLI שומר לכל היותר 50 קישורים לכל תוצאה, ומפסיק להוסיף קישורים ברגע שהרשימה מגיעה ל-64 KiB של JSON מסוּריאל. כלי שמוגדר בתוך התהליך עם tool() אף פעם לא מייצר את המפתח, כי ה-SDK משטח את בלוקי resource_link שלו לטקסט לפני שה-CLI רואה את התוצאה.

#AssistantMessage

הודעת תשובה של העוזר עם בלוקי תוכן.

@dataclass
class AssistantMessage:
    content: list[ContentBlock]
    model: str
    parent_tool_use_id: str | None = None
    error: AssistantMessageError | None = None
    usage: dict[str, Any] | None = None
    message_id: str | None = None
    stop_reason: str | None = None
    session_id: str | None = None
    uuid: str | None = None
שדהטיפוסתיאור
contentlist[ContentBlock]רשימת בלוקי התוכן בתשובה
modelstrהמודל שיצר את התשובה
parent_tool_use_idstr | Noneמזהה שימוש בכלי אם זו תשובה מקוננת
errorAssistantMessageError | Noneסוג השגיאה אם התשובה נתקלה בשגיאה
usagedict[str, Any] | Noneשימוש בטוקנים לכל הודעה (אותם מפתחות כמו ResultMessage.usage)
message_idstr | Noneמזהה הודעת API. כמה הודעות מאותה תור חולקות את אותו מזהה
stop_reasonstr | Noneסיבת העצירה מה-API (למשל end_turn, tool_use)
session_idstr | Noneהמזהה של הסשן שההודעה שייכת אליו
uuidstr | Noneמזהה ייחודי של ההודעה בתוך תמליל הסשן

#AssistantMessageError

סוגי שגיאה אפשריים להודעות עוזר.

AssistantMessageError = Literal[
    "authentication_failed",
    "billing_error",
    "rate_limit",
    "invalid_request",
    "server_error",
    "unknown",
]

תהליך ה-CLI שמתחת יכול לפלוט סוגי שגיאה שה-Literal הזה לא מפרט, כמו max_output_tokens. ה-SDK מעביר את הערך בלי שינוי, ולכן יש להתייחס למחרוזות מחוץ לרשימה הזו כמו שמתייחסים ל-unknown. טיפוס TypeScript SDKAssistantMessageError מפרט את קבוצת הערכים המלאה שה-CLI יכול לפלוט.

#SystemMessage

הודעת מערכת עם מטא נתונים.

@dataclass
class SystemMessage:
    subtype: str
    data: dict[str, Any]

תת סוגים שאין להם dataclass משלהם מגיעים כ-SystemMessage. כדי לעקוב אחרי הסשן בין תורות, מגדירים CLAUDE_CODE_EMIT_SESSION_STATE_EVENTS=1 וקוראים את message.data["state"] בכל הודעה שה-subtype שלה הוא session_state_changed. SDKSessionStateChangedMessage מפרט את המצבים שהוא יכול לשאת. עוברים עליהם עם receive_messages() כדי לקרוא אותם: receive_response() נעצר ב-ResultMessage, והודעת session_state_changed יכולה לבוא אחרי התוצאה הזו.

#ResultMessage

הודעת תוצאה סופית עם מידע על עלות ושימוש.

@dataclass
class ResultMessage:
    subtype: str
    duration_ms: int
    duration_api_ms: int
    is_error: bool
    num_turns: int
    session_id: str
    stop_reason: str | None = None
    total_cost_usd: float | None = None
    usage: dict[str, Any] | None = None
    result: str | None = None
    structured_output: Any = None
    model_usage: dict[str, ModelUsage] | None = None
    permission_denials: list[Any] | None = None
    deferred_tool_use: DeferredToolUse | None = None
    errors: list[str] | None = None
    api_error_status: int | None = None
    uuid: str | None = None
    terminal_reason: str | None = None
    origin: MessageOrigin | None = None

השדה subtype קובע אילו שדות אחרים מאוכלסים. הוא אחד מהערכים "success", "error_during_execution", "error_max_turns", "error_max_budget_usd", או "error_max_structured_output_retries". ה-dataclass של Python משטח את כל הוריאנטים לצורה אחת, כך ששדות שלא חלים על ה-subtype שהוחזר הם None.

כמה שדות נושאים פירוט אבחוני על האופן שבו השיחה הסתיימה:

  • is_error: True כשהשיחה הסתיימה במצב שגיאה. תמיד True בתת-הסוגים error_*. ב-subtype="success" הוא True בשלושה מקרים. בדקו את stop_reason כדי להבדיל ביניהם:
    • "refusal": המודל סירב להגיב. קראו את טקסט הסירוב ב-result, או ב-AssistantMessage הקודם כש-result ריק.
    • "tool_deferred_unavailable": הכלי שנדחה כבר לא היה זמין כשחידשתם את הסשן, למשל כי שרת ה-MCP שלו לא היה מחובר. בשני המקרים שלהלן, פרומפט שאתם שולחים אחרי חידוש נספר כמו פרומפט שהועבר עם ה-resume:
      • בלי פרומפט: הקריאה עדיין ממתינה. הפכו את הכלי לזמין וחדשו שוב בלי פרומפט, והקריאה תרוץ קודם.
      • פרומפט: Claude Code עונה עליו בלי תוצאת הכלי, והקריאה שנדחתה נעלמת. שלחו פרומפט חדש אם עדיין צריך לקרוא לכלי.
    • כל ערך אחר: התור הסתיים בשגיאה ש-Claude Code דיווח עליה במקום תשובת מודל, כמו שגיאת API. קראו את terminal_reason לסיבה, את result להודעה, ואת api_error_status לסטטוס ה-HTTP כשה-API החזיר אחד.
  • api_error_status: קוד סטטוס ה-HTTP של שגיאת ה-API המסיימת. None כשהתור הסתיים בלי שגיאה כזו. מאוכלס רק ב-subtype="success".
  • result: הטקסט של הודעת העוזר הסופית ב-subtype="success", או None בתת-הסוגים error_*. כש-subtype="success" ו-is_error=True, זה מחזיק את מחרוזת שגיאת ה-API אם אחת זמינה, אבל יכול להיות ריק, אז בדקו את api_error_status ואת תוכן ה-AssistantMessage הקודם לפירוט.
  • errors: מחרוזות שגיאה ברמת הלולאה, כמו הודעת מקסימום התורות. מאוכלס רק בתת-הסוגים error_*.
  • terminal_reason: למה לולאת השאילתה הסתיימה, למשל "completed", "max_turns", "api_error", "aborted_streaming", או "aborted_tools". ערך "aborted_streaming" או "aborted_tools" אומר שהתור בוטל לפני שהושלם. סיבות נפוצות הן interrupt() וקריאת callback של הרשאה שמחזירה PermissionResultDeny עם interrupt=True. None בגרסאות CLI שקדמו לשדה, בתוצאות מפקודות מקומיות כמו /voice או /usage, שעוקפות את לולאת השאילתה, או בתוצאות שגיאה מסונתזות שנפלטות כשהסשן נכשל באופן קטלני. משקף את SDKResultMessage.terminal_reason של ה-SDK של TypeScript, שמפרט את קבוצת הערכים המלאה.
  • origin: המקור של הודעת המשתמש שהפעילה את התור הזה. במצב קלט בזרימה, בדקו את זה כדי להבדיל בין התוצאה של הפרומפט שלכם, שבו origin הוא None או {"kind": "human"}, לבין התוצאה של תור שהוזרק, כמו התראת משימת רקע. דורש Python Agent SDK 0.2.137 או חדש יותר.

כשכמה משימות רקע מסתיימות קרוב זו לזו, Claude Code יכול לענות על ההתראות שלהן בתור אחד במקום בתור לכל אחת. עדיין מקבלים ResultMessage אחד לכל התראה, לפי הסדר, כל אחד עם origin ש-kind שלו הוא "task-notification". לכולם חוץ מהאחרון יש num_turns שמוגדר ל-0 ו-result ריק, והאחרון נושא את התור שעונה על כולן.

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

מפתחטיפוסתיאור
input_tokensintטוקני קלט שנצרכו על ידי לולאת הסוכן ברמה העליונה. טוקני תת-סוכן אינם כלולים; השתמשו ב-model_usage לחשבונאות של כל העץ.
output_tokensintטוקני פלט שנוצרו על ידי לולאת הסוכן ברמה העליונה. טוקני תת-סוכן אינם כלולים.
cache_creation_input_tokensintטוקנים ששימשו ליצירת רשומות מטמון חדשות.
cache_read_input_tokensintטוקנים שנקראו מרשומות מטמון קיימות.

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

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

כל ערך ב-model_usage הוא TypedDict מסוג ModelUsage, שמיובא באמצעות from claude_agent_sdk.types import ModelUsage. המפתחות שלו ב-camelCase כי ה-SDK מעביר את הערך כמו שהוא מתהליך ה-CLI שמתחת, בהתאמה לטיפוס ModelUsage של TypeScript:

מפתחטיפוסתיאור
inputTokensintטוקני קלט למודל הזה.
outputTokensintטוקני פלט למודל הזה.
cacheReadInputTokensintטוקני קריאה ממטמון למודל הזה.
cacheCreationInputTokensintטוקני יצירת מטמון למודל הזה.
webSearchRequestsintבקשות חיפוש באינטרנט שנעשו על ידי המודל הזה.
thinkingTokensintטוקני חשיבה שנוצרו על ידי המודל הזה, כבר נספרים בתוך outputTokens. נעדר עד שתור רץ על גרסת Claude Code שרושמת אותו, ולא מוצהר ב-TypedDict, אז קראו אותו עם .get(). דורש Python Agent SDK 0.2.150 או חדש יותר, שה-CLI הארוז איתו רושם אותו.
costUSDfloatעלות משוערת בדולר ארה"ב למודל הזה, מחושבת בצד הלקוח. ראו מעקב עלות ושימוש להסתייגויות חיוב.
contextWindowintגודל חלון ההקשר למודל הזה.
maxOutputTokensintמגבלת טוקני הפלט המרבית למודל הזה.
canonicalModelstrמזהה המודל הקנוני ששימש לחיפוש התמחור. עשוי להיות שונה ממחרוזת המודל הגולמית שלפיה הרשומה ממופתחת, כמו מזהה או כינוי ספציפי לספק. לא תמיד נוכח.
providerstrספק ה-API ששירת את המודל הזה, למשל firstParty, bedrock, vertex, foundry, anthropicAws, mantle, או gateway. לא תמיד נוכח.
costBasisstrטבלת המחירים שתמחרה את הבקשה האחרונה של המודל הזה: list למחיר מחירון, managed לטבלת modelPricing, או unknown כשאף אחד מהם לא התאים למזהה המודל. לא תמיד נוכח, ולא מוצהר ב-TypedDict, אז קראו אותו עם .get(). דורש Claude Code v2.1.246 או חדש יותר.

#StreamEvent

אירוע זרם לעדכוני הודעה חלקיים בזמן זרימה. מתקבל רק כש-include_partial_messages=True ב-ClaudeAgentOptions. ייבוא באמצעות from claude_agent_sdk.types import StreamEvent.

@dataclass
class StreamEvent:
    uuid: str
    session_id: str
    event: dict[str, Any]  # The raw Claude API stream event
    parent_tool_use_id: str | None = None
שדהטיפוסתיאור
uuidstrמזהה ייחודי לאירוע הזה
session_idstrמזהה סשן
eventdict[str, Any]נתוני אירוע זרם ה-API הגולמיים של Claude
parent_tool_use_idstr | Noneתמיד None. אירועי זרם נפלטים רק לסשן הראשי. לשיוך לתת-סוכן, השתמשו בהודעות שלמות כמו AssistantMessage

#RateLimitEvent

נפלט כשסטטוס מגבלת הקצב משתנה (למשל, מ-"allowed" ל-"allowed_warning"). השתמשו בזה כדי להזהיר משתמשים לפני שהם מגיעים למגבלה קשיחה, או כדי להאט כשהסטטוס הוא "rejected".

@dataclass
class RateLimitEvent:
    rate_limit_info: RateLimitInfo
    uuid: str
    session_id: str
שדהטיפוסתיאור
rate_limit_infoRateLimitInfoמצב מגבלת הקצב הנוכחי
uuidstrמזהה אירוע ייחודי
session_idstrמזהה סשן

#RateLimitInfo

מצב מגבלת קצב שנישא על ידי RateLimitEvent.

RateLimitStatus = Literal["allowed", "allowed_warning", "rejected"]
RateLimitType = Literal[
    "five_hour", "seven_day", "seven_day_opus", "seven_day_sonnet", "overage"
]


@dataclass
class RateLimitInfo:
    status: RateLimitStatus
    resets_at: int | None = None
    rate_limit_type: RateLimitType | None = None
    utilization: float | None = None
    overage_status: RateLimitStatus | None = None
    overage_resets_at: int | None = None
    overage_disabled_reason: str | None = None
    raw: dict[str, Any] = field(default_factory=dict)
שדהטיפוסתיאור
statusRateLimitStatusהסטטוס הנוכחי, אחד מ-"allowed", "allowed_warning", או "rejected". "allowed_warning" אומר שמתקרבים למגבלה; "rejected" אומר שהמגבלה הושגה
resets_atint | Noneחותמת זמן Unix שבה חלון מגבלת הקצב מתאפס
rate_limit_typeRateLimitType | Noneאיזה חלון מגבלת קצב חל
utilizationfloat | Noneהחלק ממגבלת הקצב שנצרך (0.0 עד 1.0)
overage_statusRateLimitStatus | Noneסטטוס שימוש חריגה בתשלום לפי שימוש, אם רלוונטי
overage_resets_atint | Noneחותמת זמן Unix שבה חלון החריגה מתאפס
overage_disabled_reasonstr | Noneלמה חריגה אינה זמינה, אם הסטטוס הוא "rejected"
rawdict[str, Any]המילון הגולמי המלא מה-CLI, כולל שדות שלא ממודלים למעלה

#ConversationResetMessage

נפלט כשהשיחה מוחלפת בלי לסיים את החיבור, למשל אחרי /clear. ראו מעקב עלויות במצב קלט בזרימה לאופן שבו איפוס משפיע על הסכומים הרצים באובייקטי ResultMessage מאוחרים יותר. דורש Python Agent SDK 0.2.137 או חדש יותר.

@dataclass
class ConversationResetMessage:
    new_conversation_id: str
    uuid: str
    session_id: str
שדהטיפוסתיאור
new_conversation_idstrמזהה אטום לשיחה החדשה. זה לא ה-session_id של ההודעות הבאות; קראו אותו מההודעה הבאה
uuidstrמזהה הודעה ייחודי
session_idstrהמזהה של הסשן שאופס. הודעות אחרי האיפוס נושאות session_id חדש

#TaskStartedMessage

נפלט כשמשימת רקע מתחילה. משימת רקע היא כל דבר שעוקבים אחריו מחוץ לתור הראשי: פקודת Bash שהועברה לרקע, מעקב Monitor, תת-סוכן שהופעל דרך כלי Agent, או סוכן מרוחק. השדה task_type אומר איזה. השם הזה אינו קשור לשינוי השם של הכלי מ-Task ל-Agent.

@dataclass
class TaskStartedMessage(SystemMessage):
    task_id: str
    description: str
    uuid: str
    session_id: str
    tool_use_id: str | None = None
    task_type: str | None = None
שדהטיפוסתיאור
task_idstrמזהה ייחודי למשימה
descriptionstrתיאור המשימה
uuidstrמזהה הודעה ייחודי
session_idstrמזהה סשן
tool_use_idstr | Noneמזהה שימוש בכלי המשויך
task_typestr | Noneאיזה סוג של משימת רקע: "local_bash" ל-Bash ברקע ולמעקבי Monitor, "local_agent", או "remote_agent"

#TaskUsage

נתוני טוקנים ותזמון למשימת רקע.

class TaskUsage(TypedDict):
    total_tokens: int
    tool_uses: int
    duration_ms: int

#TaskProgressMessage

נפלט מדי פעם עם עדכוני התקדמות למשימת רקע רצה.

@dataclass
class TaskProgressMessage(SystemMessage):
    task_id: str
    description: str
    usage: TaskUsage
    uuid: str
    session_id: str
    tool_use_id: str | None = None
    last_tool_name: str | None = None
שדהטיפוסתיאור
task_idstrמזהה ייחודי למשימה
descriptionstrתיאור הסטטוס הנוכחי
usageTaskUsageשימוש בטוקנים למשימה הזו עד כה
uuidstrמזהה הודעה ייחודי
session_idstrמזהה סשן
tool_use_idstr | Noneמזהה שימוש בכלי המשויך
last_tool_namestr | Noneשם הכלי האחרון שהמשימה השתמשה בו

#TaskNotificationMessage

נפלט כשמשימת רקע מסתיימת, נכשלת, או נעצרת. משימות רקע כוללות פקודות Bash עם run_in_background, מעקבי Monitor, ותת-סוכנים ברקע.

@dataclass
class TaskNotificationMessage(SystemMessage):
    task_id: str
    status: TaskNotificationStatus  # "completed" | "failed" | "stopped"
    output_file: str
    summary: str
    uuid: str
    session_id: str
    tool_use_id: str | None = None
    usage: TaskUsage | None = None
שדהטיפוסתיאור
task_idstrמזהה ייחודי למשימה
statusTaskNotificationStatusאחד מ-"completed", "failed", או "stopped"
output_filestrנתיב לקובץ הפלט של המשימה
summarystrסיכום תוצאת המשימה
uuidstrמזהה הודעה ייחודי
session_idstrמזהה סשן
tool_use_idstr | Noneמזהה שימוש בכלי המשויך
usageTaskUsage | Noneשימוש סופי בטוקנים למשימה

כשה-CLI מעביר קריאת כלי MCP ארוכה לרקע, תוצאת הכלי לקריאה הזו מחזיקה רק מציין מקום, והתוצאה האמיתית של הקריאה מגיעה בהודעה הזו. בהתראת "completed" לקריאה כזו, ה-CLI מוסיף מפתח resource_links שמפרט את הקבצים שהכלי החזיר לפי הפניה, עם אותן רשומות ומגבלות כמו מפתח resourceLinks ב-UserMessage.tool_use_result. המפתח resource_links דורש Python Agent SDK 0.2.150 או חדש יותר ו-Claude Code v2.1.257 או חדש יותר; ה-CLI הארוז עם גרסת ה-SDK הזו עומד בדרישת Claude Code.

ל-dataclass אין שדה עבור resource_links. קראו אותו ממילון data שההודעה יורשת מ-SystemMessage: message.data.get("resource_links"). התאימו את ההתראה לקריאה באמצעות tool_use_id. ה-CLI משמיט את המפתח כשלתוצאה לא היו קישורים ובהתראות למשימות שאינן קריאות כלי MCP.

#טיפוסי בלוקי תוכן

#ContentBlock

טיפוס איחוד של כל בלוקי התוכן.

ContentBlock = (
    TextBlock
    | ThinkingBlock
    | ToolUseBlock
    | ToolResultBlock
    | ServerToolUseBlock
    | ServerToolResultBlock
)

#TextBlock

בלוק תוכן טקסט.

@dataclass
class TextBlock:
    text: str

#ThinkingBlock

בלוק תוכן חשיבה (למודלים עם יכולת חשיבה).

@dataclass
class ThinkingBlock:
    thinking: str
    signature: str

#ToolUseBlock

בלוק בקשת שימוש בכלי.

@dataclass
class ToolUseBlock:
    id: str
    name: str
    input: dict[str, Any]

#ToolResultBlock

בלוק תוצאת הרצת כלי.

@dataclass
class ToolResultBlock:
    tool_use_id: str
    content: str | list[dict[str, Any]] | None = None
    is_error: bool | None = None

#סוגי שגיאות

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

#ClaudeSDKError

מחלקת חריגה בסיסית לכל שגיאות ה-SDK.

class ClaudeSDKError(Exception):
    """Base error for Claude SDK."""

כאשר query() בזריקה אחת מסתיים בתוצאת שגיאה, למשל שגיאת מגבלת תורות, ה-SDK מעלה ResultError.

#CLINotFoundError

מועלה כאשר Claude Code CLI לא מותקן או לא נמצא.

class CLINotFoundError(CLIConnectionError):
    def __init__(
        self, message: str = "Claude Code not found", cli_path: str | None = None
    ):
        """
        Args:
            message: Error message (default: "Claude Code not found")
            cli_path: Optional path to the CLI that was not found
        """

#CLIConnectionError

מועלה כאשר החיבור ל-Claude Code נכשל.

class CLIConnectionError(ClaudeSDKError):
    """Failed to connect to Claude Code."""

#ProcessError

מועלה כאשר תהליך Claude Code נכשל.

class ProcessError(ClaudeSDKError):
    def __init__(
        self, message: str, exit_code: int | None = None, stderr: str | None = None
    ):
        self.exit_code = exit_code
        self.stderr = stderr

#ResultError

מועלה כאשר תהליך Claude Code יוצא כי הריצה הסתיימה בהודעת תוצאה של שגיאה, כגון שגיאת מגבלת תורות או שגיאת API. ResultError יורש מ-ProcessError, כך שמטפל קיים של except ProcessError תופס גם אותו. המאפיינים שלו נושאים את השדות של הודעת התוצאה הזו, כך שאפשר להסתעף לפי הסיבה שהריצה נכשלה בלי לפרסר את טקסט ההודעה. דורש Python Agent SDK 0.2.140 או גרסה מאוחרת יותר.

class ResultError(ProcessError):
    subtype: str | None  # "error_max_turns", "error_during_execution", ...; "success" when the run ended on a failed request
    errors: list[str]  # an empty list when the result message reported none
    result: str | None
    api_error_status: int | None
    terminal_reason: str | None  # "max_turns", "api_error", ...; check after data["stop_reason"], before subtype
    session_id: str | None
    data: dict[str, Any]  # the raw result message payload

כדי להבדיל בין כשלים, בדקו קודם את data["stop_reason"], אחר כך את terminal_reason, ואחר כך את subtype. לתגובה שנדחתה יש stop_reason עם הערך "refusal", בדרך כלל עם subtype "success". ה-terminal_reason שלה לא מבדיל אותה בפני עצמו, ויכול לקרוא "completed" או "api_error". לבקשה סופית שנכשלה יש subtype "success" והסיבה שלה ב-terminal_reason, למשל "api_error" עבור שגיאת API. כאשר הריצה מגיעה למגבלה שהגדרתם, כגון max_turns או max_budget_usd, מתקבל subtype מסוג error_*.

#CLIJSONDecodeError

מועלה כאשר פענוח JSON נכשל.

class CLIJSONDecodeError(ClaudeSDKError):
    def __init__(self, line: str, original_error: Exception):
        """
        Args:
            line: The line that failed to parse
            original_error: The original JSON decode exception
        """
        self.line = line
        self.original_error = original_error

#סוגי Hook

למדריך מקיף על שימוש ב-hooks עם דוגמאות ודפוסים נפוצים, ראו את מדריך ה-Hooks.

#HookEvent

סוגי אירועי hook נתמכים.

HookEvent = Literal[
    "PreToolUse",  # Called before tool execution
    "PostToolUse",  # Called after tool execution
    "PostToolUseFailure",  # Called when a tool execution fails
    "UserPromptSubmit",  # Called when a prompt is submitted
    "Stop",  # Called when stopping execution
    "SubagentStop",  # Called when a subagent stops
    "PreCompact",  # Called before message compaction
    "Notification",  # Called for notification events
    "SubagentStart",  # Called when a subagent starts
    "PermissionRequest",  # Called when a permission decision is needed
]

[!NOTE]

ה-SDK של TypeScript תומך באירועי hook נוספים שעדיין אינם זמינים ב-Python. ראו את טבלת זמינות ה-hooks לתמיכה לפי SDK.

#HookCallback

הגדרת טיפוס לפונקציות callback של hook.

HookCallback = Callable[[HookInput, str | None, HookContext], Awaitable[HookJSONOutput]]

פרמטרים:

  • input: קלט hook עם טיפוס חזק, עם union מובחן לפי hook_event_name (ראו HookInput)
  • tool_use_id: מזהה שימוש בכלי אופציונלי (ל-hooks שקשורים לכלים)
  • context: הקשר ה-hook עם מידע נוסף

מחזיר HookJSONOutput.

#HookContext

מידע הקשר שמועבר ל-callback של hook.

class HookContext(TypedDict):
    signal: Any | None  # Future: abort signal support

#HookMatcher

הגדרה להתאמת hooks לאירועים או לכלים מסוימים.

@dataclass
class HookMatcher:
    matcher: str | None = (
        None  # Tool name or pattern to match (e.g., "Bash", "Write|Edit")
    )
    hooks: list[HookCallback] = field(
        default_factory=list
    )  # List of callbacks to execute
    timeout: float | None = (
        None  # Timeout in seconds. When omitted, the per-event default applies:
        # 600 for most events, 30 for UserPromptSubmit
    )
    on_failure: Literal["continue", "block"] | None = (
        None  # "block" blocks the action when a callback fails
    )

כדי להחליט מה on_failure מכסה, ראו חסימת הפעולה כאשר callback נכשל.

#HookInput

טיפוס union של כל סוגי קלט ה-hook. הטיפוס בפועל תלוי בשדה hook_event_name.

HookInput = (
    PreToolUseHookInput
    | PostToolUseHookInput
    | PostToolUseFailureHookInput
    | UserPromptSubmitHookInput
    | StopHookInput
    | SubagentStopHookInput
    | PreCompactHookInput
    | NotificationHookInput
    | SubagentStartHookInput
    | PermissionRequestHookInput
)

#BaseHookInput

שדות בסיס שנמצאים בכל סוגי קלט ה-hook.

class BaseHookInput(TypedDict):
    session_id: str
    transcript_path: str
    cwd: str
    permission_mode: NotRequired[str]
שדהטיפוסתיאור
session_idstrמזהה הסשן הנוכחי
transcript_pathstrנתיב לקובץ התמליל של הסשן
cwdstrספריית העבודה הנוכחית
permission_modestr (אופציונלי)מצב ההרשאות הנוכחי

#PreToolUseHookInput

נתוני קלט לאירועי hook מסוג PreToolUse.

class PreToolUseHookInput(BaseHookInput):
    hook_event_name: Literal["PreToolUse"]
    tool_name: str
    tool_input: dict[str, Any]
    tool_use_id: str
    agent_id: NotRequired[str]
    agent_type: NotRequired[str]
שדהטיפוסתיאור
hook_event_nameLiteral["PreToolUse"]תמיד "PreToolUse"
tool_namestrשם הכלי שעומד להתבצע
tool_inputdict[str, Any]פרמטרי הקלט של הכלי
tool_use_idstrמזהה ייחודי לשימוש הזה בכלי
agent_idstr (אופציונלי)מזהה סוכן המשנה, נוכח כאשר ה-hook מופעל בתוך סוכן משנה
agent_typestr (אופציונלי)סוג סוכן המשנה, נוכח כאשר ה-hook מופעל בתוך סוכן משנה

#PostToolUseHookInput

נתוני קלט לאירועי hook מסוג PostToolUse.

class PostToolUseHookInput(BaseHookInput):
    hook_event_name: Literal["PostToolUse"]
    tool_name: str
    tool_input: dict[str, Any]
    tool_response: Any
    tool_use_id: str
    agent_id: NotRequired[str]
    agent_type: NotRequired[str]
שדהטיפוסתיאור
hook_event_nameLiteral["PostToolUse"]תמיד "PostToolUse"
tool_namestrשם הכלי שבוצע
tool_inputdict[str, Any]פרמטרי הקלט שבהם נעשה שימוש
tool_responseAnyהתגובה מביצוע הכלי
tool_use_idstrמזהה ייחודי לשימוש הזה בכלי
agent_idstr (אופציונלי)מזהה סוכן המשנה, נוכח כאשר ה-hook מופעל בתוך סוכן משנה
agent_typestr (אופציונלי)סוג סוכן המשנה, נוכח כאשר ה-hook מופעל בתוך סוכן משנה

#PostToolUseFailureHookInput

נתוני קלט לאירועי hook מסוג PostToolUseFailure. נקרא כאשר ביצוע כלי נכשל.

class PostToolUseFailureHookInput(BaseHookInput):
    hook_event_name: Literal["PostToolUseFailure"]
    tool_name: str
    tool_input: dict[str, Any]
    tool_use_id: str
    error: str
    is_interrupt: NotRequired[bool]
    agent_id: NotRequired[str]
    agent_type: NotRequired[str]
שדהטיפוסתיאור
hook_event_nameLiteral["PostToolUseFailure"]תמיד "PostToolUseFailure"
tool_namestrשם הכלי שנכשל
tool_inputdict[str, Any]פרמטרי הקלט שבהם נעשה שימוש
tool_use_idstrמזהה ייחודי לשימוש הזה בכלי
errorstrהודעת השגיאה מהביצוע שנכשל
is_interruptbool (אופציונלי)True כאשר הכשל הגיע אל Claude Code כ-abort ולא כשגיאה שהכלי דיווח. ביטול כלי שרץ באמצעות interrupt() לא מפעיל את ה-hook הזה. תוצאת הכלי נושאת את הודעת ההפרעה במקום זאת
agent_idstr (אופציונלי)מזהה סוכן המשנה, נוכח כאשר ה-hook מופעל בתוך סוכן משנה
agent_typestr (אופציונלי)סוג סוכן המשנה, נוכח כאשר ה-hook מופעל בתוך סוכן משנה

#UserPromptSubmitHookInput

נתוני קלט לאירועי hook מסוג UserPromptSubmit.

class UserPromptSubmitHookInput(BaseHookInput):
    hook_event_name: Literal["UserPromptSubmit"]
    prompt: str
שדהטיפוסתיאור
hook_event_nameLiteral["UserPromptSubmit"]תמיד "UserPromptSubmit"
promptstrהפרומפט שנשלח

#StopHookInput

נתוני קלט לאירועי hook מסוג Stop.

class StopHookInput(BaseHookInput):
    hook_event_name: Literal["Stop"]
    stop_hook_active: bool
שדהטיפוסתיאור
hook_event_nameLiteral["Stop"]תמיד "Stop"
stop_hook_activeboolהאם ה-stop hook פעיל

#SubagentStopHookInput

נתוני קלט לאירועי hook מסוג SubagentStop.

class SubagentStopHookInput(BaseHookInput):
    hook_event_name: Literal["SubagentStop"]
    stop_hook_active: bool
    agent_id: str
    agent_transcript_path: str
    agent_type: str
שדהטיפוסתיאור
hook_event_nameLiteral["SubagentStop"]תמיד "SubagentStop"
stop_hook_activeboolהאם ה-stop hook פעיל
agent_idstrמזהה ייחודי של סוכן המשנה
agent_transcript_pathstrנתיב לקובץ התמליל של סוכן המשנה
agent_typestrסוג סוכן המשנה

#PreCompactHookInput

נתוני קלט לאירועי hook מסוג PreCompact.

class PreCompactHookInput(BaseHookInput):
    hook_event_name: Literal["PreCompact"]
    trigger: Literal["manual", "auto"]
    custom_instructions: str | None
שדהטיפוסתיאור
hook_event_nameLiteral["PreCompact"]תמיד "PreCompact"
triggerLiteral["manual", "auto"]מה הפעיל את הדחיסה
custom_instructionsstr | Noneהוראות מותאמות לדחיסה

#NotificationHookInput

נתוני קלט לאירועי hook מסוג Notification.

class NotificationHookInput(BaseHookInput):
    hook_event_name: Literal["Notification"]
    message: str
    title: NotRequired[str]
    notification_type: str
שדהטיפוסתיאור
hook_event_nameLiteral["Notification"]תמיד "Notification"
messagestrתוכן הודעת ההתראה
titlestr (אופציונלי)כותרת ההתראה
notification_typestrסוג ההתראה

#SubagentStartHookInput

נתוני קלט לאירועי hook מסוג SubagentStart.

class SubagentStartHookInput(BaseHookInput):
    hook_event_name: Literal["SubagentStart"]
    agent_id: str
    agent_type: str
שדהטיפוסתיאור
hook_event_nameLiteral["SubagentStart"]תמיד "SubagentStart"
agent_idstrמזהה ייחודי של סוכן המשנה
agent_typestrסוג סוכן המשנה

#PermissionRequestHookInput

נתוני קלט לאירועי hook מסוג PermissionRequest. מאפשר ל-hooks לטפל בהחלטות הרשאה באופן תכנותי.

class PermissionRequestHookInput(BaseHookInput):
    hook_event_name: Literal["PermissionRequest"]
    tool_name: str
    tool_input: dict[str, Any]
    permission_suggestions: NotRequired[list[Any]]
    agent_id: NotRequired[str]
    agent_type: NotRequired[str]
שדהטיפוסתיאור
hook_event_nameLiteral["PermissionRequest"]תמיד "PermissionRequest"
tool_namestrשם הכלי שמבקש הרשאה
tool_inputdict[str, Any]פרמטרי הקלט של הכלי
permission_suggestionslist[Any] (אופציונלי)עדכוני הרשאה מוצעים מה-CLI
agent_idstr (אופציונלי)מזהה סוכן המשנה, נוכח כאשר ה-hook מופעל בתוך סוכן משנה
agent_typestr (אופציונלי)סוג סוכן המשנה, נוכח כאשר ה-hook מופעל בתוך סוכן משנה

#HookJSONOutput

טיפוס union לערכי החזרה של callback של hook.

HookJSONOutput = AsyncHookJSONOutput | SyncHookJSONOutput

#SyncHookJSONOutput

פלט hook סינכרוני עם שדות שליטה והחלטה.

class SyncHookJSONOutput(TypedDict):
    # Control fields
    continue_: NotRequired[bool]  # Whether to proceed (default: True)
    suppressOutput: NotRequired[bool]  # Hide stdout from transcript
    stopReason: NotRequired[str]  # Message when continue is False

    # Decision fields
    decision: NotRequired[Literal["block"]]
    systemMessage: NotRequired[str]  # Warning message for user
    reason: NotRequired[str]  # Feedback for Claude

    # Hook-specific output
    hookSpecificOutput: NotRequired[HookSpecificOutput]

[!NOTE]

השתמשו ב-continue_ (עם קו תחתון) בקוד Python. הוא מומר אוטומטית ל-continue כאשר הוא נשלח ל-CLI.

#HookSpecificOutput

union מובחן של טיפוסי פלט TypedDict שספציפיים לאירוע. השדה hookEventName קובע אילו שדות תקפים. לפרטים מלאים על השדות הזמינים לכל אירוע hook, ראו שליטה בביצוע עם hooks.

class PreToolUseHookSpecificOutput(TypedDict):
    hookEventName: Literal["PreToolUse"]
    permissionDecision: NotRequired[Literal["allow", "deny", "ask", "defer"]]
    permissionDecisionReason: NotRequired[str]
    updatedInput: NotRequired[dict[str, Any]]
    additionalContext: NotRequired[str]


class PostToolUseHookSpecificOutput(TypedDict):
    hookEventName: Literal["PostToolUse"]
    additionalContext: NotRequired[str]
    updatedToolOutput: NotRequired[Any]
    updatedMCPToolOutput: NotRequired[Any]  # MCP tools only. Prefer updatedToolOutput, which works for all tools


class PostToolUseFailureHookSpecificOutput(TypedDict):
    hookEventName: Literal["PostToolUseFailure"]
    additionalContext: NotRequired[str]


class UserPromptSubmitHookSpecificOutput(TypedDict):
    hookEventName: Literal["UserPromptSubmit"]
    additionalContext: NotRequired[str]


class NotificationHookSpecificOutput(TypedDict):
    hookEventName: Literal["Notification"]
    additionalContext: NotRequired[str]


class SubagentStartHookSpecificOutput(TypedDict):
    hookEventName: Literal["SubagentStart"]
    additionalContext: NotRequired[str]


class PermissionRequestHookSpecificOutput(TypedDict):
    hookEventName: Literal["PermissionRequest"]
    decision: dict[str, Any]


HookSpecificOutput = (
    PreToolUseHookSpecificOutput
    | PostToolUseHookSpecificOutput
    | PostToolUseFailureHookSpecificOutput
    | UserPromptSubmitHookSpecificOutput
    | NotificationHookSpecificOutput
    | SubagentStartHookSpecificOutput
    | PermissionRequestHookSpecificOutput
)

#AsyncHookJSONOutput

פלט hook אסינכרוני שדוחה את ביצוע ה-hook.

class AsyncHookJSONOutput(TypedDict):
    async_: Literal[True]  # Set to True to defer execution
    asyncTimeout: NotRequired[int]  # Timeout in milliseconds

[!NOTE]

השתמשו ב-async_ (עם קו תחתון) בקוד Python. הוא מומר אוטומטית ל-async כאשר הוא נשלח ל-CLI.

#דוגמה לשימוש ב-Hook

הדוגמה הזו רושמת שני hooks: אחד שחוסם פקודות Bash מסוכנות כמו rm -rf /, ואחר שמתעד את כל השימוש בכלים לצורכי ביקורת. ה-hook של האבטחה רץ רק על פקודות Bash (דרך ה-matcher), בעוד שה-hook של התיעוד רץ על כל הכלים.

import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, HookMatcher, HookContext
from typing import Any


async def validate_bash_command(
    input_data: dict[str, Any], tool_use_id: str | None, context: HookContext
) -> dict[str, Any]:
    """Validate and potentially block dangerous bash commands."""
    if input_data["tool_name"] == "Bash":
        command = input_data["tool_input"].get("command", "")
        if "rm -rf /" in command:
            return {
                "hookSpecificOutput": {
                    "hookEventName": "PreToolUse",
                    "permissionDecision": "deny",
                    "permissionDecisionReason": "Dangerous command blocked",
                }
            }
    return {}


async def log_tool_use(
    input_data: dict[str, Any], tool_use_id: str | None, context: HookContext
) -> dict[str, Any]:
    """Log all tool usage for auditing."""
    print(f"Tool used: {input_data.get('tool_name')}")
    return {}


options = ClaudeAgentOptions(
    hooks={
        "PreToolUse": [
            HookMatcher(
                matcher="Bash", hooks=[validate_bash_command], timeout=120
            ),  # 2 min for validation
            HookMatcher(
                hooks=[log_tool_use]
            ),  # Applies to all tools (per-event default timeout)
        ],
        "PostToolUse": [HookMatcher(hooks=[log_tool_use])],
    }
)

async def main():
    async for message in query(prompt="Analyze this codebase", options=options):
        print(message)


asyncio.run(main())

#טיפוסי קלט ופלט של כלים

תיעוד של סכמות קלט ופלט לכלים המובנים של Claude Code. ה-SDK של Python לא מייצא אותם כטיפוסים, אבל הם מייצגים את המבנה של קלטי כלים ופלטי כלים בהודעות.

כל פלט שמוצג הוא הערך שקוראים מ-UserMessage.tool_use_result עבור הכלי הזה. שמות המפתחות מופיעים בדיוק כפי ש-Claude Code פולט אותם. מפתח שמסומן | None עם הערת "present when" או "optional" מושמט כאשר הוא לא חל.

#Agent

שם הכלי: Agent. השם הקודם Task עדיין מתקבל ככינוי כאשר הכלי הזה זמין לסשן.

רשימת tools ב-SystemMessage של האתחול מדווחת על הכלי הזה כ-Task לצורך תאימות לאחור.

קלט:

{
    "description": str,  # A short (3-5 word) description of the task
    "prompt": str,  # The task for the agent to perform
    "subagent_type": str | None,  # The type of specialized agent to use
    "model": "sonnet" | "opus" | "haiku" | "fable" | None,  # Model override for this agent
    "effort": "low" | "medium" | "high" | "xhigh" | "max" | None,  # Reasoning effort for this agent
    "run_in_background": bool | None,  # Default when omitted: your main agent's call runs the new agent in the background, and a subagent's call waits for it
    "name": str | None,  # Name for the spawned agent
    "team_name": str | None,  # Deprecated; ignored
    "mode": "acceptEdits" | "auto" | "bypassPermissions" | "default" | "dontAsk" | "plan" | None,  # Deprecated; ignored. The subagent inheritance rules decide a subagent's permission mode
    "isolation": "worktree" | "remote" | None,  # Isolation mode for the agent's changes
}

מפעיל סוכן חדש לטיפול במשימות מורכבות ורב שלביות באופן אוטונומי.

כאשר Claude משמיט את run_in_background מקריאה ל-Agent, כברירת מחדל הסוכן הראשי שלך לא ממתין לסוכן החדש, ותת סוכן ממתין:

לפני Python SDK v0.2.169, גם סוכנים שתת הסוכנים שלך הפעילו רצו ברקע כברירת מחדל. הגרסה הזו היא הראשונה שמצרפת את Claude Code v2.1.302 או מאוחר יותר.

פלט (status: "completed"):

{
    "status": "completed",
    "agentId": str,  # ID of the agent that ran
    "agentType": str | None,  # The subagent type that handled the task
    "content": [  # Result content blocks
        {
            "type": "text",
            "text": str,
            "citations": list | None,
        }
    ],
    "resolvedModel": str | None,  # Model the subagent started on
    "modelsUsed": list[str] | None,  # Models used in order, with consecutive repeats collapsed
    "totalToolUseCount": int,  # Number of tool calls the agent made
    "totalDurationMs": int,  # Execution duration in milliseconds
    "totalTokens": int,  # Token count from the final API request, not the whole run
    "usage": {  # Token usage statistics
        "input_tokens": int,
        "output_tokens": int,
        "cache_creation_input_tokens": int | None,
        "cache_read_input_tokens": int | None,
        "server_tool_use": {"web_search_requests": int, "web_fetch_requests": int} | None,
        "service_tier": str | None,
        "cache_creation": {"ephemeral_1h_input_tokens": int, "ephemeral_5m_input_tokens": int} | None,
        "inference_geo": str | None,
        "speed": str | None,
        "iterations": Any | None,
        "output_tokens_details": {"thinking_tokens": int | None} | None,
        "fallback_credit": Any | None,
    },
    "toolStats": {  # Aggregate tool activity for the run
        "readCount": int,
        "searchCount": int,
        "bashCount": int,
        "editFileCount": int,
        "linesAdded": int,
        "linesRemoved": int,
        "otherToolCount": int,
        "frameCount": int | None,
    } | None,
    "prompt": str,  # The prompt the agent ran
    "worktreePath": str | None,  # Present when Claude Code kept the subagent's worktree
    "worktreeBranch": str | None,  # Present when Claude Code created that worktree with git
}

פלט (status: "async_launched"):

{
    "status": "async_launched",
    "isAsync": bool | None,  # True on background launches
    "agentId": str,  # ID of the launched agent
    "description": str,  # The task description
    "resolvedModel": str | None,  # Model in use at the backgrounding transition
    "modelsUsed": list[str] | None,  # Models used before backgrounding, in order, with consecutive repeats collapsed
    "prompt": str,  # The prompt the agent runs
    "outputFile": str,  # File path where the agent's output is written
    "canReadOutputFile": bool | None,  # Whether the output file can be read directly
}

פלט (status: "remote_launched"):

{
    "status": "remote_launched",
    "taskId": str,  # ID of the dispatched task
    "sessionUrl": str,  # Link to the cloud session
    "description": str,  # The task description
    "prompt": str,  # The prompt the agent runs
    "outputFile": str,  # File path where the agent's output is written
}

מחזיר את התוצאה מתת הסוכן. הפלט מובחן לפי שדה status: "completed" למשימות שהסתיימו, "async_launched" למשימות רקע, ו-"remote_launched" למשימות ש-Claude Code שיגר לסשן ענן, שבו sessionUrl מקשר לסשן הזה ו-taskId מזהה אותו. אם Claude Code שמר את עץ העבודה המבודד של תת הסוכן, worktreePath בווריאנט completed הוא המקום שבו למצוא אותו, ו-worktreeBranch הוא הענף שלו כאשר Claude Code יצר את עץ העבודה עם git.

בווריאנט completed, resolvedModel מציין את המודל שעליו תת הסוכן התחיל, והוא יכול להיות שונה מקלט model המבוקש כאשר availableModels או דריסה אחרת חלים. השדה הזה דורש Claude Code v2.1.174 או מאוחר יותר. בווריאנט async_launched, resolvedModel מציין את המודל שבשימוש כאשר הסוכן עבר לרקע, כך שהחלפה שהתרחשה לפני המעבר לרקע משתקפת שם. השדה modelsUsed בשני הווריאנטים מפרט את המודלים ששימשו לפי הסדר, עם כיווץ של חזרות רצופות. הוא מוגדר רק כאשר המודל הוחלף באמצע הריצה. modelsUsed והתנהגות resolvedModel בזמן המעבר לרקע דורשים Claude Code v2.1.212 או מאוחר יותר.

Claude Code ממלא את usage ואת totalTokens מבקשת ה-API הסופית של תת הסוכן, לא מכל הריצה. כאשר הוא נוכח, thinking_tokens תחת output_tokens_details ב-usage הוא מספר אסימוני הפלט של הבקשה הזו שהיו אסימוני חשיבה. המפתח output_tokens_details דורש Python SDK v0.2.136 או מאוחר יותר, שמצרף את Claude Code v2.1.228. המפתח fallback_credit דורש Python SDK v0.2.162 או מאוחר יותר, שמצרף את Claude Code v2.1.285.

#AskUserQuestion

שם הכלי: AskUserQuestion

שואל את המשתמש שאלות הבהרה במהלך הביצוע. ראה טיפול באישורים ובקלט משתמש לפרטי שימוש.

קלט:

{
    "questions": [  # Questions to ask the user (1-4 questions)
        {
            "question": str,  # The complete question to ask the user
            "header": str,  # Very short label displayed as a chip/tag (max 12 chars)
            "options": [  # The available choices (2-4 options)
                {
                    "label": str,  # Display text for this option (1-5 words)
                    "description": str,  # Explanation of what this option means
                    "preview": str | None,  # Preview content rendered when the option is focused
                }
            ],
            "multiSelect": bool,  # Set to true to allow multiple selections
        }
    ],
    "answers": dict[str, str] | None,
    # User answers populated by the permission system. Multi-select
    # answers are a comma-joined string of the selected labels; a
    # list of labels is accepted on input and coerced to that form
    "annotations": dict[str, dict] | None,
    # Per-question annotations from the user, keyed by question text.
    # Each value can carry "preview" (the selected option's preview
    # content) and "notes" (free-text notes on the selection)
    "metadata": dict | None,  # Analytics metadata, such as {"source": "remember"}; not displayed to the user
}

פלט:

{
    "questions": [  # The questions that were asked
        {
            "question": str,
            "header": str,
            "options": [{"label": str, "description": str, "preview": str | None}],
            "multiSelect": bool,
        }
    ],
    "answers": dict[str, str],  # Maps question text to answer string
    # Multi-select answers are comma-separated
    "response": str | None,
    # Freeform reply typed instead of answering the questions; when set,
    # Claude receives "The user responded: ..." in place of the answer list
    "annotations": dict[str, dict] | None,  # Per-question "preview" and "notes" from the user's selections
    "afkTimeoutMs": int | None,  # Set when the dialog auto-resolved after this many milliseconds of user inactivity; absent when the user answered
}

#Bash

שם הכלי: Bash

למה שקובע את תקרת החזית, ראה מגבלות זמן ופלט. למגבלת הזמן ברקע, ראה מגבלת זמן לפקודות רקע.

קלט:

{
    "command": str,  # The command to execute
    "timeout": int | None,  # Milliseconds. Foreground: capped at 600000 by default, higher values are clamped. With run_in_background (Claude Code v2.1.285 or later): the background time limit, 1800000 when omitted, capped at 7200000 unless raised
    "description": str | None,  # Clear, concise description (5-10 words)
    "run_in_background": bool | None,  # Set to true to run in background
}

פלט:

{
    "stdout": str,  # The command's output; stdout and stderr arrive merged into this one interleaved stream
    "stderr": str,  # Notices the tool itself adds, not the command's stderr
    "interrupted": bool,  # Whether the command was interrupted
    "isImage": bool | None,  # Whether stdout contains image data
    "backgroundTaskId": str | None,  # ID of the background task if command is running in background
}

#Monitor

שם הכלי: Monitor

מריץ מקור רקע ומעביר כל אירוע ל-Claude כדי שיוכל להגיב בלי polling: command מריץ סקריפט ופולט אירוע אחד לכל שורת stdout, ו-ws פותח WebSocket ופולט אירוע אחד לכל מסגרת טקסט. יש לספק בדיוק אחד מבין command או ws.

כאשר Monitor מריץ פקודה, הוא פועל לפי אותם כללי הרשאה כמו Bash. מעקב WebSocket מבקש אישור בנפרד. מקור ws דורש Claude Code v2.1.195 או מאוחר יותר. ראה את הפניה לכלי Monitor להתנהגות ולזמינות ספקים.

קלט:

{
    "command": str | None,  # Shell script; each stdout line is an event, exit ends the watch
    "ws": dict | None,  # WebSocket source: {"url": str, "protocols": list[str] | None}; each text frame is an event
    "description": str,  # Short description shown in notifications
    "timeout_ms": int | None,  # Deadline in milliseconds (default 300000, max 3600000; the effective deadline is at most 1800000)
}

פלט:

{
    "taskId": str,  # ID of the background monitor task
    "timeoutMs": int,  # The watch's effective deadline in milliseconds
    "persistent": bool | None,  # False: every watch has a deadline
}

#Edit

שם הכלי: Edit

קלט:

{
    "file_path": str,  # The absolute path to the file to modify
    "old_string": str,  # The text to replace
    "new_string": str,  # The text to replace it with
    "replace_all": bool | None,  # Replace all occurrences (default False)
}

פלט:

{
    "filePath": str,  # The file that was edited
    "oldString": str,  # The text that was replaced
    "newString": str,  # The text that replaced it
    "originalFile": str | None,  # File contents before the edit
    "structuredPatch": [  # Diff hunks for the change
        {
            "oldStart": int,
            "oldLines": int,
            "newStart": int,
            "newLines": int,
            "lines": list[str],
        }
    ],
    "userModified": bool,  # Whether the user changed the proposed edit before accepting it
    "replaceAll": bool,  # Whether all occurrences were replaced
    "gitDiff": {  # Optional git diff summary for the file
        "filename": str,
        "status": "modified" | "added",
        "additions": int,
        "deletions": int,
        "changes": int,
        "patch": str,
        "repository": str | None,  # GitHub owner/repo when available
    } | None,
}

#Read

שם הכלי: Read

קלט:

{
    "file_path": str,  # The absolute path to the file to read
    "offset": int | None,  # The line number to start reading from
    "limit": int | None,  # The number of lines to read
}

הפלט מקבל אחת מהצורות הבאות לפי מה ש-Claude קרא. בדוק את המפתח type כדי להבדיל ביניהן.

פלט (type: "text"):

{
    "type": "text",
    "file": {
        "filePath": str,  # The file that was read
        "content": str,  # The returned content
        "numLines": int,  # Number of lines in the returned content
        "startLine": int,  # Line number the content starts at
        "totalLines": int,  # Total number of lines in the file
        "truncatedByTokenCap": bool | None,  # Present and True when a whole-file read exceeded the token cap and content is the first page
    },
}

פלט (type: "image"):

{
    "type": "image",
    "file": {
        "base64": str,  # Base64-encoded image data
        "type": "image/jpeg" | "image/png" | "image/gif" | "image/webp",  # Image MIME type
        "originalSize": int,  # Original file size in bytes
        "dimensions": {  # Optional sizing info for coordinate mapping
            "originalWidth": int | None,  # Optional; original width in pixels
            "originalHeight": int | None,  # Optional; original height in pixels
            "displayWidth": int | None,  # Optional; width after resizing
            "displayHeight": int | None,  # Optional; height after resizing
        } | None,
    },
}

פלט (type: "notebook"):

{
    "type": "notebook",
    "file": {
        "filePath": str,  # The notebook that was read
        "cells": list,  # Notebook cells
    },
}

פלט (type: "pdf"):

{
    "type": "pdf",
    "file": {
        "filePath": str,  # The PDF that was read
        "base64": str,  # Base64-encoded PDF data
        "originalSize": int,  # File size in bytes
    },
}

פלט (type: "parts"):

{
    "type": "parts",
    "file": {
        "filePath": str,  # The PDF that was read
        "originalSize": int,  # File size in bytes
        "count": int,  # Number of pages extracted as images
        "outputDir": str,  # Directory containing the extracted page images
    },
    "firstPage": int | None,  # Optional document page number of the first extracted page
}

פלט (type: "file_unchanged"):

{
    "type": "file_unchanged",  # The file is unchanged since Claude last read it in this session, so the content isn't repeated
    "file": {
        "filePath": str,
    },
    "source": "seeded" | None,  # Present when the earlier copy came from a CLAUDE.md or memory file loaded at startup rather than a Read call
}

#Write

שם הכלי: Write

קלט:

{
    "file_path": str,  # The absolute path to the file to write
    "content": str,  # The content to write to the file
}

פלט:

{
    "type": "create" | "update",  # Whether the write created a new file or overwrote an existing one
    "filePath": str,  # The file that was written
    "content": str,  # The content that was written
    "structuredPatch": [  # Diff hunks; empty for a new file, when nothing changed, or when Claude Code skipped the diff
        {
            "oldStart": int,
            "oldLines": int,
            "newStart": int,
            "newLines": int,
            "lines": list[str],
        }
    ],
    "originalFile": str | None,  # Previous content; None for a new file or when the previous content was too large to include
    "gitDiff": {  # Optional git diff summary for the file
        "filename": str,
        "status": "modified" | "added",
        "additions": int,
        "deletions": int,
        "changes": int,
        "patch": str,
        "repository": str | None,  # GitHub owner/repo when available
    } | None,
    "userModified": bool | None,  # Optional; whether the user edited the proposed content before accepting it
}

#Glob

שם הכלי: Glob

קלט:

{
    "pattern": str,  # The glob pattern to match files against
    "path": str | None,  # The directory to search in (defaults to cwd)
}

פלט:

{
    "durationMs": int,  # Time taken to run the search, in milliseconds
    "numFiles": int,  # Number of paths returned, after any truncation
    "filenames": list[str],  # Matching file paths
    "truncated": bool,  # Whether the results were truncated at the 100-file limit
    "totalMatches": int | None,  # Optional total number of matching files before truncation; a lower bound when countIsComplete is False
    "countIsComplete": bool | None,  # Optional; whether totalMatches is exact
}

totalMatches ו-countIsComplete דורשים Claude Code בגרסה v2.1.191 או מאוחרת יותר.

#Grep

שם הכלי: Grep

קלט:

{
    "pattern": str,  # The regular expression pattern
    "path": str | None,  # File or directory to search in
    "glob": str | None,  # Glob pattern to filter files
    "type": str | None,  # File type to search
    "output_mode": str | None,  # "content", "files_with_matches", or "count"
    "-i": bool | None,  # Case insensitive search
    "-n": bool | None,  # Show line numbers
    "-B": int | None,  # Lines to show before each match
    "-A": int | None,  # Lines to show after each match
    "-C": int | None,  # Lines to show before and after
    "context": int | None,  # Lines to show before and after; -C is an alias
    "-o": bool | None,  # Print only the matched parts of each line
    "head_limit": int | None,  # Limit output to first N lines/entries
    "offset": int | None,  # Skip first N lines/entries before applying head_limit
    "multiline": bool | None,  # Enable multiline mode
}

פלט:

{
    "mode": "content" | "files_with_matches" | "count" | None,  # The output mode that was used
    "numFiles": int,  # Number of files in the result; always 0 in content mode
    "filenames": list[str],  # Matching files in files_with_matches mode; empty in the other modes
    "content": str | None,  # Matching lines in content mode, or per-file counts in count mode
    "numLines": int | None,  # Number of lines in content, present in content mode
    "numMatches": int | None,  # Total match count, present in count mode
    "totalFiles": int | None,  # Optional total before head_limit and offset, in files_with_matches mode
    "totalLines": int | None,  # Optional total before head_limit and offset, in content mode
    "appliedLimit": int | None,  # Present when head_limit truncated the result
    "appliedOffset": int | None,  # Present when an offset was applied
}

Grep מחזיר את צורת ה-dict הזו בכל מצב פלט. אילו מפתחות אופציונליים מופיעים תלוי ב-output_mode.

totalFiles דורש Claude Code בגרסה v2.1.208 או מאוחרת יותר. totalLines דורש Claude Code בגרסה v2.1.210 או מאוחרת יותר.

#NotebookEdit

שם הכלי: NotebookEdit

קלט:

{
    "notebook_path": str,  # Absolute path to the Jupyter notebook
    "cell_id": str | None,  # The ID of the cell to edit
    "new_source": str,  # The new source for the cell
    "cell_type": "code" | "markdown" | None,  # The type of the cell
    "edit_mode": "replace" | "insert" | "delete" | None,  # Edit operation type
}

פלט:

{
    "new_source": str,  # The source written to the cell
    "old_source": str | None,  # Previous cell source, present for replace and delete
    "cell_id": str | None,  # ID of the edited cell, when available
    "cell_type": "code" | "markdown",  # The cell type
    "language": str,  # The notebook's programming language
    "edit_mode": str,  # The edit mode that was used
    "error": str | None,  # Error message when the operation failed
    "notebook_path": str,  # The notebook file
    "original_file": str,  # Notebook content before the edit
    "updated_file": str,  # Notebook content after the edit
}

#WebFetch

שם הכלי: WebFetch

קלט:

{
    "url": str,  # The URL to fetch content from
    "prompt": str,  # The prompt to run on the fetched content
    "offset": int | None,  # Number of characters to skip from the start of the page. Requires Python Agent SDK 0.2.164 or later
}

פלט:

{
    "bytes": int,  # Size of the fetched content in bytes
    "code": int,  # HTTP response code
    "codeText": str,  # HTTP response code text
    "result": str,  # Processed result from applying the prompt to the content
    "durationMs": int,  # Time to fetch and process the content, in milliseconds
    "url": str,  # URL that was fetched
}

#WebSearch

שם הכלי: WebSearch

קלט:

{
    "query": str,  # The search query to use
    "allowed_domains": list[str] | None,  # Only include results from these domains
    "blocked_domains": list[str] | None,  # Never include results from these domains
}

פלט:

{
    "query": str,  # The search query
    "results": list[str | {"tool_use_id": str, "content": list[{"title": str, "url": str}]}],
    "durationSeconds": float,  # Search duration in seconds
}

#TodoWrite

שם הכלי: TodoWrite

[!NOTE]

הכלים הבאים זמינים כברירת מחדל רק ב-Claude Opus 4.7, Claude Sonnet 4.6, Claude Haiku 4.5, ובמודלים מוקדמים יותר. בכל מודל אחר, כולל מזהי מודל ש-Claude Code לא מזהה, הם אינם זמינים אלא אם בוחרים להצטרף:

  • TodoWrite
  • TaskCreate
  • TaskGet
  • TaskUpdate
  • TaskList

בכל מקום שבו הכלים זמינים, Claude Code מספק את ארבעת כלי ה-Task, או את TodoWrite במקומם כאשר מגדירים CLAUDE_CODE_ENABLE_TASKS=0.

קבוצת ברירת המחדל הזו חלה ב-Claude Code v2.1.268 ומאוחר יותר, ש-TypeScript Agent SDK אורז מ-v0.3.268.

ראו זמינות מודלים כדי להצטרף.

קלט:

{
    "todos": [
        {
            "content": str,  # The task description
            "status": "pending" | "in_progress" | "completed",  # Task status
            "activeForm": str,  # Active form of the description
        }
    ]
}

פלט:

{
    "oldTodos": [  # The todo list before the update
        {
            "content": str,
            "status": "pending" | "in_progress" | "completed",
            "activeForm": str,
        }
    ],
    "newTodos": [  # The todo list after the update
        {
            "content": str,
            "status": "pending" | "in_progress" | "completed",
            "activeForm": str,
        }
    ],
}

#TaskCreate

שם הכלי: TaskCreate

קלט:

{
    "subject": str,  # Short task title
    "description": str,  # Detailed task body
    "activeForm": str | None,  # Present-tense label shown while in progress
    "metadata": dict | None,  # Arbitrary caller metadata
}

פלט:

{
    "task": {"id": str, "subject": str},  # Created task with assigned ID
}

#TaskUpdate

שם הכלי: TaskUpdate

קלט:

{
    "taskId": str,  # ID of the task to patch
    "status": Literal["pending", "in_progress", "completed", "deleted"] | None,
    "subject": str | None,
    "description": str | None,
    "activeForm": str | None,
    "addBlocks": list[str] | None,  # Task IDs this task now blocks
    "addBlockedBy": list[str] | None,  # Task IDs that now block this task
    "owner": str | None,
    "metadata": dict | None,
}

פלט:

{
    "success": bool,
    "taskId": str,
    "updatedFields": list[str],  # Names of fields that changed
    "error": str | None,
    "statusChange": {"from": str, "to": str} | None,
}

#TaskGet

שם הכלי: TaskGet

קלט:

{
    "taskId": str,  # ID of the task to read
}

פלט:

{
    "task": {
        "id": str,
        "subject": str,
        "description": str,
        "status": Literal["pending", "in_progress", "completed"],
        "blocks": list[str],
        "blockedBy": list[str],
    } | None,  # None when the ID is not found
}

#TaskList

שם הכלי: TaskList

קלט:

{}

פלט:

{
    "tasks": [
        {
            "id": str,
            "subject": str,
            "status": Literal["pending", "in_progress", "completed"],
            "owner": str | None,
            "blockedBy": list[str],
        }
    ],
}

#TaskOutput

הוסר ב-Claude Code v2.1.277. בעבר אחזר פלט ממשימה ברקע שרצה או שהושלמה, כאשר BashOutput התקבל ככינוי. Claude קורא את קובץ הפלט של משימת רקע באמצעות Read במקום זאת.

רשומת disallowed_tools או כלל דחייה שעדיין מציינים אחד משני השמות מתעלמים מהם בלי אזהרה.

#TaskStop

שם הכלי: TaskStop. עדיין אפשר להשתמש בשמות הקודמים KillShell ו-KillBash בכללי הרשאה, במתאמי hook, ובאפשרויות tools, allowed_tools ו-disallowed_tools.

קלט:

{
    "task_id": str | None,  # The ID of the background task to stop
    "shell_id": str | None,  # Deprecated: use task_id instead
}

פלט:

{
    "message": str,  # Status message about the operation
    "task_id": str,  # The ID of the task that was stopped
    "task_type": str,  # The type of the task that was stopped
    "command": str | None,  # The command or description of the stopped task
}

#ExitPlanMode

שם הכלי: ExitPlanMode

קלט:

{
    "plan": str  # The plan to run by the user for approval
}

פלט:

{
    "plan": str | None,  # The plan that was presented to the user
    "isAgent": bool,  # True when a subagent called the tool
    "filePath": str | None,  # Present when the plan was saved to a file
    "hasTaskTool": bool | None,  # Optional; whether the Agent tool is available in the current context
    "planWasEdited": bool | None,  # Present and True when the user edited the plan before approving
    "awaitingLeaderApproval": bool | None,  # Present and True when a teammate sent the plan to the team lead for approval
    "requestId": str | None,  # Optional ID of that approval request
}

#ListMcpResources

שם הכלי: ListMcpResourcesTool

קלט:

{
    "server": str | None  # Optional server name to filter resources by
}

התוצאה היא רשימה ולא dict, ולכן tool_use_result מחזיק list עבור הכלי הזה.

פלט:

[  # One entry per resource
    {
        "uri": str,  # Resource URI
        "name": str,  # Resource name
        "mimeType": str | None,  # Optional MIME type
        "description": str | None,  # Optional description
        "server": str,  # Server that provides this resource
    }
]

#ReadMcpResource

שם הכלי: ReadMcpResourceTool

קלט:

{
    "server": str,  # The MCP server name
    "uri": str,  # The resource URI to read
}

פלט:

{
    "contents": [
        {
            "uri": str,  # Resource URI
            "mimeType": str | None,  # Optional MIME type
            "text": str | None,  # Text content, or a note about the binary content
            "blobSavedTo": str | None,  # Present when Claude Code saved binary content to disk; path of the saved file
        }
    ],
    "error": str | None,  # Present when the server couldn't read the resource
}

#בניית ממשק שיחה רציפה

הדוגמה הבאה משאירה ClaudeSDKClient אחד מחובר לאורך התורות, כך ש-Claude זוכר הודעות קודמות. הקלידו new כדי להתנתק ולהתחבר מחדש לסשן חדש, או exit כדי לסיים את השיחה.

from claude_agent_sdk import (
    ClaudeSDKClient,
    ClaudeAgentOptions,
    AssistantMessage,
    TextBlock,
)
import asyncio


class ConversationSession:
    """Maintains a single conversation session with Claude."""

    def __init__(self, options: ClaudeAgentOptions | None = None):
        self.client = ClaudeSDKClient(options)
        self.turn_count = 0

    async def start(self):
        await self.client.connect()
        print("Starting conversation session. Claude will remember context.")
        print(
            "Commands: 'exit' to quit, 'interrupt' to stop current task, 'new' for new session"
        )

        while True:
            user_input = input(f"\n[Turn {self.turn_count + 1}] You: ")

            if user_input.lower() == "exit":
                break
            elif user_input.lower() == "interrupt":
                await self.client.interrupt()
                print("Task interrupted!")
                continue
            elif user_input.lower() == "new":
                # Disconnect and reconnect for a fresh session
                await self.client.disconnect()
                await self.client.connect()
                self.turn_count = 0
                print("Started new conversation session (previous context cleared)")
                continue

            # Send message - the session retains all previous messages
            await self.client.query(user_input)
            self.turn_count += 1

            # Process response
            print(f"[Turn {self.turn_count}] Claude: ", end="")
            async for message in self.client.receive_response():
                if isinstance(message, AssistantMessage):
                    for block in message.content:
                        if isinstance(block, TextBlock):
                            print(block.text, end="")
            print()  # New line after response

        await self.client.disconnect()
        print(f"Conversation ended after {self.turn_count} turns.")


async def main():
    options = ClaudeAgentOptions(
        allowed_tools=["Read", "Write", "Bash"], permission_mode="acceptEdits"
    )
    session = ConversationSession(options)
    await session.start()


# Example conversation:
# Turn 1 - You: "Create a file called hello.py"
# Turn 1 - Claude: "I'll create a hello.py file for you..."
# Turn 2 - You: "What's in that file?"
# Turn 2 - Claude: "The hello.py file I just created contains..." (remembers!)
# Turn 3 - You: "Add a main function to it"
# Turn 3 - Claude: "I'll add a main function to hello.py..." (knows which file!)

asyncio.run(main())

#טיפול בשגיאות

הדוגמה הבאה עוטפת קריאה ל-query() במטפלים לארבעה מתוך סוגי השגיאות שה-SDK מעלה.

הדוגמה הזו תופסת ResultError, שדורש Python Agent SDK 0.2.140 או מאוחר יותר.

import asyncio

from claude_agent_sdk import (
    query,
    CLINotFoundError,
    ProcessError,
    ResultError,
    CLIJSONDecodeError,
)


async def main():
    try:
        async for message in query(prompt="Hello"):
            print(message)
    except CLINotFoundError:
        print(
            "Claude Code CLI not found. Try reinstalling: pip install --force-reinstall claude-agent-sdk"
        )
    # Catch ResultError before ProcessError, which it subclasses. Its message
    # carries the error text. A refusal and a failed final request both usually
    # arrive with subtype "success", so check stop_reason, then terminal_reason.
    except ResultError as e:
        if e.data.get("stop_reason") == "refusal":
            print(f"Model declined to respond: {e}")
        elif e.terminal_reason == "api_error":
            print(f"API request failed: {e}")
        else:
            print(f"Query ended with an error result ({e.terminal_reason or e.subtype}): {e}")
    except ProcessError as e:
        print(f"Process failed with exit code: {e.exit_code}")
    except CLIJSONDecodeError as e:
        print(f"Failed to parse response: {e}")


asyncio.run(main())

#הגדרות ארגז חול

#SandboxSettings

הגדרה להתנהגות ארגז החול. השתמשו בזה כדי להפעיל ארגז חול לפקודות ולהגדיר הגבלות רשת באופן תכנותי.

class SandboxSettings(TypedDict, total=False):
    enabled: bool
    autoAllowBashIfSandboxed: bool
    excludedCommands: list[str]
    allowUnsandboxedCommands: bool
    network: SandboxNetworkConfig
    ignoreViolations: SandboxIgnoreViolations
    enableWeakerNestedSandbox: bool
מאפייןסוגברירת מחדלתיאור
enabledboolFalseהפעלת מצב ארגז חול להרצת פקודות
autoAllowBashIfSandboxedboolTrueאישור אוטומטי של פקודות bash כשארגז החול מופעל
excludedCommandslist[str][]פקודות שעוקפות את הגבלות ארגז החול, כגון ["docker *"]. אלה רצות מחוץ לארגז החול באופן אוטומטי בלי מעורבות של המודל. sandbox.excludedCommands מכסה מתי רשומה חלה
allowUnsandboxedCommandsboolTrueלאפשר למודל לבקש הרצת פקודות מחוץ לארגז החול. כש-True, המודל יכול להגדיר dangerouslyDisableSandbox בקלט הכלי, וזה נופל חזרה למערכת ההרשאות
networkSandboxNetworkConfigNoneהגדרת ארגז חול ספציפית לרשת
ignoreViolationsSandboxIgnoreViolationsNoneהגדרה אילו הפרות של ארגז החול להתעלם מהן
enableWeakerNestedSandboxboolFalseהפעלת ארגז חול מקונן חלש יותר לצורך תאימות

[!NOTE]

ארגז החול תלוי בתמיכת הפלטפורמה, וב-Linux בכלים כמו bubblewrap ו-socat. כברירת מחדל, כש-enabled הוא True אבל ארגז החול לא יכול להתחיל, הפקודות רצות מחוץ לארגז החול עם אזהרה ב-stderr. ברירת המחדל הזו שונה מ-SDK של TypeScript, שבו failIfUnavailable ברירת המחדל היא true.

הגדירו "failIfUnavailable": True בהגדרות ארגז החול כדי לעצור במקום זאת. ה-SDK מעביר את failIfUnavailable אל Claude Code יחד עם שדות SandboxSettings המוצהרים. query() מדווח אז על ResultMessage עם subtype="error_during_execution" והסיבה ב-errors. מכיוון שזו קריאת query() חד-פעמית, ה-SDK מעלה חריגה אחרי שהוא מניב את תוצאת השגיאה, ולכן עטפו את הלולאה בבלוק try כדי להמשיך מעבר לה. ראו טיפול בתוצאה לחוזה השגיאה.

כדי למנוע מפקודות בארגז החול לכתוב לקובץ, רשמו את הנתיב המוחלט שלו תחת denyWrite בהגדרות ארגז החול, כגון "filesystem": {"denyWrite": ["/home/user/project/.env"]}. ה-SDK מעביר את filesystem אל Claude Code יחד עם שדות SandboxSettings המוצהרים. אחרי שארגז החול מתחיל, הוא חוסם כתיבה לכל נתיב מוחלט שרשמתם.

#דוגמה לשימוש

import asyncio

from claude_agent_sdk import query, ClaudeAgentOptions

sandbox_settings = {
    "enabled": True,
    "autoAllowBashIfSandboxed": True,
    "failIfUnavailable": True,
    "network": {"allowLocalBinding": True},
}


async def main():
    try:
        async for message in query(
            prompt="Build and test my project",
            options=ClaudeAgentOptions(sandbox=sandbox_settings),
        ):
            print(message)
    except Exception as error:
        # A single-shot query() raises after yielding an error result,
        # such as when failIfUnavailable is set and the sandbox can't start.
        print(f"Session ended with an error: {error}")


asyncio.run(main())

[!WARNING]

אבטחת שקעי Unix: האפשרות allowUnixSockets יכולה להעניק גישה לשירותי מערכת שמגיעים מחוץ לארגז החול. לדוגמה, התרת /var/run/docker.sock מעניקה למעשה גישה מלאה למערכת המארחת דרך ה-API של Docker, ועוקפת את בידוד ארגז החול. התירו רק שקעי Unix שהם הכרחיים בהחלט, והבינו את השלכות האבטחה של כל אחד.

#SandboxNetworkConfig

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

class SandboxNetworkConfig(TypedDict, total=False):
    allowedDomains: list[str]
    deniedDomains: list[str]
    allowManagedDomainsOnly: bool
    allowUnixSockets: list[str]
    allowAllUnixSockets: bool
    allowLocalBinding: bool
    allowMachLookup: list[str]
    httpProxyPort: int
    socksProxyPort: int
מאפייןסוגברירת מחדלתיאור
allowedDomainslist[str][]שמות דומיין שתהליכים בארגז החול יכולים לגשת אליהם
deniedDomainslist[str][]שמות דומיין שתהליכים בארגז החול אינם יכולים לגשת אליהם. גובר על allowedDomains
allowManagedDomainsOnlyboolFalseרק להגדרות מנוהלות: כשמוגדר בהגדרות מנוהלות, מתעלמים מ-allowedDomains ומכללי היתר WebFetch(domain:...) ממקורות הגדרות שאינם מנוהלים. אין השפעה כשמוגדר דרך אפשרויות ה-SDK
allowUnixSocketslist[str][]רק ב-macOS: נתיבי שקעי Unix שתהליכים יכולים לגשת אליהם, כגון שקע Docker. מתעלמים מזה ב-Linux
allowAllUnixSocketsboolFalseהתרת גישה לכל שקעי Unix, וב-Linux גם לשקעי VM (AF_VSOCK)
allowLocalBindingboolFalseהתרת לתהליכים להיקשר לפורטים מקומיים (לדוגמה, לשרתי פיתוח)
allowMachLookuplist[str][]רק ב-macOS: שמות שירותי XPC/Mach להתיר. תומך בתו כללי בסוף
httpProxyPortintNoneפורט פרוקסי HTTP לבקשות רשת
socksProxyPortintNoneפורט פרוקסי SOCKS לבקשות רשת

[!NOTE]

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

#SandboxIgnoreViolations

הגדרה להתעלמות מהפרות ספציפיות של ארגז החול.

class SandboxIgnoreViolations(TypedDict, total=False):
    file: list[str]
    network: list[str]
מאפייןסוגברירת מחדלתיאור
filelist[str][]תבניות נתיבי קבצים שעבורן מתעלמים מהפרות
networklist[str][]תבניות רשת שעבורן מתעלמים מהפרות

#נפילה חזרה להרשאות לפקודות מחוץ לארגז החול

כש-allowUnsandboxedCommands מופעל, המודל יכול לבקש להריץ פקודות מחוץ לארגז החול על ידי הגדרת dangerouslyDisableSandbox: True בקלט הכלי. בקשות אלה נופלות חזרה למערכת ההרשאות הקיימת, כלומר ה-handler של can_use_tool שלכם מופעל, וזה מאפשר לכם לממש לוגיקת הרשאה מותאמת אישית.

רשומות excludedCommands שלכם, לעומת זאת, מוציאות קריאה מארגז החול בלי מעורבות של המודל. sandbox.excludedCommands מכסה מתי רשומה חלה.

הדוגמה הבאה רושמת כל בקשה מחוץ לארגז החול ודוחה אותה, אלא אם לוגיקת ההרשאה שלכם מתירה אותה:

import asyncio
from claude_agent_sdk import (
    query,
    ClaudeAgentOptions,
    HookMatcher,
    PermissionResultAllow,
    PermissionResultDeny,
    ToolPermissionContext,
)


def is_command_authorized(command: str | None) -> bool:
    # Replace with your own authorization logic
    return False



async def can_use_tool(
    tool: str, input: dict, context: ToolPermissionContext
) -> PermissionResultAllow | PermissionResultDeny:
    # Check if the model is requesting to bypass the sandbox
    if tool == "Bash" and input.get("dangerouslyDisableSandbox"):
        # The model is requesting to run this command outside the sandbox
        print(f"Unsandboxed command requested: {input.get('command')}")

        if is_command_authorized(input.get("command")):
            return PermissionResultAllow()
        return PermissionResultDeny(
            message="Command not authorized for unsandboxed execution"
        )
    return PermissionResultAllow()


# Required: dummy hook keeps the stream open for can_use_tool
async def dummy_hook(input_data, tool_use_id, context):
    return {"continue_": True}


async def prompt_stream():
    yield {
        "type": "user",
        "message": {"role": "user", "content": "Deploy my application"},
    }


async def main():
    async for message in query(
        prompt=prompt_stream(),
        options=ClaudeAgentOptions(
            sandbox={
                "enabled": True,
                "allowUnsandboxedCommands": True,  # Model can request unsandboxed execution
            },
            permission_mode="default",
            can_use_tool=can_use_tool,
            hooks={"PreToolUse": [HookMatcher(matcher=None, hooks=[dummy_hook])]},
        ),
    ):
        print(message)


asyncio.run(main())

[!WARNING]

לפקודות שרצות עם dangerouslyDisableSandbox: True יש גישה מלאה למערכת. ודאו שה-handler של can_use_tool מאמת את הבקשות האלה בקפידה.

אם permission_mode מוגדר ל-bypassPermissions ו-allowUnsandboxedCommands מופעל, המודל יכול להריץ באופן אוטונומי פקודות מחוץ לארגז החול בלי בקשות אישור, מלבד הפעולות שאף מצב לא מאשר אוטומטית. השילוב הזה למעשה מאפשר למודל לצאת מבידוד ארגז החול בשקט.

#ראו גם