Passer au contenu principal

Installation

pip install claude-agent-sdk

Choisir entre query() et ClaudeSDKClient

Le SDK Python offre deux façons d’interagir avec Claude Code :

Comparaison rapide

Fonctionnalitéquery()ClaudeSDKClient
SessionCrée une nouvelle session par défautRéutilise la même session
ConversationÉchange uniquePlusieurs échanges dans le même contexte
ConnexionGérée automatiquementContrôle manuel
Entrée en streaming✅ Supportée✅ Supportée
Interruptions❌ Non supportées✅ Supportées
Hooks✅ Supportés✅ Supportés
Outils personnalisés✅ Supportés✅ Supportés
Continuer la conversationManuel via continue_conversation ou resume✅ Automatique
Cas d’usageTâches ponctuellesConversations continues

Quand utiliser query() (tâches ponctuelles)

Idéal pour :
  • Les questions ponctuelles où vous n’avez pas besoin d’historique de conversation
  • Les tâches indépendantes qui ne nécessitent pas de contexte des échanges précédents
  • Les scripts d’automatisation simples
  • Quand vous voulez un nouveau départ à chaque fois

Quand utiliser ClaudeSDKClient (conversation continue)

Idéal pour :
  • Continuer les conversations - Quand vous avez besoin que Claude se souvienne du contexte
  • Questions de suivi - S’appuyer sur les réponses précédentes
  • Applications interactives - Interfaces de chat, REPLs
  • Logique basée sur les réponses - Quand l’action suivante dépend de la réponse de Claude
  • Contrôle de session - Gérer explicitement le cycle de vie de la conversation

Fonctions

query()

Crée une nouvelle session pour chaque interaction avec Claude Code par défaut. Retourne un itérateur asynchrone qui produit les messages au fur et à mesure qu’ils arrivent. Chaque appel à query() recommence à zéro sans mémoire des interactions précédentes, sauf si vous passez continue_conversation=True ou resume dans ClaudeAgentOptions. Voir Sessions.
async def query(
    *,
    prompt: str | AsyncIterable[dict[str, Any]],
    options: ClaudeAgentOptions | None = None,
    transport: Transport | None = None
) -> AsyncIterator[Message]

Paramètres

ParamètreTypeDescription
promptstr | AsyncIterable[dict]Le prompt d’entrée sous forme de chaîne ou d’itérable asynchrone pour le mode streaming
optionsClaudeAgentOptions | NoneObjet de configuration optionnel (par défaut ClaudeAgentOptions() si None)
transportTransport | NoneTransport personnalisé optionnel pour communiquer avec le processus CLI

Retours

Retourne un AsyncIterator[Message] qui produit les messages de la conversation.

Exemple - Avec options

import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions


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

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


asyncio.run(main())

tool()

Décorateur pour définir des outils MCP avec sécurité des types.
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]]

Paramètres

ParamètreTypeDescription
namestrIdentifiant unique pour l’outil
descriptionstrDescription lisible de ce que fait l’outil
input_schematype | dict[str, Any]Schéma définissant les paramètres d’entrée de l’outil (voir ci-dessous)
annotationsToolAnnotations | NoneAnnotations MCP optionnelles fournissant des indices comportementaux aux clients

Options de schéma d’entrée

  1. Mappage de type simple (recommandé) :
    {"text": str, "count": int, "enabled": bool}
    
  2. Format JSON Schema (pour la validation complexe) :
    {
        "type": "object",
        "properties": {
            "text": {"type": "string"},
            "count": {"type": "integer", "minimum": 0},
        },
        "required": ["text"],
    }
    

Retours

Une fonction décorateur qui enveloppe l’implémentation de l’outil et retourne une instance SdkMcpTool.

Exemple

from claude_agent_sdk import tool
from typing import Any


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

ToolAnnotations

Réexportée depuis mcp.types (également disponible via from claude_agent_sdk import ToolAnnotations). Tous les champs sont des indices optionnels ; les clients ne doivent pas s’y fier pour les décisions de sécurité.
ChampTypePar défautDescription
titlestr | NoneNoneTitre lisible pour l’outil
readOnlyHintbool | NoneFalseSi True, l’outil ne modifie pas son environnement
destructiveHintbool | NoneTrueSi True, l’outil peut effectuer des mises à jour destructrices (uniquement significatif quand readOnlyHint est False)
idempotentHintbool | NoneFalseSi True, les appels répétés avec les mêmes arguments n’ont pas d’effet supplémentaire (uniquement significatif quand readOnlyHint est False)
openWorldHintbool | NoneTrueSi True, l’outil interagit avec des entités externes (par exemple, recherche web). Si False, le domaine de l’outil est fermé (par exemple, un outil de mémoire)
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()

Crée un serveur MCP en processus qui s’exécute dans votre application Python.
def create_sdk_mcp_server(
    name: str,
    version: str = "1.0.0",
    tools: list[SdkMcpTool[Any]] | None = None
) -> McpSdkServerConfig

Paramètres

ParamètreTypePar défautDescription
namestr-Identifiant unique pour le serveur
versionstr"1.0.0"Chaîne de version du serveur
toolslist[SdkMcpTool[Any]] | NoneNoneListe des fonctions d’outil créées avec le décorateur @tool

Retours

Retourne un objet McpSdkServerConfig qui peut être passé à ClaudeAgentOptions.mcp_servers.

Exemple

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

Liste les sessions passées avec métadonnées. Filtrez par répertoire de projet ou listez les sessions dans tous les projets. Synchrone ; retourne immédiatement.
def list_sessions(
    directory: str | None = None,
    limit: int | None = None,
    include_worktrees: bool = True
) -> list[SDKSessionInfo]

Paramètres

ParamètreTypePar défautDescription
directorystr | NoneNoneRépertoire pour lequel lister les sessions. Quand omis, retourne les sessions dans tous les projets
limitint | NoneNoneNombre maximum de sessions à retourner
include_worktreesboolTrueQuand directory est à l’intérieur d’un dépôt git, inclure les sessions de tous les chemins worktree

Type de retour : SDKSessionInfo

PropriétéTypeDescription
session_idstrIdentifiant de session unique
summarystrTitre d’affichage : titre personnalisé, résumé généré automatiquement, ou premier prompt
last_modifiedintHeure de dernière modification en millisecondes depuis l’époque
file_sizeint | NoneTaille du fichier de session en octets (None pour les backends de stockage distant)
custom_titlestr | NoneTitre de session défini par l’utilisateur
first_promptstr | NonePremier prompt utilisateur significatif dans la session
git_branchstr | NoneBranche git à la fin de la session
cwdstr | NoneRépertoire de travail pour la session
tagstr | NoneÉtiquette de session définie par l’utilisateur (voir tag_session())
created_atint | NoneHeure de création de la session en millisecondes depuis l’époque

Exemple

Affiche les 10 sessions les plus récentes pour un projet. Les résultats sont triés par last_modified décroissant, donc le premier élément est le plus récent. Omettez directory pour rechercher dans tous les projets.
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()

Récupère les messages d’une session passée. Synchrone ; retourne immédiatement.
def get_session_messages(
    session_id: str,
    directory: str | None = None,
    limit: int | None = None,
    offset: int = 0
) -> list[SessionMessage]

Paramètres

ParamètreTypePar défautDescription
session_idstrrequisL’ID de session pour lequel récupérer les messages
directorystr | NoneNoneRépertoire de projet à regarder. Quand omis, recherche dans tous les projets
limitint | NoneNoneNombre maximum de messages à retourner
offsetint0Nombre de messages à ignorer depuis le début

Type de retour : SessionMessage

PropriétéTypeDescription
typeLiteral["user", "assistant"]Rôle du message
uuidstrIdentifiant de message unique
session_idstrIdentifiant de session
messageAnyContenu du message brut
parent_tool_use_idNoneRéservé pour un usage futur

Exemple

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

Lit les métadonnées d’une seule session par ID sans scanner le répertoire de projet complet. Synchrone ; retourne immédiatement.
def get_session_info(
    session_id: str,
    directory: str | None = None,
) -> SDKSessionInfo | None

Paramètres

ParamètreTypePar défautDescription
session_idstrrequisUUID de la session à rechercher
directorystr | NoneNoneChemin du répertoire de projet. Quand omis, recherche dans tous les répertoires de projet
Retourne SDKSessionInfo, ou None si la session n’est pas trouvée.

Exemple

Recherchez les métadonnées d’une seule session sans scanner le répertoire de projet. Utile quand vous avez déjà un ID de session d’une exécution précédente.
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()

Renomme une session en ajoutant une entrée de titre personnalisé. Les appels répétés sont sûrs ; le titre le plus récent gagne. Synchrone.
def rename_session(
    session_id: str,
    title: str,
    directory: str | None = None,
) -> None

Paramètres

ParamètreTypePar défautDescription
session_idstrrequisUUID de la session à renommer
titlestrrequisNouveau titre. Doit être non-vide après suppression des espaces
directorystr | NoneNoneChemin du répertoire de projet. Quand omis, recherche dans tous les répertoires de projet
Lève ValueError si session_id n’est pas un UUID valide ou si title est vide ; FileNotFoundError si la session ne peut pas être trouvée.

Exemple

Renommez la session la plus récente pour qu’elle soit plus facile à trouver plus tard. Le nouveau titre apparaît dans SDKSessionInfo.custom_title lors des lectures ultérieures.
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()

Étiquette une session. Passez None pour effacer l’étiquette. Les appels répétés sont sûrs ; l’étiquette la plus récente gagne. Synchrone.
def tag_session(
    session_id: str,
    tag: str | None,
    directory: str | None = None,
) -> None

