Zum Hauptinhalt springen

Installation

pip install claude-agent-sdk

Wahl zwischen query() und ClaudeSDKClient

Das Python SDK bietet zwei Möglichkeiten, um mit Claude Code zu interagieren:

Schnellvergleich

Funktionquery()ClaudeSDKClient
SitzungErstellt standardmäßig eine neue SitzungVerwendet dieselbe Sitzung erneut
KonversationEinzelner AustauschMehrere Austausche im gleichen Kontext
VerbindungAutomatisch verwaltetManuelle Kontrolle
Streaming-Eingabe✅ Unterstützt✅ Unterstützt
Unterbrechungen❌ Nicht unterstützt✅ Unterstützt
Hooks✅ Unterstützt✅ Unterstützt
Benutzerdefinierte Tools✅ Unterstützt✅ Unterstützt
Konversation fortsetzenManuell über continue_conversation oder resume✅ Automatisch
AnwendungsfallEinmalige AufgabenKontinuierliche Konversationen

Wann query() verwendet werden sollte (einmalige Aufgaben)

Am besten für:
  • Einmalige Fragen, bei denen Sie keinen Konversationsverlauf benötigen
  • Unabhängige Aufgaben, die keinen Kontext aus vorherigen Austauschen erfordern
  • Einfache Automatisierungsskripte
  • Wenn Sie jedes Mal einen neuen Anfang möchten

Wann ClaudeSDKClient verwendet werden sollte (kontinuierliche Konversation)

Am besten für:
  • Konversationen fortsetzen - Wenn Claude den Kontext merken muss
  • Nachfolgefragen - Aufbauend auf vorherigen Antworten
  • Interaktive Anwendungen - Chat-Schnittstellen, REPLs
  • Antwortgesteuerte Logik - Wenn die nächste Aktion von Claudes Antwort abhängt
  • Sitzungskontrolle - Explizite Verwaltung des Konversationslebenszyklus

Funktionen

query()

Erstellt für jede Interaktion mit Claude Code standardmäßig eine neue Sitzung. Gibt einen asynchronen Iterator zurück, der Nachrichten bei ihrer Ankunft liefert. Jeder Aufruf von query() beginnt neu ohne Erinnerung an vorherige Interaktionen, es sei denn, Sie übergeben continue_conversation=True oder resume in ClaudeAgentOptions. Siehe Sitzungen.
async def query(
    *,
    prompt: str | AsyncIterable[dict[str, Any]],
    options: ClaudeAgentOptions | None = None,
    transport: Transport | None = None
) -> AsyncIterator[Message]

Parameter

ParameterTypBeschreibung
promptstr | AsyncIterable[dict]Die Eingabeaufforderung als Zeichenkette oder asynchroner Iterator für den Streaming-Modus
optionsClaudeAgentOptions | NoneOptionales Konfigurationsobjekt (standardmäßig ClaudeAgentOptions(), wenn None)
transportTransport | NoneOptionaler benutzerdefinierter Transport für die Kommunikation mit dem CLI-Prozess

Rückgabewert

Gibt einen AsyncIterator[Message] zurück, der Nachrichten aus der Konversation liefert.

Beispiel - Mit Optionen

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",
        cwd="/home/user/project",
    )

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


asyncio.run(main())

tool()

Dekorator zum Definieren von MCP-Tools mit Typsicherheit.
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]]

Parameter

ParameterTypBeschreibung
namestrEindeutige Kennung für das Tool
descriptionstrLesbare Beschreibung, was das Tool tut
input_schematype | dict[str, Any]Schema, das die Eingabeparameter des Tools definiert (siehe unten)
annotationsToolAnnotations | NoneOptionale MCP-Tool-Anmerkungen, die Verhaltenshinweise für Clients bereitstellen

Eingabeschema-Optionen

  1. Einfache Typ-Zuordnung (empfohlen):
    {"text": str, "count": int, "enabled": bool}
    
  2. JSON-Schema-Format (für komplexe Validierung):
    {
        "type": "object",
        "properties": {
            "text": {"type": "string"},
            "count": {"type": "integer", "minimum": 0},
        },
        "required": ["text"],
    }
    

Rückgabewert

Eine Dekoratorfunktion, die die Tool-Implementierung umhüllt und eine SdkMcpTool-Instanz zurückgibt.

Beispiel

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

Erneut exportiert aus mcp.types (auch verfügbar als from claude_agent_sdk import ToolAnnotations). Alle Felder sind optionale Hinweise; Clients sollten sich nicht auf sie für Sicherheitsentscheidungen verlassen.
FeldTypStandardBeschreibung
titlestr | NoneNoneLesbare Bezeichnung für das Tool
readOnlyHintbool | NoneFalseWenn True, ändert das Tool seine Umgebung nicht
destructiveHintbool | NoneTrueWenn True, kann das Tool destruktive Aktualisierungen durchführen (nur sinnvoll, wenn readOnlyHint False ist)
idempotentHintbool | NoneFalseWenn True, haben wiederholte Aufrufe mit denselben Argumenten keine zusätzliche Auswirkung (nur sinnvoll, wenn readOnlyHint False ist)
openWorldHintbool | NoneTrueWenn True, interagiert das Tool mit externen Entitäten (z. B. Websuche). Wenn False, ist die Domäne des Tools geschlossen (z. B. ein Memory-Tool)
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()

Erstellt einen In-Process-MCP-Server, der in Ihrer Python-Anwendung ausgeführt wird.
def create_sdk_mcp_server(
    name: str,
    version: str = "1.0.0",
    tools: list[SdkMcpTool[Any]] | None = None
) -> McpSdkServerConfig

Parameter

ParameterTypStandardBeschreibung
namestr-Eindeutige Kennung für den Server
versionstr"1.0.0"Versionsnummer des Servers
toolslist[SdkMcpTool[Any]] | NoneNoneListe von Tool-Funktionen, die mit dem @tool-Dekorator erstellt wurden

Rückgabewert

Gibt ein McpSdkServerConfig-Objekt zurück, das an ClaudeAgentOptions.mcp_servers übergeben werden kann.

Beispiel

from claude_agent_sdk import tool, create_sdk_mcp_server


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

Listet vergangene Sitzungen mit Metadaten auf. Filtern Sie nach Projektverzeichnis oder listen Sie Sitzungen über alle Projekte auf. Synchron; gibt sofort zurück.
def list_sessions(
    directory: str | None = None,
    limit: int | None = None,
    include_worktrees: bool = True
) -> list[SDKSessionInfo]

Parameter

ParameterTypStandardBeschreibung
directorystr | NoneNoneVerzeichnis, für das Sitzungen aufgelistet werden sollen. Wenn weggelassen, werden Sitzungen über alle Projekte zurückgegeben
limitint | NoneNoneMaximale Anzahl der zurückzugebenden Sitzungen
include_worktreesboolTrueWenn directory sich in einem Git-Repository befindet, Sitzungen aus allen worktrees einbeziehen

Rückgabetyp: SDKSessionInfo

EigenschaftTypBeschreibung
session_idstrEindeutige Sitzungskennung
summarystrAnzeigetitel: benutzerdefinierter Titel, automatisch generierte Zusammenfassung oder erste Aufforderung
last_modifiedintLetzte Änderungszeit in Millisekunden seit Epoche
file_sizeint | NoneSitzungsdateigröße in Bytes (None für Remote-Speicher-Backends)
custom_titlestr | NoneVom Benutzer festgelegter Sitzungstitel
first_promptstr | NoneErste aussagekräftige Benutzeraufforderung in der Sitzung
git_branchstr | NoneGit-Branch am Ende der Sitzung
cwdstr | NoneArbeitsverzeichnis für die Sitzung
tagstr | NoneVom Benutzer festgelegtes Sitzungs-Tag (siehe tag_session())
created_atint | NoneSitzungserstellungszeit in Millisekunden seit Epoche

Beispiel

Geben Sie die 10 neuesten Sitzungen für ein Projekt aus. Die Ergebnisse werden nach last_modified absteigend sortiert, daher ist das erste Element das neueste. Lassen Sie directory weg, um über alle Projekte zu suchen.
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()

Ruft Nachrichten aus einer vergangenen Sitzung ab. Synchron; gibt sofort zurück.
def get_session_messages(
    session_id: str,
    directory: str | None = None,
    limit: int | None = None,
    offset: int = 0
) -> list[SessionMessage]

Parameter

ParameterTypStandardBeschreibung
session_idstrerforderlichDie Sitzungs-ID, für die Nachrichten abgerufen werden sollen
directorystr | NoneNoneProjektverzeichnis zum Suchen. Wenn weggelassen, werden alle Projekte durchsucht
limitint | NoneNoneMaximale Anzahl der zurückzugebenden Nachrichten
offsetint0Anzahl der Nachrichten, die vom Anfang übersprungen werden sollen

Rückgabetyp: SessionMessage

EigenschaftTypBeschreibung
typeLiteral["user", "assistant"]Nachrichtenrolle
uuidstrEindeutige Nachrichtenkennung
session_idstrSitzungskennung
messageAnyRoher Nachrichteninhalt
parent_tool_use_idNoneReserviert für zukünftige Verwendung

Beispiel

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

Liest Metadaten für eine einzelne Sitzung nach ID, ohne das vollständige Projektverzeichnis zu durchsuchen. Synchron; gibt sofort zurück.
def get_session_info(
    session_id: str,
    directory: str | None = None,
) -> SDKSessionInfo | None

Parameter

ParameterTypStandardBeschreibung
session_idstrerforderlichUUID der zu suchenden Sitzung
directorystr | NoneNoneProjektverzeichnispath. Wenn weggelassen, werden alle Projektverzeichnisse durchsucht
Gibt SDKSessionInfo zurück, oder None, wenn die Sitzung nicht gefunden wird.

Beispiel

Suchen Sie die Metadaten einer einzelnen Sitzung, ohne das Projektverzeichnis zu durchsuchen. Nützlich, wenn Sie bereits eine Sitzungs-ID aus einem vorherigen Durchlauf haben.
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()

Benennt eine Sitzung um, indem ein benutzerdefinierter Titeleintrag angehängt wird. Wiederholte Aufrufe sind sicher; der neueste Titel gewinnt. Synchron.
def rename_session(
    session_id: str,
    title: str,
    directory: str | None = None,
) -> None

Parameter

ParameterTypStandardBeschreibung
session_idstrerforderlichUUID der umzubenennenden Sitzung
titlestrerforderlichNeuer Titel. Muss nach dem Entfernen von Leerzeichen nicht leer sein
directorystr | NoneNoneProjektverzeichnispath. Wenn weggelassen, werden alle Projektverzeichnisse durchsucht
Wirft ValueError, wenn session_id keine gültige UUID ist oder title leer ist; FileNotFoundError, wenn die Sitzung nicht gefunden werden kann.

Beispiel

Benennen Sie die neueste Sitzung um, damit sie später leichter zu finden ist. Der neue Titel wird in SDKSessionInfo.custom_title bei nachfolgenden Lesevorgängen angezeigt.
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()

Markiert eine Sitzung mit einem Tag. Übergeben Sie None, um das Tag zu löschen. Wiederholte Aufrufe sind sicher; das neueste Tag gewinnt. Synchron.
def tag_session(
    session_id: str,
    tag: str | None,
    directory: str | None = None,
) -> None

Parameter

ParameterTypStandardBeschreibung
session_idstrerforderlichUUID der zu markierenden Sitzung
tagstr | NoneerforderlichTag-Zeichenkette oder None zum Löschen. Unicode-bereinigt vor dem Speichern
directorystr | NoneNoneProjektverzeichnispath. Wenn weggelassen, werden alle Projektverzeichnisse durchsucht
Wirft ValueError, wenn session_id keine gültige UUID ist oder tag nach der Bereinigung leer ist; FileNotFoundError, wenn die Sitzung nicht gefunden werden kann.

Beispiel

Markieren Sie eine Sitzung mit einem Tag, und filtern Sie später nach diesem Tag. Übergeben Sie None, um ein vorhandenes Tag zu löschen.
from claude_agent_sdk import list_sessions, tag_session

