Vai al contenuto principale

Installazione

pip install claude-agent-sdk

Scelta tra query() e ClaudeSDKClient

Python SDK fornisce due modi per interagire con Claude Code:

Confronto rapido

Funzionalitàquery()ClaudeSDKClient
SessioneCrea una nuova sessione per impostazione predefinitaRiutilizza la stessa sessione
ConversazioneSingolo scambioPiù scambi nello stesso contesto
ConnessioneGestita automaticamenteControllo manuale
Input Streaming✅ Supportato✅ Supportato
Interruzioni❌ Non supportato✅ Supportato
Hooks✅ Supportato✅ Supportato
Strumenti personalizzati✅ Supportato✅ Supportato
Continua chatManuale tramite continue_conversation o resume✅ Automatico
Caso d’usoAttività una tantumConversazioni continue

Quando usare query() (attività una tantum)

Migliore per:
  • Domande una tantum dove non hai bisogno della cronologia della conversazione
  • Attività indipendenti che non richiedono contesto da scambi precedenti
  • Script di automazione semplici
  • Quando vuoi un nuovo inizio ogni volta

Quando usare ClaudeSDKClient (conversazione continua)

Migliore per:
  • Continuare conversazioni - Quando hai bisogno che Claude ricordi il contesto
  • Domande di follow-up - Costruire su risposte precedenti
  • Applicazioni interattive - Interfacce chat, REPL
  • Logica guidata dalla risposta - Quando l’azione successiva dipende dalla risposta di Claude
  • Controllo della sessione - Gestire il ciclo di vita della conversazione in modo esplicito

Funzioni

query()

Crea una nuova sessione per ogni interazione con Claude Code per impostazione predefinita. Restituisce un iteratore asincrono che produce messaggi man mano che arrivano. Ogni chiamata a query() inizia da zero senza memoria di interazioni precedenti a meno che non passiate continue_conversation=True o resume in ClaudeAgentOptions. Vedi Sessions.
async def query(
    *,
    prompt: str | AsyncIterable[dict[str, Any]],
    options: ClaudeAgentOptions | None = None,
    transport: Transport | None = None
) -> AsyncIterator[Message]

Parametri

ParametroTipoDescrizione
promptstr | AsyncIterable[dict]Il prompt di input come stringa o iterabile asincrono per la modalità streaming
optionsClaudeAgentOptions | NoneOggetto di configurazione opzionale (per impostazione predefinita ClaudeAgentOptions() se None)
transportTransport | NoneTrasporto personalizzato opzionale per comunicare con il processo CLI

Restituisce

Restituisce un AsyncIterator[Message] che produce messaggi dalla conversazione.

Esempio - Con opzioni

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

Decoratore per definire strumenti MCP con sicurezza dei tipi.
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]]

Parametri

ParametroTipoDescrizione
namestrIdentificatore univoco per lo strumento
descriptionstrDescrizione leggibile di cosa fa lo strumento
input_schematype | dict[str, Any]Schema che definisce i parametri di input dello strumento (vedi sotto)
annotationsToolAnnotations | NoneAnnotazioni MCP dello strumento opzionali che forniscono suggerimenti comportamentali ai client

Opzioni dello schema di input

  1. Mappatura di tipo semplice (consigliato):
    {"text": str, "count": int, "enabled": bool}
    
  2. Formato JSON Schema (per validazione complessa):
    {
        "type": "object",
        "properties": {
            "text": {"type": "string"},
            "count": {"type": "integer", "minimum": 0},
        },
        "required": ["text"],
    }
    

Restituisce

Una funzione decoratore che avvolge l’implementazione dello strumento e restituisce un’istanza SdkMcpTool.

Esempio

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

Riesportato da mcp.types (disponibile anche come from claude_agent_sdk import ToolAnnotations). Tutti i campi sono suggerimenti opzionali; i client non dovrebbero fare affidamento su di essi per decisioni di sicurezza.
CampoTipoPredefinitoDescrizione
titlestr | NoneNoneTitolo leggibile per lo strumento
readOnlyHintbool | NoneFalseSe True, lo strumento non modifica il suo ambiente
destructiveHintbool | NoneTrueSe True, lo strumento può eseguire aggiornamenti distruttivi (significativo solo quando readOnlyHint è False)
idempotentHintbool | NoneFalseSe True, le chiamate ripetute con gli stessi argomenti non hanno effetto aggiuntivo (significativo solo quando readOnlyHint è False)
openWorldHintbool | NoneTrueSe True, lo strumento interagisce con entità esterne (ad esempio, ricerca web). Se False, il dominio dello strumento è chiuso (ad esempio, uno strumento di memoria)
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()

Crea un server MCP in-process che viene eseguito all’interno della tua applicazione Python.
def create_sdk_mcp_server(
    name: str,
    version: str = "1.0.0",
    tools: list[SdkMcpTool[Any]] | None = None
) -> McpSdkServerConfig

Parametri

ParametroTipoPredefinitoDescrizione
namestr-Identificatore univoco per il server
versionstr"1.0.0"Stringa della versione del server
toolslist[SdkMcpTool[Any]] | NoneNoneElenco di funzioni di strumento create con il decoratore @tool

Restituisce

Restituisce un oggetto McpSdkServerConfig che può essere passato a ClaudeAgentOptions.mcp_servers.

Esempio

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

Elenca le sessioni passate con metadati. Filtra per directory di progetto o elenca le sessioni in tutti i progetti. Sincrono; restituisce immediatamente.
def list_sessions(
    directory: str | None = None,
    limit: int | None = None,
    include_worktrees: bool = True
) -> list[SDKSessionInfo]

Parametri

ParametroTipoPredefinitoDescrizione
directorystr | NoneNoneDirectory per cui elencare le sessioni. Se omesso, restituisce le sessioni in tutti i progetti
limitint | NoneNoneNumero massimo di sessioni da restituire
include_worktreesboolTrueQuando directory si trova all’interno di un repository git, includi le sessioni da tutti i percorsi worktree

Tipo di ritorno: SDKSessionInfo

ProprietàTipoDescrizione
session_idstrIdentificatore di sessione univoco
summarystrTitolo di visualizzazione: titolo personalizzato, riepilogo generato automaticamente o primo prompt
last_modifiedintOra dell’ultima modifica in millisecondi dall’epoca
file_sizeint | NoneDimensione del file di sessione in byte (None per backend di archiviazione remota)
custom_titlestr | NoneTitolo della sessione impostato dall’utente
first_promptstr | NonePrimo prompt utente significativo nella sessione
git_branchstr | NoneRamo Git alla fine della sessione
cwdstr | NoneDirectory di lavoro per la sessione
tagstr | NoneTag della sessione impostato dall’utente (vedi tag_session())
created_atint | NoneOra di creazione della sessione in millisecondi dall’epoca

Esempio

Stampa le 10 sessioni più recenti per un progetto. I risultati sono ordinati per last_modified decrescente, quindi il primo elemento è il più recente. Ometti directory per cercare in tutti i progetti.
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()

Recupera i messaggi da una sessione passata. Sincrono; restituisce immediatamente.
def get_session_messages(
    session_id: str,
    directory: str | None = None,
    limit: int | None = None,
    offset: int = 0
) -> list[SessionMessage]

Parametri

ParametroTipoPredefinitoDescrizione
session_idstrobbligatorioL’ID della sessione per cui recuperare i messaggi
directorystr | NoneNoneDirectory del progetto in cui cercare. Se omesso, cerca in tutti i progetti
limitint | NoneNoneNumero massimo di messaggi da restituire
offsetint0Numero di messaggi da saltare dall’inizio

Tipo di ritorno: SessionMessage

ProprietàTipoDescrizione
typeLiteral["user", "assistant"]Ruolo del messaggio
uuidstrIdentificatore di messaggio univoco
session_idstrIdentificatore di sessione
messageAnyContenuto del messaggio grezzo
parent_tool_use_idNoneRiservato per uso futuro

Esempio

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

Legge i metadati per una singola sessione per ID senza scansionare la directory del progetto completo. Sincrono; restituisce immediatamente.
def get_session_info(
    session_id: str,
    directory: str | None = None,
) -> SDKSessionInfo | None

Parametri

ParametroTipoPredefinitoDescrizione
session_idstrobbligatorioUUID della sessione da cercare
directorystr | NoneNonePercorso della directory del progetto. Se omesso, cerca in tutte le directory del progetto
Restituisce SDKSessionInfo, o None se la sessione non viene trovata.

Esempio

Cerca i metadati di una singola sessione senza scansionare la directory del progetto. Utile quando hai già un ID di sessione da un’esecuzione precedente.
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()

Rinomina una sessione aggiungendo una voce di titolo personalizzato. Le chiamate ripetute sono sicure; il titolo più recente vince. Sincrono.
def rename_session(
    session_id: str,
    title: str,
    directory: str | None = None,
) -> None

Parametri

ParametroTipoPredefinitoDescrizione
session_idstrobbligatorioUUID della sessione da rinominare
titlestrobbligatorioNuovo titolo. Deve essere non vuoto dopo la rimozione degli spazi bianchi
directorystr | NoneNonePercorso della directory del progetto. Se omesso, cerca in tutte le directory del progetto
Genera ValueError se session_id non è un UUID valido o title è vuoto; FileNotFoundError se la sessione non può essere trovata.

Esempio

Rinomina la sessione più recente in modo che sia più facile da trovare in seguito. Il nuovo titolo appare in SDKSessionInfo.custom_title nelle letture successive.
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()