Paramètres

ParamètreTypePar défautDescription
session_idstrrequisUUID de la session à étiqueter
tagstr | NonerequisChaîne d’étiquette, ou None pour effacer. Nettoyée Unicode avant stockage
directorystr | NoneNoneChemin du répertoire de projet. Quand omis, recherche dans tous les répertoires de projet
Lève ValueError si session_id n’est pas un UUID valide ou si tag est vide après nettoyage ; FileNotFoundError si la session ne peut pas être trouvée.

Exemple

Étiquetez une session, puis filtrez par cette étiquette lors d’une lecture ultérieure. Passez None pour effacer une étiquette existante.
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)

Classes

ClaudeSDKClient

Maintient une session de conversation sur plusieurs échanges. C’est l’équivalent Python de la façon dont la fonction query() du SDK TypeScript fonctionne en interne - elle crée un objet client qui peut continuer les conversations.

Fonctionnalités clés

  • Continuité de session : Maintient le contexte de conversation sur plusieurs appels query()
  • Même conversation : La session conserve les messages précédents
  • Support des interruptions : Peut arrêter l’exécution en cours de tâche
  • Cycle de vie explicite : Vous contrôlez quand la session commence et se termine
  • Flux basé sur les réponses : Peut réagir aux réponses et envoyer des suivis
  • Outils personnalisés et hooks : Supporte les outils personnalisés (créés avec le décorateur @tool) et les 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

Méthodes

MéthodeDescription
__init__(options)Initialise le client avec une configuration optionnelle
connect(prompt)Se connecte à Claude avec un prompt initial optionnel ou un flux de messages
query(prompt, session_id)Envoie une nouvelle requête en mode streaming
receive_messages()Reçoit tous les messages de Claude comme un itérateur asynchrone
receive_response()Reçoit les messages jusqu’à et incluant un ResultMessage
interrupt()Envoie un signal d’interruption (fonctionne uniquement en mode streaming)
set_permission_mode(mode)Change le mode de permission pour la session actuelle
set_model(model)Change le modèle pour la session actuelle. Passez None pour réinitialiser à la valeur par défaut
rewind_files(user_message_id)Restaure les fichiers à leur état au message utilisateur spécifié. Nécessite enable_file_checkpointing=True. Voir File checkpointing
get_mcp_status()Obtient le statut de tous les serveurs MCP configurés. Retourne McpStatusResponse
reconnect_mcp_server(server_name)Réessaye de se connecter à un serveur MCP qui a échoué ou a été déconnecté
toggle_mcp_server(server_name, enabled)Active ou désactive un serveur MCP en cours de session. La désactivation supprime ses outils
stop_task(task_id)Arrête une tâche de fond en cours d’exécution. Un TaskNotificationMessage avec le statut "stopped" suit dans le flux de messages
get_server_info()Obtient les informations du serveur incluant l’ID de session et les capacités
disconnect()Se déconnecte de Claude

Support du gestionnaire de contexte

Le client peut être utilisé comme un gestionnaire de contexte asynchrone pour la gestion automatique de la connexion :
async with ClaudeSDKClient() as client:
    await client.query("Hello Claude")
    async for message in client.receive_response():
        print(message)
Important : Lors de l’itération sur les messages, évitez d’utiliser break pour quitter tôt car cela peut causer des problèmes de nettoyage asyncio. À la place, laissez l’itération se terminer naturellement ou utilisez des drapeaux pour suivre quand vous avez trouvé ce que vous cherchiez.

Exemple - Continuer une conversation

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

Exemple - Entrée en streaming avec 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())

Exemple - Utiliser les interruptions

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())
Comportement du buffer après interruption : interrupt() envoie un signal d’arrêt mais ne vide pas le buffer de messages. Les messages déjà produits par la tâche interrompue, incluant son ResultMessage (avec subtype="error_during_execution"), restent dans le flux. Vous devez les vider avec receive_response() avant de lire la réponse à une nouvelle requête. Si vous envoyez une nouvelle requête immédiatement après interrupt() et appelez receive_response() une seule fois, vous recevrez les messages de la tâche interrompue, pas la réponse de la nouvelle requête.

Exemple - Contrôle avancé des permissions

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

Types

@dataclass vs TypedDict : Ce SDK utilise deux types de types. Les classes décorées avec @dataclass (telles que ResultMessage, AgentDefinition, TextBlock) sont des instances d’objet à l’exécution et supportent l’accès par attribut : msg.result. Les classes définies avec TypedDict (telles que ThinkingConfigEnabled, McpStdioServerConfig, SyncHookJSONOutput) sont des dicts simples à l’exécution et nécessitent l’accès par clé : config["budget_tokens"], pas config.budget_tokens. La syntaxe d’appel ClassName(field=value) fonctionne pour les deux, mais seules les dataclasses produisent des objets avec des attributs.

SdkMcpTool

Définition pour un outil MCP SDK créé avec le décorateur @tool.
@dataclass
class SdkMcpTool(Generic[T]):
    name: str
    description: str
    input_schema: type[T] | dict[str, Any]
    handler: Callable[[T], Awaitable[dict[str, Any]]]
    annotations: ToolAnnotations | None = None
PropriétéTypeDescription
namestrIdentifiant unique pour l’outil
descriptionstrDescription lisible
input_schematype[T] | dict[str, Any]Schéma pour la validation d’entrée
handlerCallable[[T], Awaitable[dict[str, Any]]]Fonction asynchrone qui gère l’exécution de l’outil
annotationsToolAnnotations | NoneAnnotations MCP optionnelles (par exemple, readOnlyHint, destructiveHint, openWorldHint). De mcp.types

Transport

Classe de base abstraite pour les implémentations de transport personnalisées. Utilisez ceci pour communiquer avec le processus Claude sur un canal personnalisé (par exemple, une connexion distante au lieu d’un sous-processus local).
C’est une API interne de bas niveau. L’interface peut changer dans les versions futures. Les implémentations personnalisées doivent être mises à jour pour correspondre à tout changement d’interface.
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: ...
MéthodeDescription
connect()Connecte le transport et prépare la communication
write(data)Écrit les données brutes (JSON + nouvelle ligne) dans le transport
read_messages()Itérateur asynchrone qui produit les messages JSON analysés
close()Ferme la connexion et nettoie les ressources
is_ready()Retourne True si le transport peut envoyer et recevoir
end_input()Ferme le flux d’entrée (par exemple, fermer stdin pour les transports de sous-processus)
Importation : from claude_agent_sdk import Transport

ClaudeAgentOptions