# Tag a session
tag_session("550e8400-e29b-41d4-a716-446655440000", "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)

Klassen

ClaudeSDKClient

Behält eine Konversationssitzung über mehrere Austausche hinweg bei. Dies ist das Python-Äquivalent dazu, wie die query()-Funktion des TypeScript SDK intern funktioniert - sie erstellt ein Client-Objekt, das Konversationen fortsetzen kann.

Wichtige Funktionen

  • Sitzungskontinuität: Behält Konversationskontext über mehrere query()-Aufrufe hinweg bei
  • Gleiche Konversation: Die Sitzung behält vorherige Nachrichten bei
  • Unterbrechungsunterstützung: Kann die Ausführung mitten in einer Aufgabe stoppen
  • Expliziter Lebenszyklus: Sie kontrollieren, wann die Sitzung beginnt und endet
  • Antwortgesteuerte Abläufe: Kann auf Antworten reagieren und Nachfolgefragen senden
  • Benutzerdefinierte Tools und Hooks: Unterstützt benutzerdefinierte Tools (erstellt mit dem @tool-Dekorator) und Hooks
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: str) -> 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 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

Methoden

MethodeBeschreibung
__init__(options)Initialisieren Sie den Client mit optionaler Konfiguration
connect(prompt)Verbinden Sie sich mit Claude mit einer optionalen anfänglichen Aufforderung oder einem Nachrichtenstrom
query(prompt, session_id)Senden Sie eine neue Anfrage im Streaming-Modus
receive_messages()Empfangen Sie alle Nachrichten von Claude als asynchronen Iterator
receive_response()Empfangen Sie Nachrichten bis einschließlich einer ResultMessage
interrupt()Senden Sie ein Unterbrechungssignal (funktioniert nur im Streaming-Modus)
set_permission_mode(mode)Ändern Sie den Berechtigungsmodus für die aktuelle Sitzung
set_model(model)Ändern Sie das Modell für die aktuelle Sitzung. Übergeben Sie None, um auf Standard zurückzusetzen
rewind_files(user_message_id)Stellen Sie Dateien in ihren Zustand bei der angegebenen Benutzernachricht wieder her. Erfordert enable_file_checkpointing=True. Siehe Datei-Checkpointing
get_mcp_status()Rufen Sie den Status aller konfigurierten MCP-Server ab. Gibt McpStatusResponse zurück
reconnect_mcp_server(server_name)Versuchen Sie, eine Verbindung zu einem MCP-Server herzustellen, der fehlgeschlagen ist oder getrennt wurde
toggle_mcp_server(server_name, enabled)Aktivieren oder deaktivieren Sie einen MCP-Server während der Sitzung. Das Deaktivieren entfernt seine Tools
stop_task(task_id)Stoppen Sie eine laufende Hintergrundaufgabe. Eine TaskNotificationMessage mit Status "stopped" folgt im Nachrichtenstrom
get_server_info()Rufen Sie Serverinformationen einschließlich Sitzungs-ID und Funktionen ab
disconnect()Trennen Sie die Verbindung zu Claude

Context Manager-Unterstützung

Der Client kann als asynchroner Context Manager für automatische Verbindungsverwaltung verwendet werden:
async with ClaudeSDKClient() as client:
    await client.query("Hello Claude")
    async for message in client.receive_response():
        print(message)
Wichtig: Vermeiden Sie bei der Iteration über Nachrichten die Verwendung von break, um vorzeitig zu beenden, da dies zu asyncio-Bereinigungsproblemen führen kann. Lassen Sie die Iteration stattdessen natürlich abschließen oder verwenden Sie Flags, um zu verfolgen, wann Sie gefunden haben, was Sie brauchen.

Beispiel - Konversation fortsetzen

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

Beispiel - Streaming-Eingabe mit ClaudeSDKClient

import asyncio
from claude_agent_sdk import ClaudeSDKClient


async def message_stream():
    """Generate messages dynamically."""
    yield {
        "type": "user",
        "message": {"role": "user", "content": "Analyze the following data:"},
    }
    await asyncio.sleep(0.5)
    yield {
        "type": "user",
        "message": {"role": "user", "content": "Temperature: 25°C, Humidity: 60%"},
    }
    await asyncio.sleep(0.5)
    yield {
        "type": "user",
        "message": {"role": "user", "content": "What patterns do you see?"},
    }


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

Beispiel - Unterbrechungen verwenden

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 finished with subtype={message.subtype!r}")
                # subtype is "error_during_execution" for interrupted tasks

        # 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())
Pufferverhalten nach Unterbrechung: interrupt() sendet ein Stopsignal, löscht aber nicht den Nachrichtenpuffer. Nachrichten, die bereits von der unterbrochenen Aufgabe produziert wurden, einschließlich ihrer ResultMessage (mit subtype="error_during_execution"), bleiben im Stream. Sie müssen sie mit receive_response() entleeren, bevor Sie die Antwort auf eine neue Abfrage lesen. Wenn Sie unmittelbar nach interrupt() eine neue Abfrage senden und receive_response() nur einmal aufrufen, erhalten Sie die Nachrichten der unterbrochenen Aufgabe, nicht die Antwort der neuen Abfrage.

Beispiel - Erweiterte Berechtigungskontrolle

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():
    options = ClaudeAgentOptions(
        can_use_tool=custom_permission_handler, allowed_tools=["Read", "Write", "Edit"]
    )

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

Typen

@dataclass vs TypedDict: Dieses SDK verwendet zwei Arten von Typen. Klassen, die mit @dataclass dekoriert sind (wie ResultMessage, AgentDefinition, TextBlock), sind zur Laufzeit Objektinstanzen und unterstützen Attributzugriff: msg.result. Klassen, die mit TypedDict definiert sind (wie ThinkingConfigEnabled, McpStdioServerConfig, SyncHookJSONOutput), sind zur Laufzeit einfache Dicts und erfordern Schlüsselzugriff: config["budget_tokens"], nicht config.budget_tokens. Die ClassName(field=value)-Aufrufsyntax funktioniert für beide, aber nur Dataclasses erzeugen Objekte mit Attributen.

SdkMcpTool

Definition für ein SDK MCP-Tool, das mit dem @tool-Dekorator erstellt wurde.
@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
EigenschaftTypBeschreibung
namestrEindeutige Kennung für das Tool
descriptionstrLesbare Beschreibung
input_schematype[T] | dict[str, Any]Schema für Eingabevalidierung
handlerCallable[[T], Awaitable[dict[str, Any]]]Asynchrone Funktion, die die Tool-Ausführung handhabt
annotationsToolAnnotations | NoneOptionale MCP-Tool-Anmerkungen (z. B. readOnlyHint, destructiveHint, openWorldHint). Aus mcp.types

Transport

Abstrakte Basisklasse für benutzerdefinierte Transport-Implementierungen. Verwenden Sie dies, um mit dem Claude-Prozess über einen benutzerdefinierten Kanal zu kommunizieren (z. B. eine Remote-Verbindung statt eines lokalen Subprozesses).
Dies ist eine Low-Level-interne API. Die Schnittstelle kann sich in zukünftigen Versionen ändern. Benutzerdefinierte Implementierungen müssen aktualisiert werden, um Schnittstellenänderungen zu entsprechen.
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: ...
MethodeBeschreibung
connect()Verbinden Sie den Transport und bereiten Sie ihn für die Kommunikation vor
write(data)Schreiben Sie Rohdaten (JSON + Zeilenumbruch) in den Transport
read_messages()Asynchroner Iterator, der geparste JSON-Nachrichten liefert
close()Schließen Sie die Verbindung und bereinigen Sie Ressourcen
is_ready()Gibt True zurück, wenn der Transport senden und empfangen kann
end_input()Schließen Sie den Eingabestrom (z. B. stdin für Subprozess-Transporte)
Import: from claude_agent_sdk import Transport

ClaudeAgentOptions

Konfigurationsdatenklasse für Claude Code-Abfragen.
@dataclass
class ClaudeAgentOptions:
    tools: list[str] | ToolsPreset | None = None
    allowed_tools: list[str] = field(default_factory=list)
    system_prompt: str | SystemPromptPreset | 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
    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
    fork_session: bool = False
    agents: dict[str, AgentDefinition] | None = None
    setting_sources: list[SettingSource] | 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"
EigenschaftTypStandardBeschreibung
toolslist[str] | ToolsPreset | NoneNoneTools-Konfiguration. Verwenden Sie {"type": "preset", "preset": "claude_code"} für die Standard-Tools von Claude Code
allowed_toolslist[str][]Tools, die automatisch genehmigt werden, ohne zu fragen. Dies beschränkt Claude nicht nur auf diese Tools; nicht aufgelistete Tools fallen durch permission_mode und can_use_tool. Verwenden Sie disallowed_tools, um Tools zu blockieren. Siehe Berechtigungen
system_promptstr | SystemPromptPreset | NoneNoneSystem-Prompt-Konfiguration. Übergeben Sie eine Zeichenkette für einen benutzerdefinierten Prompt, oder verwenden Sie {"type": "preset", "preset": "claude_code"} für den System-Prompt von Claude Code. Fügen Sie "append" hinzu, um den Preset zu erweitern
mcp_serversdict[str, McpServerConfig] | str | Path{}MCP-Server-Konfigurationen oder Pfad zur Konfigurationsdatei
strict_mcp_configboolFalseWenn True, verwenden Sie nur die Server, die in mcp_servers übergeben werden, und ignorieren Sie das Projekt .mcp.json, Benutzereinstellungen, von Plugins bereitgestellte MCP-Server und claude.ai-Konnektoren. Entspricht dem CLI-Flag --strict-mcp-config
permission_modePermissionMode | NoneNoneBerechtigungsmodus für die Tool-Nutzung
continue_conversationboolFalseSetzen Sie die neueste Konversation fort
resumestr | NoneNoneSitzungs-ID zum Fortsetzen
max_turnsint | NoneNoneMaximale agentengesteuerte Umdrehungen (Tool-Use-Rundgänge)
max_budget_usdfloat | NoneNoneStoppen Sie die Abfrage, wenn die clientseitige Kostenschätzung diesen USD-Wert erreicht. Verglichen mit der gleichen Schätzung wie total_cost_usd; siehe Kosten und Nutzung verfolgen für Genauigkeitsvorbehalt
disallowed_toolslist[str][]Tools, die verweigert werden. Ein einfacher Name wie "Bash" entfernt das Tool aus Claudes Kontext. Eine scoped-Regel wie "Bash(rm *)" lässt das Tool verfügbar und verweigert übereinstimmende Aufrufe in jedem Berechtigungsmodus, einschließlich bypassPermissions. Siehe Berechtigungen
enable_file_checkpointingboolFalseAktivieren Sie die Dateienänderungsverfolgung zum Zurückspulen. Siehe Datei-Checkpointing
modelstr | NoneNoneClaude-Modell zum Verwenden
fallback_modelstr | NoneNoneFallback-Modell, das verwendet wird, wenn das primäre Modell fehlschlägt
betaslist[SdkBeta][]Beta-Funktionen zum Aktivieren. Siehe SdkBeta für verfügbare Optionen
output_formatdict[str, Any] | NoneNoneAusgabeformat für strukturierte Antworten (z. B. {"type": "json_schema", "schema": {...}}). Siehe Strukturierte Ausgaben für Details
permission_prompt_tool_namestr | NoneNoneMCP-Tool-Name für Berechtigungsaufforderungen
cwdstr | Path | NoneNoneAktuelles Arbeitsverzeichnis
cli_pathstr | Path | NoneNoneBenutzerdefinierter Pfad zur Claude Code CLI-Ausführungsdatei
settingsstr | NoneNonePfad zur Einstellungsdatei
add_dirslist[str | Path][]Zusätzliche Verzeichnisse, auf die Claude zugreifen kann
envdict[str, str]{}Umgebungsvariablen, die auf der geerbten Prozessumgebung zusammengeführt werden. Siehe Umgebungsvariablen für Variablen, die die zugrunde liegende CLI liest, und Langsame oder steckengebliebene API-Antworten handhaben für Timeout-bezogene Variablen
extra_argsdict[str, str | None]{}Zusätzliche CLI-Argumente, die direkt an die CLI übergeben werden
max_buffer_sizeint | NoneNoneMaximale Bytes beim Puffern der CLI-Stdout
debug_stderrAnysys.stderrVeraltet - Dateiähnliches Objekt für Debug-Ausgabe. Verwenden Sie stattdessen den stderr-Callback
stderrCallable[[str], None] | NoneNoneCallback-Funktion für stderr-Ausgabe von CLI
can_use_toolCanUseTool | NoneNoneTool-Berechtigungs-Callback-Funktion. Siehe Berechtigungstypen für Details
hooksdict[HookEvent, list[HookMatcher]] | NoneNoneHook-Konfigurationen zum Abfangen von Ereignissen
userstr | NoneNoneBenutzerkennung
include_partial_messagesboolFalseSchließen Sie partielle Nachrichtenstreaming-Ereignisse ein. Wenn aktiviert, werden StreamEvent-Nachrichten geliefert
include_hook_eventsboolFalseSchließen Sie Hook-Lebenszyklusereignisse im Nachrichtenstrom als HookEventMessage-Objekte ein
fork_sessionboolFalseWenn Sie mit resume fortsetzen, verzweigen Sie sich zu einer neuen Sitzungs-ID, anstatt die ursprüngliche Sitzung fortzusetzen
agentsdict[str, AgentDefinition] | NoneNoneProgrammgesteuert definierte Subagenten
pluginslist[SdkPluginConfig][]Laden Sie benutzerdefinierte Plugins aus lokalen Pfaden. Siehe Plugins für Details
sandboxSandboxSettings | NoneNoneKonfigurieren Sie das Sandbox-Verhalten programmgesteuert. Siehe Sandbox-Einstellungen für Details
setting_sourceslist[SettingSource] | NoneNone (CLI-Standard: alle Quellen)Kontrollieren Sie, welche Dateisystem-Einstellungen geladen werden. Übergeben Sie [], um Benutzer-, Projekt- und lokale Einstellungen zu deaktivieren. Verwaltete Richtlinieneinstellungen werden unabhängig davon geladen. Siehe Claude Code-Funktionen verwenden
skillslist[str] | Literal["all"] | NoneNoneSkills, die der Sitzung zur Verfügung stehen. Übergeben Sie "all", um jeden erkannten Skill zu aktivieren, oder eine Liste von Skill-Namen. Wenn gesetzt, aktiviert das SDK das Skill-Tool automatisch in allowed_tools. Wenn Sie auch tools übergeben, schließen Sie "Skill" in diese Liste ein. Siehe Skills
max_thinking_tokensint | NoneNoneVeraltet - Maximale Token für Thinking-Blöcke. Verwenden Sie stattdessen thinking
thinkingThinkingConfig | NoneNoneSteuert das Verhalten des erweiterten Denkens. Hat Vorrang vor max_thinking_tokens
effortEffortLevel | NoneNoneAnstrengungsstufe für die Denktiefe
session_storeSessionStore | NoneNoneSpiegeln Sie Sitzungstranskripte zu einem externen Backend, damit jeder Host sie fortsetzen kann. Siehe Sitzungen im externen Speicher beibehalten
session_store_flushLiteral["batched", "eager"]"batched"Wann sollen gespiegelte Transkripteinträge zu session_store geleert werden. "batched" leert einmal pro Umdrehung oder wenn der Puffer voll wird; "eager" löst nach jedem Frame einen Hintergrund-Flush aus. Wird ignoriert, wenn session_store None ist