Etichetta una sessione. Passa None per cancellare l’etichetta. Le chiamate ripetute sono sicure; l’etichetta più recente vince. Sincrono.
def tag_session(
    session_id: str,
    tag: str | None,
    directory: str | None = None,
) -> None

Parametri

ParametroTipoPredefinitoDescrizione
session_idstrobbligatorioUUID della sessione da etichettare
tagstr | NoneobbligatorioStringa di etichetta, o None per cancellare. Sanitizzato Unicode prima dell’archiviazione
directorystr | NoneNonePercorso della directory del progetto. Se omesso, cerca in tutte le directory del progetto
Genera ValueError se session_id non è un UUID valido o tag è vuoto dopo la sanitizzazione; FileNotFoundError se la sessione non può essere trovata.

Esempio

Etichetta una sessione, quindi filtra per quell’etichetta in una lettura successiva. Passa None per cancellare un’etichetta esistente.
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)

Classi

ClaudeSDKClient

Mantiene una sessione di conversazione in più scambi. Questo è l’equivalente Python di come la funzione query() di TypeScript SDK funziona internamente - crea un oggetto client che può continuare le conversazioni.

Caratteristiche principali

  • Continuità della sessione: Mantiene il contesto della conversazione in più chiamate query()
  • Stessa conversazione: La sessione conserva i messaggi precedenti
  • Supporto per interruzioni: Può interrompere l’esecuzione a metà attività
  • Ciclo di vita esplicito: Controlli quando la sessione inizia e termina
  • Flusso guidato dalla risposta: Può reagire alle risposte e inviare follow-up
  • Strumenti personalizzati e hooks: Supporta strumenti personalizzati (creati con il decoratore @tool) e 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

Metodi

MetodoDescrizione
__init__(options)Inizializza il client con configurazione opzionale
connect(prompt)Connettiti a Claude con un prompt iniziale opzionale o flusso di messaggi
query(prompt, session_id)Invia una nuova richiesta in modalità streaming
receive_messages()Ricevi tutti i messaggi da Claude come iteratore asincrono
receive_response()Ricevi messaggi fino a e incluso un ResultMessage
interrupt()Invia segnale di interruzione (funziona solo in modalità streaming)
set_permission_mode(mode)Cambia la modalità di autorizzazione per la sessione corrente
set_model(model)Cambia il modello per la sessione corrente. Passa None per ripristinare il valore predefinito
rewind_files(user_message_id)Ripristina i file al loro stato al messaggio utente specificato. Richiede enable_file_checkpointing=True. Vedi File checkpointing
get_mcp_status()Ottieni lo stato di tutti i server MCP configurati. Restituisce McpStatusResponse
reconnect_mcp_server(server_name)Riprova a connettersi a un server MCP che ha fallito o è stato disconnesso
toggle_mcp_server(server_name, enabled)Abilita o disabilita un server MCP a metà sessione. La disabilitazione rimuove i suoi strumenti
stop_task(task_id)Interrompi un’attività in background in esecuzione. Un TaskNotificationMessage con stato "stopped" segue nel flusso di messaggi
get_server_info()Ottieni informazioni sul server incluso l’ID della sessione e le capacità
disconnect()Disconnettiti da Claude

Supporto Context Manager

Il client può essere utilizzato come context manager asincrono per la gestione automatica della connessione:
async with ClaudeSDKClient() as client:
    await client.query("Hello Claude")
    async for message in client.receive_response():
        print(message)
Importante: Quando iteri sui messaggi, evita di usare break per uscire anticipatamente poiché questo può causare problemi di pulizia asyncio. Invece, lascia che l’iterazione si completi naturalmente o usa flag per tracciare quando hai trovato quello che cerchi.

Esempio - Continuare una conversazione

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

Esempio - Input streaming con 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())

Esempio - Utilizzo di interruzioni

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())
Comportamento del buffer dopo l’interruzione: interrupt() invia un segnale di arresto ma non cancella il buffer dei messaggi. I messaggi già prodotti dall’attività interrotta, incluso il suo ResultMessage (con subtype="error_during_execution"), rimangono nel flusso. Devi drenare con receive_response() prima di leggere la risposta a una nuova query. Se invii una nuova query immediatamente dopo interrupt() e chiami receive_response() una sola volta, riceverai i messaggi dell’attività interrotta, non la risposta della nuova query.

Esempio - Controllo avanzato delle autorizzazioni

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

Tipi

@dataclass vs TypedDict: Questo SDK utilizza due tipi di tipi. Le classi decorate con @dataclass (come ResultMessage, AgentDefinition, TextBlock) sono istanze di oggetti in fase di esecuzione e supportano l’accesso agli attributi: msg.result. Le classi definite con TypedDict (come ThinkingConfigEnabled, McpStdioServerConfig, SyncHookJSONOutput) sono dicts semplici in fase di esecuzione e richiedono l’accesso alle chiavi: config["budget_tokens"], non config.budget_tokens. La sintassi di chiamata ClassName(field=value) funziona per entrambi, ma solo le dataclass producono oggetti con attributi.

SdkMcpTool

Definizione per uno strumento SDK MCP creato con il decoratore @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
ProprietàTipoDescrizione
namestrIdentificatore univoco per lo strumento
descriptionstrDescrizione leggibile
input_schematype[T] | dict[str, Any]Schema per la validazione dell’input
handlerCallable[[T], Awaitable[dict[str, Any]]]Funzione asincrona che gestisce l’esecuzione dello strumento
annotationsToolAnnotations | NoneAnnotazioni MCP dello strumento opzionali (ad es. readOnlyHint, destructiveHint, openWorldHint). Da mcp.types

Transport

Classe base astratta per implementazioni di trasporto personalizzate. Usala per comunicare con il processo Claude su un canale personalizzato (ad esempio, una connessione remota invece di un subprocess locale).
Questa è un’API interna di basso livello. L’interfaccia potrebbe cambiare nelle versioni future. Le implementazioni personalizzate devono essere aggiornate per corrispondere a eventuali modifiche dell’interfaccia.
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: ...
MetodoDescrizione
connect()Connetti il trasporto e preparati per la comunicazione
write(data)Scrivi dati grezzi (JSON + newline) nel trasporto
read_messages()Iteratore asincrono che produce messaggi JSON analizzati
close()Chiudi la connessione e pulisci le risorse
is_ready()Restituisce True se il trasporto può inviare e ricevere
end_input()Chiudi il flusso di input (ad esempio, chiudi stdin per trasporti subprocess)
Importazione: from claude_agent_sdk import Transport

ClaudeAgentOptions