Dataclass de configuration pour les requêtes Claude Code.
@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"
PropriétéTypePar défautDescription
toolslist[str] | ToolsPreset | NoneNoneConfiguration des outils. Utilisez {"type": "preset", "preset": "claude_code"} pour les outils par défaut de Claude Code
allowed_toolslist[str][]Outils à approuver automatiquement sans demander. Ceci ne restreint pas Claude à seulement ces outils ; les outils non listés passent par permission_mode et can_use_tool. Utilisez disallowed_tools pour bloquer les outils. Voir Permissions
system_promptstr | SystemPromptPreset | NoneNoneConfiguration du prompt système. Passez une chaîne pour un prompt personnalisé, ou utilisez {"type": "preset", "preset": "claude_code"} pour le prompt système de Claude Code. Ajoutez "append" pour étendre le preset
mcp_serversdict[str, McpServerConfig] | str | Path{}Configurations de serveur MCP ou chemin vers le fichier de configuration
strict_mcp_configboolFalseQuand True, utilisez uniquement les serveurs passés dans mcp_servers et ignorez le projet .mcp.json, les paramètres utilisateur, les serveurs MCP fournis par les plugins, et les connecteurs claude.ai. Correspond à l’indicateur CLI --strict-mcp-config
permission_modePermissionMode | NoneNoneMode de permission pour l’utilisation des outils
continue_conversationboolFalseContinuer la conversation la plus récente
resumestr | NoneNoneID de session à reprendre
max_turnsint | NoneNoneNombre maximum de tours agentiques (allers-retours d’utilisation d’outils)
max_budget_usdfloat | NoneNoneArrêtez la requête quand l’estimation du coût côté client atteint cette valeur USD. Comparé à la même estimation que total_cost_usd ; voir Suivi du coût et de l’utilisation pour les avertissements de précision
disallowed_toolslist[str][]Outils à refuser. Un nom simple tel que "Bash" supprime l’outil du contexte de Claude. Une règle délimitée telle que "Bash(rm *)" laisse l’outil disponible et refuse les appels correspondants dans chaque mode de permission, y compris bypassPermissions. Voir Permissions
enable_file_checkpointingboolFalseActivez le suivi des modifications de fichiers pour le rembobinage. Voir Sauvegarde de points de contrôle de fichiers
modelstr | NoneNoneModèle Claude à utiliser
fallback_modelstr | NoneNoneModèle de secours à utiliser si le modèle principal échoue
betaslist[SdkBeta][]Fonctionnalités bêta à activer. Voir SdkBeta pour les options disponibles
output_formatdict[str, Any] | NoneNoneFormat de sortie pour les réponses structurées (par exemple, {"type": "json_schema", "schema": {...}}). Voir Sorties structurées pour les détails
permission_prompt_tool_namestr | NoneNoneNom de l’outil MCP pour les prompts de permission
cwdstr | Path | NoneNoneRépertoire de travail actuel
cli_pathstr | Path | NoneNoneChemin personnalisé vers l’exécutable CLI de Claude Code
settingsstr | NoneNoneChemin vers le fichier de paramètres
add_dirslist[str | Path][]Répertoires supplémentaires auxquels Claude peut accéder
envdict[str, str]{}Variables d’environnement fusionnées au-dessus de l’environnement de processus hérité. Voir Variables d’environnement pour les variables que le CLI sous-jacent lit, et Gérer les réponses API lentes ou bloquées pour les variables liées aux délais d’expiration
extra_argsdict[str, str | None]{}Arguments CLI supplémentaires à passer directement au CLI
max_buffer_sizeint | NoneNoneOctets maximum lors de la mise en buffer de la sortie standard du CLI
debug_stderrAnysys.stderrDéprécié - Objet de type fichier pour la sortie de débogage. Utilisez plutôt le callback stderr
stderrCallable[[str], None] | NoneNoneFonction de callback pour la sortie stderr du CLI
can_use_toolCanUseTool | NoneNoneFonction de callback de permission d’outil. Voir Types de permission pour les détails
hooksdict[HookEvent, list[HookMatcher]] | NoneNoneConfigurations de hook pour intercepter les événements
userstr | NoneNoneIdentifiant utilisateur
include_partial_messagesboolFalseInclure les événements de streaming de messages partiels. Quand activé, les messages StreamEvent sont produits
include_hook_eventsboolFalseInclure les événements du cycle de vie des hooks dans le flux de messages en tant qu’objets HookEventMessage
fork_sessionboolFalseQuand reprendre avec resume, bifurquer vers un nouvel ID de session au lieu de continuer la session originale
agentsdict[str, AgentDefinition] | NoneNoneSous-agents définis programmatiquement
pluginslist[SdkPluginConfig][]Charger les plugins personnalisés à partir de chemins locaux. Voir Plugins pour les détails
sandboxSandboxSettings | NoneNoneConfigurez le comportement du sandbox programmatiquement. Voir Paramètres du sandbox pour les détails
setting_sourceslist[SettingSource] | NoneNone (CLI defaults: all sources)Contrôlez quels paramètres du système de fichiers charger. Passez [] pour désactiver les paramètres utilisateur, projet et locaux. Les paramètres de politique gérée se chargent indépendamment. Voir Utiliser les fonctionnalités de Claude Code
skillslist[str] | Literal["all"] | NoneNoneCompétences disponibles pour la session. Passez "all" pour activer chaque compétence découverte, ou une liste de noms de compétences. Quand défini, le SDK active l’outil Skill automatiquement sans le lister dans allowed_tools. Voir Compétences
max_thinking_tokensint | NoneNoneDéprécié - Tokens maximum pour les blocs de réflexion. Utilisez thinking à la place
thinkingThinkingConfig | NoneNoneContrôle le comportement de la réflexion étendue. Prend la priorité sur max_thinking_tokens
effortEffortLevel | NoneNoneNiveau d’effort pour la profondeur de réflexion
session_storeSessionStore | NoneNoneMiroir les transcriptions de session vers un backend externe pour que n’importe quel hôte puisse les reprendre. Voir Persister les sessions vers un stockage externe
session_store_flushLiteral["batched", "eager"]"batched"Quand vider les entrées de transcription en miroir vers session_store. "batched" vide une fois par tour ou quand le buffer se remplit ; "eager" déclenche un vidage en arrière-plan après chaque frame. Ignoré quand session_store est None

Gérer les réponses API lentes ou bloquées

Le sous-processus CLI lit plusieurs variables d’environnement qui contrôlent les délais d’expiration de l’API et la détection de blocage. Passez-les via ClaudeAgentOptions.env :
options = ClaudeAgentOptions(
    env={
        "API_TIMEOUT_MS": "120000",
        "CLAUDE_CODE_MAX_RETRIES": "2",
        "CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS": "120000",
    },
)
  • API_TIMEOUT_MS : délai d’expiration par requête sur le client Anthropic, en millisecondes. Par défaut 600000. S’applique à la boucle principale et à tous les sous-agents.
  • CLAUDE_CODE_MAX_RETRIES : nombre maximum de tentatives API. Par défaut 10. Chaque tentative obtient sa propre fenêtre API_TIMEOUT_MS, donc le pire temps mural est approximativement API_TIMEOUT_MS × (CLAUDE_CODE_MAX_RETRIES + 1) plus le backoff.
  • CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS : chien de garde de blocage pour les sous-agents lancés avec run_in_background. Par défaut 600000. Réinitialise à chaque événement de flux ; en cas de blocage, il abandonne le sous-agent, marque la tâche comme échouée et expose l’erreur au parent avec tout résultat partiel. Ne s’applique pas aux sous-agents synchrones.
  • CLAUDE_ENABLE_STREAM_WATCHDOG=1 avec CLAUDE_STREAM_IDLE_TIMEOUT_MS : abandonne la requête quand les en-têtes sont arrivés mais le corps de la réponse cesse de faire du streaming. Désactivé par défaut. CLAUDE_STREAM_IDLE_TIMEOUT_MS par défaut à 300000 et est limité à ce minimum. La requête abandonnée passe par le chemin de tentative normal.

OutputFormat

Configuration pour la validation de sortie structurée. Passez ceci comme un dict au champ output_format sur ClaudeAgentOptions :
# Expected dict shape for output_format
{
    "type": "json_schema",
    "schema": {...},  # Your JSON Schema definition
}
ChampRequisDescription
typeOuiDoit être "json_schema" pour la validation JSON Schema
schemaOuiDéfinition JSON Schema pour la validation de sortie

SystemPromptPreset

Configuration pour utiliser le preset de prompt système de Claude Code avec des ajouts optionnels.
class SystemPromptPreset(TypedDict):
    type: Literal["preset"]
    preset: Literal["claude_code"]
    append: NotRequired[str]
    exclude_dynamic_sections: NotRequired[bool]
ChampRequisDescription
typeOuiDoit être "preset" pour utiliser un preset de prompt système
presetOuiDoit être "claude_code" pour utiliser le prompt système de Claude Code
appendNonInstructions supplémentaires à ajouter au preset de prompt système
exclude_dynamic_sectionsNonDéplacez le contexte par session comme le répertoire de travail, le statut git et les chemins de mémoire du prompt système vers le premier message utilisateur. Améliore la réutilisation du cache de prompt entre les utilisateurs et les machines. Voir Modifier les prompts système

SettingSource

Contrôle quelles sources de configuration basées sur le système de fichiers le SDK charge les paramètres à partir de.
SettingSource = Literal["user", "project", "local"]
ValeurDescriptionEmplacement
"user"Paramètres utilisateur globaux~/.claude/settings.json
"project"Paramètres de projet partagés (contrôle de version).claude/settings.json
"local"Paramètres de projet locaux (gitignored).claude/settings.local.json

Comportement par défaut

Quand setting_sources est omis ou None, query() charge les mêmes paramètres du système de fichiers que le CLI Claude Code : utilisateur, projet et local. Les paramètres de politique gérée sont chargés dans tous les cas. Voir Ce que settingSources ne contrôle pas pour les entrées qui sont lues indépendamment de cette option, et comment les désactiver.

Pourquoi utiliser setting_sources

Désactiver les paramètres du système de fichiers :
# 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)
Dans le SDK Python 0.1.59 et antérieur, une liste vide était traitée de la même manière que l’omission de l’option, donc setting_sources=[] n’a pas désactivé les paramètres du système de fichiers. Mettez à niveau vers une version plus récente si vous avez besoin qu’une liste vide prenne effet. Le SDK TypeScript n’est pas affecté.
Charger tous les paramètres du système de fichiers explicitement :
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)
Charger uniquement des sources de paramètres spécifiques :
# 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)
Environnements de test et CI :
# 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)
Applications SDK uniquement :
# 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)
Chargement des instructions de projet CLAUDE.md :
# 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)

Précédence des paramètres

Quand plusieurs sources sont chargées, les paramètres sont fusionnés avec cette précédence (la plus haute à la plus basse) :
  1. Paramètres locaux (.claude/settings.local.json)
  2. Paramètres de projet (.claude/settings.json)
  3. Paramètres utilisateur (~/.claude/settings.json)
Les options programmatiques telles que agents et allowed_tools remplacent les paramètres du système de fichiers utilisateur, projet et local. Les paramètres de politique gérée prennent la priorité sur les options programmatiques.

AgentDefinition

Configuration pour un sous-agent défini programmatiquement.
@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
ChampRequisDescription
descriptionOuiDescription en langage naturel de quand utiliser cet agent
promptOuiLe prompt système de l’agent
toolsNonTableau des noms d’outils autorisés. Si omis, hérite de tous les outils
disallowedToolsNonTableau des noms d’outils à supprimer de l’ensemble d’outils de l’agent
modelNonRemplacement de modèle pour cet agent. Accepte un alias tel que "sonnet", "opus", "haiku", ou "inherit", ou un ID de modèle complet. Si omis, utilise le modèle principal
skillsNonListe des noms de compétences à précharger dans le contexte de l’agent au démarrage. Les compétences non listées restent invocables via l’outil Skill
memoryNonSource de mémoire pour cet agent : "user", "project", ou "local"
mcpServersNonServeurs MCP disponibles pour cet agent. Chaque entrée est un nom de serveur ou un dict {name: config} en ligne
initialPromptNonAuto-soumis comme le premier tour utilisateur quand cet agent s’exécute comme l’agent du fil principal
maxTurnsNonNombre maximum de tours agentiques avant que l’agent s’arrête
backgroundNonExécutez cet agent comme une tâche de fond non-bloquante quand invoqué
effortNonNiveau d’effort de raisonnement pour cet agent. Accepte un niveau nommé ou un entier. Voir EffortLevel
permissionModeNonMode de permission pour l’exécution des outils dans cet agent. Voir PermissionMode
Les noms de champs AgentDefinition utilisent camelCase, tels que disallowedTools, permissionMode, et maxTurns. Ces noms correspondent directement au format de fil partagé avec le SDK TypeScript. Ceci diffère de ClaudeAgentOptions, qui utilise Python snake_case pour les champs de niveau supérieur équivalents tels que disallowed_tools et permission_mode. Parce que AgentDefinition est une dataclass, passer un mot-clé snake_case lève une TypeError au moment de la construction.