Langsame oder steckengebliebene API-Antworten handhaben

Die CLI-Subprozess liest mehrere Umgebungsvariablen, die API-Timeouts und Stall-Erkennung steuern. Übergeben Sie sie durch ClaudeAgentOptions.env:
options = ClaudeAgentOptions(
    env={
        "API_TIMEOUT_MS": "120000",
        "CLAUDE_CODE_MAX_RETRIES": "2",
        "CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS": "120000",
    },
)
  • API_TIMEOUT_MS: Pro-Request-Timeout auf dem Anthropic-Client in Millisekunden. Standard 600000. Gilt für die Hauptschleife und alle Subagenten.
  • CLAUDE_CODE_MAX_RETRIES: Maximale API-Wiederholungen. Standard 10. Jede Wiederholung erhält sein eigenes API_TIMEOUT_MS-Fenster, daher ist die schlimmste Wandzeit ungefähr API_TIMEOUT_MS × (CLAUDE_CODE_MAX_RETRIES + 1) plus Backoff.
  • CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS: Stall-Watchdog für Subagenten, die mit run_in_background gestartet werden. Standard 600000. Setzt sich bei jedem Stream-Ereignis zurück; bei Stall bricht es den Subagenten ab, markiert die Aufgabe als fehlgeschlagen und zeigt den Fehler dem übergeordneten Element mit jedem Teilergebnis. Gilt nicht für synchrone Subagenten.
  • CLAUDE_ENABLE_STREAM_WATCHDOG=1 mit CLAUDE_STREAM_IDLE_TIMEOUT_MS: Bricht die Anfrage ab, wenn Header angekommen sind, aber der Antwortkörper nicht mehr streamt. Standardmäßig deaktiviert. CLAUDE_STREAM_IDLE_TIMEOUT_MS hat einen Standard von 300000 und ist auf dieses Minimum begrenzt. Die abgebrochene Anfrage durchläuft den normalen Wiederholungspfad.

OutputFormat

Konfiguration für die Validierung strukturierter Ausgaben. Übergeben Sie dies als dict an das Feld output_format auf ClaudeAgentOptions:
# Expected dict shape for output_format
{
    "type": "json_schema",
    "schema": {...},  # Your JSON Schema definition
}
FeldErforderlichBeschreibung
typeJaMuss "json_schema" für JSON-Schema-Validierung sein
schemaJaJSON-Schema-Definition für Ausgabevalidierung

SystemPromptPreset

Konfiguration für die Verwendung des Preset-System-Prompts von Claude Code mit optionalen Ergänzungen.
class SystemPromptPreset(TypedDict):
    type: Literal["preset"]
    preset: Literal["claude_code"]
    append: NotRequired[str]
    exclude_dynamic_sections: NotRequired[bool]
FeldErforderlichBeschreibung
typeJaMuss "preset" sein, um einen Preset-System-Prompt zu verwenden
presetJaMuss "claude_code" sein, um den System-Prompt von Claude Code zu verwenden
appendNeinZusätzliche Anweisungen, die an den Preset-System-Prompt angehängt werden
exclude_dynamic_sectionsNeinVerschieben Sie sitzungsspezifischen Kontext wie Arbeitsverzeichnis, Git-Status und Memory-Pfade aus dem System-Prompt in die erste Benutzernachricht. Verbessert die Prompt-Cache-Wiederverwendung über Benutzer und Maschinen hinweg. Siehe System-Prompts ändern

SettingSource

Steuert, welche dateisystembasierte Konfigurationsquellen das SDK Einstellungen aus lädt.
SettingSource = Literal["user", "project", "local"]
WertBeschreibungOrt
"user"Globale Benutzereinstellungen~/.claude/settings.json
"project"Gemeinsame Projekteinstellungen (versionskontrolliert).claude/settings.json
"local"Lokale Projekteinstellungen (gitignoriert).claude/settings.local.json

Standardverhalten

Wenn setting_sources weggelassen oder None ist, lädt query() die gleichen Dateisystem-Einstellungen wie die Claude Code CLI: Benutzer, Projekt und lokal. Verwaltete Richtlinieneinstellungen werden in allen Fällen geladen. Siehe Was settingSources nicht kontrolliert für Eingaben, die unabhängig von dieser Option gelesen werden, und wie man sie deaktiviert.

Warum setting_sources verwenden

Dateisystem-Einstellungen deaktivieren:
# Do not load user, project, or local settings from disk
from claude_agent_sdk import query, ClaudeAgentOptions

async for message in query(
    prompt="Analyze this code",
    options=ClaudeAgentOptions(
        setting_sources=[]
    ),
):
    print(message)
Im Python SDK 0.1.59 und früher wurde eine leere Liste gleich behandelt wie das Weglassen der Option, daher hatte setting_sources=[] keine Auswirkung auf die Deaktivierung von Dateisystem-Einstellungen. Aktualisieren Sie auf eine neuere Version, wenn Sie benötigen, dass eine leere Liste wirksam wird. Das TypeScript SDK ist nicht betroffen.
Alle Dateisystem-Einstellungen explizit laden:
from claude_agent_sdk import query, ClaudeAgentOptions

async for message in query(
    prompt="Analyze this code",
    options=ClaudeAgentOptions(
        setting_sources=["user", "project", "local"]
    ),
):
    print(message)
Nur bestimmte Einstellungsquellen laden:
# Load only project settings, ignore user and local
async for message in query(
    prompt="Run CI checks",
    options=ClaudeAgentOptions(
        setting_sources=["project"]  # Only .claude/settings.json
    ),
):
    print(message)
Test- und CI-Umgebungen:
# Ensure consistent behavior in CI by excluding local settings
async for message in query(
    prompt="Run tests",
    options=ClaudeAgentOptions(
        setting_sources=["project"],  # Only team-shared settings
        permission_mode="bypassPermissions",
    ),
):
    print(message)
SDK-only-Anwendungen:
# Define everything programmatically.
# Pass [] to opt out of filesystem setting sources.
async for message in query(
    prompt="Review this PR",
    options=ClaudeAgentOptions(
        setting_sources=[],
        agents={...},
        mcp_servers={...},
        allowed_tools=["Read", "Grep", "Glob"],
    ),
):
    print(message)
Laden von CLAUDE.md-Projektanweisungen:
# Load project settings to include CLAUDE.md files
async for message in query(
    prompt="Add a new feature following project conventions",
    options=ClaudeAgentOptions(
        system_prompt={
            "type": "preset",
            "preset": "claude_code",  # Use Claude Code's system prompt
        },
        setting_sources=["project"],  # Loads CLAUDE.md from project
        allowed_tools=["Read", "Write", "Edit"],
    ),
):
    print(message)

Einstellungspriorität

Wenn mehrere Quellen geladen werden, werden Einstellungen mit dieser Priorität zusammengeführt (höchste zu niedrigste):
  1. Lokale Einstellungen (.claude/settings.local.json)
  2. Projekteinstellungen (.claude/settings.json)
  3. Benutzereinstellungen (~/.claude/settings.json)
Programmgesteuerte Optionen wie agents und allowed_tools überschreiben Benutzer-, Projekt- und lokale Dateisystem-Einstellungen. Verwaltete Richtlinieneinstellungen haben Vorrang vor programmgesteuerten Optionen.

AgentDefinition

Konfiguration für einen programmgesteuert definierten Subagenten.
@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
FeldErforderlichBeschreibung
descriptionJaNatürlichsprachige Beschreibung, wann dieser Agent verwendet werden sollte
promptJaDer System-Prompt des Agenten
toolsNeinArray von zulässigen Tool-Namen. Wenn weggelassen, erbt alle Tools
disallowedToolsNeinArray von Tool-Namen, die aus dem Tool-Set des Agenten entfernt werden
modelNeinModell-Override für diesen Agenten. Akzeptiert einen Alias wie "sonnet", "opus", "haiku" oder "inherit", oder eine vollständige Modell-ID. Wenn weggelassen, verwendet das Hauptmodell
skillsNeinListe von Skill-Namen, die diesem Agenten zur Verfügung stehen
memoryNeinMemory-Quelle für diesen Agenten: "user", "project" oder "local"
mcpServersNeinMCP-Server, die diesem Agenten zur Verfügung stehen. Jeder Eintrag ist ein Servername oder ein Inline-{name: config}-Dict
initialPromptNeinWird automatisch als erste Benutzerdrehung eingereicht, wenn dieser Agent als Haupt-Thread-Agent läuft
maxTurnsNeinMaximale Anzahl von Agenten-Umdrehungen, bevor der Agent stoppt
backgroundNeinFühren Sie diesen Agenten als nicht-blockierende Hintergrundaufgabe aus, wenn aufgerufen
effortNeinReasoning-Anstrengungsstufe für diesen Agenten. Akzeptiert eine benannte Stufe oder eine Ganzzahl. Siehe EffortLevel
permissionModeNeinBerechtigungsmodus für die Tool-Ausführung innerhalb dieses Agenten. Siehe PermissionMode
AgentDefinition-Feldnamen verwenden camelCase, wie disallowedTools, permissionMode und maxTurns. Diese Namen werden direkt dem Drahtformat zugeordnet, das mit dem TypeScript SDK geteilt wird. Dies unterscheidet sich von ClaudeAgentOptions, das Python snake_case für die entsprechenden Top-Level-Felder wie disallowed_tools und permission_mode verwendet. Da AgentDefinition eine Dataclass ist, wirft das Übergeben eines snake_case-Schlüsselworts einen TypeError zur Konstruktionszeit auf.