Dataclass di configurazione per le query 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"
ProprietàTipoPredefinitoDescrizione
toolslist[str] | ToolsPreset | NoneNoneConfigurazione degli strumenti. Usa {"type": "preset", "preset": "claude_code"} per gli strumenti predefiniti di Claude Code
allowed_toolslist[str][]Strumenti da approvare automaticamente senza chiedere. Questo non limita Claude a solo questi strumenti; gli strumenti non elencati ricadono in permission_mode e can_use_tool. Usa disallowed_tools per bloccare gli strumenti. Vedi Autorizzazioni
system_promptstr | SystemPromptPreset | NoneNoneConfigurazione del prompt di sistema. Passa una stringa per un prompt personalizzato, o usa {"type": "preset", "preset": "claude_code"} per il prompt di sistema di Claude Code. Aggiungi "append" per estendere il preset
mcp_serversdict[str, McpServerConfig] | str | Path{}Configurazioni del server MCP o percorso al file di configurazione
strict_mcp_configboolFalseQuando True, usa solo i server passati in mcp_servers e ignora il progetto .mcp.json, le impostazioni utente, i server MCP forniti dai plugin e i connettori claude.ai. Mappa al flag CLI --strict-mcp-config
permission_modePermissionMode | NoneNoneModalità di autorizzazione per l’utilizzo dello strumento
continue_conversationboolFalseContinua la conversazione più recente
resumestr | NoneNoneID della sessione da riprendere
max_turnsint | NoneNoneNumero massimo di turni agentici (round trip di utilizzo dello strumento)
max_budget_usdfloat | NoneNoneInterrompi la query quando la stima del costo lato client raggiunge questo valore in USD. Confrontato con la stessa stima di total_cost_usd; vedi Traccia costo e utilizzo per avvertenze di accuratezza
disallowed_toolslist[str][]Strumenti da negare. Un nome semplice come "Bash" rimuove lo strumento dal contesto di Claude. Una regola con ambito come "Bash(rm *)" lascia lo strumento disponibile e nega le chiamate corrispondenti in ogni modalità di autorizzazione, incluso bypassPermissions. Vedi Autorizzazioni
enable_file_checkpointingboolFalseAbilita il tracciamento dei cambiamenti dei file per il rewind. Vedi File checkpointing
modelstr | NoneNoneModello Claude da utilizzare
fallback_modelstr | NoneNoneModello di fallback da utilizzare se il modello primario fallisce
betaslist[SdkBeta][]Funzionalità beta da abilitare. Vedi SdkBeta per le opzioni disponibili
output_formatdict[str, Any] | NoneNoneFormato di output per risposte strutturate (ad es. {"type": "json_schema", "schema": {...}}). Vedi Output strutturati per i dettagli
permission_prompt_tool_namestr | NoneNoneNome dello strumento MCP per i prompt di autorizzazione
cwdstr | Path | NoneNoneDirectory di lavoro corrente
cli_pathstr | Path | NoneNonePercorso personalizzato all’eseguibile CLI di Claude Code
settingsstr | NoneNonePercorso al file di impostazioni
add_dirslist[str | Path][]Directory aggiuntive a cui Claude può accedere
envdict[str, str]{}Variabili di ambiente unite in cima all’ambiente del processo ereditato. Vedi Variabili di ambiente per le variabili che la CLI sottostante legge, e Gestisci risposte API lente o bloccate per le variabili relative ai timeout
extra_argsdict[str, str | None]{}Argomenti CLI aggiuntivi da passare direttamente alla CLI
max_buffer_sizeint | NoneNoneByte massimi durante il buffering dell’stdout della CLI
debug_stderrAnysys.stderrDeprecato - Oggetto simile a un file per l’output di debug. Usa il callback stderr invece
stderrCallable[[str], None] | NoneNoneFunzione di callback per l’output stderr dalla CLI
can_use_toolCanUseTool | NoneNoneFunzione di callback per l’autorizzazione dello strumento. Vedi Tipi di autorizzazione per i dettagli
hooksdict[HookEvent, list[HookMatcher]] | NoneNoneConfigurazioni hook per intercettare gli eventi
userstr | NoneNoneIdentificatore utente
include_partial_messagesboolFalseIncludi eventi di streaming di messaggi parziali. Se abilitato, i messaggi StreamEvent vengono prodotti
include_hook_eventsboolFalseIncludi eventi del ciclo di vita dei hook nel flusso di messaggi come oggetti HookEventMessage
fork_sessionboolFalseQuando si riprende con resume, esegui il fork a un nuovo ID di sessione invece di continuare la sessione originale
agentsdict[str, AgentDefinition] | NoneNoneSubagenti definiti programmaticamente
pluginslist[SdkPluginConfig][]Carica plugin personalizzati da percorsi locali. Vedi Plugin per i dettagli
sandboxSandboxSettings | NoneNoneConfigura il comportamento della sandbox a livello di programmazione. Vedi Impostazioni sandbox per i dettagli
setting_sourceslist[SettingSource] | NoneNone (Impostazioni predefinite CLI: tutte le fonti)Controlla quali impostazioni del filesystem caricare. Passa [] per disabilitare le impostazioni utente, progetto e locali. Le impostazioni della politica gestita vengono caricate indipendentemente. Vedi Usa le funzionalità di Claude Code
skillslist[str] | Literal["all"] | NoneNoneSkills disponibili per la sessione. Passa "all" per abilitare ogni skill scoperta, o un elenco di nomi di skill. Quando impostato, l’SDK aggiunge lo strumento Skill a allowed_tools automaticamente. Se passi anche tools, includi "Skill" in quell’elenco. Vedi Skills
max_thinking_tokensint | NoneNoneDeprecato - Token massimi per i blocchi di pensiero. Usa thinking invece
thinkingThinkingConfig | NoneNoneControlla il comportamento del pensiero esteso. Ha la precedenza su max_thinking_tokens
effortEffortLevel | NoneNoneLivello di sforzo per la profondità del pensiero
session_storeSessionStore | NoneNoneSpecchia i trascritti di sessione in un backend esterno in modo che qualsiasi host possa riprenderli. Vedi Persisti le sessioni nell’archiviazione esterna
session_store_flushLiteral["batched", "eager"]"batched"Quando eseguire il flush delle voci di trascritto mirrorato a session_store. "batched" esegue il flush una volta per turno o quando il buffer si riempie; "eager" attiva un flush in background dopo ogni frame. Ignorato quando session_store è None

Gestisci risposte API lente o bloccate

Il subprocess CLI legge diverse variabili di ambiente che controllano i timeout dell’API e il rilevamento dei blocchi. Passale attraverso ClaudeAgentOptions.env:
options = ClaudeAgentOptions(
    env={
        "API_TIMEOUT_MS": "120000",
        "CLAUDE_CODE_MAX_RETRIES": "2",
        "CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS": "120000",
    },
)
  • API_TIMEOUT_MS: timeout per richiesta sul client Anthropic, in millisecondi. Predefinito 600000. Si applica al ciclo principale e a tutti i subagenti.
  • CLAUDE_CODE_MAX_RETRIES: numero massimo di tentativi API. Predefinito 10. Ogni tentativo ottiene la propria finestra API_TIMEOUT_MS, quindi il tempo di parete nel caso peggiore è approssimativamente API_TIMEOUT_MS × (CLAUDE_CODE_MAX_RETRIES + 1) più backoff.
  • CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS: watchdog di blocco per i subagenti lanciati con run_in_background. Predefinito 600000. Si ripristina su ogni evento di flusso; in caso di blocco interrompe il subagente, contrassegna l’attività come non riuscita e presenta l’errore al genitore con qualsiasi risultato parziale. Non si applica ai subagenti sincroni.
  • CLAUDE_ENABLE_STREAM_WATCHDOG=1 con CLAUDE_STREAM_IDLE_TIMEOUT_MS: interrompe la richiesta quando le intestazioni sono arrivate ma il corpo della risposta smette di trasmettere. Disabilitato per impostazione predefinita. CLAUDE_STREAM_IDLE_TIMEOUT_MS predefinito a 300000 e viene bloccato a quel minimo. La richiesta interrotta passa attraverso il percorso di ripetizione normale.

OutputFormat

Configurazione per la validazione dell’output strutturato. Passa questo come dict al campo output_format su ClaudeAgentOptions:
# Expected dict shape for output_format
{
    "type": "json_schema",
    "schema": {...},  # Your JSON Schema definition
}
CampoObbligatorioDescrizione
typeDeve essere "json_schema" per la validazione JSON Schema
schemaDefinizione JSON Schema per la validazione dell’output

SystemPromptPreset

Configurazione per l’utilizzo del prompt di sistema preset di Claude Code con aggiunte opzionali.
class SystemPromptPreset(TypedDict):
    type: Literal["preset"]
    preset: Literal["claude_code"]
    append: NotRequired[str]
    exclude_dynamic_sections: NotRequired[bool]
CampoObbligatorioDescrizione
typeDeve essere "preset" per utilizzare un prompt di sistema preset
presetDeve essere "claude_code" per utilizzare il prompt di sistema di Claude Code
appendNoIstruzioni aggiuntive da aggiungere al prompt di sistema preset
exclude_dynamic_sectionsNoSposta il contesto per sessione come directory di lavoro, stato git e percorsi di memoria dal prompt di sistema nel primo messaggio utente. Migliora il riutilizzo della cache dei prompt tra utenti e macchine. Vedi Modifica i prompt di sistema

SettingSource

Controlla quali fonti di configurazione basate su filesystem l’SDK carica le impostazioni da.
SettingSource = Literal["user", "project", "local"]
ValoreDescrizionePosizione
"user"Impostazioni utente globali~/.claude/settings.json
"project"Impostazioni di progetto condivise (controllate dalla versione).claude/settings.json
"local"Impostazioni di progetto locali (gitignored).claude/settings.local.json

Comportamento predefinito

Quando setting_sources è omesso o None, query() carica le stesse impostazioni del filesystem della CLI di Claude Code: utente, progetto e locale. Le impostazioni della politica gestita vengono caricate in tutti i casi. Vedi Cosa settingSources non controlla per gli input che vengono letti indipendentemente da questa opzione, e come disabilitarli.

Perché usare setting_sources

Disabilita le impostazioni del filesystem:
# 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)
In Python SDK 0.1.59 e versioni precedenti, un elenco vuoto era trattato come l’omissione dell’opzione, quindi setting_sources=[] non disabilitava le impostazioni del filesystem. Aggiorna a una versione più recente se hai bisogno che un elenco vuoto abbia effetto. TypeScript SDK non è interessato.
Carica tutte le impostazioni del filesystem in modo esplicito:
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)
Carica solo fonti di impostazioni specifiche:
# 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)
Ambienti di test e 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)
Applicazioni solo SDK:
# 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)
Caricamento delle istruzioni del progetto 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)

Precedenza delle impostazioni

Quando più fonti vengono caricate, le impostazioni vengono unite con questa precedenza (da più alta a più bassa):
  1. Impostazioni locali (.claude/settings.local.json)
  2. Impostazioni di progetto (.claude/settings.json)
  3. Impostazioni utente (~/.claude/settings.json)
Le opzioni programmatiche come agents e allowed_tools sovrascrivono le impostazioni del filesystem utente, progetto e locale. Le impostazioni della politica gestita hanno la precedenza sulle opzioni programmatiche.

AgentDefinition

Configurazione per un subagente definito programmaticamente.
@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
CampoObbligatorioDescrizione
descriptionDescrizione in linguaggio naturale di quando utilizzare questo agente
promptIl prompt di sistema dell’agente
toolsNoArray di nomi di strumenti consentiti. Se omesso, eredita tutti gli strumenti
disallowedToolsNoArray di nomi di strumenti da rimuovere dal set di strumenti dell’agente
modelNoOverride del modello per questo agente. Accetta un alias come "sonnet", "opus", "haiku", o "inherit", o un ID modello completo. Se omesso, utilizza il modello principale
skillsNoElenco dei nomi di skills da precaricare nel contesto dell’agente all’avvio. Le skills non elencate rimangono invocabili attraverso lo strumento Skill
memoryNoFonte di memoria per questo agente: "user", "project", o "local"
mcpServersNoServer MCP disponibili per questo agente. Ogni voce è un nome di server o un dict {name: config} inline
initialPromptNoAuto-inviato come il primo turno utente quando questo agente viene eseguito come agente del thread principale
maxTurnsNoNumero massimo di turni agentici prima che l’agente si fermi
backgroundNoEsegui questo agente come attività in background non bloccante quando invocato
effortNoLivello di sforzo di ragionamento per questo agente. Accetta un livello denominato o un numero intero. Vedi EffortLevel
permissionModeNoModalità di autorizzazione per l’esecuzione dello strumento all’interno di questo agente. Vedi PermissionMode
I nomi dei campi AgentDefinition usano camelCase, come disallowedTools, permissionMode e maxTurns. Questi nomi si mappano direttamente al formato wire condiviso con TypeScript SDK. Questo differisce da ClaudeAgentOptions, che usa Python snake_case per i campi di livello superiore equivalenti come disallowed_tools e permission_mode. Poiché AgentDefinition è una dataclass, passare una parola chiave snake_case genera un TypeError al momento della costruzione.