PermissionMode

Modes de permission pour contrôler l’exécution des outils.
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

Niveaux d’effort pour guider la profondeur de réflexion.
EffortLevel = Literal[
    "low",  # Minimal thinking, fastest responses
    "medium",  # Moderate thinking
    "high",  # Deep reasoning
    "xhigh",  # Extended reasoning (Opus 4.7 only; falls back to "high" on other models)
    "max",  # Maximum effort
]

CanUseTool

Alias de type pour les fonctions de callback de permission d’outil.
CanUseTool = Callable[
    [str, dict[str, Any], ToolPermissionContext], Awaitable[PermissionResult]
]
Le callback reçoit :
  • tool_name : Nom de l’outil en cours d’appel
  • input_data : Les paramètres d’entrée de l’outil
  • context : Un ToolPermissionContext avec des informations supplémentaires
Retourne un PermissionResult (soit PermissionResultAllow soit PermissionResultDeny).

ToolPermissionContext

Informations de contexte passées aux callbacks de permission d’outil.
@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
ChampTypeDescription
signalAny | NoneRéservé pour le support futur du signal d’abandon
suggestionslist[PermissionUpdate]Suggestions de mise à jour de permission du CLI. Les prompts Bash incluent une suggestion avec la destination localSettings, donc la retourner dans updated_permissions écrit la règle dans .claude/settings.local.json et persiste entre les sessions.
blocked_pathstr | NoneChemin de fichier qui a déclenché la demande de permission, le cas échéant. Par exemple, quand une commande Bash essaie d’accéder à un chemin en dehors des répertoires autorisés
decision_reasonstr | NoneRaison pour laquelle cette demande de permission a été déclenchée. Transférée depuis le permissionDecisionReason d’un hook PreToolUse quand le hook a retourné "ask"
titlestr | NonePhrase complète du prompt de permission, telle que Claude wants to read foo.txt. Utilisez comme texte du prompt principal quand présent
display_namestr | NonePhrase nominale courte pour l’action de l’outil, telle que Read file, appropriée pour les étiquettes de bouton
descriptionstr | NoneSous-titre lisible pour l’interface utilisateur de permission

PermissionResult

Type union pour les résultats de callback de permission.
PermissionResult = PermissionResultAllow | PermissionResultDeny

PermissionResultAllow

Résultat indiquant que l’appel d’outil doit être autorisé.
@dataclass
class PermissionResultAllow:
    behavior: Literal["allow"] = "allow"
    updated_input: dict[str, Any] | None = None
    updated_permissions: list[PermissionUpdate] | None = None
ChampTypePar défautDescription
behaviorLiteral["allow"]"allow"Doit être « allow »
updated_inputdict[str, Any] | NoneNoneEntrée modifiée à utiliser à la place de l’original
updated_permissionslist[PermissionUpdate] | NoneNoneMises à jour de permission à appliquer

PermissionResultDeny

Résultat indiquant que l’appel d’outil doit être refusé.
@dataclass
class PermissionResultDeny:
    behavior: Literal["deny"] = "deny"
    message: str = ""
    interrupt: bool = False
ChampTypePar défautDescription
behaviorLiteral["deny"]"deny"Doit être « deny »
messagestr""Message expliquant pourquoi l’outil a été refusé
interruptboolFalseS’il faut interrompre l’exécution actuelle

PermissionUpdate

Configuration pour mettre à jour les permissions programmatiquement.
@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
ChampTypeDescription
typeLiteral[...]Le type d’opération de mise à jour de permission
ruleslist[PermissionRuleValue] | NoneRègles pour les opérations d’ajout/remplacement/suppression
behaviorLiteral["allow", "deny", "ask"] | NoneComportement pour les opérations basées sur les règles
modePermissionMode | NoneMode pour l’opération setMode
directorieslist[str] | NoneRépertoires pour les opérations d’ajout/suppression de répertoire
destinationLiteral[...] | NoneOù appliquer la mise à jour de permission

PermissionRuleValue

Une règle à ajouter, remplacer ou supprimer dans une mise à jour de permission.
@dataclass
class PermissionRuleValue:
    tool_name: str
    rule_content: str | None = None

ToolsPreset

Configuration des outils preset pour utiliser l’ensemble d’outils par défaut de Claude Code.
class ToolsPreset(TypedDict):
    type: Literal["preset"]
    preset: Literal["claude_code"]

ThinkingConfig

Contrôle le comportement de la réflexion étendue. Une union de trois configurations :
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
VarianteChampsDescription
adaptivetype, displayClaude décide de manière adaptative quand réfléchir
enabledtype, budget_tokens, displayActivez la réflexion avec un budget de tokens spécifique
disabledtypeDésactivez la réflexion
Le champ optionnel display contrôle si le texte de réflexion est retourné "summarized" ou "omitted". Sur Claude Opus 4.7 et ultérieur, la valeur par défaut de l’API est "omitted", donc définissez "summarized" pour recevoir le contenu de réflexion dans les sorties ThinkingBlock. Parce que ce sont des classes TypedDict, ce sont des dicts simples à l’exécution. Construisez-les soit comme des littéraux dict soit appelez la classe comme un constructeur ; les deux produisent un dict. Accédez aux champs avec config["budget_tokens"], pas 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

Type littéral pour les fonctionnalités bêta du SDK.
SdkBeta = Literal["context-1m-2025-08-07"]
Utilisez avec le champ betas dans ClaudeAgentOptions pour activer les fonctionnalités bêta.
La bêta context-1m-2025-08-07 est retirée à partir du 30 avril 2026. Passer cet en-tête avec Claude Sonnet 4.5 ou Sonnet 4 n’a aucun effet, et les requêtes qui dépassent la fenêtre de contexte standard de 200k tokens retournent une erreur. Pour utiliser une fenêtre de contexte de 1M tokens, migrez vers Claude Sonnet 4.6, Claude Opus 4.6, ou Claude Opus 4.7, qui incluent 1M de contexte à prix standard sans en-tête bêta requis.

McpSdkServerConfig

Configuration pour les serveurs MCP SDK créés avec create_sdk_mcp_server().
class McpSdkServerConfig(TypedDict):
    type: Literal["sdk"]
    name: str
    instance: Any  # MCP Server instance

McpServerConfig

Type union pour les configurations de serveur MCP.
McpServerConfig = (
    McpStdioServerConfig | McpSSEServerConfig | McpHttpServerConfig | McpSdkServerConfig
)

McpStdioServerConfig

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

McpSSEServerConfig

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

McpHttpServerConfig

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

McpServerStatusConfig

La configuration d’un serveur MCP telle que rapportée par get_mcp_status(). C’est l’union de toutes les variantes de transport McpServerConfig plus une variante de sortie uniquement claudeai-proxy pour les serveurs proxifiés via claude.ai.
McpServerStatusConfig = (
    McpStdioServerConfig
    | McpSSEServerConfig
    | McpHttpServerConfig
    | McpSdkServerConfigStatus
    | McpClaudeAIProxyServerConfig
)
McpSdkServerConfigStatus est la forme sérialisable de McpSdkServerConfig avec seulement les champs type ("sdk") et name (str) ; l’instance en processus est omise. McpClaudeAIProxyServerConfig a les champs type ("claudeai-proxy"), url (str), et id (str).

McpStatusResponse

Réponse de ClaudeSDKClient.get_mcp_status(). Enveloppe la liste des statuts de serveur sous la clé mcpServers.
class McpStatusResponse(TypedDict):
    mcpServers: list[McpServerStatus]

McpServerStatus

Statut d’un serveur MCP connecté, contenu dans 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]]
ChampTypeDescription
namestrNom du serveur
statusstrL’un de "connected", "failed", "needs-auth", "pending", ou "disabled"
serverInfodict (optionnel)Nom et version du serveur ({"name": str, "version": str})
errorstr (optionnel)Message d’erreur si le serveur n’a pas pu se connecter
configMcpServerStatusConfig (optionnel)Configuration du serveur. Même forme que McpServerConfig (stdio, SSE, HTTP, ou SDK), plus une variante claudeai-proxy pour les serveurs connectés via claude.ai
scopestr (optionnel)Portée de la configuration
toolslist (optionnel)Outils fournis par ce serveur, chacun avec les champs name, description, et annotations

SdkPluginConfig

Configuration pour charger les plugins dans le SDK.
class SdkPluginConfig(TypedDict):
    type: Literal["local"]
    path: str
ChampTypeDescription
typeLiteral["local"]Doit être "local" (seuls les plugins locaux sont actuellement supportés)
pathstrChemin absolu ou relatif vers le répertoire du plugin
Exemple :
plugins = [
    {"type": "local", "path": "./my-plugin"},
    {"type": "local", "path": "/absolute/path/to/plugin"},
]
Pour des informations complètes sur la création et l’utilisation de plugins, voir Plugins.