PermissionMode

Berechtigungsmodi zur Kontrolle der Tool-Ausführung.
PermissionMode = Literal[
    "default",  # Standard permission behavior
    "acceptEdits",  # Auto-accept file edits
    "plan",  # Planning mode - read-only tools only
    "dontAsk",  # Deny anything not pre-approved instead of prompting
    "bypassPermissions",  # Bypass all permission checks (use with caution)
]

EffortLevel

Anstrengungsstufen zur Steuerung der Denktiefe.
EffortLevel = Literal[
    "low",  # Minimal thinking, fastest responses
    "medium",  # Moderate thinking
    "high",  # Deep reasoning
    "xhigh",  # Extended reasoning (Opus 4.7 only; falls back to "high" on other models)
    "max",  # Maximum effort
]

CanUseTool

Typ-Alias für Tool-Berechtigungs-Callback-Funktionen.
CanUseTool = Callable[
    [str, dict[str, Any], ToolPermissionContext], Awaitable[PermissionResult]
]
Der Callback empfängt:
  • tool_name: Name des aufgerufenen Tools
  • input_data: Die Eingabeparameter des Tools
  • context: Ein ToolPermissionContext mit zusätzlichen Informationen
Gibt ein PermissionResult zurück (entweder PermissionResultAllow oder PermissionResultDeny).

ToolPermissionContext

Kontextinformationen, die an Tool-Berechtigungs-Callbacks übergeben werden.
@dataclass
class ToolPermissionContext:
    signal: Any | None = None  # Future: abort signal support
    suggestions: list[PermissionUpdate] = field(default_factory=list)
    blocked_path: str | None = None
    decision_reason: str | None = None
    title: str | None = None
    display_name: str | None = None
    description: str | None = None
FeldTypBeschreibung
signalAny | NoneReserviert für zukünftige Abort-Signal-Unterstützung
suggestionslist[PermissionUpdate]Berechtigungsaktualisierungsvorschläge von der CLI. Bash-Aufforderungen enthalten einen Vorschlag mit dem localSettings-Ziel, daher gibt das Zurückgeben in updated_permissions die Regel in .claude/settings.local.json aus und bleibt über Sitzungen hinweg bestehen.
blocked_pathstr | NoneDateipfad, der die Berechtigungsanfrage ausgelöst hat, falls zutreffend. Zum Beispiel, wenn ein Bash-Befehl versucht, auf einen Pfad außerhalb zulässiger Verzeichnisse zuzugreifen
decision_reasonstr | NoneGrund, warum diese Berechtigungsanfrage ausgelöst wurde. Weitergeleitet von einem PreToolUse-Hook’s permissionDecisionReason, wenn der Hook "ask" zurückgegeben hat
titlestr | NoneVollständiger Berechtigungsaufforderungssatz, wie Claude wants to read foo.txt. Verwenden Sie als primären Aufforderungstext, wenn vorhanden
display_namestr | NoneKurze Nominalphrase für die Tool-Aktion, wie Read file, geeignet für Schaltflächenbeschriftungen
descriptionstr | NoneLesbare Untertitel für die Berechtigungs-UI

PermissionResult

Union-Typ für Berechtigungs-Callback-Ergebnisse.
PermissionResult = PermissionResultAllow | PermissionResultDeny

PermissionResultAllow

Ergebnis, das angibt, dass der Tool-Aufruf zulässig sein sollte.
@dataclass
class PermissionResultAllow:
    behavior: Literal["allow"] = "allow"
    updated_input: dict[str, Any] | None = None
    updated_permissions: list[PermissionUpdate] | None = None
FeldTypStandardBeschreibung
behaviorLiteral["allow"]"allow"Muss “allow” sein
updated_inputdict[str, Any] | NoneNoneGeänderte Eingabe, die stattdessen verwendet werden soll
updated_permissionslist[PermissionUpdate] | NoneNoneBerechtigungsaktualisierungen zum Anwenden

PermissionResultDeny

Ergebnis, das angibt, dass der Tool-Aufruf verweigert werden sollte.
@dataclass
class PermissionResultDeny:
    behavior: Literal["deny"] = "deny"
    message: str = ""
    interrupt: bool = False
FeldTypStandardBeschreibung
behaviorLiteral["deny"]"deny"Muss “deny” sein
messagestr""Nachricht, die erklärt, warum das Tool verweigert wurde
interruptboolFalseOb die aktuelle Ausführung unterbrochen werden soll

PermissionUpdate

Konfiguration zum programmgesteuerten Aktualisieren von Berechtigungen.
@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
FeldTypBeschreibung
typeLiteral[...]Der Typ der Berechtigungsaktualisierungsoperation
ruleslist[PermissionRuleValue] | NoneRegeln für Add/Replace/Remove-Operationen
behaviorLiteral["allow", "deny", "ask"] | NoneVerhalten für regelbasierte Operationen
modePermissionMode | NoneModus für setMode-Operation
directorieslist[str] | NoneVerzeichnisse für Add/Remove-Verzeichnis-Operationen
destinationLiteral[...] | NoneWo die Berechtigungsaktualisierung angewendet werden soll

PermissionRuleValue

Eine Regel, die in einer Berechtigungsaktualisierung hinzugefügt, ersetzt oder entfernt werden soll.
@dataclass
class PermissionRuleValue:
    tool_name: str
    rule_content: str | None = None

ToolsPreset

Preset-Tools-Konfiguration für die Verwendung des Standard-Tool-Sets von Claude Code.
class ToolsPreset(TypedDict):
    type: Literal["preset"]
    preset: Literal["claude_code"]

ThinkingConfig

Steuert das Verhalten des erweiterten Denkens. Eine Union von drei Konfigurationen:
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
VarianteFelderBeschreibung
adaptivetype, displayClaude entscheidet adaptiv, wann gedacht werden soll
enabledtype, budget_tokens, displayAktivieren Sie das Denken mit einem bestimmten Token-Budget
disabledtypeDeaktivieren Sie das Denken
Das optionale Feld display steuert, ob Thinking-Text "summarized" oder "omitted" zurückgegeben wird. Bei Claude Opus 4.7 und später ist der API-Standard "omitted", daher setzen Sie "summarized", um Thinking-Inhalte in ThinkingBlock-Ausgaben zu erhalten. Da dies TypedDict-Klassen sind, sind sie zur Laufzeit einfache Dicts. Konstruieren Sie sie entweder als Dict-Literale oder rufen Sie die Klasse wie einen Konstruktor auf; beide erzeugen ein dict. Greifen Sie auf Felder mit config["budget_tokens"] zu, nicht mit 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

SdkBeta

Literal-Typ für SDK-Beta-Funktionen.
SdkBeta = Literal["context-1m-2025-08-07"]
Verwenden Sie mit dem Feld betas in ClaudeAgentOptions, um Beta-Funktionen zu aktivieren.
Die context-1m-2025-08-07-Beta ist seit dem 30. April 2026 veraltet. Das Übergeben dieses Headers mit Claude Sonnet 4.5 oder Sonnet 4 hat keine Auswirkung, und Anfragen, die das Standard-200k-Token-Kontextfenster überschreiten, geben einen Fehler zurück. Um ein 1M-Token-Kontextfenster zu verwenden, migrieren Sie zu Claude Sonnet 4.6, Claude Opus 4.6 oder Claude Opus 4.7, die 1M-Kontext zu Standardpreisen ohne Beta-Header enthalten.

McpSdkServerConfig

Konfiguration für SDK MCP-Server, die mit create_sdk_mcp_server() erstellt wurden.
class McpSdkServerConfig(TypedDict):
    type: Literal["sdk"]
    name: str
    instance: Any  # MCP Server instance

McpServerConfig

Union-Typ für MCP-Server-Konfigurationen.
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

Die Konfiguration eines MCP-Servers, wie von get_mcp_status() gemeldet. Dies ist die Union aller McpServerConfig-Transport-Varianten plus eine nur-Ausgabe-claudeai-proxy-Variante für Server, die durch claude.ai proxiert werden.
McpServerStatusConfig = (
    McpStdioServerConfig
    | McpSSEServerConfig
    | McpHttpServerConfig
    | McpSdkServerConfigStatus
    | McpClaudeAIProxyServerConfig
)
McpSdkServerConfigStatus ist die serialisierbare Form von McpSdkServerConfig mit nur type ("sdk") und name (str)-Feldern; die In-Process-instance wird weggelassen. McpClaudeAIProxyServerConfig hat type ("claudeai-proxy"), url (str) und id (str)-Felder.

McpStatusResponse

Antwort von ClaudeSDKClient.get_mcp_status(). Umhüllt die Liste der Server-Status unter dem mcpServers-Schlüssel.
class McpStatusResponse(TypedDict):
    mcpServers: list[McpServerStatus]

McpServerStatus

Status eines verbundenen MCP-Servers, enthalten in 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]]
FeldTypBeschreibung
namestrServername
statusstrEiner von "connected", "failed", "needs-auth", "pending" oder "disabled"
serverInfodict (optional)Servername und Version ({"name": str, "version": str})
errorstr (optional)Fehlermeldung, wenn der Server keine Verbindung herstellen konnte
configMcpServerStatusConfig (optional)Server-Konfiguration. Gleiche Form wie McpServerConfig (stdio, SSE, HTTP oder SDK), plus eine claudeai-proxy-Variante für Server, die über claude.ai verbunden sind
scopestr (optional)Konfigurationsbereich
toolslist (optional)Tools, die von diesem Server bereitgestellt werden, jeweils mit name, description und annotations-Feldern

SdkPluginConfig

Konfiguration zum Laden von Plugins im SDK.
class SdkPluginConfig(TypedDict):
    type: Literal["local"]
    path: str
FeldTypBeschreibung
typeLiteral["local"]Muss "local" sein (derzeit werden nur lokale Plugins unterstützt)
pathstrAbsoluter oder relativer Pfad zum Plugin-Verzeichnis
Beispiel:
plugins = [
    {"type": "local", "path": "./my-plugin"},
    {"type": "local", "path": "/absolute/path/to/plugin"},
]
Vollständige Informationen zum Erstellen und Verwenden von Plugins finden Sie unter Plugins.

Nachrichtentypen

Message

Union-Typ aller möglichen Nachrichten.
Message = (
    UserMessage
    | AssistantMessage
    | SystemMessage
    | ResultMessage
    | StreamEvent
    | RateLimitEvent
)

UserMessage

Benutzereingabe-Nachricht.
@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
FeldTypBeschreibung
contentstr | list[ContentBlock]Nachrichteninhalt als Text oder Inhaltsblöcke
uuidstr | NoneEindeutige Nachrichtenkennung
parent_tool_use_idstr | NoneTool-Use-ID, wenn diese Nachricht eine Tool-Ergebnis-Antwort ist
tool_use_resultdict[str, Any] | NoneTool-Ergebnisdaten, falls zutreffend

AssistantMessage

Assistent-Antwortnachricht mit Inhaltsblöcken.
@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
FeldTypBeschreibung
contentlist[ContentBlock]Liste von Inhaltsblöcken in der Antwort
modelstrModell, das die Antwort generiert hat
parent_tool_use_idstr | NoneTool-Use-ID, wenn dies eine verschachtelte Antwort ist
errorAssistantMessageError | NoneFehlertyp, wenn die Antwort auf einen Fehler stieß
usagedict[str, Any] | NoneToken-Nutzung pro Nachricht (gleiche Schlüssel wie ResultMessage.usage)
message_idstr | NoneAPI-Nachrichtenkennung. Mehrere Nachrichten aus einer Umdrehung teilen die gleiche ID