PermissionMode

Modalità di autorizzazione per controllare l’esecuzione dello strumento.
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

Livelli di sforzo per guidare la profondità del pensiero.
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 di tipo per le funzioni di callback di autorizzazione dello strumento.
CanUseTool = Callable[
    [str, dict[str, Any], ToolPermissionContext], Awaitable[PermissionResult]
]
Il callback riceve:
  • tool_name: Nome dello strumento che viene chiamato
  • input_data: I parametri di input dello strumento
  • context: Un ToolPermissionContext con informazioni aggiuntive
Restituisce un PermissionResult (sia PermissionResultAllow che PermissionResultDeny).

ToolPermissionContext

Informazioni di contesto passate ai callback di autorizzazione dello strumento.
@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
CampoTipoDescrizione
signalAny | NoneRiservato per il supporto futuro del segnale di interruzione
suggestionslist[PermissionUpdate]Suggerimenti di aggiornamento delle autorizzazioni dalla CLI. I prompt Bash includono un suggerimento con la destinazione localSettings, quindi restituirlo in updated_permissions scrive la regola in .claude/settings.local.json e persiste tra le sessioni.
blocked_pathstr | NonePercorso del file che ha attivato la richiesta di autorizzazione, se applicabile. Ad esempio, quando un comando Bash tenta di accedere a un percorso al di fuori delle directory consentite
decision_reasonstr | NoneMotivo per cui questa richiesta di autorizzazione è stata attivata. Inoltrato dal permissionDecisionReason di un hook PreToolUse quando l’hook ha restituito "ask"
titlestr | NoneFrase completa del prompt di autorizzazione, come Claude wants to read foo.txt. Usa come testo del prompt principale quando presente
display_namestr | NoneBreve frase nominale per l’azione dello strumento, come Read file, adatta per etichette di pulsanti
descriptionstr | NoneSottotitolo leggibile per l’interfaccia utente di autorizzazione

PermissionResult

Tipo di unione per i risultati del callback di autorizzazione.
PermissionResult = PermissionResultAllow | PermissionResultDeny

PermissionResultAllow

Risultato che indica che la chiamata dello strumento deve essere consentita.
@dataclass
class PermissionResultAllow:
    behavior: Literal["allow"] = "allow"
    updated_input: dict[str, Any] | None = None
    updated_permissions: list[PermissionUpdate] | None = None
CampoTipoPredefinitoDescrizione
behaviorLiteral["allow"]"allow"Deve essere “allow”
updated_inputdict[str, Any] | NoneNoneInput modificato da utilizzare al posto dell’originale
updated_permissionslist[PermissionUpdate] | NoneNoneAggiornamenti delle autorizzazioni da applicare

PermissionResultDeny

Risultato che indica che la chiamata dello strumento deve essere negata.
@dataclass
class PermissionResultDeny:
    behavior: Literal["deny"] = "deny"
    message: str = ""
    interrupt: bool = False
CampoTipoPredefinitoDescrizione
behaviorLiteral["deny"]"deny"Deve essere “deny”
messagestr""Messaggio che spiega perché lo strumento è stato negato
interruptboolFalseSe interrompere l’esecuzione corrente

PermissionUpdate

Configurazione per l’aggiornamento delle autorizzazioni a livello di programmazione.
@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
CampoTipoDescrizione
typeLiteral[...]Il tipo di operazione di aggiornamento delle autorizzazioni
ruleslist[PermissionRuleValue] | NoneRegole per le operazioni add/replace/remove
behaviorLiteral["allow", "deny", "ask"] | NoneComportamento per le operazioni basate su regole
modePermissionMode | NoneModalità per l’operazione setMode
directorieslist[str] | NoneDirectory per le operazioni add/remove directory
destinationLiteral[...] | NoneDove applicare l’aggiornamento delle autorizzazioni

PermissionRuleValue

Una regola da aggiungere, sostituire o rimuovere in un aggiornamento delle autorizzazioni.
@dataclass
class PermissionRuleValue:
    tool_name: str
    rule_content: str | None = None

ToolsPreset

Configurazione degli strumenti preset per l’utilizzo del set di strumenti predefinito di Claude Code.
class ToolsPreset(TypedDict):
    type: Literal["preset"]
    preset: Literal["claude_code"]

ThinkingConfig

Controlla il comportamento del pensiero esteso. Un’unione di tre configurazioni:
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
VarianteCampiDescrizione
adaptivetype, displayClaude decide adattivamente quando pensare
enabledtype, budget_tokens, displayAbilita il pensiero con un budget di token specifico
disabledtypeDisabilita il pensiero
Il campo opzionale display controlla se il testo di pensiero viene restituito "summarized" o "omitted". Su Claude Opus 4.7 e versioni successive, l’impostazione predefinita dell’API è "omitted", quindi imposta "summarized" per ricevere il contenuto di pensiero negli output ThinkingBlock. Poiché queste sono classi TypedDict, sono dicts semplici in fase di esecuzione. Costruiscile come letterali dict o chiama la classe come costruttore; entrambi producono un dict. Accedi ai campi con config["budget_tokens"], non 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

Tipo letterale per le funzionalità beta dell’SDK.
SdkBeta = Literal["context-1m-2025-08-07"]
Usa con il campo betas in ClaudeAgentOptions per abilitare le funzionalità beta.
La beta context-1m-2025-08-07 è ritirata a partire dal 30 aprile 2026. Passare questo header con Claude Sonnet 4.5 o Sonnet 4 non ha effetto, e le richieste che superano la finestra di contesto standard di 200k token restituiscono un errore. Per utilizzare una finestra di contesto di 1M token, esegui la migrazione a Claude Sonnet 4.6, Claude Opus 4.6, o Claude Opus 4.7, che includono 1M di contesto a prezzi standard senza header beta richiesto.

McpSdkServerConfig

Configurazione per i server MCP dell’SDK creati con create_sdk_mcp_server().
class McpSdkServerConfig(TypedDict):
    type: Literal["sdk"]
    name: str
    instance: Any  # MCP Server instance

McpServerConfig

Tipo di unione per le configurazioni del server 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 configurazione di un server MCP come riportato da get_mcp_status(). Questa è l’unione di tutte le varianti di trasporto McpServerConfig più una variante di output-only claudeai-proxy per i server proxy attraverso claude.ai.
McpServerStatusConfig = (
    McpStdioServerConfig
    | McpSSEServerConfig
    | McpHttpServerConfig
    | McpSdkServerConfigStatus
    | McpClaudeAIProxyServerConfig
)
McpSdkServerConfigStatus è la forma serializzabile di McpSdkServerConfig con solo i campi type ("sdk") e name (str); l’instance in-process viene omesso. McpClaudeAIProxyServerConfig ha i campi type ("claudeai-proxy"), url (str), e id (str).

McpStatusResponse

Risposta da ClaudeSDKClient.get_mcp_status(). Avvolge l’elenco degli stati del server sotto la chiave mcpServers.
class McpStatusResponse(TypedDict):
    mcpServers: list[McpServerStatus]

McpServerStatus

Stato di un server MCP connesso, contenuto in McpStatusResponse.
class McpServerStatus(TypedDict):
    name: str
    status: McpServerConnectionStatus  # "connected" | "failed" | "needs-auth" | "pending" | "disabled"
    serverInfo: NotRequired[McpServerInfo]
    error: NotRequired[str]
    config: NotRequired[McpServerStatusConfig]
    scope: NotRequired[str]
    tools: NotRequired[list[McpToolInfo]]
CampoTipoDescrizione
namestrNome del server
statusstrUno di "connected", "failed", "needs-auth", "pending", o "disabled"
serverInfodict (opzionale)Nome e versione del server ({"name": str, "version": str})
errorstr (opzionale)Messaggio di errore se il server non si è connesso
configMcpServerStatusConfig (opzionale)Configurazione del server. Stessa forma di McpServerConfig (stdio, SSE, HTTP, o SDK), più una variante claudeai-proxy per i server connessi tramite claude.ai
scopestr (opzionale)Ambito di configurazione
toolslist (opzionale)Strumenti forniti da questo server, ognuno con i campi name, description, e annotations

SdkPluginConfig

Configurazione per il caricamento dei plugin nell’SDK.
class SdkPluginConfig(TypedDict):
    type: Literal["local"]
    path: str
CampoTipoDescrizione
typeLiteral["local"]Deve essere "local" (attualmente sono supportati solo plugin locali)
pathstrPercorso assoluto o relativo alla directory del plugin
Esempio:
plugins = [
    {"type": "local", "path": "./my-plugin"},
    {"type": "local", "path": "/absolute/path/to/plugin"},
]
Per informazioni complete sulla creazione e l’utilizzo dei plugin, vedi Plugin.