Types de messages

Message

Type union de tous les messages possibles.
Message = (
    UserMessage
    | AssistantMessage
    | SystemMessage
    | ResultMessage
    | StreamEvent
    | RateLimitEvent
)

UserMessage

Message d’entrée utilisateur.
@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
ChampTypeDescription
contentstr | list[ContentBlock]Contenu du message sous forme de texte ou de blocs de contenu
uuidstr | NoneIdentifiant de message unique
parent_tool_use_idstr | NoneID d’utilisation d’outil si ce message est une réponse de résultat d’outil
tool_use_resultdict[str, Any] | NoneDonnées de résultat d’outil si applicable

AssistantMessage

Message de réponse d’assistant avec blocs de contenu.
@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
ChampTypeDescription
contentlist[ContentBlock]Liste des blocs de contenu dans la réponse
modelstrModèle qui a généré la réponse
parent_tool_use_idstr | NoneID d’utilisation d’outil si c’est une réponse imbriquée
errorAssistantMessageError | NoneType d’erreur si la réponse a rencontré une erreur
usagedict[str, Any] | NoneUtilisation de tokens par message (mêmes clés que ResultMessage.usage)
message_idstr | NoneID de message API. Plusieurs messages d’un tour partagent le même ID

AssistantMessageError

Types d’erreur possibles pour les messages d’assistant.
AssistantMessageError = Literal[
    "authentication_failed",
    "billing_error",
    "rate_limit",
    "invalid_request",
    "server_error",
    "max_output_tokens",
    "unknown",
]

SystemMessage

Message système avec métadonnées.
@dataclass
class SystemMessage:
    subtype: str
    data: dict[str, Any]

ResultMessage

Message de résultat final avec informations de coût et d’utilisation.
@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
Le dict usage contient les clés suivantes quand présentes :
CléTypeDescription
input_tokensintTokens d’entrée totaux consommés.
output_tokensintTokens de sortie totaux générés.
cache_creation_input_tokensintTokens utilisés pour créer de nouvelles entrées de cache.
cache_read_input_tokensintTokens lus à partir des entrées de cache existantes.
Le dict model_usage mappe les noms de modèles à l’utilisation par modèle. Les clés du dict interne utilisent camelCase parce que la valeur est passée inchangée du processus CLI sous-jacent, correspondant au type TypeScript ModelUsage :
CléTypeDescription
inputTokensintTokens d’entrée pour ce modèle.
outputTokensintTokens de sortie pour ce modèle.
cacheReadInputTokensintTokens de lecture de cache pour ce modèle.
cacheCreationInputTokensintTokens de création de cache pour ce modèle.
webSearchRequestsintRequêtes de recherche web effectuées par ce modèle.
costUSDfloatCoût estimé en USD pour ce modèle, calculé côté client. Voir Suivre le coût et l’utilisation pour les avertissements de facturation.
contextWindowintTaille de la fenêtre de contexte pour ce modèle.
maxOutputTokensintLimite de tokens de sortie maximum pour ce modèle.

StreamEvent

Événement de flux pour les mises à jour de messages partiels pendant le streaming. Reçu uniquement quand include_partial_messages=True dans ClaudeAgentOptions. Importez via 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
ChampTypeDescription
uuidstrIdentifiant unique pour cet événement
session_idstrIdentifiant de session
eventdict[str, Any]Les données d’événement de flux Claude API brutes
parent_tool_use_idstr | NoneID d’utilisation d’outil parent si cet événement provient d’un sous-agent

RateLimitEvent

Émis quand le statut de limite de débit change (par exemple, de "allowed" à "allowed_warning"). Utilisez ceci pour avertir les utilisateurs avant qu’ils ne frappent une limite dure, ou pour reculer quand le statut est "rejected".
@dataclass
class RateLimitEvent:
    rate_limit_info: RateLimitInfo
    uuid: str
    session_id: str
ChampTypeDescription
rate_limit_infoRateLimitInfoÉtat actuel de la limite de débit
uuidstrIdentifiant d’événement unique
session_idstrIdentifiant de session

RateLimitInfo

État de limite de débit porté par RateLimitEvent.
RateLimitStatus = Literal["allowed", "allowed_warning", "rejected"]
RateLimitType = Literal[
    "five_hour", "seven_day", "seven_day_opus", "seven_day_sonnet", "overage"
]


@dataclass
class RateLimitInfo:
    status: RateLimitStatus
    resets_at: int | None = None
    rate_limit_type: RateLimitType | None = None
    utilization: float | None = None
    overage_status: RateLimitStatus | None = None
    overage_resets_at: int | None = None
    overage_disabled_reason: str | None = None
    raw: dict[str, Any] = field(default_factory=dict)
ChampTypeDescription
statusRateLimitStatusStatut actuel. "allowed_warning" signifie approcher la limite ; "rejected" signifie que la limite a été atteinte
resets_atint | NoneTimestamp Unix quand la fenêtre de limite de débit se réinitialise
rate_limit_typeRateLimitType | NoneQuelle fenêtre de limite de débit s’applique
utilizationfloat | NoneFraction de la limite de débit consommée (0,0 à 1,0)
overage_statusRateLimitStatus | NoneStatut de l’utilisation de dépassement à l’usage, si applicable
overage_resets_atint | NoneTimestamp Unix quand la fenêtre de dépassement se réinitialise
overage_disabled_reasonstr | NonePourquoi le dépassement est indisponible, si le statut est "rejected"
rawdict[str, Any]Dict brut complet du CLI, incluant les champs non modélisés ci-dessus

TaskStartedMessage

Émis quand une tâche de fond démarre. Une tâche de fond est tout ce qui est suivi en dehors du tour principal : une commande Bash en arrière-plan, une montre Monitor, un sous-agent généré via l’outil Agent, ou un agent distant. Le champ task_type vous dit lequel. Ce nommage n’est pas lié au renommage de l’outil Task-à-Agent.
@dataclass
class TaskStartedMessage(SystemMessage):
    task_id: str
    description: str
    uuid: str
    session_id: str
    tool_use_id: str | None = None
    task_type: str | None = None
ChampTypeDescription
task_idstrIdentifiant unique pour la tâche
descriptionstrDescription de la tâche
uuidstrIdentifiant de message unique
session_idstrIdentifiant de session
tool_use_idstr | NoneID d’utilisation d’outil associé
task_typestr | NoneQuel type de tâche de fond : "local_bash" pour Bash en arrière-plan et les montres Monitor, "local_agent", ou "remote_agent"

TaskUsage

Données de tokens et de timing pour une tâche de fond.
class TaskUsage(TypedDict):
    total_tokens: int
    tool_uses: int
    duration_ms: int

TaskProgressMessage

Émis périodiquement avec les mises à jour de progression pour une tâche de fond en cours d’exécution.
@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
ChampTypeDescription
task_idstrIdentifiant unique pour la tâche
descriptionstrDescription du statut actuel
usageTaskUsageUtilisation de tokens pour cette tâche jusqu’à présent
uuidstrIdentifiant de message unique
session_idstrIdentifiant de session
tool_use_idstr | NoneID d’utilisation d’outil associé
last_tool_namestr | NoneNom du dernier outil utilisé par la tâche

TaskNotificationMessage

Émis quand une tâche de fond se termine, échoue, ou est arrêtée. Les tâches de fond incluent les commandes Bash run_in_background, les montres Monitor, et les sous-agents en arrière-plan.
@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
ChampTypeDescription
task_idstrIdentifiant unique pour la tâche
statusTaskNotificationStatusL’un de "completed", "failed", ou "stopped"
output_filestrChemin vers le fichier de sortie de la tâche
summarystrRésumé du résultat de la tâche
uuidstrIdentifiant de message unique
session_idstrIdentifiant de session
tool_use_idstr | NoneID d’utilisation d’outil associé
usageTaskUsage | NoneUtilisation de tokens finale pour la tâche

Types de blocs de contenu

ContentBlock

Type union de tous les blocs de contenu.
ContentBlock = TextBlock | ThinkingBlock | ToolUseBlock | ToolResultBlock

TextBlock

Bloc de contenu texte.
@dataclass
class TextBlock:
    text: str

ThinkingBlock

Bloc de contenu de réflexion (pour les modèles avec capacité de réflexion).
@dataclass
class ThinkingBlock:
    thinking: str
    signature: str

ToolUseBlock

Bloc de requête d’utilisation d’outil.
@dataclass
class ToolUseBlock:
    id: str
    name: str
    input: dict[str, Any]

ToolResultBlock

Bloc de résultat d’exécution d’outil.
@dataclass
class ToolResultBlock:
    tool_use_id: str
    content: str | list[dict[str, Any]] | None = None
    is_error: bool | None = None

Types d’erreur

ClaudeSDKError

Classe d’exception de base pour toutes les erreurs du SDK.
class ClaudeSDKError(Exception):
    """Base error for Claude SDK."""

CLINotFoundError

Levée quand Claude Code CLI n’est pas installé ou introuvable.
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

Levée quand la connexion à Claude Code échoue.
class CLIConnectionError(ClaudeSDKError):
    """Failed to connect to Claude Code."""

ProcessError

Levée quand le processus Claude Code échoue.
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

Levée quand l’analyse JSON échoue.
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

Types de hooks

Pour un guide complet sur l’utilisation des hooks avec des exemples et des modèles courants, voir le guide Hooks.

HookEvent