AssistantMessageError

Mögliche Fehlertypen für Assistent-Nachrichten.
AssistantMessageError = Literal[
    "authentication_failed",
    "billing_error",
    "rate_limit",
    "invalid_request",
    "server_error",
    "max_output_tokens",
    "unknown",
]

SystemMessage

System-Nachricht mit Metadaten.
@dataclass
class SystemMessage:
    subtype: str
    data: dict[str, Any]

ResultMessage

Endgültige Ergebnis-Nachricht mit Kosten- und Nutzungsinformationen.
@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, Any] | 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
Das usage-Dict enthält die folgenden Schlüssel, wenn vorhanden:
SchlüsselTypBeschreibung
input_tokensintGesamte verbrauchte Eingabe-Token.
output_tokensintGesamte generierte Ausgabe-Token.
cache_creation_input_tokensintToken, die zum Erstellen neuer Cache-Einträge verwendet wurden.
cache_read_input_tokensintToken, die aus vorhandenen Cache-Einträgen gelesen wurden.
Das model_usage-Dict ordnet Modellnamen der Nutzung pro Modell zu. Die inneren Dict-Schlüssel verwenden camelCase, da der Wert unverändert vom zugrunde liegenden CLI-Prozess übergeben wird und dem TypeScript ModelUsage-Typ entspricht:
SchlüsselTypBeschreibung
inputTokensintEingabe-Token für dieses Modell.
outputTokensintAusgabe-Token für dieses Modell.
cacheReadInputTokensintCache-Lese-Token für dieses Modell.
cacheCreationInputTokensintCache-Erstellungs-Token für dieses Modell.
webSearchRequestsintWebsuch-Anfragen, die von diesem Modell gestellt wurden.
costUSDfloatGeschätzte Kosten in USD für dieses Modell, clientseitig berechnet. Siehe Kosten und Nutzung verfolgen für Abrechnungsvorbehalt.
contextWindowintKontextfenstergröße für dieses Modell.
maxOutputTokensintMaximale Ausgabe-Token-Grenze für dieses Modell.

StreamEvent

Stream-Ereignis für partielle Nachrichtenaktualisierungen während des Streamings. Wird nur empfangen, wenn include_partial_messages=True in ClaudeAgentOptions. Import über 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
FeldTypBeschreibung
uuidstrEindeutige Kennung für dieses Ereignis
session_idstrSitzungskennung
eventdict[str, Any]Die rohen Claude API-Stream-Ereignisdaten
parent_tool_use_idstr | NoneÜbergeordnete Tool-Use-ID, wenn dieses Ereignis von einem Subagenten stammt

RateLimitEvent

Wird ausgegeben, wenn sich der Rate-Limit-Status ändert (z. B. von "allowed" zu "allowed_warning"). Verwenden Sie dies, um Benutzer zu warnen, bevor sie eine harte Grenze erreichen, oder um zu backoff, wenn der Status "rejected" ist.
@dataclass
class RateLimitEvent:
    rate_limit_info: RateLimitInfo
    uuid: str
    session_id: str
FeldTypBeschreibung
rate_limit_infoRateLimitInfoAktueller Rate-Limit-Status
uuidstrEindeutige Ereigniskennung
session_idstrSitzungskennung

RateLimitInfo

Rate-Limit-Status, den RateLimitEvent trägt.
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)
FeldTypBeschreibung
statusRateLimitStatusAktueller Status. "allowed_warning" bedeutet, dass die Grenze näher rückt; "rejected" bedeutet, dass die Grenze erreicht wurde
resets_atint | NoneUnix-Zeitstempel, wenn das Rate-Limit-Fenster zurückgesetzt wird
rate_limit_typeRateLimitType | NoneWelches Rate-Limit-Fenster gilt
utilizationfloat | NoneAnteil des Rate-Limits, das verbraucht wurde (0,0 bis 1,0)
overage_statusRateLimitStatus | NoneStatus der Pay-as-you-go-Übernutzung, falls zutreffend
overage_resets_atint | NoneUnix-Zeitstempel, wenn das Übernutzungs-Fenster zurückgesetzt wird
overage_disabled_reasonstr | NoneWarum Übernutzung nicht verfügbar ist, wenn Status "rejected" ist
rawdict[str, Any]Vollständiges Rohdictionary von der CLI, einschließlich Felder, die oben nicht modelliert sind

TaskStartedMessage

Wird ausgegeben, wenn eine Hintergrundaufgabe startet. Eine Hintergrundaufgabe ist alles, was außerhalb der Hauptumdrehung verfolgt wird: ein backgroundierter Bash-Befehl, eine Monitor-Überwachung, ein Subagent, der über das Agent-Tool erzeugt wird, oder ein Remote-Agent. Das Feld task_type sagt Ihnen, welches. Diese Benennung ist nicht verwandt mit der Task-zu-Agent-Tool-Umbenennung.
@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
FeldTypBeschreibung
task_idstrEindeutige Kennung für die Aufgabe
descriptionstrBeschreibung der Aufgabe
uuidstrEindeutige Nachrichtenkennung
session_idstrSitzungskennung
tool_use_idstr | NoneZugeordnete Tool-Use-ID
task_typestr | NoneWelche Art von Hintergrundaufgabe: "local_bash" für Background Bash und Monitor-Überwachungen, "local_agent" oder "remote_agent"

TaskUsage

Token- und Timing-Daten für eine Hintergrundaufgabe.
class TaskUsage(TypedDict):
    total_tokens: int
    tool_uses: int
    duration_ms: int

TaskProgressMessage

Wird regelmäßig mit Fortschrittsaktualisierungen für eine laufende Hintergrundaufgabe ausgegeben.
@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
FeldTypBeschreibung
task_idstrEindeutige Kennung für die Aufgabe
descriptionstrAktuelle Statusbeschreibung
usageTaskUsageToken-Nutzung für diese Aufgabe bisher
uuidstrEindeutige Nachrichtenkennung
session_idstrSitzungskennung
tool_use_idstr | NoneZugeordnete Tool-Use-ID
last_tool_namestr | NoneName des letzten Tools, das die Aufgabe verwendet hat

TaskNotificationMessage

Wird ausgegeben, wenn eine Hintergrundaufgabe abgeschlossen, fehlgeschlagen oder gestoppt wird. Hintergrundaufgaben umfassen run_in_background-Bash-Befehle, Monitor-Überwachungen und Background-Subagenten.
@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
FeldTypBeschreibung
task_idstrEindeutige Kennung für die Aufgabe
statusTaskNotificationStatusEiner von "completed", "failed" oder "stopped"
output_filestrPfad zur Aufgabenausgabedatei
summarystrZusammenfassung des Aufgabenergebnisses
uuidstrEindeutige Nachrichtenkennung
session_idstrSitzungskennung
tool_use_idstr | NoneZugeordnete Tool-Use-ID
usageTaskUsage | NoneEndgültige Token-Nutzung für die Aufgabe

Inhaltsblock-Typen

ContentBlock

Union-Typ aller Inhaltsblöcke.
ContentBlock = TextBlock | ThinkingBlock | ToolUseBlock | ToolResultBlock

TextBlock

Text-Inhaltsblock.
@dataclass
class TextBlock:
    text: str

ThinkingBlock

Thinking-Inhaltsblock (für Modelle mit Thinking-Fähigkeit).
@dataclass
class ThinkingBlock:
    thinking: str
    signature: str

ToolUseBlock

Tool-Use-Anfrage-Block.
@dataclass
class ToolUseBlock:
    id: str
    name: str
    input: dict[str, Any]

ToolResultBlock

Tool-Ausführungs-Ergebnis-Block.
@dataclass
class ToolResultBlock:
    tool_use_id: str
    content: str | list[dict[str, Any]] | None = None
    is_error: bool | None = None

Fehlertypen

ClaudeSDKError

Basis-Ausnahmeklasse für alle SDK-Fehler.
class ClaudeSDKError(Exception):
    """Base error for Claude SDK."""

CLINotFoundError

Wird ausgelöst, wenn Claude Code CLI nicht installiert oder nicht gefunden ist.
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

Wird ausgelöst, wenn die Verbindung zu Claude Code fehlschlägt.
class CLIConnectionError(ClaudeSDKError):
    """Failed to connect to Claude Code."""

ProcessError

Wird ausgelöst, wenn der Claude Code-Prozess fehlschlägt.
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

CLIJSONDecodeError

Wird ausgelöst, wenn JSON-Parsing fehlschlägt.
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-Typen

Einen umfassenden Leitfaden zur Verwendung von Hooks mit Beispielen und häufigen Mustern finden Sie im Hooks-Leitfaden.

HookEvent

Unterstützte Hook-Ereignistypen.
HookEvent = Literal[
    "PreToolUse",  # Called before tool execution
    "PostToolUse",  # Called after tool execution
    "PostToolUseFailure",  # Called when a tool execution fails
    "UserPromptSubmit",  # Called when user submits a prompt
    "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
]
Das TypeScript SDK unterstützt zusätzliche Hook-Ereignisse, die in Python noch nicht verfügbar sind: SessionStart, SessionEnd, Setup, TeammateIdle, TaskCompleted, ConfigChange, WorktreeCreate, WorktreeRemove, PostToolBatch und MessageDisplay.

HookCallback

Typ-Definition für Hook-Callback-Funktionen.
HookCallback = Callable[[HookInput, str | None, HookContext], Awaitable[HookJSONOutput]]
Parameter:
  • input: Stark typisierte Hook-Eingabe mit diskriminierten Unions basierend auf hook_event_name (siehe HookInput)
  • tool_use_id: Optionale Tool-Use-Kennung (für Tool-bezogene Hooks)
  • context: Hook-Kontext mit zusätzlichen Informationen
Gibt ein HookJSONOutput zurück, das enthalten kann:
  • decision: "block", um die Aktion zu blockieren
  • systemMessage: Warnmeldung, die dem Benutzer angezeigt wird
  • hookSpecificOutput: Hook-spezifische Ausgabedaten

HookContext

Kontextinformationen, die an Hook-Callbacks übergeben werden.
class HookContext(TypedDict):
    signal: Any | None  # Future: abort signal support

HookMatcher

Konfiguration zum Abgleichen von Hooks mit bestimmten Ereignissen oder Tools.
@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 for all hooks in this matcher (default: 60)
    )

HookInput

Union-Typ aller Hook-Eingabetypen. Der tatsächliche Typ hängt vom Feld hook_event_name ab.
HookInput = (
    PreToolUseHookInput
    | PostToolUseHookInput
    | PostToolUseFailureHookInput
    | UserPromptSubmitHookInput
    | StopHookInput
    | SubagentStopHookInput
    | PreCompactHookInput
    | NotificationHookInput
    | SubagentStartHookInput
    | PermissionRequestHookInput
)

BaseHookInput

Basis-Felder, die in allen Hook-Eingabetypen vorhanden sind.
class BaseHookInput(TypedDict):
    session_id: str
    transcript_path: str
    cwd: str
    permission_mode: NotRequired[str]
FeldTypBeschreibung
session_idstrAktuelle Sitzungskennung
transcript_pathstrPfad zur Sitzungstranskript-Datei
cwdstrAktuelles Arbeitsverzeichnis
permission_modestr (optional)Aktueller Berechtigungsmodus

PreToolUseHookInput

Eingabedaten für PreToolUse-Hook-Ereignisse.
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]
FeldTypBeschreibung
hook_event_nameLiteral["PreToolUse"]Immer “PreToolUse”
tool_namestrName des Tools, das ausgeführt werden soll
tool_inputdict[str, Any]Eingabeparameter für das Tool
tool_use_idstrEindeutige Kennung für diese Tool-Nutzung
agent_idstr (optional)Subagenten-Kennung, vorhanden, wenn der Hook innerhalb eines Subagenten ausgelöst wird
agent_typestr (optional)Subagenten-Typ, vorhanden, wenn der Hook innerhalb eines Subagenten ausgelöst wird