Tipi di messaggio

Message

Tipo di unione di tutti i possibili messaggi.
Message = (
    UserMessage
    | AssistantMessage
    | SystemMessage
    | ResultMessage
    | StreamEvent
    | RateLimitEvent
)

UserMessage

Messaggio di input dell’utente.
@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
CampoTipoDescrizione
contentstr | list[ContentBlock]Contenuto del messaggio come testo o blocchi di contenuto
uuidstr | NoneIdentificatore di messaggio univoco
parent_tool_use_idstr | NoneID di utilizzo dello strumento se questo messaggio è una risposta al risultato dello strumento
tool_use_resultdict[str, Any] | NoneDati del risultato dello strumento se applicabile

AssistantMessage

Messaggio di risposta dell’assistente con blocchi di contenuto.
@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
CampoTipoDescrizione
contentlist[ContentBlock]Elenco di blocchi di contenuto nella risposta
modelstrModello che ha generato la risposta
parent_tool_use_idstr | NoneID di utilizzo dello strumento se questa è una risposta nidificata
errorAssistantMessageError | NoneTipo di errore se la risposta ha riscontrato un errore
usagedict[str, Any] | NoneUtilizzo dei token per messaggio (stesse chiavi di ResultMessage.usage)
message_idstr | NoneID del messaggio API. Più messaggi da un turno condividono lo stesso ID

AssistantMessageError

Possibili tipi di errore per i messaggi dell’assistente.
AssistantMessageError = Literal[
    "authentication_failed",
    "billing_error",
    "rate_limit",
    "invalid_request",
    "server_error",
    "max_output_tokens",
    "unknown",
]

SystemMessage

Messaggio di sistema con metadati.
@dataclass
class SystemMessage:
    subtype: str
    data: dict[str, Any]

ResultMessage

Messaggio di risultato finale con informazioni su costo e utilizzo.
@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
Il dict usage contiene le seguenti chiavi quando presenti:
ChiaveTipoDescrizione
input_tokensintToken di input totali consumati.
output_tokensintToken di output totali generati.
cache_creation_input_tokensintToken utilizzati per creare nuove voci di cache.
cache_read_input_tokensintToken letti dalle voci di cache esistenti.
Il dict model_usage mappa i nomi dei modelli all’utilizzo per modello. Le chiavi del dict interno usano camelCase perché il valore viene passato senza modifiche dal processo CLI sottostante, corrispondendo al tipo TypeScript ModelUsage:
ChiaveTipoDescrizione
inputTokensintToken di input per questo modello.
outputTokensintToken di output per questo modello.
cacheReadInputTokensintToken di lettura della cache per questo modello.
cacheCreationInputTokensintToken di creazione della cache per questo modello.
webSearchRequestsintRichieste di ricerca web effettuate da questo modello.
costUSDfloatCosto stimato in USD per questo modello, calcolato lato client. Vedi Traccia costo e utilizzo per avvertenze di fatturazione.
contextWindowintDimensione della finestra di contesto per questo modello.
maxOutputTokensintLimite massimo di token di output per questo modello.

StreamEvent

Evento di flusso per aggiornamenti di messaggi parziali durante lo streaming. Ricevuto solo quando include_partial_messages=True in ClaudeAgentOptions. Importa tramite 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
CampoTipoDescrizione
uuidstrIdentificatore univoco per questo evento
session_idstrIdentificatore di sessione
eventdict[str, Any]I dati dell’evento di flusso dell’API Claude grezzo
parent_tool_use_idstr | NoneID di utilizzo dello strumento padre se questo evento proviene da un subagente

RateLimitEvent

Emesso quando lo stato del limite di velocità cambia (ad esempio, da "allowed" a "allowed_warning"). Usalo per avvertire gli utenti prima che raggiungano un limite rigido, o per fare backoff quando lo stato è "rejected".
@dataclass
class RateLimitEvent:
    rate_limit_info: RateLimitInfo
    uuid: str
    session_id: str
CampoTipoDescrizione
rate_limit_infoRateLimitInfoStato del limite di velocità corrente
uuidstrIdentificatore di evento univoco
session_idstrIdentificatore di sessione

RateLimitInfo

Stato del limite di velocità trasportato da 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)
CampoTipoDescrizione
statusRateLimitStatusStato corrente. "allowed_warning" significa avvicinarsi al limite; "rejected" significa che il limite è stato raggiunto
resets_atint | NoneTimestamp Unix quando la finestra del limite di velocità si ripristina
rate_limit_typeRateLimitType | NoneQuale finestra del limite di velocità si applica
utilizationfloat | NoneFrazione del limite di velocità consumato (0.0 a 1.0)
overage_statusRateLimitStatus | NoneStato dell’utilizzo di overage pay-as-you-go, se applicabile
overage_resets_atint | NoneTimestamp Unix quando la finestra di overage si ripristina
overage_disabled_reasonstr | NonePerché l’overage non è disponibile, se lo stato è "rejected"
rawdict[str, Any]Dict grezzo completo dalla CLI, inclusi i campi non modellati sopra

TaskStartedMessage

Emesso quando un’attività in background inizia. Un’attività in background è qualsiasi cosa tracciata al di fuori del turno principale: un comando Bash in background, un watch Monitor, un subagente generato tramite lo strumento Agent, o un agente remoto. Il campo task_type ti dice quale. Questo nome non è correlato al rinomina dello strumento Task-to-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
CampoTipoDescrizione
task_idstrIdentificatore univoco per l’attività
descriptionstrDescrizione dell’attività
uuidstrIdentificatore di messaggio univoco
session_idstrIdentificatore di sessione
tool_use_idstr | NoneID di utilizzo dello strumento associato
task_typestr | NoneQuale tipo di attività in background: "local_bash" per Bash in background e watch Monitor, "local_agent", o "remote_agent"

TaskUsage

Dati di token e timing per un’attività in background.
class TaskUsage(TypedDict):
    total_tokens: int
    tool_uses: int
    duration_ms: int

TaskProgressMessage

Emesso periodicamente con aggiornamenti di progresso per un’attività in background in esecuzione.
@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
CampoTipoDescrizione
task_idstrIdentificatore univoco per l’attività
descriptionstrDescrizione dello stato corrente
usageTaskUsageUtilizzo dei token per questa attività finora
uuidstrIdentificatore di messaggio univoco
session_idstrIdentificatore di sessione
tool_use_idstr | NoneID di utilizzo dello strumento associato
last_tool_namestr | NoneNome dell’ultimo strumento utilizzato dall’attività

TaskNotificationMessage

Emesso quando un’attività in background si completa, fallisce o viene interrotta. Le attività in background includono comandi Bash run_in_background, watch Monitor e subagenti in background.
@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
CampoTipoDescrizione
task_idstrIdentificatore univoco per l’attività
statusTaskNotificationStatusUno di "completed", "failed", o "stopped"
output_filestrPercorso al file di output dell’attività
summarystrRiepilogo del risultato dell’attività
uuidstrIdentificatore di messaggio univoco
session_idstrIdentificatore di sessione
tool_use_idstr | NoneID di utilizzo dello strumento associato
usageTaskUsage | NoneUtilizzo dei token finale per l’attività

Tipi di blocco di contenuto

ContentBlock

Tipo di unione di tutti i blocchi di contenuto.
ContentBlock = TextBlock | ThinkingBlock | ToolUseBlock | ToolResultBlock

TextBlock

Blocco di contenuto di testo.
@dataclass
class TextBlock:
    text: str

ThinkingBlock

Blocco di contenuto di pensiero (per modelli con capacità di pensiero).
@dataclass
class ThinkingBlock:
    thinking: str
    signature: str

ToolUseBlock

Blocco di richiesta di utilizzo dello strumento.
@dataclass
class ToolUseBlock:
    id: str
    name: str
    input: dict[str, Any]

ToolResultBlock

Blocco di risultato dell’esecuzione dello strumento.
@dataclass
class ToolResultBlock:
    tool_use_id: str
    content: str | list[dict[str, Any]] | None = None
    is_error: bool | None = None

Tipi di errore

ClaudeSDKError

Classe di eccezione base per tutti gli errori dell’SDK.
class ClaudeSDKError(Exception):
    """Base error for Claude SDK."""

CLINotFoundError

Generato quando Claude Code CLI non è installato o non viene trovato.
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

Generato quando la connessione a Claude Code fallisce.
class CLIConnectionError(ClaudeSDKError):
    """Failed to connect to Claude Code."""

ProcessError

Generato quando il processo Claude Code fallisce.
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

Generato quando l’analisi JSON fallisce.
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

Tipi di Hook

Per una guida completa sull’utilizzo degli hooks con esempi e modelli comuni, vedi la guida Hooks.

HookEvent

Tipi di evento hook supportati.
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
]
TypeScript SDK supporta eventi hook aggiuntivi non ancora disponibili in Python: SessionStart, SessionEnd, Setup, TeammateIdle, TaskCompleted, ConfigChange, WorktreeCreate, WorktreeRemove, PostToolBatch e MessageDisplay.

HookCallback

Definizione di tipo per le funzioni di callback hook.
HookCallback = Callable[[HookInput, str | None, HookContext], Awaitable[HookJSONOutput]]
Parametri:
  • input: Input hook fortemente tipizzato con unioni discriminate basate su hook_event_name (vedi HookInput)
  • tool_use_id: Identificatore di utilizzo dello strumento opzionale (per hook correlati allo strumento)
  • context: Contesto hook con informazioni aggiuntive