Types d’événements de hook supportés.
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
]
Le SDK TypeScript supporte des événements de hook supplémentaires non encore disponibles en Python : SessionStart, SessionEnd, Setup, TeammateIdle, TaskCompleted, ConfigChange, WorktreeCreate, WorktreeRemove, PostToolBatch et MessageDisplay.

HookCallback

Définition de type pour les fonctions de callback de hook.
HookCallback = Callable[[HookInput, str | None, HookContext], Awaitable[HookJSONOutput]]
Paramètres :
  • input : Entrée de hook fortement typée avec unions discriminées basées sur hook_event_name (voir HookInput)
  • tool_use_id : Identifiant d’utilisation d’outil optionnel (pour les hooks liés aux outils)
  • context : Contexte de hook avec des informations supplémentaires
Retourne un HookJSONOutput qui peut contenir :
  • decision : "block" pour bloquer l’action
  • systemMessage : Message d’avertissement affiché à l’utilisateur
  • hookSpecificOutput : Données de sortie spécifiques au hook

HookContext

Informations de contexte passées aux callbacks de hook.
class HookContext(TypedDict):
    signal: Any | None  # Future: abort signal support

HookMatcher

Configuration pour faire correspondre les hooks à des événements ou des outils spécifiques.
@dataclass
class HookMatcher:
    matcher: str | None = (
        None  # Tool name or pattern to match (e.g., "Bash", "Write|Edit")
    )
    hooks: list[HookCallback] = field(
        default_factory=list
    )  # List of callbacks to execute
    timeout: float | None = (
        None  # Timeout in seconds for all hooks in this matcher (default: 60)
    )

HookInput

Type union de tous les types d’entrée de hook. Le type réel dépend du champ hook_event_name.
HookInput = (
    PreToolUseHookInput
    | PostToolUseHookInput
    | PostToolUseFailureHookInput
    | UserPromptSubmitHookInput
    | StopHookInput
    | SubagentStopHookInput
    | PreCompactHookInput
    | NotificationHookInput
    | SubagentStartHookInput
    | PermissionRequestHookInput
)

BaseHookInput

Champs de base présents dans tous les types d’entrée de hook.
class BaseHookInput(TypedDict):
    session_id: str
    transcript_path: str
    cwd: str
    permission_mode: NotRequired[str]
ChampTypeDescription
session_idstrIdentifiant de session actuel
transcript_pathstrChemin vers le fichier de transcription de session
cwdstrRépertoire de travail actuel
permission_modestr (optionnel)Mode de permission actuel

PreToolUseHookInput

Données d’entrée pour les événements de hook PreToolUse.
class PreToolUseHookInput(BaseHookInput):
    hook_event_name: Literal["PreToolUse"]
    tool_name: str
    tool_input: dict[str, Any]
    tool_use_id: str
    agent_id: NotRequired[str]
    agent_type: NotRequired[str]
ChampTypeDescription
hook_event_nameLiteral["PreToolUse"]Toujours « PreToolUse »
tool_namestrNom de l’outil sur le point d’être exécuté
tool_inputdict[str, Any]Paramètres d’entrée pour l’outil
tool_use_idstrIdentifiant unique pour cette utilisation d’outil
agent_idstr (optionnel)Identifiant de sous-agent, présent quand le hook se déclenche à l’intérieur d’un sous-agent
agent_typestr (optionnel)Type de sous-agent, présent quand le hook se déclenche à l’intérieur d’un sous-agent

PostToolUseHookInput

Données d’entrée pour les événements de hook PostToolUse.
class PostToolUseHookInput(BaseHookInput):
    hook_event_name: Literal["PostToolUse"]
    tool_name: str
    tool_input: dict[str, Any]
    tool_response: Any
    tool_use_id: str
    agent_id: NotRequired[str]
    agent_type: NotRequired[str]
ChampTypeDescription
hook_event_nameLiteral["PostToolUse"]Toujours « PostToolUse »
tool_namestrNom de l’outil qui a été exécuté
tool_inputdict[str, Any]Paramètres d’entrée qui ont été utilisés
tool_responseAnyRéponse de l’exécution de l’outil
tool_use_idstrIdentifiant unique pour cette utilisation d’outil
agent_idstr (optionnel)Identifiant de sous-agent, présent quand le hook se déclenche à l’intérieur d’un sous-agent
agent_typestr (optionnel)Type de sous-agent, présent quand le hook se déclenche à l’intérieur d’un sous-agent

PostToolUseFailureHookInput

Données d’entrée pour les événements de hook PostToolUseFailure. Appelé quand l’exécution d’un outil échoue.
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]
ChampTypeDescription
hook_event_nameLiteral["PostToolUseFailure"]Toujours « PostToolUseFailure »
tool_namestrNom de l’outil qui a échoué
tool_inputdict[str, Any]Paramètres d’entrée qui ont été utilisés
tool_use_idstrIdentifiant unique pour cette utilisation d’outil
errorstrMessage d’erreur de l’exécution échouée
is_interruptbool (optionnel)Si l’échec a été causé par une interruption
agent_idstr (optionnel)Identifiant de sous-agent, présent quand le hook se déclenche à l’intérieur d’un sous-agent
agent_typestr (optionnel)Type de sous-agent, présent quand le hook se déclenche à l’intérieur d’un sous-agent

UserPromptSubmitHookInput

Données d’entrée pour les événements de hook UserPromptSubmit.
class UserPromptSubmitHookInput(BaseHookInput):
    hook_event_name: Literal["UserPromptSubmit"]
    prompt: str
ChampTypeDescription
hook_event_nameLiteral["UserPromptSubmit"]Toujours « UserPromptSubmit »
promptstrLe prompt soumis par l’utilisateur

StopHookInput

Données d’entrée pour les événements de hook Stop.
class StopHookInput(BaseHookInput):
    hook_event_name: Literal["Stop"]
    stop_hook_active: bool
ChampTypeDescription
hook_event_nameLiteral["Stop"]Toujours « Stop »
stop_hook_activeboolSi le hook d’arrêt est actif

SubagentStopHookInput

Données d’entrée pour les événements de hook SubagentStop.
class SubagentStopHookInput(BaseHookInput):
    hook_event_name: Literal["SubagentStop"]
    stop_hook_active: bool
    agent_id: str
    agent_transcript_path: str
    agent_type: str
ChampTypeDescription
hook_event_nameLiteral["SubagentStop"]Toujours « SubagentStop »
stop_hook_activeboolSi le hook d’arrêt est actif
agent_idstrIdentifiant unique pour le sous-agent
agent_transcript_pathstrChemin vers le fichier de transcription du sous-agent
agent_typestrType du sous-agent

PreCompactHookInput

Données d’entrée pour les événements de hook PreCompact.
class PreCompactHookInput(BaseHookInput):
    hook_event_name: Literal["PreCompact"]
    trigger: Literal["manual", "auto"]
    custom_instructions: str | None
ChampTypeDescription
hook_event_nameLiteral["PreCompact"]Toujours « PreCompact »
triggerLiteral["manual", "auto"]Ce qui a déclenché la compaction
custom_instructionsstr | NoneInstructions personnalisées pour la compaction

NotificationHookInput

Données d’entrée pour les événements de hook Notification.
class NotificationHookInput(BaseHookInput):
    hook_event_name: Literal["Notification"]
    message: str
    title: NotRequired[str]
    notification_type: str
ChampTypeDescription
hook_event_nameLiteral["Notification"]Toujours « Notification »
messagestrContenu du message de notification
titlestr (optionnel)Titre de la notification
notification_typestrType de notification

SubagentStartHookInput

Données d’entrée pour les événements de hook SubagentStart.
class SubagentStartHookInput(BaseHookInput):
    hook_event_name: Literal["SubagentStart"]
    agent_id: str
    agent_type: str
ChampTypeDescription
hook_event_nameLiteral["SubagentStart"]Toujours « SubagentStart »
agent_idstrIdentifiant unique pour le sous-agent
agent_typestrType du sous-agent

PermissionRequestHookInput

Données d’entrée pour les événements de hook PermissionRequest. Permet aux hooks de gérer les décisions de permission programmatiquement.
class PermissionRequestHookInput(BaseHookInput):
    hook_event_name: Literal["PermissionRequest"]
    tool_name: str
    tool_input: dict[str, Any]
    permission_suggestions: NotRequired[list[Any]]
ChampTypeDescription
hook_event_nameLiteral["PermissionRequest"]Toujours « PermissionRequest »
tool_namestrNom de l’outil demandant la permission
tool_inputdict[str, Any]Paramètres d’entrée pour l’outil
permission_suggestionslist[Any] (optionnel)Mises à jour de permission suggérées du CLI

HookJSONOutput

Type union pour les valeurs de retour de callback de hook.
HookJSONOutput = AsyncHookJSONOutput | SyncHookJSONOutput

SyncHookJSONOutput

Sortie de hook synchrone avec champs de contrôle et de décision.
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]
Utilisez continue_ (avec trait de soulignement) dans le code Python. Il est automatiquement converti en continue quand envoyé au CLI.

HookSpecificOutput

Un TypedDict contenant le nom d’événement de hook et les champs spécifiques à l’événement. La forme dépend de la valeur hookEventName. Pour les détails complets sur les champs disponibles par événement de hook, voir Contrôler l’exécution avec les hooks. Une union discriminée de types de sortie spécifiques à l’événement. Le champ hookEventName détermine quels champs sont valides.
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

Sortie de hook asynchrone qui diffère l’exécution du hook.
class AsyncHookJSONOutput(TypedDict):
    async_: Literal[True]  # Set to True to defer execution
    asyncTimeout: NotRequired[int]  # Timeout in milliseconds