PostToolUseHookInput

Eingabedaten für PostToolUse-Hook-Ereignisse.
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]
FeldTypBeschreibung
hook_event_nameLiteral["PostToolUse"]Immer “PostToolUse”
tool_namestrName des Tools, das ausgeführt wurde
tool_inputdict[str, Any]Eingabeparameter, die verwendet wurden
tool_responseAnyAntwort aus der Tool-Ausführung
tool_use_idstrEindeutige Kennung für diese Tool-Nutzung
agent_idstr (optional)Subagenten-Kennung, vorhanden, wenn der Hook innerhalb eines Subagenten ausgelöst wird
agent_typestr (optional)Subagenten-Typ, vorhanden, wenn der Hook innerhalb eines Subagenten ausgelöst wird

PostToolUseFailureHookInput

Eingabedaten für PostToolUseFailure-Hook-Ereignisse. Wird aufgerufen, wenn eine Tool-Ausführung fehlschlägt.
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]
FeldTypBeschreibung
hook_event_nameLiteral["PostToolUseFailure"]Immer “PostToolUseFailure”
tool_namestrName des Tools, das fehlgeschlagen ist
tool_inputdict[str, Any]Eingabeparameter, die verwendet wurden
tool_use_idstrEindeutige Kennung für diese Tool-Nutzung
errorstrFehlermeldung aus der fehlgeschlagenen Ausführung
is_interruptbool (optional)Ob der Fehler durch eine Unterbrechung verursacht wurde
agent_idstr (optional)Subagenten-Kennung, vorhanden, wenn der Hook innerhalb eines Subagenten ausgelöst wird
agent_typestr (optional)Subagenten-Typ, vorhanden, wenn der Hook innerhalb eines Subagenten ausgelöst wird

UserPromptSubmitHookInput

Eingabedaten für UserPromptSubmit-Hook-Ereignisse.
class UserPromptSubmitHookInput(BaseHookInput):
    hook_event_name: Literal["UserPromptSubmit"]
    prompt: str
FeldTypBeschreibung
hook_event_nameLiteral["UserPromptSubmit"]Immer “UserPromptSubmit”
promptstrDie vom Benutzer eingereichte Aufforderung

StopHookInput

Eingabedaten für Stop-Hook-Ereignisse.
class StopHookInput(BaseHookInput):
    hook_event_name: Literal["Stop"]
    stop_hook_active: bool
FeldTypBeschreibung
hook_event_nameLiteral["Stop"]Immer “Stop”
stop_hook_activeboolOb der Stop-Hook aktiv ist

SubagentStopHookInput

Eingabedaten für SubagentStop-Hook-Ereignisse.
class SubagentStopHookInput(BaseHookInput):
    hook_event_name: Literal["SubagentStop"]
    stop_hook_active: bool
    agent_id: str
    agent_transcript_path: str
    agent_type: str
FeldTypBeschreibung
hook_event_nameLiteral["SubagentStop"]Immer “SubagentStop”
stop_hook_activeboolOb der Stop-Hook aktiv ist
agent_idstrEindeutige Kennung für den Subagenten
agent_transcript_pathstrPfad zur Transkript-Datei des Subagenten
agent_typestrTyp des Subagenten

PreCompactHookInput

Eingabedaten für PreCompact-Hook-Ereignisse.
class PreCompactHookInput(BaseHookInput):
    hook_event_name: Literal["PreCompact"]
    trigger: Literal["manual", "auto"]
    custom_instructions: str | None
FeldTypBeschreibung
hook_event_nameLiteral["PreCompact"]Immer “PreCompact”
triggerLiteral["manual", "auto"]Was die Komprimierung ausgelöst hat
custom_instructionsstr | NoneBenutzerdefinierte Anweisungen für die Komprimierung

NotificationHookInput

Eingabedaten für Notification-Hook-Ereignisse.
class NotificationHookInput(BaseHookInput):
    hook_event_name: Literal["Notification"]
    message: str
    title: NotRequired[str]
    notification_type: str
FeldTypBeschreibung
hook_event_nameLiteral["Notification"]Immer “Notification”
messagestrBenachrichtigungsnachrichteninhalt
titlestr (optional)Benachrichtigungstitel
notification_typestrBenachrichtigungstyp

SubagentStartHookInput

Eingabedaten für SubagentStart-Hook-Ereignisse.
class SubagentStartHookInput(BaseHookInput):
    hook_event_name: Literal["SubagentStart"]
    agent_id: str
    agent_type: str
FeldTypBeschreibung
hook_event_nameLiteral["SubagentStart"]Immer “SubagentStart”
agent_idstrEindeutige Kennung für den Subagenten
agent_typestrTyp des Subagenten

PermissionRequestHookInput

Eingabedaten für PermissionRequest-Hook-Ereignisse. Ermöglicht Hooks, Berechtigungsentscheidungen programmgesteuert zu handhaben.
class PermissionRequestHookInput(BaseHookInput):
    hook_event_name: Literal["PermissionRequest"]
    tool_name: str
    tool_input: dict[str, Any]
    permission_suggestions: NotRequired[list[Any]]
FeldTypBeschreibung
hook_event_nameLiteral["PermissionRequest"]Immer “PermissionRequest”
tool_namestrName des Tools, das Berechtigung anfordert
tool_inputdict[str, Any]Eingabeparameter für das Tool
permission_suggestionslist[Any] (optional)Vorgeschlagene Berechtigungsaktualisierungen von der CLI

HookJSONOutput

Union-Typ für Hook-Callback-Rückgabewerte.
HookJSONOutput = AsyncHookJSONOutput | SyncHookJSONOutput

SyncHookJSONOutput

Synchrone Hook-Ausgabe mit Kontroll- und Entscheidungsfeldern.
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]
Verwenden Sie continue_ (mit Unterstrich) im Python-Code. Es wird automatisch in continue konvertiert, wenn es an die CLI gesendet wird.

HookSpecificOutput

Ein TypedDict, das den Hook-Ereignisnamen und ereignisspezifische Felder enthält. Die Form hängt vom hookEventName-Wert ab. Vollständige Details zu verfügbaren Feldern pro Hook-Ereignis finden Sie unter Ausführung mit Hooks kontrollieren. Eine diskriminierte Union von ereignisspezifischen Ausgabetypen. Das Feld hookEventName bestimmt, welche Felder gültig sind.
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]  # Deprecated: use 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

Asynchrone Hook-Ausgabe, die Hook-Ausführung aufschiebt.
class AsyncHookJSONOutput(TypedDict):
    async_: Literal[True]  # Set to True to defer execution
    asyncTimeout: NotRequired[int]  # Timeout in milliseconds
Verwenden Sie async_ (mit Unterstrich) im Python-Code. Es wird automatisch in async konvertiert, wenn es an die CLI gesendet wird.

Hook-Verwendungsbeispiel

Dieses Beispiel registriert zwei Hooks: einen, der gefährliche Bash-Befehle wie rm -rf / blockiert, und einen anderen, der alle Tool-Nutzung für Auditing protokolliert. Der Sicherheits-Hook wird nur auf Bash-Befehle ausgeführt (über den matcher), während der Logging-Hook auf alle Tools angewendet wird.
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 (default 60s timeout)
        ],
        "PostToolUse": [HookMatcher(hooks=[log_tool_use])],
    }
)

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

Tool-Eingabe-/Ausgabetypen

Dokumentation von Eingabe-/Ausgabeschemas für alle integrierten Claude Code-Tools. Während das Python SDK diese nicht als Typen exportiert, stellen sie die Struktur von Tool-Eingaben und -Ausgaben in Nachrichten dar.

Agent

Tool-Name: Agent (früher Task, das immer noch als Alias akzeptiert wird) Eingabe:
{
    "description": str,  # Eine kurze (3-5 Wörter) Beschreibung der Aufgabe
    "prompt": str,  # Die Aufgabe, die der Agent ausführen soll
    "subagent_type": str,  # Der Typ des spezialisierten Agenten, der verwendet werden soll
}
Ausgabe:
{
    "result": str,  # Endergebnis vom Subagenten
    "usage": dict | None,  # Token-Nutzungsstatistiken
    "total_cost_usd": float | None,  # Geschätzte Gesamtkosten in USD
    "duration_ms": int | None,  # Ausführungsdauer in Millisekunden
}

AskUserQuestion

Tool-Name: AskUserQuestion Stellt dem Benutzer während der Ausführung Klärungsfragen. Siehe Genehmigungen und Benutzereingaben handhaben für Verwendungsdetails. Eingabe:
{
    "questions": [  # Fragen, die dem Benutzer gestellt werden (1-4 Fragen)
        {
            "question": str,  # Die vollständige Frage, die dem Benutzer gestellt werden soll
            "header": str,  # Sehr kurzes Label, das als Chip/Tag angezeigt wird (max. 12 Zeichen)
            "options": [  # Die verfügbaren Auswahlmöglichkeiten (2-4 Optionen)
                {
                    "label": str,  # Anzeigetext für diese Option (1-5 Wörter)
                    "description": str,  # Erklärung, was diese Option bedeutet
                }
            ],
            "multiSelect": bool,  # Auf true setzen, um mehrere Auswahlen zu ermöglichen
        }
    ],
    "answers": dict[str, str | list[str]] | None,
    # Benutzerantworten, die vom Berechtigungssystem ausgefüllt werden. Multi-Select-
    # Antworten können eine Liste von Labels oder eine kommagetrennte Zeichenkette sein
}
Ausgabe:
{
    "questions": [  # Die Fragen, die gestellt wurden
        {
            "question": str,
            "header": str,
            "options": [{"label": str, "description": str}],
            "multiSelect": bool,
        }
    ],
    "answers": dict[str, str],  # Ordnet Fragetext der Antwortzeichenkette zu
    # Multi-Select-Antworten sind kommagetrennt
}

Bash

Tool-Name: Bash Eingabe:
{
    "command": str,  # Der auszuführende Befehl
    "timeout": int | None,  # Optionales Timeout in Millisekunden (max. 600000)
    "description": str | None,  # Klare, prägnante Beschreibung (5-10 Wörter)
    "run_in_background": bool | None,  # Auf true setzen, um im Hintergrund auszuführen
}
Ausgabe:
{
    "output": str,  # Kombinierte stdout- und stderr-Ausgabe
    "exitCode": int,  # Exit-Code des Befehls
    "killed": bool | None,  # Ob der Befehl aufgrund eines Timeouts beendet wurde
    "shellId": str | None,  # Shell-ID für Hintergrundprozesse
}

Monitor

Tool-Name: Monitor Führt ein Background-Skript aus und liefert jede stdout-Zeile an Claude als Ereignis, damit es reagieren kann, ohne zu pollen. Monitor folgt den gleichen Berechtigungsregeln wie Bash. Siehe die Monitor-Tool-Referenz für Verhalten und Provider-Verfügbarkeit. Eingabe:
{
    "command": str,  # Shell-Skript; jede stdout-Zeile ist ein Ereignis, exit beendet die Überwachung
    "description": str,  # Kurze Beschreibung, die in Benachrichtigungen angezeigt wird
    "timeout_ms": int | None,  # Nach dieser Frist beenden (Standard 300000, max. 3600000)
    "persistent": bool | None,  # Für die Lebensdauer der Sitzung ausführen; mit TaskStop stoppen
}
Ausgabe:
{
    "taskId": str,  # ID der Background-Monitor-Aufgabe
    "timeoutMs": int,  # Timeout-Frist in Millisekunden (0 wenn persistent)
    "persistent": bool | None,  # True, wenn bis TaskStop oder Sitzungsende ausgeführt wird
}

Edit

Tool-Name: Edit Eingabe:
{
    "file_path": str,  # Der absolute Pfad zur zu ändernden Datei
    "old_string": str,  # Der zu ersetzende Text
    "new_string": str,  # Der Text, durch den er ersetzt werden soll
    "replace_all": bool | None,  # Alle Vorkommen ersetzen (Standard False)
}
Ausgabe:
{
    "message": str,  # Bestätigungsmeldung
    "replacements": int,  # Anzahl der durchgeführten Ersetzungen
    "file_path": str,  # Dateipfad, der bearbeitet wurde
}