Restituisce un HookJSONOutput che può contenere:
  • decision: "block" per bloccare l’azione
  • systemMessage: Messaggio di avviso mostrato all’utente
  • hookSpecificOutput: Dati di output specifici dell’hook

HookContext

Informazioni di contesto passate ai callback hook.
class HookContext(TypedDict):
    signal: Any | None  # Future: abort signal support

HookMatcher

Configurazione per l’abbinamento degli hook a eventi o strumenti specifici.
@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

Tipo di unione di tutti i tipi di input hook. Il tipo effettivo dipende dal campo hook_event_name.
HookInput = (
    PreToolUseHookInput
    | PostToolUseHookInput
    | PostToolUseFailureHookInput
    | UserPromptSubmitHookInput
    | StopHookInput
    | SubagentStopHookInput
    | PreCompactHookInput
    | NotificationHookInput
    | SubagentStartHookInput
    | PermissionRequestHookInput
)

BaseHookInput

Campi di base presenti in tutti i tipi di input hook.
class BaseHookInput(TypedDict):
    session_id: str
    transcript_path: str
    cwd: str
    permission_mode: NotRequired[str]
CampoTipoDescrizione
session_idstrIdentificatore di sessione corrente
transcript_pathstrPercorso al file di trascritto della sessione
cwdstrDirectory di lavoro corrente
permission_modestr (opzionale)Modalità di autorizzazione corrente

PreToolUseHookInput

Dati di input per gli eventi 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]
CampoTipoDescrizione
hook_event_nameLiteral["PreToolUse"]Sempre “PreToolUse”
tool_namestrNome dello strumento che sta per essere eseguito
tool_inputdict[str, Any]Parametri di input per lo strumento
tool_use_idstrIdentificatore univoco per questo utilizzo dello strumento
agent_idstr (opzionale)Identificatore del subagente, presente quando l’hook si attiva all’interno di un subagente
agent_typestr (opzionale)Tipo di subagente, presente quando l’hook si attiva all’interno di un subagente

PostToolUseHookInput

Dati di input per gli eventi 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]
CampoTipoDescrizione
hook_event_nameLiteral["PostToolUse"]Sempre “PostToolUse”
tool_namestrNome dello strumento che è stato eseguito
tool_inputdict[str, Any]Parametri di input che sono stati utilizzati
tool_responseAnyRisposta dall’esecuzione dello strumento
tool_use_idstrIdentificatore univoco per questo utilizzo dello strumento
agent_idstr (opzionale)Identificatore del subagente, presente quando l’hook si attiva all’interno di un subagente
agent_typestr (opzionale)Tipo di subagente, presente quando l’hook si attiva all’interno di un subagente

PostToolUseFailureHookInput

Dati di input per gli eventi hook PostToolUseFailure. Chiamato quando l’esecuzione di uno strumento fallisce.
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]
CampoTipoDescrizione
hook_event_nameLiteral["PostToolUseFailure"]Sempre “PostToolUseFailure”
tool_namestrNome dello strumento che ha fallito
tool_inputdict[str, Any]Parametri di input che sono stati utilizzati
tool_use_idstrIdentificatore univoco per questo utilizzo dello strumento
errorstrMessaggio di errore dall’esecuzione fallita
is_interruptbool (opzionale)Se il fallimento è stato causato da un’interruzione
agent_idstr (opzionale)Identificatore del subagente, presente quando l’hook si attiva all’interno di un subagente
agent_typestr (opzionale)Tipo di subagente, presente quando l’hook si attiva all’interno di un subagente

UserPromptSubmitHookInput

Dati di input per gli eventi hook UserPromptSubmit.
class UserPromptSubmitHookInput(BaseHookInput):
    hook_event_name: Literal["UserPromptSubmit"]
    prompt: str
CampoTipoDescrizione
hook_event_nameLiteral["UserPromptSubmit"]Sempre “UserPromptSubmit”
promptstrIl prompt inviato dall’utente

StopHookInput

Dati di input per gli eventi hook Stop.
class StopHookInput(BaseHookInput):
    hook_event_name: Literal["Stop"]
    stop_hook_active: bool
CampoTipoDescrizione
hook_event_nameLiteral["Stop"]Sempre “Stop”
stop_hook_activeboolSe l’hook di arresto è attivo

SubagentStopHookInput

Dati di input per gli eventi hook SubagentStop.
class SubagentStopHookInput(BaseHookInput):
    hook_event_name: Literal["SubagentStop"]
    stop_hook_active: bool
    agent_id: str
    agent_transcript_path: str
    agent_type: str
CampoTipoDescrizione
hook_event_nameLiteral["SubagentStop"]Sempre “SubagentStop”
stop_hook_activeboolSe l’hook di arresto è attivo
agent_idstrIdentificatore univoco per il subagente
agent_transcript_pathstrPercorso al file di trascritto del subagente
agent_typestrTipo del subagente

PreCompactHookInput

Dati di input per gli eventi hook PreCompact.
class PreCompactHookInput(BaseHookInput):
    hook_event_name: Literal["PreCompact"]
    trigger: Literal["manual", "auto"]
    custom_instructions: str | None
CampoTipoDescrizione
hook_event_nameLiteral["PreCompact"]Sempre “PreCompact”
triggerLiteral["manual", "auto"]Cosa ha attivato la compattazione
custom_instructionsstr | NoneIstruzioni personalizzate per la compattazione

NotificationHookInput

Dati di input per gli eventi hook Notification.
class NotificationHookInput(BaseHookInput):
    hook_event_name: Literal["Notification"]
    message: str
    title: NotRequired[str]
    notification_type: str
CampoTipoDescrizione
hook_event_nameLiteral["Notification"]Sempre “Notification”
messagestrContenuto del messaggio di notifica
titlestr (opzionale)Titolo della notifica
notification_typestrTipo di notifica

SubagentStartHookInput

Dati di input per gli eventi hook SubagentStart.
class SubagentStartHookInput(BaseHookInput):
    hook_event_name: Literal["SubagentStart"]
    agent_id: str
    agent_type: str
CampoTipoDescrizione
hook_event_nameLiteral["SubagentStart"]Sempre “SubagentStart”
agent_idstrIdentificatore univoco per il subagente
agent_typestrTipo del subagente

PermissionRequestHookInput

Dati di input per gli eventi hook PermissionRequest. Consente agli hook di gestire le decisioni di autorizzazione a livello di programmazione.
class PermissionRequestHookInput(BaseHookInput):
    hook_event_name: Literal["PermissionRequest"]
    tool_name: str
    tool_input: dict[str, Any]
    permission_suggestions: NotRequired[list[Any]]
CampoTipoDescrizione
hook_event_nameLiteral["PermissionRequest"]Sempre “PermissionRequest”
tool_namestrNome dello strumento che richiede l’autorizzazione
tool_inputdict[str, Any]Parametri di input per lo strumento
permission_suggestionslist[Any] (opzionale)Aggiornamenti di autorizzazione suggeriti dalla CLI

HookJSONOutput

Tipo di unione per i valori di ritorno del callback hook.
HookJSONOutput = AsyncHookJSONOutput | SyncHookJSONOutput

SyncHookJSONOutput

Output hook sincrono con campi di controllo e decisione.
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]
Usa continue_ (con underscore) nel codice Python. Viene automaticamente convertito a continue quando inviato alla CLI.

HookSpecificOutput

Un TypedDict contenente il nome dell’evento hook e i campi specifici dell’evento. La forma dipende dal valore hookEventName. Per i dettagli completi sui campi disponibili per evento hook, vedi Controlla l’esecuzione con gli hooks. Un’unione discriminata di tipi di output specifici dell’evento. Il campo hookEventName determina quali campi sono validi.
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

Output hook asincrono che rinvia l’esecuzione dell’hook.
class AsyncHookJSONOutput(TypedDict):
    async_: Literal[True]  # Set to True to defer execution
    asyncTimeout: NotRequired[int]  # Timeout in milliseconds
Usa async_ (con underscore) nel codice Python. Viene automaticamente convertito a async quando inviato alla CLI.

Esempio di utilizzo di Hook

Questo esempio registra due hook: uno che blocca i comandi bash pericolosi come rm -rf /, e un altro che registra tutto l’utilizzo dello strumento per il controllo. L’hook di sicurezza viene eseguito solo sui comandi Bash (tramite il matcher), mentre l’hook di registrazione viene eseguito su tutti gli strumenti.
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)

Tipi di input/output dello strumento

Documentazione degli schemi di input/output per tutti gli strumenti Claude Code integrati. Mentre Python SDK non esporta questi come tipi, rappresentano la struttura degli input e output dello strumento nei messaggi.

Agent

Nome dello strumento: Agent (precedentemente Task, che è ancora accettato come alias) Input:
{
    "description": str,  # Una breve descrizione del compito (3-5 parole)
    "prompt": str,  # Il compito che l'agente deve eseguire
    "subagent_type": str,  # Il tipo di agente specializzato da utilizzare
}
Output:
{
    "result": str,  # Risultato finale dal subagente
    "usage": dict | None,  # Statistiche di utilizzo dei token
    "total_cost_usd": float | None,  # Costo totale stimato in USD
    "duration_ms": int | None,  # Durata dell'esecuzione in millisecondi
}

AskUserQuestion

