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
| Funktion | query() | ClaudeSDKClient |
|---|
| Sitzung | Erstellt standardmäßig eine neue Sitzung | Verwendet dieselbe Sitzung erneut |
| Konversation | Einzelner Austausch | Mehrere Austausche im gleichen Kontext |
| Verbindung | Automatisch verwaltet | Manuelle 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 fortsetzen | Manuell über continue_conversation oder resume | ✅ Automatisch |
| Anwendungsfall | Einmalige Aufgaben | Kontinuierliche 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
| Parameter | Typ | Beschreibung |
|---|
prompt | str | AsyncIterable[dict] | Die Eingabeaufforderung als Zeichenkette oder asynchroner Iterator für den Streaming-Modus |
options | ClaudeAgentOptions | None | Optionales Konfigurationsobjekt (standardmäßig ClaudeAgentOptions(), wenn None) |
transport | Transport | None | Optionaler 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())
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
| Parameter | Typ | Beschreibung |
|---|
name | str | Eindeutige Kennung für das Tool |
description | str | Lesbare Beschreibung, was das Tool tut |
input_schema | type | dict[str, Any] | Schema, das die Eingabeparameter des Tools definiert (siehe unten) |
annotations | ToolAnnotations | None | Optionale MCP-Tool-Anmerkungen, die Verhaltenshinweise für Clients bereitstellen |
Eingabeschema-Optionen
-
Einfache Typ-Zuordnung (empfohlen):
{"text": str, "count": int, "enabled": bool}
-
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']}!"}]}
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.
| Feld | Typ | Standard | Beschreibung |
|---|
title | str | None | None | Lesbare Bezeichnung für das Tool |
readOnlyHint | bool | None | False | Wenn True, ändert das Tool seine Umgebung nicht |
destructiveHint | bool | None | True | Wenn True, kann das Tool destruktive Aktualisierungen durchführen (nur sinnvoll, wenn readOnlyHint False ist) |
idempotentHint | bool | None | False | Wenn True, haben wiederholte Aufrufe mit denselben Argumenten keine zusätzliche Auswirkung (nur sinnvoll, wenn readOnlyHint False ist) |
openWorldHint | bool | None | True | Wenn 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
| Parameter | Typ | Standard | Beschreibung |
|---|
name | str | - | Eindeutige Kennung für den Server |
version | str | "1.0.0" | Versionsnummer des Servers |
tools | list[SdkMcpTool[Any]] | None | None | Liste 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
| Parameter | Typ | Standard | Beschreibung |
|---|
directory | str | None | None | Verzeichnis, für das Sitzungen aufgelistet werden sollen. Wenn weggelassen, werden Sitzungen über alle Projekte zurückgegeben |
limit | int | None | None | Maximale Anzahl der zurückzugebenden Sitzungen |
include_worktrees | bool | True | Wenn directory sich in einem Git-Repository befindet, Sitzungen aus allen worktrees einbeziehen |
Rückgabetyp: SDKSessionInfo
| Eigenschaft | Typ | Beschreibung |
|---|
session_id | str | Eindeutige Sitzungskennung |
summary | str | Anzeigetitel: benutzerdefinierter Titel, automatisch generierte Zusammenfassung oder erste Aufforderung |
last_modified | int | Letzte Änderungszeit in Millisekunden seit Epoche |
file_size | int | None | Sitzungsdateigröße in Bytes (None für Remote-Speicher-Backends) |
custom_title | str | None | Vom Benutzer festgelegter Sitzungstitel |
first_prompt | str | None | Erste aussagekräftige Benutzeraufforderung in der Sitzung |
git_branch | str | None | Git-Branch am Ende der Sitzung |
cwd | str | None | Arbeitsverzeichnis für die Sitzung |
tag | str | None | Vom Benutzer festgelegtes Sitzungs-Tag (siehe tag_session()) |
created_at | int | None | Sitzungserstellungszeit 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
| Parameter | Typ | Standard | Beschreibung |
|---|
session_id | str | erforderlich | Die Sitzungs-ID, für die Nachrichten abgerufen werden sollen |
directory | str | None | None | Projektverzeichnis zum Suchen. Wenn weggelassen, werden alle Projekte durchsucht |
limit | int | None | None | Maximale Anzahl der zurückzugebenden Nachrichten |
offset | int | 0 | Anzahl der Nachrichten, die vom Anfang übersprungen werden sollen |
Rückgabetyp: SessionMessage
| Eigenschaft | Typ | Beschreibung |
|---|
type | Literal["user", "assistant"] | Nachrichtenrolle |
uuid | str | Eindeutige Nachrichtenkennung |
session_id | str | Sitzungskennung |
message | Any | Roher Nachrichteninhalt |
parent_tool_use_id | None | Reserviert 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
| Parameter | Typ | Standard | Beschreibung |
|---|
session_id | str | erforderlich | UUID der zu suchenden Sitzung |
directory | str | None | None | Projektverzeichnispath. 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
| Parameter | Typ | Standard | Beschreibung |
|---|
session_id | str | erforderlich | UUID der umzubenennenden Sitzung |
title | str | erforderlich | Neuer Titel. Muss nach dem Entfernen von Leerzeichen nicht leer sein |
directory | str | None | None | Projektverzeichnispath. 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
| Parameter | Typ | Standard | Beschreibung |
|---|
session_id | str | erforderlich | UUID der zu markierenden Sitzung |
tag | str | None | erforderlich | Tag-Zeichenkette oder None zum Löschen. Unicode-bereinigt vor dem Speichern |
directory | str | None | None | Projektverzeichnispath. 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
| Methode | Beschreibung |
|---|
__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.
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
| Eigenschaft | Typ | Beschreibung |
|---|
name | str | Eindeutige Kennung für das Tool |
description | str | Lesbare Beschreibung |
input_schema | type[T] | dict[str, Any] | Schema für Eingabevalidierung |
handler | Callable[[T], Awaitable[dict[str, Any]]] | Asynchrone Funktion, die die Tool-Ausführung handhabt |
annotations | ToolAnnotations | None | Optionale 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: ...
| Methode | Beschreibung |
|---|
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"
| Eigenschaft | Typ | Standard | Beschreibung |
|---|
tools | list[str] | ToolsPreset | None | None | Tools-Konfiguration. Verwenden Sie {"type": "preset", "preset": "claude_code"} für die Standard-Tools von Claude Code |
allowed_tools | list[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_prompt | str | SystemPromptPreset | None | None | System-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_servers | dict[str, McpServerConfig] | str | Path | {} | MCP-Server-Konfigurationen oder Pfad zur Konfigurationsdatei |
strict_mcp_config | bool | False | Wenn 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_mode | PermissionMode | None | None | Berechtigungsmodus für die Tool-Nutzung |
continue_conversation | bool | False | Setzen Sie die neueste Konversation fort |
resume | str | None | None | Sitzungs-ID zum Fortsetzen |
max_turns | int | None | None | Maximale agentengesteuerte Umdrehungen (Tool-Use-Rundgänge) |
max_budget_usd | float | None | None | Stoppen 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_tools | list[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_checkpointing | bool | False | Aktivieren Sie die Dateienänderungsverfolgung zum Zurückspulen. Siehe Datei-Checkpointing |
model | str | None | None | Claude-Modell zum Verwenden |
fallback_model | str | None | None | Fallback-Modell, das verwendet wird, wenn das primäre Modell fehlschlägt |
betas | list[SdkBeta] | [] | Beta-Funktionen zum Aktivieren. Siehe SdkBeta für verfügbare Optionen |
output_format | dict[str, Any] | None | None | Ausgabeformat für strukturierte Antworten (z. B. {"type": "json_schema", "schema": {...}}). Siehe Strukturierte Ausgaben für Details |
permission_prompt_tool_name | str | None | None | MCP-Tool-Name für Berechtigungsaufforderungen |
cwd | str | Path | None | None | Aktuelles Arbeitsverzeichnis |
cli_path | str | Path | None | None | Benutzerdefinierter Pfad zur Claude Code CLI-Ausführungsdatei |
settings | str | None | None | Pfad zur Einstellungsdatei |
add_dirs | list[str | Path] | [] | Zusätzliche Verzeichnisse, auf die Claude zugreifen kann |
env | dict[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_args | dict[str, str | None] | {} | Zusätzliche CLI-Argumente, die direkt an die CLI übergeben werden |
max_buffer_size | int | None | None | Maximale Bytes beim Puffern der CLI-Stdout |
debug_stderr | Any | sys.stderr | Veraltet - Dateiähnliches Objekt für Debug-Ausgabe. Verwenden Sie stattdessen den stderr-Callback |
stderr | Callable[[str], None] | None | None | Callback-Funktion für stderr-Ausgabe von CLI |
can_use_tool | CanUseTool | None | None | Tool-Berechtigungs-Callback-Funktion. Siehe Berechtigungstypen für Details |
hooks | dict[HookEvent, list[HookMatcher]] | None | None | Hook-Konfigurationen zum Abfangen von Ereignissen |
user | str | None | None | Benutzerkennung |
include_partial_messages | bool | False | Schließen Sie partielle Nachrichtenstreaming-Ereignisse ein. Wenn aktiviert, werden StreamEvent-Nachrichten geliefert |
include_hook_events | bool | False | Schließen Sie Hook-Lebenszyklusereignisse im Nachrichtenstrom als HookEventMessage-Objekte ein |
fork_session | bool | False | Wenn Sie mit resume fortsetzen, verzweigen Sie sich zu einer neuen Sitzungs-ID, anstatt die ursprüngliche Sitzung fortzusetzen |
agents | dict[str, AgentDefinition] | None | None | Programmgesteuert definierte Subagenten |
plugins | list[SdkPluginConfig] | [] | Laden Sie benutzerdefinierte Plugins aus lokalen Pfaden. Siehe Plugins für Details |
sandbox | SandboxSettings | None | None | Konfigurieren Sie das Sandbox-Verhalten programmgesteuert. Siehe Sandbox-Einstellungen für Details |
setting_sources | list[SettingSource] | None | None (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 |
skills | list[str] | Literal["all"] | None | None | Skills, 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_tokens | int | None | None | Veraltet - Maximale Token für Thinking-Blöcke. Verwenden Sie stattdessen thinking |
thinking | ThinkingConfig | None | None | Steuert das Verhalten des erweiterten Denkens. Hat Vorrang vor max_thinking_tokens |
effort | EffortLevel | None | None | Anstrengungsstufe für die Denktiefe |
session_store | SessionStore | None | None | Spiegeln Sie Sitzungstranskripte zu einem externen Backend, damit jeder Host sie fortsetzen kann. Siehe Sitzungen im externen Speicher beibehalten |
session_store_flush | Literal["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.
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
}
| Feld | Erforderlich | Beschreibung |
|---|
type | Ja | Muss "json_schema" für JSON-Schema-Validierung sein |
schema | Ja | JSON-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]
| Feld | Erforderlich | Beschreibung |
|---|
type | Ja | Muss "preset" sein, um einen Preset-System-Prompt zu verwenden |
preset | Ja | Muss "claude_code" sein, um den System-Prompt von Claude Code zu verwenden |
append | Nein | Zusätzliche Anweisungen, die an den Preset-System-Prompt angehängt werden |
exclude_dynamic_sections | Nein | Verschieben 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"]
| Wert | Beschreibung | Ort |
|---|
"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):
- Lokale Einstellungen (
.claude/settings.local.json)
- Projekteinstellungen (
.claude/settings.json)
- 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
| Feld | Erforderlich | Beschreibung |
|---|
description | Ja | Natürlichsprachige Beschreibung, wann dieser Agent verwendet werden sollte |
prompt | Ja | Der System-Prompt des Agenten |
tools | Nein | Array von zulässigen Tool-Namen. Wenn weggelassen, erbt alle Tools |
disallowedTools | Nein | Array von Tool-Namen, die aus dem Tool-Set des Agenten entfernt werden |
model | Nein | Modell-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 |
skills | Nein | Liste von Skill-Namen, die diesem Agenten zur Verfügung stehen |
memory | Nein | Memory-Quelle für diesen Agenten: "user", "project" oder "local" |
mcpServers | Nein | MCP-Server, die diesem Agenten zur Verfügung stehen. Jeder Eintrag ist ein Servername oder ein Inline-{name: config}-Dict |
initialPrompt | Nein | Wird automatisch als erste Benutzerdrehung eingereicht, wenn dieser Agent als Haupt-Thread-Agent läuft |
maxTurns | Nein | Maximale Anzahl von Agenten-Umdrehungen, bevor der Agent stoppt |
background | Nein | Führen Sie diesen Agenten als nicht-blockierende Hintergrundaufgabe aus, wenn aufgerufen |
effort | Nein | Reasoning-Anstrengungsstufe für diesen Agenten. Akzeptiert eine benannte Stufe oder eine Ganzzahl. Siehe EffortLevel |
permissionMode | Nein | Berechtigungsmodus 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
]
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
| Feld | Typ | Beschreibung |
|---|
signal | Any | None | Reserviert für zukünftige Abort-Signal-Unterstützung |
suggestions | list[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_path | str | None | Dateipfad, 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_reason | str | None | Grund, warum diese Berechtigungsanfrage ausgelöst wurde. Weitergeleitet von einem PreToolUse-Hook’s permissionDecisionReason, wenn der Hook "ask" zurückgegeben hat |
title | str | None | Vollständiger Berechtigungsaufforderungssatz, wie Claude wants to read foo.txt. Verwenden Sie als primären Aufforderungstext, wenn vorhanden |
display_name | str | None | Kurze Nominalphrase für die Tool-Aktion, wie Read file, geeignet für Schaltflächenbeschriftungen |
description | str | None | Lesbare 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
| Feld | Typ | Standard | Beschreibung |
|---|
behavior | Literal["allow"] | "allow" | Muss “allow” sein |
updated_input | dict[str, Any] | None | None | Geänderte Eingabe, die stattdessen verwendet werden soll |
updated_permissions | list[PermissionUpdate] | None | None | Berechtigungsaktualisierungen 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
| Feld | Typ | Standard | Beschreibung |
|---|
behavior | Literal["deny"] | "deny" | Muss “deny” sein |
message | str | "" | Nachricht, die erklärt, warum das Tool verweigert wurde |
interrupt | bool | False | Ob 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
| Feld | Typ | Beschreibung |
|---|
type | Literal[...] | Der Typ der Berechtigungsaktualisierungsoperation |
rules | list[PermissionRuleValue] | None | Regeln für Add/Replace/Remove-Operationen |
behavior | Literal["allow", "deny", "ask"] | None | Verhalten für regelbasierte Operationen |
mode | PermissionMode | None | Modus für setMode-Operation |
directories | list[str] | None | Verzeichnisse für Add/Remove-Verzeichnis-Operationen |
destination | Literal[...] | None | Wo 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
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
| Variante | Felder | Beschreibung |
|---|
adaptive | type, display | Claude entscheidet adaptiv, wann gedacht werden soll |
enabled | type, budget_tokens, display | Aktivieren Sie das Denken mit einem bestimmten Token-Budget |
disabled | type | Deaktivieren 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]]
| Feld | Typ | Beschreibung |
|---|
name | str | Servername |
status | str | Einer von "connected", "failed", "needs-auth", "pending" oder "disabled" |
serverInfo | dict (optional) | Servername und Version ({"name": str, "version": str}) |
error | str (optional) | Fehlermeldung, wenn der Server keine Verbindung herstellen konnte |
config | McpServerStatusConfig (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 |
scope | str (optional) | Konfigurationsbereich |
tools | list (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
| Feld | Typ | Beschreibung |
|---|
type | Literal["local"] | Muss "local" sein (derzeit werden nur lokale Plugins unterstützt) |
path | str | Absoluter 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
| Feld | Typ | Beschreibung |
|---|
content | str | list[ContentBlock] | Nachrichteninhalt als Text oder Inhaltsblöcke |
uuid | str | None | Eindeutige Nachrichtenkennung |
parent_tool_use_id | str | None | Tool-Use-ID, wenn diese Nachricht eine Tool-Ergebnis-Antwort ist |
tool_use_result | dict[str, Any] | None | Tool-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
| Feld | Typ | Beschreibung |
|---|
content | list[ContentBlock] | Liste von Inhaltsblöcken in der Antwort |
model | str | Modell, das die Antwort generiert hat |
parent_tool_use_id | str | None | Tool-Use-ID, wenn dies eine verschachtelte Antwort ist |
error | AssistantMessageError | None | Fehlertyp, wenn die Antwort auf einen Fehler stieß |
usage | dict[str, Any] | None | Token-Nutzung pro Nachricht (gleiche Schlüssel wie ResultMessage.usage) |
message_id | str | None | API-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üssel | Typ | Beschreibung |
|---|
input_tokens | int | Gesamte verbrauchte Eingabe-Token. |
output_tokens | int | Gesamte generierte Ausgabe-Token. |
cache_creation_input_tokens | int | Token, die zum Erstellen neuer Cache-Einträge verwendet wurden. |
cache_read_input_tokens | int | Token, 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üssel | Typ | Beschreibung |
|---|
inputTokens | int | Eingabe-Token für dieses Modell. |
outputTokens | int | Ausgabe-Token für dieses Modell. |
cacheReadInputTokens | int | Cache-Lese-Token für dieses Modell. |
cacheCreationInputTokens | int | Cache-Erstellungs-Token für dieses Modell. |
webSearchRequests | int | Websuch-Anfragen, die von diesem Modell gestellt wurden. |
costUSD | float | Geschätzte Kosten in USD für dieses Modell, clientseitig berechnet. Siehe Kosten und Nutzung verfolgen für Abrechnungsvorbehalt. |
contextWindow | int | Kontextfenstergröße für dieses Modell. |
maxOutputTokens | int | Maximale 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
| Feld | Typ | Beschreibung |
|---|
uuid | str | Eindeutige Kennung für dieses Ereignis |
session_id | str | Sitzungskennung |
event | dict[str, Any] | Die rohen Claude API-Stream-Ereignisdaten |
parent_tool_use_id | str | 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
| Feld | Typ | Beschreibung |
|---|
rate_limit_info | RateLimitInfo | Aktueller Rate-Limit-Status |
uuid | str | Eindeutige Ereigniskennung |
session_id | str | Sitzungskennung |
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)
| Feld | Typ | Beschreibung |
|---|
status | RateLimitStatus | Aktueller Status. "allowed_warning" bedeutet, dass die Grenze näher rückt; "rejected" bedeutet, dass die Grenze erreicht wurde |
resets_at | int | None | Unix-Zeitstempel, wenn das Rate-Limit-Fenster zurückgesetzt wird |
rate_limit_type | RateLimitType | None | Welches Rate-Limit-Fenster gilt |
utilization | float | None | Anteil des Rate-Limits, das verbraucht wurde (0,0 bis 1,0) |
overage_status | RateLimitStatus | None | Status der Pay-as-you-go-Übernutzung, falls zutreffend |
overage_resets_at | int | None | Unix-Zeitstempel, wenn das Übernutzungs-Fenster zurückgesetzt wird |
overage_disabled_reason | str | None | Warum Übernutzung nicht verfügbar ist, wenn Status "rejected" ist |
raw | dict[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
| Feld | Typ | Beschreibung |
|---|
task_id | str | Eindeutige Kennung für die Aufgabe |
description | str | Beschreibung der Aufgabe |
uuid | str | Eindeutige Nachrichtenkennung |
session_id | str | Sitzungskennung |
tool_use_id | str | None | Zugeordnete Tool-Use-ID |
task_type | str | None | Welche 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
| Feld | Typ | Beschreibung |
|---|
task_id | str | Eindeutige Kennung für die Aufgabe |
description | str | Aktuelle Statusbeschreibung |
usage | TaskUsage | Token-Nutzung für diese Aufgabe bisher |
uuid | str | Eindeutige Nachrichtenkennung |
session_id | str | Sitzungskennung |
tool_use_id | str | None | Zugeordnete Tool-Use-ID |
last_tool_name | str | None | Name 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
| Feld | Typ | Beschreibung |
|---|
task_id | str | Eindeutige Kennung für die Aufgabe |
status | TaskNotificationStatus | Einer von "completed", "failed" oder "stopped" |
output_file | str | Pfad zur Aufgabenausgabedatei |
summary | str | Zusammenfassung des Aufgabenergebnisses |
uuid | str | Eindeutige Nachrichtenkennung |
session_id | str | Sitzungskennung |
tool_use_id | str | None | Zugeordnete Tool-Use-ID |
usage | TaskUsage | None | Endgü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
Tool-Use-Anfrage-Block.
@dataclass
class ToolUseBlock:
id: str
name: str
input: dict[str, Any]
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)
)
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
)
Basis-Felder, die in allen Hook-Eingabetypen vorhanden sind.
class BaseHookInput(TypedDict):
session_id: str
transcript_path: str
cwd: str
permission_mode: NotRequired[str]
| Feld | Typ | Beschreibung |
|---|
session_id | str | Aktuelle Sitzungskennung |
transcript_path | str | Pfad zur Sitzungstranskript-Datei |
cwd | str | Aktuelles Arbeitsverzeichnis |
permission_mode | str (optional) | Aktueller Berechtigungsmodus |
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]
| Feld | Typ | Beschreibung |
|---|
hook_event_name | Literal["PreToolUse"] | Immer “PreToolUse” |
tool_name | str | Name des Tools, das ausgeführt werden soll |
tool_input | dict[str, Any] | Eingabeparameter für das Tool |
tool_use_id | str | Eindeutige Kennung für diese Tool-Nutzung |
agent_id | str (optional) | Subagenten-Kennung, vorhanden, wenn der Hook innerhalb eines Subagenten ausgelöst wird |
agent_type | str (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]
| Feld | Typ | Beschreibung |
|---|
hook_event_name | Literal["PostToolUse"] | Immer “PostToolUse” |
tool_name | str | Name des Tools, das ausgeführt wurde |
tool_input | dict[str, Any] | Eingabeparameter, die verwendet wurden |
tool_response | Any | Antwort aus der Tool-Ausführung |
tool_use_id | str | Eindeutige Kennung für diese Tool-Nutzung |
agent_id | str (optional) | Subagenten-Kennung, vorhanden, wenn der Hook innerhalb eines Subagenten ausgelöst wird |
agent_type | str (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]
| Feld | Typ | Beschreibung |
|---|
hook_event_name | Literal["PostToolUseFailure"] | Immer “PostToolUseFailure” |
tool_name | str | Name des Tools, das fehlgeschlagen ist |
tool_input | dict[str, Any] | Eingabeparameter, die verwendet wurden |
tool_use_id | str | Eindeutige Kennung für diese Tool-Nutzung |
error | str | Fehlermeldung aus der fehlgeschlagenen Ausführung |
is_interrupt | bool (optional) | Ob der Fehler durch eine Unterbrechung verursacht wurde |
agent_id | str (optional) | Subagenten-Kennung, vorhanden, wenn der Hook innerhalb eines Subagenten ausgelöst wird |
agent_type | str (optional) | Subagenten-Typ, vorhanden, wenn der Hook innerhalb eines Subagenten ausgelöst wird |
Eingabedaten für UserPromptSubmit-Hook-Ereignisse.
class UserPromptSubmitHookInput(BaseHookInput):
hook_event_name: Literal["UserPromptSubmit"]
prompt: str
| Feld | Typ | Beschreibung |
|---|
hook_event_name | Literal["UserPromptSubmit"] | Immer “UserPromptSubmit” |
prompt | str | Die vom Benutzer eingereichte Aufforderung |
Eingabedaten für Stop-Hook-Ereignisse.
class StopHookInput(BaseHookInput):
hook_event_name: Literal["Stop"]
stop_hook_active: bool
| Feld | Typ | Beschreibung |
|---|
hook_event_name | Literal["Stop"] | Immer “Stop” |
stop_hook_active | bool | Ob der Stop-Hook aktiv ist |
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
| Feld | Typ | Beschreibung |
|---|
hook_event_name | Literal["SubagentStop"] | Immer “SubagentStop” |
stop_hook_active | bool | Ob der Stop-Hook aktiv ist |
agent_id | str | Eindeutige Kennung für den Subagenten |
agent_transcript_path | str | Pfad zur Transkript-Datei des Subagenten |
agent_type | str | Typ des Subagenten |
Eingabedaten für PreCompact-Hook-Ereignisse.
class PreCompactHookInput(BaseHookInput):
hook_event_name: Literal["PreCompact"]
trigger: Literal["manual", "auto"]
custom_instructions: str | None
| Feld | Typ | Beschreibung |
|---|
hook_event_name | Literal["PreCompact"] | Immer “PreCompact” |
trigger | Literal["manual", "auto"] | Was die Komprimierung ausgelöst hat |
custom_instructions | str | None | Benutzerdefinierte Anweisungen für die Komprimierung |
Eingabedaten für Notification-Hook-Ereignisse.
class NotificationHookInput(BaseHookInput):
hook_event_name: Literal["Notification"]
message: str
title: NotRequired[str]
notification_type: str
| Feld | Typ | Beschreibung |
|---|
hook_event_name | Literal["Notification"] | Immer “Notification” |
message | str | Benachrichtigungsnachrichteninhalt |
title | str (optional) | Benachrichtigungstitel |
notification_type | str | Benachrichtigungstyp |
Eingabedaten für SubagentStart-Hook-Ereignisse.
class SubagentStartHookInput(BaseHookInput):
hook_event_name: Literal["SubagentStart"]
agent_id: str
agent_type: str
| Feld | Typ | Beschreibung |
|---|
hook_event_name | Literal["SubagentStart"] | Immer “SubagentStart” |
agent_id | str | Eindeutige Kennung für den Subagenten |
agent_type | str | Typ des Subagenten |
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]]
| Feld | Typ | Beschreibung |
|---|
hook_event_name | Literal["PermissionRequest"] | Immer “PermissionRequest” |
tool_name | str | Name des Tools, das Berechtigung anfordert |
tool_input | dict[str, Any] | Eingabeparameter für das Tool |
permission_suggestions | list[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)
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())
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
| Eigenschaft | Typ | Standard | Beschreibung |
|---|
enabled | bool | False | Aktivieren Sie den Sandbox-Modus für die Befehlsausführung |
autoAllowBashIfSandboxed | bool | True | Genehmigen Sie Bash-Befehle automatisch, wenn die Sandbox aktiviert ist |
excludedCommands | list[str] | [] | Befehle, die immer Sandbox-Beschränkungen umgehen (z. B. ["docker"]). Diese werden automatisch ohne Modellbeteiligung unsandboxed ausgeführt |
allowUnsandboxedCommands | bool | True | Erlauben 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 |
network | SandboxNetworkConfig | None | Netzwerkspezifische Sandbox-Konfiguration |
ignoreViolations | SandboxIgnoreViolations | None | Konfigurieren Sie, welche Sandbox-Verstöße ignoriert werden sollen |
enableWeakerNestedSandbox | bool | False | Aktivieren 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
| Eigenschaft | Typ | Standard | Beschreibung |
|---|
allowedDomains | list[str] | [] | Domänennamen, auf die Sandbox-Prozesse zugreifen können |
deniedDomains | list[str] | [] | Domänennamen, auf die Sandbox-Prozesse nicht zugreifen können. Hat Vorrang vor allowedDomains |
allowManagedDomainsOnly | bool | False | Nur verwaltete Einstellungen: Wenn in verwalteten Einstellungen gesetzt, ignorieren Sie allowedDomains aus nicht verwalteten Einstellungsquellen. Hat keine Auswirkung, wenn über SDK-Optionen gesetzt |
allowUnixSockets | list[str] | [] | Unix-Socket-Pfade, auf die Prozesse zugreifen können (z. B. Docker-Socket) |
allowAllUnixSockets | bool | False | Erlauben Sie Zugriff auf alle Unix-Sockets |
allowLocalBinding | bool | False | Erlauben Sie Prozessen, sich an lokale Ports zu binden (z. B. für Dev-Server) |
allowMachLookup | list[str] | [] | Nur macOS: XPC/Mach-Servicenamen zum Zulassen. Unterstützt ein nachfolgendes Platzhalterzeichen |
httpProxyPort | int | None | HTTP-Proxy-Port für Netzwerkanfragen |
socksProxyPort | int | None | SOCKS-Proxy-Port für Netzwerkanfragen |
SandboxIgnoreViolations
Konfiguration zum Ignorieren bestimmter Sandbox-Verstöße.
class SandboxIgnoreViolations(TypedDict, total=False):
file: list[str]
network: list[str]
| Eigenschaft | Typ | Standard | Beschreibung |
|---|
file | list[str] | [] | Dateipfad-Muster, für die Verstöße ignoriert werden sollen |
network | list[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