Read

Tool-Name: Read Eingabe:
{
    "file_path": str,  # Der absolute Pfad zur zu lesenden Datei
    "offset": int | None,  # Die Zeilennummer, ab der gelesen werden soll
    "limit": int | None,  # Die Anzahl der zu lesenden Zeilen
}
Ausgabe (Textdateien):
{
    "content": str,  # Dateiinhalt mit Zeilennummern
    "total_lines": int,  # Gesamtzahl der Zeilen in der Datei
    "lines_returned": int,  # Tatsächlich zurückgegebene Zeilen
}
Ausgabe (Bilder):
{
    "image": str,  # Base64-codierte Bilddaten
    "mime_type": str,  # MIME-Typ des Bildes
    "file_size": int,  # Dateigröße in Bytes
}

Write

Tool-Name: Write Eingabe:
{
    "file_path": str,  # Der absolute Pfad zur zu schreibenden Datei
    "content": str,  # Der in die Datei zu schreibende Inhalt
}
Ausgabe:
{
    "message": str,  # Erfolgsmeldung
    "bytes_written": int,  # Anzahl der geschriebenen Bytes
    "file_path": str,  # Dateipfad, der geschrieben wurde
}

Glob

Tool-Name: Glob Eingabe:
{
    "pattern": str,  # Das Glob-Muster zum Abgleich von Dateien
    "path": str | None,  # Das zu durchsuchende Verzeichnis (Standard: cwd)
}
Ausgabe:
{
    "matches": list[str],  # Array von übereinstimmenden Dateipfaden
    "count": int,  # Anzahl der gefundenen Übereinstimmungen
    "search_path": str,  # Verwendetes Suchverzeichnis
}

Grep

Tool-Name: Grep Eingabe:
{
    "pattern": str,  # Das reguläre Ausdrucksmuster
    "path": str | None,  # Datei oder Verzeichnis zum Durchsuchen
    "glob": str | None,  # Glob-Muster zum Filtern von Dateien
    "type": str | None,  # Dateityp zum Durchsuchen
    "output_mode": str | None,  # "content", "files_with_matches" oder "count"
    "-i": bool | None,  # Suche ohne Berücksichtigung der Groß-/Kleinschreibung
    "-n": bool | None,  # Zeilennummern anzeigen
    "-B": int | None,  # Zeilen vor jeder Übereinstimmung anzeigen
    "-A": int | None,  # Zeilen nach jeder Übereinstimmung anzeigen
    "-C": int | None,  # Zeilen vor und nach anzeigen
    "head_limit": int | None,  # Ausgabe auf erste N Zeilen/Einträge begrenzen
    "multiline": bool | None,  # Mehrzeilenmodus aktivieren
}
Ausgabe (content-Modus):
{
    "matches": [
        {
            "file": str,
            "line_number": int | None,
            "line": str,
            "before_context": list[str] | None,
            "after_context": list[str] | None,
        }
    ],
    "total_matches": int,
}
Ausgabe (files_with_matches-Modus):
{
    "files": list[str],  # Dateien mit Übereinstimmungen
    "count": int,  # Anzahl der Dateien mit Übereinstimmungen
}

NotebookEdit

Tool-Name: NotebookEdit Eingabe:
{
    "notebook_path": str,  # Absoluter Pfad zum Jupyter-Notebook
    "cell_id": str | None,  # Die ID der zu bearbeitenden Zelle
    "new_source": str,  # Die neue Quelle für die Zelle
    "cell_type": "code" | "markdown" | None,  # Der Typ der Zelle
    "edit_mode": "replace" | "insert" | "delete" | None,  # Bearbeitungsvorgangstyp
}
Ausgabe:
{
    "message": str,  # Erfolgsmeldung
    "edit_type": "replaced" | "inserted" | "deleted",  # Typ der durchgeführten Bearbeitung
    "cell_id": str | None,  # Zellen-ID, die betroffen war
    "total_cells": int,  # Gesamtzellen im Notebook nach Bearbeitung
}

WebFetch

Tool-Name: WebFetch Eingabe:
{
    "url": str,  # Die URL, von der Inhalte abgerufen werden sollen
    "prompt": str,  # Der Prompt, der auf den abgerufenen Inhalt angewendet werden soll
}
Ausgabe:
{
    "bytes": int,  # Größe des abgerufenen Inhalts in Bytes
    "code": int,  # HTTP-Antwortcode
    "codeText": str,  # HTTP-Antwortcodetext
    "result": str,  # Verarbeitetes Ergebnis aus der Anwendung des Prompts auf den Inhalt
    "durationMs": int,  # Zeit zum Abrufen und Verarbeiten des Inhalts in Millisekunden
    "url": str,  # URL, die abgerufen wurde
}

WebSearch

Tool-Name: WebSearch Eingabe:
{
    "query": str,  # Die zu verwendende Suchanfrage
    "allowed_domains": list[str] | None,  # Nur Ergebnisse von diesen Domains einbeziehen
    "blocked_domains": list[str] | None,  # Niemals Ergebnisse von diesen Domains einbeziehen
}
Ausgabe:
{
    "query": str,  # Die Suchanfrage
    "results": list[str | {"tool_use_id": str, "content": list[{"title": str, "url": str}]}],
    "durationSeconds": float,  # Suchdauer in Sekunden
}

TodoWrite

Tool-Name: TodoWrite
Ab Claude Code v2.1.142 ist TodoWrite standardmäßig deaktiviert. Verwenden Sie stattdessen TaskCreate, TaskGet, TaskUpdate und TaskList. Siehe Zu Task-Tools migrieren, um Ihren Überwachungscode zu aktualisieren, oder setzen Sie CLAUDE_CODE_ENABLE_TASKS=0, um zu TodoWrite zurückzukehren.
Eingabe:
{
    "todos": [
        {
            "content": str,  # Die Aufgabenbeschreibung
            "status": "pending" | "in_progress" | "completed",  # Aufgabenstatus
            "activeForm": str,  # Aktive Form der Beschreibung
        }
    ]
}
Ausgabe:
{
    "message": str,  # Erfolgsmeldung
    "stats": {"total": int, "pending": int, "in_progress": int, "completed": int},
}

TaskCreate

Tool-Name: TaskCreate Eingabe:
{
    "subject": str,  # Kurzer Aufgabentitel
    "description": str,  # Detaillierter Aufgabentext
    "activeForm": str | None,  # Präsens-Label, das während der Ausführung angezeigt wird
    "metadata": dict | None,  # Beliebige Aufrufer-Metadaten
}
Ausgabe:
{
    "task": {"id": str, "subject": str},  # Erstellte Aufgabe mit zugewiesener ID
}

TaskUpdate

Tool-Name: TaskUpdate Eingabe:
{
    "taskId": str,  # ID der zu patchenden Aufgabe
    "status": Literal["pending", "in_progress", "completed", "deleted"] | None,
    "subject": str | None,
    "description": str | None,
    "activeForm": str | None,
    "addBlocks": list[str] | None,  # Aufgaben-IDs, die diese Aufgabe jetzt blockiert
    "addBlockedBy": list[str] | None,  # Aufgaben-IDs, die diese Aufgabe jetzt blockieren
    "owner": str | None,
    "metadata": dict | None,
}
Ausgabe:
{
    "success": bool,
    "taskId": str,
    "updatedFields": list[str],  # Namen der Felder, die sich geändert haben
    "error": str | None,
    "statusChange": {"from": str, "to": str} | None,
}

TaskGet

Tool-Name: TaskGet Eingabe:
{
    "taskId": str,  # ID der zu lesenden Aufgabe
}
Ausgabe:
{
    "task": {
        "id": str,
        "subject": str,
        "description": str,
        "status": Literal["pending", "in_progress", "completed"],
        "blocks": list[str],
        "blockedBy": list[str],
    } | None,  # None, wenn die ID nicht gefunden wird
}

TaskList

Tool-Name: TaskList Eingabe:
{}
Ausgabe:
{
    "tasks": [
        {
            "id": str,
            "subject": str,
            "status": Literal["pending", "in_progress", "completed"],
            "owner": str | None,
            "blockedBy": list[str],
        }
    ],
}

BashOutput

Tool-Name: BashOutput Eingabe:
{
    "bash_id": str,  # Die ID der Background-Shell
    "filter": str | None,  # Optionaler Regex zum Filtern von Ausgabezeilen
}
Ausgabe:
{
    "output": str,  # Neue Ausgabe seit der letzten Überprüfung
    "status": "running" | "completed" | "failed",  # Aktueller Shell-Status
    "exitCode": int | None,  # Exit-Code bei Abschluss
}

KillBash

Tool-Name: KillBash Eingabe:
{
    "shell_id": str  # Die ID der zu beendenden Background-Shell
}
Ausgabe:
{
    "message": str,  # Erfolgsmeldung
    "shell_id": str,  # ID der beendeten Shell
}

ExitPlanMode

Tool-Name: ExitPlanMode Eingabe:
{
    "plan": str  # Der Plan, der vom Benutzer zur Genehmigung ausgeführt werden soll
}
Ausgabe:
{
    "message": str,  # Bestätigungsmeldung
    "approved": bool | None,  # Ob der Benutzer den Plan genehmigt hat
}

ListMcpResources

Tool-Name: ListMcpResourcesTool Eingabe:
{
    "server": str | None  # Optionaler Servername zum Filtern von Ressourcen
}
Ausgabe:
{
    "resources": [
        {
            "uri": str,
            "name": str,
            "description": str | None,
            "mimeType": str | None,
            "server": str,
        }
    ],
    "total": int,
}

ReadMcpResource

Tool-Name: ReadMcpResourceTool Eingabe:
{
    "server": str,  # Der MCP-Servername
    "uri": str,  # Die zu lesende Ressourcen-URI
}
Ausgabe:
{
    "contents": [
        {"uri": str, "mimeType": str | None, "text": str | None, "blob": str | None}
    ],
    "server": str,
}

Erweiterte Funktionen mit ClaudeSDKClient

Erstellen einer kontinuierlichen Konversationsschnittstelle

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

Verwendung von Hooks zur Verhaltensänderung

from claude_agent_sdk import (
    ClaudeSDKClient,
    ClaudeAgentOptions,
    HookMatcher,
    HookContext,
)
import asyncio
from typing import Any


async def pre_tool_logger(
    input_data: dict[str, Any], tool_use_id: str | None, context: HookContext
) -> dict[str, Any]:
    """Log all tool usage before execution."""
    tool_name = input_data.get("tool_name", "unknown")
    print(f"[PRE-TOOL] About to use: {tool_name}")

    # You can modify or block the tool execution here
    if tool_name == "Bash" and "rm -rf" in str(input_data.get("tool_input", {})):
        return {
            "hookSpecificOutput": {
                "hookEventName": "PreToolUse",
                "permissionDecision": "deny",
                "permissionDecisionReason": "Dangerous command blocked",
            }
        }
    return {}


async def post_tool_logger(
    input_data: dict[str, Any], tool_use_id: str | None, context: HookContext
) -> dict[str, Any]:
    """Log results after tool execution."""
    tool_name = input_data.get("tool_name", "unknown")
    print(f"[POST-TOOL] Completed: {tool_name}")
    return {}


async def user_prompt_modifier(
    input_data: dict[str, Any], tool_use_id: str | None, context: HookContext
) -> dict[str, Any]:
    """Add context to user prompts."""
    original_prompt = input_data.get("prompt", "")

    # Add a timestamp as additional context for Claude to see
    from datetime import datetime

    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

    return {
        "hookSpecificOutput": {
            "hookEventName": "UserPromptSubmit",
            "additionalContext": f"[Submitted at {timestamp}] Original prompt: {original_prompt}",
        }
    }