Nome dello strumento: AskUserQuestion Chiede all’utente domande di chiarimento durante l’esecuzione. Vedi Gestisci approvazioni e input dell’utente per i dettagli di utilizzo. Input:
{
    "questions": [  # Domande da porre all'utente (1-4 domande)
        {
            "question": str,  # La domanda completa da porre all'utente
            "header": str,  # Etichetta molto breve visualizzata come chip/tag (max 12 caratteri)
            "options": [  # Le scelte disponibili (2-4 opzioni)
                {
                    "label": str,  # Testo visualizzato per questa opzione (1-5 parole)
                    "description": str,  # Spiegazione di cosa significa questa opzione
                }
            ],
            "multiSelect": bool,  # Impostare su true per consentire selezioni multiple
        }
    ],
    "answers": dict[str, str | list[str]] | None,
    # Risposte dell'utente popolate dal sistema di autorizzazione. Le risposte
    # multi-select possono essere un elenco di etichette o una stringa unita da virgole
}
Output:
{
    "questions": [  # Le domande che sono state poste
        {
            "question": str,
            "header": str,
            "options": [{"label": str, "description": str}],
            "multiSelect": bool,
        }
    ],
    "answers": dict[str, str],  # Mappa il testo della domanda alla stringa di risposta
    # Le risposte multi-select sono separate da virgole
}

Bash

Nome dello strumento: Bash Input:
{
    "command": str,  # Il comando da eseguire
    "timeout": int | None,  # Timeout opzionale in millisecondi (max 600000)
    "description": str | None,  # Descrizione chiara e concisa (5-10 parole)
    "run_in_background": bool | None,  # Impostare su true per eseguire in background
}
Output:
{
    "output": str,  # Output combinato di stdout e stderr
    "exitCode": int,  # Codice di uscita del comando
    "killed": bool | None,  # Se il comando è stato terminato a causa del timeout
    "shellId": str | None,  # ID della shell per i processi in background
}

Monitor

Nome dello strumento: Monitor Esegue uno script in background e fornisce ogni riga stdout a Claude come evento in modo che possa reagire senza polling. Monitor segue le stesse regole di autorizzazione di Bash. Vedi il riferimento dello strumento Monitor per il comportamento e la disponibilità del provider. Input:
{
    "command": str,  # Script shell; ogni riga stdout è un evento, exit termina il monitoraggio
    "description": str,  # Breve descrizione mostrata nelle notifiche
    "timeout_ms": int | None,  # Termina dopo questa scadenza (default 300000, max 3600000)
    "persistent": bool | None,  # Esegui per la durata della sessione; ferma con TaskStop
}
Output:
{
    "taskId": str,  # ID dell'attività di monitoraggio in background
    "timeoutMs": int,  # Scadenza del timeout in millisecondi (0 quando persistente)
    "persistent": bool | None,  # True quando in esecuzione fino a TaskStop o fine sessione
}

Edit

Nome dello strumento: Edit Input:
{
    "file_path": str,  # Il percorso assoluto del file da modificare
    "old_string": str,  # Il testo da sostituire
    "new_string": str,  # Il testo con cui sostituirlo
    "replace_all": bool | None,  # Sostituisci tutte le occorrenze (default False)
}
Output:
{
    "message": str,  # Messaggio di conferma
    "replacements": int,  # Numero di sostituzioni effettuate
    "file_path": str,  # Percorso del file che è stato modificato
}

Read

Nome dello strumento: Read Input:
{
    "file_path": str,  # Il percorso assoluto del file da leggere
    "offset": int | None,  # Il numero di riga da cui iniziare la lettura
    "limit": int | None,  # Il numero di righe da leggere
}
Output (File di testo):
{
    "content": str,  # Contenuto del file con numeri di riga
    "total_lines": int,  # Numero totale di righe nel file
    "lines_returned": int,  # Righe effettivamente restituite
}
Output (Immagini):
{
    "image": str,  # Dati dell'immagine codificati in Base64
    "mime_type": str,  # Tipo MIME dell'immagine
    "file_size": int,  # Dimensione del file in byte
}

Write

Nome dello strumento: Write Input:
{
    "file_path": str,  # Il percorso assoluto del file da scrivere
    "content": str,  # Il contenuto da scrivere nel file
}
Output:
{
    "message": str,  # Messaggio di successo
    "bytes_written": int,  # Numero di byte scritti
    "file_path": str,  # Percorso del file che è stato scritto
}

Glob

Nome dello strumento: Glob Input:
{
    "pattern": str,  # Il pattern glob per abbinare i file
    "path": str | None,  # La directory da cercare (default cwd)
}
Output:
{
    "matches": list[str],  # Array dei percorsi dei file corrispondenti
    "count": int,  # Numero di corrispondenze trovate
    "search_path": str,  # Directory di ricerca utilizzata
}

Grep

Nome dello strumento: Grep Input:
{
    "pattern": str,  # Il pattern di espressione regolare
    "path": str | None,  # File o directory da cercare
    "glob": str | None,  # Pattern glob per filtrare i file
    "type": str | None,  # Tipo di file da cercare
    "output_mode": str | None,  # "content", "files_with_matches", o "count"
    "-i": bool | None,  # Ricerca senza distinzione maiuscole/minuscole
    "-n": bool | None,  # Mostra i numeri di riga
    "-B": int | None,  # Righe da mostrare prima di ogni corrispondenza
    "-A": int | None,  # Righe da mostrare dopo ogni corrispondenza
    "-C": int | None,  # Righe da mostrare prima e dopo
    "head_limit": int | None,  # Limita l'output alle prime N righe/voci
    "multiline": bool | None,  # Abilita la modalità multilinea
}
Output (modalità content):
{
    "matches": [
        {
            "file": str,
            "line_number": int | None,
            "line": str,
            "before_context": list[str] | None,
            "after_context": list[str] | None,
        }
    ],
    "total_matches": int,
}
Output (modalità files_with_matches):
{
    "files": list[str],  # File contenenti corrispondenze
    "count": int,  # Numero di file con corrispondenze
}

NotebookEdit

Nome dello strumento: NotebookEdit Input:
{
    "notebook_path": str,  # Percorso assoluto del notebook Jupyter
    "cell_id": str | None,  # L'ID della cella da modificare
    "new_source": str,  # La nuova sorgente per la cella
    "cell_type": "code" | "markdown" | None,  # Il tipo della cella
    "edit_mode": "replace" | "insert" | "delete" | None,  # Tipo di operazione di modifica
}
Output:
{
    "message": str,  # Messaggio di successo
    "edit_type": "replaced" | "inserted" | "deleted",  # Tipo di modifica eseguita
    "cell_id": str | None,  # ID della cella interessata
    "total_cells": int,  # Numero totale di celle nel notebook dopo la modifica
}

WebFetch

Nome dello strumento: WebFetch Input:
{
    "url": str,  # L'URL da cui recuperare il contenuto
    "prompt": str,  # Il prompt da eseguire sul contenuto recuperato
}
Output:
{
    "bytes": int,  # Dimensione del contenuto recuperato in byte
    "code": int,  # Codice di risposta HTTP
    "codeText": str,  # Testo del codice di risposta HTTP
    "result": str,  # Risultato elaborato dall'applicazione del prompt al contenuto
    "durationMs": int,  # Tempo per recuperare ed elaborare il contenuto, in millisecondi
    "url": str,  # URL che è stato recuperato
}

WebSearch

Nome dello strumento: WebSearch Input:
{
    "query": str,  # La query di ricerca da utilizzare
    "allowed_domains": list[str] | None,  # Includi solo risultati da questi domini
    "blocked_domains": list[str] | None,  # Non includere mai risultati da questi domini
}
Output:
{
    "query": str,  # La query di ricerca
    "results": list[str | {"tool_use_id": str, "content": list[{"title": str, "url": str}]}],
    "durationSeconds": float,  # Durata della ricerca in secondi
}

TodoWrite

Nome dello strumento: TodoWrite
A partire da Claude Code v2.1.142, TodoWrite è disabilitato per impostazione predefinita. Utilizza invece TaskCreate, TaskGet, TaskUpdate e TaskList. Vedi Migra agli strumenti Task per aggiornare il tuo codice di monitoraggio, oppure imposta CLAUDE_CODE_ENABLE_TASKS=0 per ripristinare TodoWrite.
Input:
{
    "todos": [
        {
            "content": str,  # La descrizione del compito
            "status": "pending" | "in_progress" | "completed",  # Stato del compito
            "activeForm": str,  # Forma attiva della descrizione
        }
    ]
}
Output:
{
    "message": str,  # Messaggio di successo
    "stats": {"total": int, "pending": int, "in_progress": int, "completed": int},
}

TaskCreate

Nome dello strumento: TaskCreate Input:
{
    "subject": str,  # Titolo breve del compito
    "description": str,  # Corpo dettagliato del compito
    "activeForm": str | None,  # Etichetta al tempo presente mostrata mentre in corso
    "metadata": dict | None,  # Metadati arbitrari del chiamante
}
Output:
{
    "task": {"id": str, "subject": str},  # Compito creato con ID assegnato
}

TaskUpdate

Nome dello strumento: TaskUpdate Input:
{
    "taskId": str,  # ID del compito da modificare
    "status": Literal["pending", "in_progress", "completed", "deleted"] | None,
    "subject": str | None,
    "description": str | None,
    "activeForm": str | None,
    "addBlocks": list[str] | None,  # ID dei compiti che questo compito ora blocca
    "addBlockedBy": list[str] | None,  # ID dei compiti che ora bloccano questo compito
    "owner": str | None,
    "metadata": dict | None,
}
Output:
{
    "success": bool,
    "taskId": str,
    "updatedFields": list[str],  # Nomi dei campi che sono cambiati
    "error": str | None,
    "statusChange": {"from": str, "to": str} | None,
}