Utilisez async_ (avec trait de soulignement) dans le code Python. Il est automatiquement converti en async quand envoyé au CLI.

Exemple d’utilisation de hook

Cet exemple enregistre deux hooks : l’un qui bloque les commandes bash dangereuses comme rm -rf /, et un autre qui enregistre toute l’utilisation d’outils pour l’audit. Le hook de sécurité s’exécute uniquement sur les commandes Bash (via le matcher), tandis que le hook de journalisation s’exécute sur tous les outils.
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)

Types d’entrée/sortie d’outil

Documentation des schémas d’entrée/sortie pour tous les outils Claude Code intégrés. Bien que le SDK Python n’exporte pas ceux-ci en tant que types, ils représentent la structure des entrées et sorties d’outils dans les messages.

Agent

Nom de l’outil : Agent (précédemment Task, qui est toujours accepté comme alias) Entrée :
{
    "description": str,  # A short (3-5 word) description of the task
    "prompt": str,  # The task for the agent to perform
    "subagent_type": str,  # The type of specialized agent to use
}
Sortie :
{
    "result": str,  # Final result from the subagent
    "usage": dict | None,  # Token usage statistics
    "total_cost_usd": float | None,  # Estimated total cost in USD
    "duration_ms": int | None,  # Execution duration in milliseconds
}

AskUserQuestion

Nom de l’outil : AskUserQuestion Pose des questions de clarification à l’utilisateur pendant l’exécution. Voir Gérer les approbations et les entrées utilisateur pour les détails d’utilisation. Entrée :
{
    "questions": [  # Questions to ask the user (1-4 questions)
        {
            "question": str,  # The complete question to ask the user
            "header": str,  # Very short label displayed as a chip/tag (max 12 chars)
            "options": [  # The available choices (2-4 options)
                {
                    "label": str,  # Display text for this option (1-5 words)
                    "description": str,  # Explanation of what this option means
                }
            ],
            "multiSelect": bool,  # Set to true to allow multiple selections
        }
    ],
    "answers": dict[str, str | list[str]] | None,
    # User answers populated by the permission system. Multi-select
    # answers may be a list of labels or a comma-joined string
}
Sortie :
{
    "questions": [  # The questions that were asked
        {
            "question": str,
            "header": str,
            "options": [{"label": str, "description": str}],
            "multiSelect": bool,
        }
    ],
    "answers": dict[str, str],  # Maps question text to answer string
    # Multi-select answers are comma-separated
}

Bash

Nom de l’outil : Bash Entrée :
{
    "command": str,  # The command to execute
    "timeout": int | None,  # Optional timeout in milliseconds (max 600000)
    "description": str | None,  # Clear, concise description (5-10 words)
    "run_in_background": bool | None,  # Set to true to run in background
}
Sortie :
{
    "output": str,  # Combined stdout and stderr output
    "exitCode": int,  # Exit code of the command
    "killed": bool | None,  # Whether command was killed due to timeout
    "shellId": str | None,  # Shell ID for background processes
}

Monitor

Nom de l’outil : Monitor Exécute un script de fond et livre chaque ligne stdout à Claude comme un événement pour qu’il puisse réagir sans interrogation. Monitor suit les mêmes règles de permission que Bash. Voir la référence de l’outil Monitor pour le comportement et la disponibilité du fournisseur. Entrée :
{
    "command": str,  # Shell script; each stdout line is an event, exit ends the watch
    "description": str,  # Short description shown in notifications
    "timeout_ms": int | None,  # Kill after this deadline (default 300000, max 3600000)
    "persistent": bool | None,  # Run for the lifetime of the session; stop with TaskStop
}
Sortie :
{
    "taskId": str,  # ID of the background monitor task
    "timeoutMs": int,  # Timeout deadline in milliseconds (0 when persistent)
    "persistent": bool | None,  # True when running until TaskStop or session end
}

Edit

Nom de l’outil : Edit Entrée :
{
    "file_path": str,  # The absolute path to the file to modify
    "old_string": str,  # The text to replace
    "new_string": str,  # The text to replace it with
    "replace_all": bool | None,  # Replace all occurrences (default False)
}
Sortie :
{
    "message": str,  # Confirmation message
    "replacements": int,  # Number of replacements made
    "file_path": str,  # File path that was edited
}

Read

Nom de l’outil : Read Entrée :
{
    "file_path": str,  # The absolute path to the file to read
    "offset": int | None,  # The line number to start reading from
    "limit": int | None,  # The number of lines to read
}
Sortie (fichiers texte) :
{
    "content": str,  # File contents with line numbers
    "total_lines": int,  # Total number of lines in file
    "lines_returned": int,  # Lines actually returned
}
Sortie (images) :
{
    "image": str,  # Base64 encoded image data
    "mime_type": str,  # Image MIME type
    "file_size": int,  # File size in bytes
}

Write

Nom de l’outil : Write Entrée :
{
    "file_path": str,  # The absolute path to the file to write
    "content": str,  # The content to write to the file
}
Sortie :
{
    "message": str,  # Success message
    "bytes_written": int,  # Number of bytes written
    "file_path": str,  # File path that was written
}

Glob

Nom de l’outil : Glob Entrée :
{
    "pattern": str,  # The glob pattern to match files against
    "path": str | None,  # The directory to search in (defaults to cwd)
}
Sortie :
{
    "matches": list[str],  # Array of matching file paths
    "count": int,  # Number of matches found
    "search_path": str,  # Search directory used
}

Grep

Nom de l’outil : Grep Entrée :
{
    "pattern": str,  # The regular expression pattern
    "path": str | None,  # File or directory to search in
    "glob": str | None,  # Glob pattern to filter files
    "type": str | None,  # File type to search
    "output_mode": str | None,  # "content", "files_with_matches", or "count"
    "-i": bool | None,  # Case insensitive search
    "-n": bool | None,  # Show line numbers
    "-B": int | None,  # Lines to show before each match
    "-A": int | None,  # Lines to show after each match
    "-C": int | None,  # Lines to show before and after
    "head_limit": int | None,  # Limit output to first N lines/entries
    "multiline": bool | None,  # Enable multiline mode
}
Sortie (mode contenu) :
{
    "matches": [
        {
            "file": str,
            "line_number": int | None,
            "line": str,
            "before_context": list[str] | None,
            "after_context": list[str] | None,
        }
    ],
    "total_matches": int,
}
Sortie (mode fichiers_avec_correspondances) :
{
    "files": list[str],  # Files containing matches
    "count": int,  # Number of files with matches
}

NotebookEdit

Nom de l’outil : NotebookEdit Entrée :
{
    "notebook_path": str,  # Absolute path to the Jupyter notebook
    "cell_id": str | None,  # The ID of the cell to edit
    "new_source": str,  # The new source for the cell
    "cell_type": "code" | "markdown" | None,  # The type of the cell
    "edit_mode": "replace" | "insert" | "delete" | None,  # Edit operation type
}
Sortie :
{
    "message": str,  # Success message
    "edit_type": "replaced" | "inserted" | "deleted",  # Type of edit performed
    "cell_id": str | None,  # Cell ID that was affected
    "total_cells": int,  # Total cells in notebook after edit
}

WebFetch

Nom de l’outil : WebFetch Entrée :
{
    "url": str,  # The URL to fetch content from
    "prompt": str,  # The prompt to run on the fetched content
}
Sortie :
{
    "bytes": int,  # Size of the fetched content in bytes
    "code": int,  # HTTP response code
    "codeText": str,  # HTTP response code text
    "result": str,  # Processed result from applying the prompt to the content
    "durationMs": int,  # Time to fetch and process the content, in milliseconds
    "url": str,  # URL that was fetched
}

WebSearch

Nom de l’outil : WebSearch Entrée :
{
    "query": str,  # The search query to use
    "allowed_domains": list[str] | None,  # Only include results from these domains
    "blocked_domains": list[str] | None,  # Never include results from these domains
}
Sortie :
{
    "query": str,  # The search query
    "results": list[str | {"tool_use_id": str, "content": list[{"title": str, "url": str}]}],
    "durationSeconds": float,  # Search duration in seconds
}

TodoWrite

Nom de l’outil : TodoWrite
À partir de Claude Code v2.1.142, TodoWrite est désactivé par défaut. Utilisez TaskCreate, TaskGet, TaskUpdate et TaskList à la place. Voir Migrer vers les outils Task pour mettre à jour votre code de surveillance, ou définissez CLAUDE_CODE_ENABLE_TASKS=0 pour revenir à TodoWrite.
Entrée :
{
    "todos": [
        {
            "content": str,  # The task description
            "status": "pending" | "in_progress" | "completed",  # Task status
            "activeForm": str,  # Active form of the description
        }
    ]
}
Sortie :
{
    "message": str,  # Success message
    "stats": {"total": int, "pending": int, "in_progress": int, "completed": int},
}

TaskCreate

Nom de l’outil : TaskCreate Entrée :
{
    "subject": str,  # Short task title
    "description": str,  # Detailed task body
    "activeForm": str | None,  # Present-tense label shown while in progress
    "metadata": dict | None,  # Arbitrary caller metadata
}
Sortie :
{
    "task": {"id": str, "subject": str},  # Created task with assigned ID
}

TaskUpdate