async def main():
    options = ClaudeAgentOptions(
        hooks={
            "PreToolUse": [
                HookMatcher(hooks=[pre_tool_logger]),
                HookMatcher(matcher="Bash", hooks=[pre_tool_logger]),
            ],
            "PostToolUse": [HookMatcher(hooks=[post_tool_logger])],
            "UserPromptSubmit": [HookMatcher(hooks=[user_prompt_modifier])],
        },
        allowed_tools=["Read", "Write", "Bash"],
    )

    async with ClaudeSDKClient(options=options) as client:
        await client.query("List files in current directory")

        async for message in client.receive_response():
            # Hooks will automatically log tool usage
            pass


asyncio.run(main())

Echtzeit-Fortschrittsüberwachung

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


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

    async with ClaudeSDKClient(options=options) as client:
        await client.query("Create 5 Python files with different sorting algorithms")

        # Monitor progress in real-time
        async for message in client.receive_response():
            if isinstance(message, AssistantMessage):
                for block in message.content:
                    if isinstance(block, ToolUseBlock):
                        if block.name == "Write":
                            file_path = block.input.get("file_path", "")
                            print(f"Creating: {file_path}")
                    elif isinstance(block, ToolResultBlock):
                        print("Completed tool execution")
                    elif isinstance(block, TextBlock):
                        print(f"Claude says: {block.text[:100]}...")

        print("Task completed!")


asyncio.run(monitor_progress())

Beispielverwendung

Grundlegende Dateivorgänge (mit query)

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


async def create_project():
    options = ClaudeAgentOptions(
        allowed_tools=["Read", "Write", "Bash"],
        permission_mode="acceptEdits",
        cwd="/home/user/project",
    )

    async for message in query(
        prompt="Create a Python project structure with setup.py", options=options
    ):
        if isinstance(message, AssistantMessage):
            for block in message.content:
                if isinstance(block, ToolUseBlock):
                    print(f"Using tool: {block.name}")


asyncio.run(create_project())

Fehlerbehandlung

from claude_agent_sdk import query, CLINotFoundError, ProcessError, CLIJSONDecodeError

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

Streaming-Modus mit Client

from claude_agent_sdk import ClaudeSDKClient
import asyncio


async def interactive_session():
    async with ClaudeSDKClient() as client:
        # Send initial message
        await client.query("What's the weather like?")

        # Process responses
        async for msg in client.receive_response():
            print(msg)

        # Send follow-up
        await client.query("Tell me more about that")

        # Process follow-up response
        async for msg in client.receive_response():
            print(msg)


asyncio.run(interactive_session())

Verwendung benutzerdefinierter Tools mit ClaudeSDKClient

from claude_agent_sdk import (
    ClaudeSDKClient,
    ClaudeAgentOptions,
    tool,
    create_sdk_mcp_server,
    AssistantMessage,
    TextBlock,
)
import asyncio
from typing import Any


# Define custom tools with @tool decorator
@tool("calculate", "Perform mathematical calculations", {"expression": str})
async def calculate(args: dict[str, Any]) -> dict[str, Any]:
    try:
        result = eval(args["expression"], {"__builtins__": {}})
        return {"content": [{"type": "text", "text": f"Result: {result}"}]}
    except Exception as e:
        return {
            "content": [{"type": "text", "text": f"Error: {str(e)}"}],
            "is_error": True,
        }


@tool("get_time", "Get current time", {})
async def get_time(args: dict[str, Any]) -> dict[str, Any]:
    from datetime import datetime

    current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    return {"content": [{"type": "text", "text": f"Current time: {current_time}"}]}


async def main():
    # Create SDK MCP server with custom tools
    my_server = create_sdk_mcp_server(
        name="utilities", version="1.0.0", tools=[calculate, get_time]
    )

    # Configure options with the server
    options = ClaudeAgentOptions(
        mcp_servers={"utils": my_server},
        allowed_tools=["mcp__utils__calculate", "mcp__utils__get_time"],
    )

    # Use ClaudeSDKClient for interactive tool usage
    async with ClaudeSDKClient(options=options) as client:
        await client.query("What's 123 * 456?")

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

        # Follow up with time query
        await client.query("What time is it now?")

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


asyncio.run(main())

Sandbox-Konfiguration

SandboxSettings

Konfiguration für das Sandbox-Verhalten. Verwenden Sie dies, um Command-Sandboxing zu aktivieren und Netzwerkbeschränkungen programmgesteuert zu konfigurieren.
class SandboxSettings(TypedDict, total=False):
    enabled: bool
    autoAllowBashIfSandboxed: bool
    excludedCommands: list[str]
    allowUnsandboxedCommands: bool
    network: SandboxNetworkConfig
    ignoreViolations: SandboxIgnoreViolations
    enableWeakerNestedSandbox: bool
EigenschaftTypStandardBeschreibung
enabledboolFalseAktivieren Sie den Sandbox-Modus für die Befehlsausführung
autoAllowBashIfSandboxedboolTrueGenehmigen Sie Bash-Befehle automatisch, wenn die Sandbox aktiviert ist
excludedCommandslist[str][]Befehle, die immer Sandbox-Beschränkungen umgehen (z. B. ["docker"]). Diese werden automatisch ohne Modellbeteiligung unsandboxed ausgeführt
allowUnsandboxedCommandsboolTrueErlauben Sie dem Modell, die Ausführung von Befehlen außerhalb der Sandbox anzufordern. Wenn True, kann das Modell dangerouslyDisableSandbox in der Tool-Eingabe setzen, was auf das Berechtigungssystem zurückfällt
networkSandboxNetworkConfigNoneNetzwerkspezifische Sandbox-Konfiguration
ignoreViolationsSandboxIgnoreViolationsNoneKonfigurieren Sie, welche Sandbox-Verstöße ignoriert werden sollen
enableWeakerNestedSandboxboolFalseAktivieren Sie eine schwächere verschachtelte Sandbox für Kompatibilität
Die Sandbox hängt von der Plattformunterstützung ab und benötigt unter Linux Tools wie bubblewrap und socat. Standardmäßig werden Befehle, wenn enabled auf True gesetzt ist, aber die Sandbox nicht gestartet werden kann, unsandboxed mit einer Warnung auf stderr ausgeführt. Dieses Standardverhalten unterscheidet sich vom TypeScript SDK, wo failIfUnavailable standardmäßig auf true gesetzt ist.Setzen Sie "failIfUnavailable": True in Ihren Sandbox-Einstellungen, um stattdessen zu stoppen. Der Schlüssel ist noch nicht auf SandboxSettings deklariert, aber das SDK leitet ihn an Claude Code weiter, das ihn berücksichtigt. query() meldet dann eine ResultMessage mit subtype="error_during_execution" und den Grund in errors. Achten Sie auf diesen Subtyp, anstatt zu erwarten, dass query() vor dem Yielding von Nachrichten eine Ausnahme auslöst.

Beispielverwendung

from claude_agent_sdk import query, ClaudeAgentOptions, SandboxSettings

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

async for message in query(
    prompt="Build and test my project",
    options=ClaudeAgentOptions(sandbox=sandbox_settings),
):
    print(message)
Unix-Socket-Sicherheit: Die Option allowUnixSockets kann Zugriff auf leistungsstarke Systemdienste gewähren. Zum Beispiel ermöglicht das Zulassen von /var/run/docker.sock effektiv vollständigen Host-Systemzugriff über die Docker-API und umgeht die Sandbox-Isolation. Erlauben Sie nur Unix-Sockets, die absolut notwendig sind, und verstehen Sie die Sicherheitsauswirkungen jedes einzelnen.

SandboxNetworkConfig

Netzwerkspezifische Konfiguration für den Sandbox-Modus. Diese Einstellungen gelten für Sandbox-Bash-Befehle, wenn enabled in den übergeordneten SandboxSettings auf True gesetzt ist. Sie beschränken das WebFetch-Tool nicht, das stattdessen Berechtigungsregeln verwendet.
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
EigenschaftTypStandardBeschreibung
allowedDomainslist[str][]Domänennamen, auf die Sandbox-Prozesse zugreifen können
deniedDomainslist[str][]Domänennamen, auf die Sandbox-Prozesse nicht zugreifen können. Hat Vorrang vor allowedDomains
allowManagedDomainsOnlyboolFalseNur verwaltete Einstellungen: Wenn in verwalteten Einstellungen gesetzt, ignorieren Sie allowedDomains aus nicht verwalteten Einstellungsquellen. Hat keine Auswirkung, wenn über SDK-Optionen gesetzt
allowUnixSocketslist[str][]Unix-Socket-Pfade, auf die Prozesse zugreifen können (z. B. Docker-Socket)
allowAllUnixSocketsboolFalseErlauben Sie Zugriff auf alle Unix-Sockets
allowLocalBindingboolFalseErlauben Sie Prozessen, sich an lokale Ports zu binden (z. B. für Dev-Server)
allowMachLookuplist[str][]Nur macOS: XPC/Mach-Servicenamen zum Zulassen. Unterstützt ein nachfolgendes Platzhalterzeichen
httpProxyPortintNoneHTTP-Proxy-Port für Netzwerkanfragen
socksProxyPortintNoneSOCKS-Proxy-Port für Netzwerkanfragen
Der integrierte Sandbox-Proxy erzwingt die Netzwerk-Allowlist basierend auf dem angeforderten Hostnamen und beendet oder inspiziert keinen TLS-Verkehr, daher können Techniken wie Domain Fronting ihn möglicherweise umgehen. Siehe Sandboxing-Sicherheitsbeschränkungen für Details und Sichere Bereitstellung für die Konfiguration eines TLS-terminierenden Proxys.

SandboxIgnoreViolations

Konfiguration zum Ignorieren bestimmter Sandbox-Verstöße.
class SandboxIgnoreViolations(TypedDict, total=False):
    file: list[str]
    network: list[str]
EigenschaftTypStandardBeschreibung
filelist[str][]Dateipfad-Muster, für die Verstöße ignoriert werden sollen
networklist[str][]Netzwerkmuster, für die Verstöße ignoriert werden sollen

Berechtigungen-Fallback für Unsandboxed-Befehle

Wenn allowUnsandboxedCommands aktiviert ist, kann das Modell anfordern, Befehle außerhalb der Sandbox auszuführen, indem es dangerouslyDisableSandbox: True in der Tool-Eingabe setzt. Diese Anfragen fallen auf das bestehende Berechtigungssystem zurück, was bedeutet, dass Ihr can_use_tool-Handler aufgerufen wird, sodass Sie benutzerdefinierte Autorisierungslogik implementieren können.
excludedCommands vs allowUnsandboxedCommands:
  • excludedCommands: Eine statische Liste von Befehlen, die immer automatisch die Sandbox umgehen (z. B. ["docker"]). Das Modell hat keine Kontrolle darüber.
  • allowUnsandboxedCommands: Ermöglicht dem Modell, zur Laufzeit zu entscheiden, ob es die Ausführung außerhalb der Sandbox anfordert, indem es dangerouslyDisableSandbox: True in der Tool-Eingabe setzt.
from claude_agent_sdk import (
    query,
    ClaudeAgentOptions,
    HookMatcher,
    PermissionResultAllow,
    PermissionResultDeny,
    ToolPermissionContext,
)


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)
Dieses Muster ermöglicht es Ihnen:
  • Modell-Anfragen prüfen: Protokollieren Sie, wenn das Modell die Ausführung außerhalb der Sandbox anfordert
  • Allowlists implementieren: Erlauben Sie nur bestimmten Befehlen, außerhalb der Sandbox ausgeführt zu werden
  • Genehmigungsworkflows hinzufügen: Erfordern Sie explizite Autorisierung für privilegierte Operationen
Befehle, die mit dangerouslyDisableSandbox: True ausgeführt werden, haben vollständigen Systemzugriff. Stellen Sie sicher, dass Ihr can_use_tool-Handler diese Anfragen sorgfältig validiert.Wenn permission_mode auf bypassPermissions gesetzt ist und allow_unsandboxed_commands aktiviert ist, kann das Modell autonom Befehle außerhalb der Sandbox ausführen, ohne dass Genehmigungsaufforderungen angezeigt werden. Diese Kombination ermöglicht dem Modell effektiv, die Sandbox-Isolation stillschweigend zu verlassen.

Siehe auch