TaskGet

Nome dello strumento: TaskGet Input:
{
    "taskId": str,  # ID del compito da leggere
}
Output:
{
    "task": {
        "id": str,
        "subject": str,
        "description": str,
        "status": Literal["pending", "in_progress", "completed"],
        "blocks": list[str],
        "blockedBy": list[str],
    } | None,  # None quando l'ID non viene trovato
}

TaskList

Nome dello strumento: TaskList Input:
{}
Output:
{
    "tasks": [
        {
            "id": str,
            "subject": str,
            "status": Literal["pending", "in_progress", "completed"],
            "owner": str | None,
            "blockedBy": list[str],
        }
    ],
}

BashOutput

Nome dello strumento: BashOutput Input:
{
    "bash_id": str,  # L'ID della shell in background
    "filter": str | None,  # Regex opzionale per filtrare le righe di output
}
Output:
{
    "output": str,  # Nuovo output dall'ultimo controllo
    "status": "running" | "completed" | "failed",  # Stato attuale della shell
    "exitCode": int | None,  # Codice di uscita al completamento
}

KillBash

Nome dello strumento: KillBash Input:
{
    "shell_id": str  # L'ID della shell in background da terminare
}
Output:
{
    "message": str,  # Messaggio di successo
    "shell_id": str,  # ID della shell terminata
}

ExitPlanMode

Nome dello strumento: ExitPlanMode Input:
{
    "plan": str  # Il piano da eseguire dall'utente per l'approvazione
}
Output:
{
    "message": str,  # Messaggio di conferma
    "approved": bool | None,  # Se l'utente ha approvato il piano
}

ListMcpResources

Nome dello strumento: ListMcpResourcesTool Input:
{
    "server": str | None  # Nome del server opzionale per filtrare le risorse
}
Output:
{
    "resources": [
        {
            "uri": str,
            "name": str,
            "description": str | None,
            "mimeType": str | None,
            "server": str,
        }
    ],
    "total": int,
}

ReadMcpResource

Nome dello strumento: ReadMcpResourceTool Input:
{
    "server": str,  # Il nome del server MCP
    "uri": str,  # L'URI della risorsa da leggere
}
Output:
{
    "contents": [
        {"uri": str, "mimeType": str | None, "text": str | None, "blob": str | None}
    ],
    "server": str,
}

Funzionalità avanzate con ClaudeSDKClient

Costruire un’interfaccia di conversazione continua

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

Utilizzo di Hook per la modifica del comportamento

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

Monitoraggio del progresso in tempo reale

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

Utilizzo di esempio

Operazioni di file di base (usando 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())

Gestione degli errori

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

Modalità streaming con 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())

Utilizzo di strumenti personalizzati con 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())

Configurazione della Sandbox

SandboxSettings

Configurazione per il comportamento della sandbox. Usala per abilitare il sandboxing dei comandi e configurare le restrizioni di rete a livello di programmazione.
class SandboxSettings(TypedDict, total=False):
    enabled: bool
    autoAllowBashIfSandboxed: bool
    excludedCommands: list[str]
    allowUnsandboxedCommands: bool
    network: SandboxNetworkConfig
    ignoreViolations: SandboxIgnoreViolations
    enableWeakerNestedSandbox: bool
ProprietàTipoPredefinitoDescrizione
enabledboolFalseAbilita la modalità sandbox per l’esecuzione dei comandi
autoAllowBashIfSandboxedboolTrueApprova automaticamente i comandi bash quando la sandbox è abilitata
excludedCommandslist[str][]Comandi che sempre bypassano le restrizioni della sandbox (ad es. ["docker"]). Questi vengono eseguiti senza sandbox automaticamente senza coinvolgimento del modello
allowUnsandboxedCommandsboolTrueConsenti al modello di richiedere l’esecuzione di comandi al di fuori della sandbox. Quando True, il modello può impostare dangerouslyDisableSandbox nell’input dello strumento, che ricade nel sistema di autorizzazioni
networkSandboxNetworkConfigNoneConfigurazione della sandbox specifica della rete
ignoreViolationsSandboxIgnoreViolationsNoneConfigura quali violazioni della sandbox ignorare
enableWeakerNestedSandboxboolFalseAbilita una sandbox nidificata più debole per la compatibilità
La sandbox dipende dal supporto della piattaforma e, su Linux, da strumenti come bubblewrap e socat. Per impostazione predefinita, quando enabled è True ma la sandbox non può avviarsi, i comandi vengono eseguiti senza sandbox con un avviso su stderr. Questo comportamento predefinito differisce dall’SDK TypeScript, dove failIfUnavailable è predefinito su true.Imposta "failIfUnavailable": True nelle impostazioni della sandbox per interrompere invece. La chiave non è ancora dichiarata su SandboxSettings, ma l’SDK la inoltra a Claude Code, che la rispetta. query() quindi segnala un ResultMessage con subtype="error_during_execution" e il motivo in errors. Guarda quel sottotipo piuttosto che aspettarti che query() generi un’eccezione prima di cedere i messaggi.

Utilizzo di esempio

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)
Sicurezza del socket Unix: L’opzione allowUnixSockets può concedere l’accesso a potenti servizi di sistema. Ad esempio, consentire /var/run/docker.sock concede effettivamente l’accesso completo al sistema host tramite l’API Docker, bypassando l’isolamento della sandbox. Consenti solo i socket Unix strettamente necessari e comprendi le implicazioni di sicurezza di ognuno.

SandboxNetworkConfig

Configurazione specifica della rete per la modalità sandbox. Queste impostazioni si applicano ai comandi Bash in sandbox quando enabled è True nella SandboxSettings padre. Non limitano lo strumento WebFetch, che utilizza invece regole di autorizzazione.
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
ProprietàTipoPredefinitoDescrizione
allowedDomainslist[str][]Nomi di dominio a cui i processi in sandbox possono accedere
deniedDomainslist[str][]Nomi di dominio a cui i processi in sandbox non possono accedere. Ha la precedenza su allowedDomains
allowManagedDomainsOnlyboolFalseSolo impostazioni gestite: quando impostato nelle impostazioni gestite, ignora allowedDomains da fonti di impostazioni non gestite. Non ha effetto quando impostato tramite opzioni SDK
allowUnixSocketslist[str][]Percorsi dei socket Unix a cui i processi possono accedere (ad es. socket Docker)
allowAllUnixSocketsboolFalseConsenti l’accesso a tutti i socket Unix
allowLocalBindingboolFalseConsenti ai processi di associarsi alle porte locali (ad es. per server di sviluppo)
allowMachLookuplist[str][]Solo macOS: nomi dei servizi XPC/Mach da consentire. Supporta un carattere jolly finale
httpProxyPortintNonePorta proxy HTTP per le richieste di rete
socksProxyPortintNonePorta proxy SOCKS per le richieste di rete
Il proxy sandbox integrato applica l’allowlist di rete in base al nome host richiesto e non termina o ispeziona il traffico TLS, quindi tecniche come il domain fronting possono potenzialmente bypassarlo. Vedi Limitazioni di sicurezza del sandboxing per i dettagli e Distribuzione sicura per configurare un proxy che termina TLS.

SandboxIgnoreViolations

Configurazione per ignorare violazioni specifiche della sandbox.
class SandboxIgnoreViolations(TypedDict, total=False):
    file: list[str]
    network: list[str]
ProprietàTipoPredefinitoDescrizione
filelist[str][]Modelli di percorso file per cui ignorare le violazioni
networklist[str][]Modelli di rete per cui ignorare le violazioni

Fallback delle autorizzazioni per i comandi senza sandbox

Quando allowUnsandboxedCommands è abilitato, il modello può richiedere di eseguire comandi al di fuori della sandbox impostando dangerouslyDisableSandbox: True nell’input dello strumento. Queste richieste ricadono nel sistema di autorizzazioni esistente, il che significa che il tuo handler can_use_tool verrà invocato, permettendoti di implementare una logica di autorizzazione personalizzata.
excludedCommands vs allowUnsandboxedCommands:
  • excludedCommands: Un elenco statico di comandi che sempre bypassano la sandbox automaticamente (ad es. ["docker"]). Il modello non ha controllo su questo.
  • allowUnsandboxedCommands: Consenti al modello di decidere in fase di esecuzione se richiedere l’esecuzione senza sandbox impostando dangerouslyDisableSandbox: True nell’input dello strumento.
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)
Questo modello ti consente di:
  • Controllare le richieste del modello: Registra quando il modello richiede l’esecuzione senza sandbox
  • Implementare allowlist: Consenti solo comandi specifici di essere eseguiti senza sandbox
  • Aggiungere flussi di lavoro di approvazione: Richiedi un’autorizzazione esplicita per operazioni privilegiate
I comandi in esecuzione con dangerouslyDisableSandbox: True hanno accesso completo al sistema. Assicurati che il tuo handler can_use_tool validi queste richieste attentamente.Se permission_mode è impostato su bypassPermissions e allow_unsandboxed_commands è abilitato, il modello può autonomamente eseguire comandi al di fuori della sandbox senza alcun prompt di approvazione. Questa combinazione consente effettivamente al modello di sfuggire all’isolamento della sandbox silenziosamente.

Vedi anche