Nom de l’outil : TaskUpdate Entrée :
{
    "taskId": str,  # ID of the task to patch
    "status": Literal["pending", "in_progress", "completed", "deleted"] | None,
    "subject": str | None,
    "description": str | None,
    "activeForm": str | None,
    "addBlocks": list[str] | None,  # Task IDs this task now blocks
    "addBlockedBy": list[str] | None,  # Task IDs that now block this task
    "owner": str | None,
    "metadata": dict | None,
}
Sortie :
{
    "success": bool,
    "taskId": str,
    "updatedFields": list[str],  # Names of fields that changed
    "error": str | None,
    "statusChange": {"from": str, "to": str} | None,
}

TaskGet

Nom de l’outil : TaskGet Entrée :
{
    "taskId": str,  # ID of the task to read
}
Sortie :
{
    "task": {
        "id": str,
        "subject": str,
        "description": str,
        "status": Literal["pending", "in_progress", "completed"],
        "blocks": list[str],
        "blockedBy": list[str],
    } | None,  # None when the ID is not found
}

TaskList

Nom de l’outil : TaskList Entrée :
{}
Sortie :
{
    "tasks": [
        {
            "id": str,
            "subject": str,
            "status": Literal["pending", "in_progress", "completed"],
            "owner": str | None,
            "blockedBy": list[str],
        }
    ],
}

BashOutput

Nom de l’outil : BashOutput Entrée :
{
    "bash_id": str,  # The ID of the background shell
    "filter": str | None,  # Optional regex to filter output lines
}
Sortie :
{
    "output": str,  # New output since last check
    "status": "running" | "completed" | "failed",  # Current shell status
    "exitCode": int | None,  # Exit code when completed
}

KillBash

Nom de l’outil : KillBash Entrée :
{
    "shell_id": str  # The ID of the background shell to kill
}
Sortie :
{
    "message": str,  # Success message
    "shell_id": str,  # ID of the killed shell
}

ExitPlanMode

Nom de l’outil : ExitPlanMode Entrée :
{
    "plan": str  # The plan to run by the user for approval
}
Sortie :
{
    "message": str,  # Confirmation message
    "approved": bool | None,  # Whether user approved the plan
}

ListMcpResources

Nom de l’outil : ListMcpResourcesTool Entrée :
{
    "server": str | None  # Optional server name to filter resources by
}
Sortie :
{
    "resources": [
        {
            "uri": str,
            "name": str,
            "description": str | None,
            "mimeType": str | None,
            "server": str,
        }
    ],
    "total": int,
}

ReadMcpResource

Nom de l’outil : ReadMcpResourceTool Entrée :
{
    "server": str,  # The MCP server name
    "uri": str,  # The resource URI to read
}
Sortie :
{
    "contents": [
        {"uri": str, "mimeType": str | None, "text": str | None, "blob": str | None}
    ],
    "server": str,
}

Fonctionnalités avancées avec ClaudeSDKClient

Construire une interface de conversation continue

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

Utiliser les hooks pour la modification du comportement

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

Surveillance de la progression en temps réel

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

Exemple d’utilisation

Opérations de fichiers de base (utilisant 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())

Gestion des erreurs

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

Mode streaming avec 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())

Utiliser les outils personnalisés avec ClaudeSDKClient

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


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


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

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


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

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

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

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

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

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


asyncio.run(main())

Configuration du sandbox

SandboxSettings

Configuration pour le comportement du sandbox. Utilisez ceci pour activer le sandboxing des commandes et configurer les restrictions réseau programmatiquement.
class SandboxSettings(TypedDict, total=False):
    enabled: bool
    autoAllowBashIfSandboxed: bool
    excludedCommands: list[str]
    allowUnsandboxedCommands: bool
    network: SandboxNetworkConfig
    ignoreViolations: SandboxIgnoreViolations
    enableWeakerNestedSandbox: bool
PropriétéTypePar défautDescription
enabledboolFalseActivez le mode sandbox pour l’exécution des commandes
autoAllowBashIfSandboxedboolTrueApprouvez automatiquement les commandes bash quand le sandbox est activé
excludedCommandslist[str][]Commandes qui contournent toujours les restrictions du sandbox (par exemple, ["docker"]). Celles-ci s’exécutent sans sandbox automatiquement sans implication du modèle
allowUnsandboxedCommandsboolTruePermettez au modèle de demander l’exécution de commandes en dehors du sandbox. Quand True, le modèle peut définir dangerouslyDisableSandbox dans l’entrée d’outil, qui revient au système de permissions
networkSandboxNetworkConfigNoneConfiguration de sandbox spécifique au réseau
ignoreViolationsSandboxIgnoreViolationsNoneConfigurez quelles violations de sandbox ignorer
enableWeakerNestedSandboxboolFalseActivez un sandbox imbriqué plus faible pour la compatibilité
Le sandbox dépend du support de la plateforme et, sur Linux, d’outils comme bubblewrap et socat. Par défaut, quand enabled est True mais que le sandbox ne peut pas démarrer, les commandes s’exécutent sans sandbox avec un avertissement sur stderr. Ce comportement par défaut diffère du SDK TypeScript, où failIfUnavailable est par défaut true.Définissez "failIfUnavailable": True dans vos paramètres de sandbox pour arrêter à la place. La clé n’est pas encore déclarée sur SandboxSettings, mais le SDK la transmet à Claude Code, qui la respecte. query() rapporte alors un ResultMessage avec subtype="error_during_execution" et la raison dans errors. Surveillez ce sous-type plutôt que de vous attendre à ce que query() lève une exception avant de produire des messages.

Exemple d’utilisation

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)
Sécurité des sockets Unix : L’option allowUnixSockets peut accorder l’accès à des services système puissants. Par exemple, permettre /var/run/docker.sock accorde effectivement un accès complet au système hôte via l’API Docker, contournant l’isolation du sandbox. Autorisez uniquement les sockets Unix strictement nécessaires et comprenez les implications de sécurité de chacun.

SandboxNetworkConfig

Configuration spécifique au réseau pour le mode sandbox. Ces paramètres s’appliquent aux commandes Bash en sandbox quand enabled est True dans le parent SandboxSettings. Ils ne restreignent pas l’outil WebFetch, qui utilise à la place des règles de permission.
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
PropriétéTypePar défautDescription
allowedDomainslist[str][]Noms de domaine auxquels les processus en sandbox peuvent accéder
deniedDomainslist[str][]Noms de domaine auxquels les processus en sandbox ne peuvent pas accéder. Prend la priorité sur allowedDomains
allowManagedDomainsOnlyboolFalseParamètres gérés uniquement : quand défini dans les paramètres gérés, ignorez allowedDomains des sources de paramètres non gérées. N’a aucun effet quand défini via les options SDK
allowUnixSocketslist[str][]Chemins de socket Unix auxquels les processus peuvent accéder (par exemple, socket Docker)
allowAllUnixSocketsboolFalsePermettez l’accès à tous les sockets Unix
allowLocalBindingboolFalsePermettez aux processus de se lier aux ports locaux (par exemple, pour les serveurs de développement)
allowMachLookuplist[str][]macOS uniquement : noms de services XPC/Mach à autoriser. Supporte un caractère générique à la fin
httpProxyPortintNonePort du proxy HTTP pour les requêtes réseau
socksProxyPortintNonePort du proxy SOCKS pour les requêtes réseau
Le proxy sandbox intégré applique la liste blanche réseau en fonction du nom d’hôte demandé et ne termine pas ou n’inspecte pas le trafic TLS, donc des techniques telles que le domain fronting peuvent potentiellement le contourner. Voir Limitations de sécurité du sandboxing pour les détails et Déploiement sécurisé pour configurer un proxy qui termine TLS.

SandboxIgnoreViolations

Configuration pour ignorer les violations de sandbox spécifiques.
class SandboxIgnoreViolations(TypedDict, total=False):
    file: list[str]
    network: list[str]
PropriétéTypePar défautDescription
filelist[str][]Modèles de chemin de fichier pour ignorer les violations
networklist[str][]Modèles réseau pour ignorer les violations

Fallback de permissions pour les commandes sans sandbox

Quand allowUnsandboxedCommands est activé, le modèle peut demander l’exécution de commandes en dehors du sandbox en définissant dangerouslyDisableSandbox: True dans l’entrée d’outil. Ces requêtes reviennent au système de permissions existant, ce qui signifie que votre gestionnaire can_use_tool sera invoqué, vous permettant d’implémenter une logique d’autorisation personnalisée.
excludedCommands vs allowUnsandboxedCommands :
  • excludedCommands : Une liste statique de commandes qui contournent toujours le sandbox automatiquement (par exemple, ["docker"]). Le modèle n’a aucun contrôle sur ceci.
  • allowUnsandboxedCommands : Permet au modèle de décider à l’exécution s’il faut demander l’exécution sans sandbox en définissant dangerouslyDisableSandbox: True dans l’entrée d’outil.
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)
Ce modèle vous permet de :
  • Auditer les requêtes du modèle : Enregistrez quand le modèle demande l’exécution sans sandbox
  • Implémenter des listes blanches : Autorisez uniquement des commandes spécifiques à s’exécuter sans sandbox
  • Ajouter des flux d’approbation : Nécessitez une autorisation explicite pour les opérations privilégiées
Les commandes s’exécutant avec dangerouslyDisableSandbox: True ont un accès complet au système. Assurez-vous que votre gestionnaire can_use_tool valide ces requêtes avec soin.Si permission_mode est défini sur bypassPermissions et allow_unsandboxed_commands est activé, le modèle peut exécuter de manière autonome des commandes en dehors du sandbox sans aucun prompt d’approbation. Cette combinaison permet effectivement au modèle d’échapper à l’isolation du sandbox silencieusement.

Voir aussi