Pular para o conteúdo principal

Instalação

pip install claude-agent-sdk

Escolhendo entre query() e ClaudeSDKClient

O SDK Python fornece duas maneiras de interagir com Claude Code:

Comparação rápida

Recursoquery()ClaudeSDKClient
SessãoCria uma nova sessão por padrãoReutiliza a mesma sessão
ConversaTroca únicaMúltiplas trocas no mesmo contexto
ConexãoGerenciada automaticamenteControle manual
Entrada em Streaming✅ Suportado✅ Suportado
Interrupções❌ Não suportado✅ Suportado
hooks✅ Suportado✅ Suportado
Ferramentas Personalizadas✅ Suportado✅ Suportado
Continuar ChatManual via continue_conversation ou resume✅ Automático
Caso de UsoTarefas únicasConversas contínuas

Quando usar query() (tarefas únicas)

Melhor para:
  • Perguntas únicas onde você não precisa do histórico de conversa
  • Tarefas independentes que não requerem contexto de trocas anteriores
  • Scripts de automação simples
  • Quando você quer um novo começo cada vez

Quando usar ClaudeSDKClient (conversa contínua)

Melhor para:
  • Continuando conversas - Quando você precisa que Claude se lembre do contexto
  • Perguntas de acompanhamento - Construindo sobre respostas anteriores
  • Aplicações interativas - Interfaces de chat, REPLs
  • Lógica orientada por resposta - Quando a próxima ação depende da resposta de Claude
  • Controle de sessão - Gerenciando o ciclo de vida da conversa explicitamente

Funções

query()

Cria uma nova sessão para cada interação com Claude Code por padrão. Retorna um iterador assíncrono que produz mensagens conforme chegam. Cada chamada para query() começa do zero sem memória de interações anteriores, a menos que você passe continue_conversation=True ou resume em ClaudeAgentOptions. Veja Sessions.
async def query(
    *,
    prompt: str | AsyncIterable[dict[str, Any]],
    options: ClaudeAgentOptions | None = None,
    transport: Transport | None = None
) -> AsyncIterator[Message]

Parâmetros

ParâmetroTipoDescrição
promptstr | AsyncIterable[dict]O prompt de entrada como uma string ou iterável assíncrono para modo de streaming
optionsClaudeAgentOptions | NoneObjeto de configuração opcional (padrão para ClaudeAgentOptions() se None)
transportTransport | NoneTransport personalizado opcional para comunicação com o processo CLI

Retorna

Retorna um AsyncIterator[Message] que produz mensagens da conversa.

Exemplo - Com opções

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

Decorador para definir ferramentas MCP com segurança de tipo.
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]]

Parâmetros

ParâmetroTipoDescrição
namestrIdentificador único para a ferramenta
descriptionstrDescrição legível por humanos do que a ferramenta faz
input_schematype | dict[str, Any]Schema definindo os parâmetros de entrada da ferramenta (veja abaixo)
annotationsToolAnnotations | NoneAnotações MCP opcionais fornecendo dicas de comportamento aos clientes

Opções de schema de entrada

  1. Mapeamento de tipo simples (recomendado):
    {"text": str, "count": int, "enabled": bool}
    
  2. Formato JSON Schema (para validação complexa):
    {
        "type": "object",
        "properties": {
            "text": {"type": "string"},
            "count": {"type": "integer", "minimum": 0},
        },
        "required": ["text"],
    }
    

Retorna

Uma função decoradora que envolve a implementação da ferramenta e retorna uma instância SdkMcpTool.

Exemplo

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

Re-exportado de mcp.types (também disponível como from claude_agent_sdk import ToolAnnotations). Todos os campos são dicas opcionais; clientes não devem confiar neles para decisões de segurança.
CampoTipoPadrãoDescrição
titlestr | NoneNoneTítulo legível por humanos para a ferramenta
readOnlyHintbool | NoneFalseSe True, a ferramenta não modifica seu ambiente
destructiveHintbool | NoneTrueSe True, a ferramenta pode realizar atualizações destrutivas (apenas significativo quando readOnlyHint é False)
idempotentHintbool | NoneFalseSe True, chamadas repetidas com os mesmos argumentos não têm efeito adicional (apenas significativo quando readOnlyHint é False)
openWorldHintbool | NoneTrueSe True, a ferramenta interage com entidades externas (por exemplo, busca na web). Se False, o domínio da ferramenta é fechado (por exemplo, uma ferramenta de memória)
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()

Cria um servidor MCP em processo que é executado dentro de sua aplicação Python.
def create_sdk_mcp_server(
    name: str,
    version: str = "1.0.0",
    tools: list[SdkMcpTool[Any]] | None = None
) -> McpSdkServerConfig

Parâmetros

ParâmetroTipoPadrãoDescrição
namestr-Identificador único para o servidor
versionstr"1.0.0"String de versão do servidor
toolslist[SdkMcpTool[Any]] | NoneNoneLista de funções de ferramenta criadas com decorador @tool

Retorna

Retorna um objeto McpSdkServerConfig que pode ser passado para ClaudeAgentOptions.mcp_servers.

Exemplo

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

Lista sessões passadas com metadados. Filtre por diretório de projeto ou liste sessões em todos os projetos. Síncrono; retorna imediatamente.
def list_sessions(
    directory: str | None = None,
    limit: int | None = None,
    include_worktrees: bool = True
) -> list[SDKSessionInfo]

Parâmetros

ParâmetroTipoPadrãoDescrição
directorystr | NoneNoneDiretório para listar sessões. Quando omitido, retorna sessões em todos os projetos
limitint | NoneNoneNúmero máximo de sessões a retornar
include_worktreesboolTrueQuando directory está dentro de um repositório git, inclua sessões de todos os caminhos de worktree

Tipo de retorno: SDKSessionInfo

PropriedadeTipoDescrição
session_idstrIdentificador único de sessão
summarystrTítulo de exibição: título personalizado, resumo gerado automaticamente ou primeiro prompt
last_modifiedintHora da última modificação em milissegundos desde a época
file_sizeint | NoneTamanho do arquivo de sessão em bytes (None para backends de armazenamento remoto)
custom_titlestr | NoneTítulo de sessão definido pelo usuário
first_promptstr | NonePrimeiro prompt de usuário significativo na sessão
git_branchstr | NoneBranch Git no final da sessão
cwdstr | NoneDiretório de trabalho para a sessão
tagstr | NoneTag de sessão definida pelo usuário (veja tag_session())
created_atint | NoneHora de criação da sessão em milissegundos desde a época

Exemplo

Imprima as 10 sessões mais recentes para um projeto. Os resultados são classificados por last_modified descendente, então o primeiro item é o mais novo. Omita directory para pesquisar em todos os projetos.
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 mensagens de uma sessão passada. Síncrono; retorna imediatamente.
def get_session_messages(
    session_id: str,
    directory: str | None = None,
    limit: int | None = None,
    offset: int = 0
) -> list[SessionMessage]

Parâmetros

ParâmetroTipoPadrãoDescrição
session_idstrobrigatórioO ID da sessão para recuperar mensagens
directorystr | NoneNoneDiretório do projeto para procurar. Quando omitido, pesquisa todos os projetos
limitint | NoneNoneNúmero máximo de mensagens a retornar
offsetint0Número de mensagens a pular do início

Tipo de retorno: SessionMessage

PropriedadeTipoDescrição
typeLiteral["user", "assistant"]Papel da mensagem
uuidstrIdentificador único de mensagem
session_idstrIdentificador de sessão
messageAnyConteúdo bruto da mensagem
parent_tool_use_idNoneReservado para uso futuro

Exemplo

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

Lê metadados para uma única sessão por ID sem verificar o diretório do projeto completo. Síncrono; retorna imediatamente.
def get_session_info(
    session_id: str,
    directory: str | None = None,
) -> SDKSessionInfo | None

Parâmetros

ParâmetroTipoPadrãoDescrição
session_idstrobrigatórioUUID da sessão a procurar
directorystr | NoneNoneCaminho do diretório do projeto. Quando omitido, pesquisa todos os diretórios de projeto
Retorna SDKSessionInfo, ou None se a sessão não for encontrada.

Exemplo

Procure os metadados de uma única sessão sem verificar o diretório do projeto. Útil quando você já tem um ID de sessão de uma execução anterior.
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()

Renomeia uma sessão anexando uma entrada de título personalizado. Chamadas repetidas são seguras; o título mais recente vence. Síncrono.
def rename_session(
    session_id: str,
    title: str,
    directory: str | None = None,
) -> None

Parâmetros

ParâmetroTipoPadrãoDescrição
session_idstrobrigatórioUUID da sessão a renomear
titlestrobrigatórioNovo título. Deve ser não vazio após remover espaços em branco
directorystr | NoneNoneCaminho do diretório do projeto. Quando omitido, pesquisa todos os diretórios de projeto
Lança ValueError se session_id não for um UUID válido ou title estiver vazio; FileNotFoundError se a sessão não puder ser encontrada.

Exemplo

Renomeie a sessão mais recente para que seja mais fácil encontrá-la depois. O novo título aparece em SDKSessionInfo.custom_title em leituras subsequentes.
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()

Marca uma sessão. Passe None para limpar a tag. Chamadas repetidas são seguras; a tag mais recente vence. Síncrono.
def tag_session(
    session_id: str,
    tag: str | None,
    directory: str | None = None,
) -> None

Parâmetros

ParâmetroTipoPadrãoDescrição
session_idstrobrigatórioUUID da sessão a marcar
tagstr | NoneobrigatórioString de tag, ou None para limpar. Unicode-sanitizado antes de armazenar
directorystr | NoneNoneCaminho do diretório do projeto. Quando omitido, pesquisa todos os diretórios de projeto
Lança ValueError se session_id não for um UUID válido ou tag estiver vazio após sanitização; FileNotFoundError se a sessão não puder ser encontrada.

Exemplo

Marque uma sessão e depois filtre por essa tag em uma leitura posterior. Passe None para limpar uma tag existente.
from claude_agent_sdk import list_sessions, tag_session

# Tag a session
tag_session("550e8400-e29b-41d4-a716-446655440000", "needs-review")

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

Classes

ClaudeSDKClient

Mantém uma sessão de conversa em múltiplas trocas. Este é o equivalente Python de como a função query() do SDK TypeScript funciona internamente - cria um objeto cliente que pode continuar conversas.

Recursos principais

  • Continuidade de sessão: Mantém contexto de conversa em múltiplas chamadas query()
  • Mesma conversa: A sessão retém mensagens anteriores
  • Suporte a interrupção: Pode parar a execução no meio da tarefa
  • Ciclo de vida explícito: Você controla quando a sessão começa e termina
  • Fluxo orientado por resposta: Pode reagir a respostas e enviar acompanhamentos
  • Ferramentas e hooks personalizados: Suporta ferramentas personalizadas (criadas com decorador @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

Métodos

MétodoDescrição
__init__(options)Inicializa o cliente com configuração opcional
connect(prompt)Conecta a Claude com um prompt inicial opcional ou fluxo de mensagem
query(prompt, session_id)Envia uma nova solicitação em modo de streaming
receive_messages()Recebe todas as mensagens de Claude como um iterador assíncrono
receive_response()Recebe mensagens até e incluindo uma ResultMessage
interrupt()Envia sinal de interrupção (funciona apenas em modo de streaming)
set_permission_mode(mode)Altera o modo de permissão para a sessão atual
set_model(model)Altera o modelo para a sessão atual. Passe None para redefinir para padrão
rewind_files(user_message_id)Restaura arquivos para seu estado na mensagem de usuário especificada. Requer enable_file_checkpointing=True. Veja File checkpointing
get_mcp_status()Obtém o status de todos os servidores MCP configurados. Retorna McpStatusResponse
reconnect_mcp_server(server_name)Tenta reconectar a um servidor MCP que falhou ou foi desconectado
toggle_mcp_server(server_name, enabled)Ativa ou desativa um servidor MCP no meio da sessão. Desativar remove suas ferramentas
stop_task(task_id)Para uma tarefa de fundo em execução. Uma TaskNotificationMessage com status "stopped" segue no fluxo de mensagens
get_server_info()Obtém informações do servidor incluindo ID de sessão e capacidades
disconnect()Desconecta de Claude

Suporte a Gerenciador de Contexto

O cliente pode ser usado como um gerenciador de contexto assíncrono para gerenciamento automático de conexão:
async with ClaudeSDKClient() as client:
    await client.query("Hello Claude")
    async for message in client.receive_response():
        print(message)
Importante: Ao iterar sobre mensagens, evite usar break para sair cedo, pois isso pode causar problemas de limpeza do asyncio. Em vez disso, deixe a iteração ser concluída naturalmente ou use sinalizadores para rastrear quando você encontrou o que precisa.

Exemplo - Continuando uma conversa

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

Exemplo - Entrada em streaming com 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())

Exemplo - Usando interrupções

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 do buffer após interrupção: interrupt() envia um sinal de parada mas não limpa o buffer de mensagens. Mensagens já produzidas pela tarefa interrompida, incluindo sua ResultMessage (com subtype="error_during_execution"), permanecem no fluxo. Você deve drená-las com receive_response() antes de ler a resposta a uma nova consulta. Se você enviar uma nova consulta imediatamente após interrupt() e chamar receive_response() apenas uma vez, você receberá as mensagens da tarefa interrompida, não a resposta da nova consulta.

Exemplo - Controle avançado de permissão

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

Tipos

@dataclass vs TypedDict: Este SDK usa dois tipos de tipos. Classes decoradas com @dataclass (como ResultMessage, AgentDefinition, TextBlock) são instâncias de objeto em tempo de execução e suportam acesso a atributos: msg.result. Classes definidas com TypedDict (como ThinkingConfigEnabled, McpStdioServerConfig, SyncHookJSONOutput) são dicts simples em tempo de execução e requerem acesso a chave: config["budget_tokens"], não config.budget_tokens. A sintaxe de chamada ClassName(field=value) funciona para ambos, mas apenas dataclasses produzem objetos com atributos.

SdkMcpTool

Definição para uma ferramenta SDK MCP criada com o decorador @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
PropriedadeTipoDescrição
namestrIdentificador único para a ferramenta
descriptionstrDescrição legível por humanos
input_schematype[T] | dict[str, Any]Schema para validação de entrada
handlerCallable[[T], Awaitable[dict[str, Any]]]Função assíncrona que manipula a execução da ferramenta
annotationsToolAnnotations | NoneAnotações MCP opcionais (por exemplo, readOnlyHint, destructiveHint, openWorldHint). De mcp.types

Transport

Classe base abstrata para implementações de transport personalizado. Use isso para comunicar com o processo Claude sobre um canal personalizado (por exemplo, uma conexão remota em vez de um subprocess local).
Esta é uma API interna de baixo nível. A interface pode mudar em versões futuras. Implementações personalizadas devem ser atualizadas para corresponder a qualquer mudança de interface.
from abc import ABC, abstractmethod
from collections.abc import AsyncIterator
from typing import Any


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

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

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

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

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

    @abstractmethod
    async def end_input(self) -> None: ...
MétodoDescrição
connect()Conecta o transport e prepara para comunicação
write(data)Escreve dados brutos (JSON + nova linha) para o transport
read_messages()Iterador assíncrono que produz mensagens JSON analisadas
close()Fecha a conexão e limpa recursos
is_ready()Retorna True se o transport pode enviar e receber
end_input()Fecha o fluxo de entrada (por exemplo, fechar stdin para transports de subprocess)
Importação: from claude_agent_sdk import Transport

ClaudeAgentOptions

Dataclass de configuração para consultas 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"
PropriedadeTipoPadrãoDescrição
toolslist[str] | ToolsPreset | NoneNoneConfiguração de ferramentas. Use {"type": "preset", "preset": "claude_code"} para as ferramentas padrão do Claude Code
allowed_toolslist[str][]Ferramentas para auto-aprovar sem solicitar. Isso não restringe Claude apenas a essas ferramentas; ferramentas não listadas caem através de permission_mode e can_use_tool. Use disallowed_tools para bloquear ferramentas. Veja Permissions
system_promptstr | SystemPromptPreset | NoneNoneConfiguração de prompt do sistema. Passe uma string para prompt personalizado, ou use {"type": "preset", "preset": "claude_code"} para o prompt do sistema do Claude Code. Adicione "append" para estender o preset
mcp_serversdict[str, McpServerConfig] | str | Path{}Configurações de servidor MCP ou caminho para arquivo de configuração
strict_mcp_configboolFalseQuando True, use apenas os servidores passados em mcp_servers e ignore o projeto .mcp.json, configurações do usuário, servidores MCP fornecidos por plugins e conectores claude.ai. Mapeia para o sinalizador CLI --strict-mcp-config
permission_modePermissionMode | NoneNoneModo de permissão para uso de ferramentas
continue_conversationboolFalseContinua a conversa mais recente
resumestr | NoneNoneID de sessão para retomar
max_turnsint | NoneNoneNúmero máximo de turnos agênticos (rodadas de uso de ferramenta)
max_budget_usdfloat | NoneNonePara a consulta quando a estimativa de custo do lado do cliente atinge este valor em USD. Comparado com a mesma estimativa que total_cost_usd; veja Track cost and usage para ressalvas de precisão
disallowed_toolslist[str][]Ferramentas para negar. Um nome simples como "Bash" remove a ferramenta do contexto do Claude. Uma regra com escopo como "Bash(rm *)" deixa a ferramenta disponível e nega chamadas correspondentes em todos os modos de permissão, incluindo bypassPermissions. Veja Permissions
enable_file_checkpointingboolFalseAtiva rastreamento de mudança de arquivo para retrocesso. Veja File checkpointing
modelstr | NoneNoneModelo Claude a usar
fallback_modelstr | NoneNoneModelo de fallback a usar se o modelo primário falhar
betaslist[SdkBeta][]Recursos beta para ativar. Veja SdkBeta para opções disponíveis
output_formatdict[str, Any] | NoneNoneFormato de saída para respostas estruturadas (por exemplo, {"type": "json_schema", "schema": {...}}). Veja Structured outputs para detalhes
permission_prompt_tool_namestr | NoneNoneNome da ferramenta MCP para prompts de permissão
cwdstr | Path | NoneNoneDiretório de trabalho atual
cli_pathstr | Path | NoneNoneCaminho personalizado para o executável CLI do Claude Code
settingsstr | NoneNoneCaminho para arquivo de configurações
add_dirslist[str | Path][]Diretórios adicionais que Claude pode acessar
envdict[str, str]{}Variáveis de ambiente mescladas no topo do ambiente de processo herdado. Veja Environment variables para variáveis que o CLI subjacente lê, e Handle slow or stalled API responses para variáveis relacionadas a timeout
extra_argsdict[str, str | None]{}Argumentos CLI adicionais a passar diretamente para o CLI
max_buffer_sizeint | NoneNoneBytes máximos ao fazer buffer da saída padrão do CLI
debug_stderrAnysys.stderrDeprecated - Objeto semelhante a arquivo para saída de depuração. Use callback stderr em vez disso
stderrCallable[[str], None] | NoneNoneFunção de callback para saída stderr do CLI
can_use_toolCanUseTool | NoneNoneFunção de callback de permissão de ferramenta. Veja Permission types para detalhes
hooksdict[HookEvent, list[HookMatcher]] | NoneNoneConfigurações de hook para interceptar eventos
userstr | NoneNoneIdentificador de usuário
include_partial_messagesboolFalseInclua eventos de streaming de mensagem parcial. Quando ativado, mensagens StreamEvent são produzidas
include_hook_eventsboolFalseInclua eventos de ciclo de vida de hook no fluxo de mensagens como objetos HookEventMessage
fork_sessionboolFalseAo retomar com resume, bifurque para um novo ID de sessão em vez de continuar a sessão original
agentsdict[str, AgentDefinition] | NoneNoneSubagentes definidos programaticamente
pluginslist[SdkPluginConfig][]Carregue plugins personalizados de caminhos locais. Veja Plugins para detalhes
sandboxSandboxSettings | NoneNoneConfigure o comportamento do sandbox programaticamente. Veja Sandbox settings para detalhes
setting_sourceslist[SettingSource] | NoneNone (CLI defaults: all sources)Controle quais configurações do sistema de arquivos carregar. Passe [] para desabilitar configurações de usuário, projeto e local. Configurações de política gerenciada carregam independentemente. Veja Use Claude Code features
skillslist[str] | Literal["all"] | NoneNoneSkills disponíveis para a sessão. Passe "all" para ativar cada skill descoberto, ou uma lista de nomes de skills. Quando definido, o SDK ativa a ferramenta Skill automaticamente sem listá-la em allowed_tools. Veja Skills
max_thinking_tokensint | NoneNoneDeprecated - Tokens máximos para blocos de pensamento. Use thinking em vez disso
thinkingThinkingConfig | NoneNoneControla o comportamento de pensamento estendido. Tem precedência sobre max_thinking_tokens
effortEffortLevel | NoneNoneNível de esforço para profundidade de pensamento
session_storeSessionStore | NoneNoneEspelhe transcrições de sessão para um backend externo para que qualquer host possa retomá-las. Veja Persist sessions to external storage
session_store_flushLiteral["batched", "eager"]"batched"Quando fazer flush das entradas de transcrição espelhadas para session_store. "batched" faz flush uma vez por turno ou quando o buffer enche; "eager" dispara um flush de fundo após cada frame. Ignorado quando session_store é None

Lidar com respostas de API lentas ou travadas

O subprocess CLI lê várias variáveis de ambiente que controlam timeouts de API e detecção de travamento. Passe-as através de 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 por solicitação no cliente Anthropic, em milissegundos. Padrão 600000. Aplica-se ao loop principal e a todos os subagentes.
  • CLAUDE_CODE_MAX_RETRIES: máximo de tentativas de API. Padrão 10. Cada tentativa obtém sua própria janela API_TIMEOUT_MS, então o tempo de parede no pior caso é aproximadamente API_TIMEOUT_MS × (CLAUDE_CODE_MAX_RETRIES + 1) mais backoff.
  • CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS: watchdog de travamento para subagentes lançados com run_in_background. Padrão 600000. Redefine em cada evento de stream; em caso de travamento, aborta o subagente, marca a tarefa como falha e expõe o erro ao pai com qualquer resultado parcial. Não se aplica a subagentes síncronos.
  • CLAUDE_ENABLE_STREAM_WATCHDOG=1 com CLAUDE_STREAM_IDLE_TIMEOUT_MS: aborta a solicitação quando os cabeçalhos chegaram mas o corpo da resposta para de fazer stream. Desativado por padrão. CLAUDE_STREAM_IDLE_TIMEOUT_MS padrão é 300000 e é fixado nesse mínimo. A solicitação abortada passa pelo caminho de tentativa normal.

OutputFormat

Configuração para validação de saída estruturada. Passe isso como um dict para o campo output_format em ClaudeAgentOptions:
# Expected dict shape for output_format
{
    "type": "json_schema",
    "schema": {...},  # Your JSON Schema definition
}
CampoObrigatórioDescrição
typeSimDeve ser "json_schema" para validação JSON Schema
schemaSimDefinição JSON Schema para validação de saída

SystemPromptPreset

Configuração para usar o prompt do sistema preset do Claude Code com adições opcionais.
class SystemPromptPreset(TypedDict):
    type: Literal["preset"]
    preset: Literal["claude_code"]
    append: NotRequired[str]
    exclude_dynamic_sections: NotRequired[bool]
CampoObrigatórioDescrição
typeSimDeve ser "preset" para usar um prompt do sistema preset
presetSimDeve ser "claude_code" para usar o prompt do sistema do Claude Code
appendNãoInstruções adicionais para anexar ao prompt do sistema preset
exclude_dynamic_sectionsNãoMova contexto por sessão como diretório de trabalho, status git e caminhos de memória da prompt do sistema para a primeira mensagem do usuário. Melhora a reutilização de cache de prompt entre usuários e máquinas. Veja Modify system prompts

SettingSource

Controla quais fontes de configuração baseadas em sistema de arquivos o SDK carrega configurações.
SettingSource = Literal["user", "project", "local"]
ValorDescriçãoLocalização
"user"Configurações globais do usuário~/.claude/settings.json
"project"Configurações de projeto compartilhadas (controladas por versão).claude/settings.json
"local"Configurações de projeto local (gitignored).claude/settings.local.json

Comportamento padrão

Quando setting_sources é omitido ou None, query() carrega as mesmas configurações do sistema de arquivos que o CLI do Claude Code: usuário, projeto e local. Configurações de política gerenciada são carregadas em todos os casos. Veja What settingSources does not control para entradas que são lidas independentemente desta opção, e como desabilitá-las.

Por que usar setting_sources

Desabilitar configurações do sistema de arquivos:
# 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)
No Python SDK 0.1.59 e anterior, uma lista vazia era tratada da mesma forma que omitir a opção, então setting_sources=[] não desabilitava configurações do sistema de arquivos. Atualize para uma versão mais recente se você precisar que uma lista vazia tenha efeito. O SDK TypeScript não é afetado.
Carregue todas as configurações do sistema de arquivos explicitamente:
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)
Carregue apenas fontes de configuração específicas:
# 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)
Ambientes de teste 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)
Aplicações apenas 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)
Carregando instruções de projeto 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)

Precedência de configurações

Quando múltiplas fontes são carregadas, as configurações são mescladas com esta precedência (maior para menor):
  1. Configurações locais (.claude/settings.local.json)
  2. Configurações de projeto (.claude/settings.json)
  3. Configurações de usuário (~/.claude/settings.json)
Opções programáticas como agents e allowed_tools substituem configurações do sistema de arquivos de usuário, projeto e local. Configurações de política gerenciada têm precedência sobre opções programáticas.

AgentDefinition

Configuração para um subagente definido programaticamente.
@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
CampoObrigatórioDescrição
descriptionSimDescrição em linguagem natural de quando usar este agente
promptSimO prompt do sistema do agente
toolsNãoArray de nomes de ferramentas permitidas. Se omitido, herda todas as ferramentas
disallowedToolsNãoArray de nomes de ferramentas a remover do conjunto de ferramentas do agente
modelNãoSubstituição de modelo para este agente. Aceita um alias como "sonnet", "opus", "haiku", ou "inherit", ou um ID de modelo completo. Se omitido, usa o modelo principal
skillsNãoLista de nomes de skills a pré-carregar no contexto do agente na inicialização. Skills não listados permanecem invocáveis através da ferramenta Skill
memoryNãoFonte de memória para este agente: "user", "project", ou "local"
mcpServersNãoServidores MCP disponíveis para este agente. Cada entrada é um nome de servidor ou um dict {name: config} inline
initialPromptNãoAuto-enviado como o primeiro turno de usuário quando este agente é executado como o agente de thread principal
maxTurnsNãoNúmero máximo de turnos agênticos antes do agente parar
backgroundNãoExecute este agente como uma tarefa de fundo não bloqueante quando invocado
effortNãoNível de esforço de raciocínio para este agente. Aceita um nível nomeado ou um inteiro. Veja EffortLevel
permissionModeNãoModo de permissão para execução de ferramenta dentro deste agente. Veja PermissionMode
Os nomes de campo AgentDefinition usam camelCase, como disallowedTools, permissionMode e maxTurns. Esses nomes mapeiam diretamente para o formato de fio compartilhado com o SDK TypeScript. Isso difere de ClaudeAgentOptions, que usa snake_case Python para campos de nível superior equivalentes como disallowed_tools e permission_mode. Como AgentDefinition é uma dataclass, passar uma palavra-chave snake_case levanta um TypeError no tempo de construção.

PermissionMode

Modos de permissão para controlar a execução de ferramentas.
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

Níveis de esforço para guiar a profundidade de pensamento.
EffortLevel = Literal[
    "low",  # Minimal thinking, fastest responses
    "medium",  # Moderate thinking
    "high",  # Deep reasoning
    "xhigh",  # Extended reasoning (Opus 4.7 only; falls back to "high" on other models)
    "max",  # Maximum effort
]

CanUseTool

Alias de tipo para funções de callback de permissão de ferramenta.
CanUseTool = Callable[
    [str, dict[str, Any], ToolPermissionContext], Awaitable[PermissionResult]
]
O callback recebe:
  • tool_name: Nome da ferramenta sendo chamada
  • input_data: Os parâmetros de entrada da ferramenta
  • context: Um ToolPermissionContext com informações adicionais
Retorna um PermissionResult (ou PermissionResultAllow ou PermissionResultDeny).

ToolPermissionContext

Informações de contexto passadas para callbacks de permissão de ferramenta.
@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
CampoTipoDescrição
signalAny | NoneReservado para suporte futuro de sinal de aborto
suggestionslist[PermissionUpdate]Sugestões de atualização de permissão do CLI. Prompts Bash incluem uma sugestão com o destino localSettings, então retorná-la em updated_permissions escreve a regra em .claude/settings.local.json e persiste entre sessões.
blocked_pathstr | NoneCaminho de arquivo que acionou a solicitação de permissão, quando aplicável. Por exemplo, quando um comando Bash tenta acessar um caminho fora dos diretórios permitidos
decision_reasonstr | NoneRazão pela qual esta solicitação de permissão foi acionada. Encaminhada de um hook PreToolUse permissionDecisionReason quando o hook retornou "ask"
titlestr | NoneSentença completa do prompt de permissão, como Claude wants to read foo.txt. Use como o texto do prompt principal quando presente
display_namestr | NoneFrase de substantivo curta para a ação da ferramenta, como Read file, adequada para rótulos de botão
descriptionstr | NoneSubtítulo legível por humanos para a UI de permissão

PermissionResult

Tipo de união para resultados de callback de permissão.
PermissionResult = PermissionResultAllow | PermissionResultDeny

PermissionResultAllow

Resultado indicando que a chamada de ferramenta deve ser permitida.
@dataclass
class PermissionResultAllow:
    behavior: Literal["allow"] = "allow"
    updated_input: dict[str, Any] | None = None
    updated_permissions: list[PermissionUpdate] | None = None
CampoTipoPadrãoDescrição
behaviorLiteral["allow"]"allow"Deve ser “allow”
updated_inputdict[str, Any] | NoneNoneEntrada modificada a usar em vez da original
updated_permissionslist[PermissionUpdate] | NoneNoneAtualizações de permissão a aplicar

PermissionResultDeny

Resultado indicando que a chamada de ferramenta deve ser negada.
@dataclass
class PermissionResultDeny:
    behavior: Literal["deny"] = "deny"
    message: str = ""
    interrupt: bool = False
CampoTipoPadrãoDescrição
behaviorLiteral["deny"]"deny"Deve ser “deny”
messagestr""Mensagem explicando por que a ferramenta foi negada
interruptboolFalseSe deve interromper a execução atual

PermissionUpdate

Configuração para atualizar permissões programaticamente.
@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
CampoTipoDescrição
typeLiteral[...]O tipo de operação de atualização de permissão
ruleslist[PermissionRuleValue] | NoneRegras para operações de adicionar/substituir/remover
behaviorLiteral["allow", "deny", "ask"] | NoneComportamento para operações baseadas em regras
modePermissionMode | NoneModo para operação setMode
directorieslist[str] | NoneDiretórios para operações de adicionar/remover diretório
destinationLiteral[...] | NoneOnde aplicar a atualização de permissão

PermissionRuleValue

Uma regra a adicionar, substituir ou remover em uma atualização de permissão.
@dataclass
class PermissionRuleValue:
    tool_name: str
    rule_content: str | None = None

ToolsPreset

Configuração de ferramentas preset para usar o conjunto de ferramentas padrão do Claude Code.
class ToolsPreset(TypedDict):
    type: Literal["preset"]
    preset: Literal["claude_code"]

ThinkingConfig

Controla o comportamento de pensamento estendido. Uma união de três configurações:
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
VarianteCamposDescrição
adaptivetype, displayClaude decide adaptativamente quando pensar
enabledtype, budget_tokens, displayAtiva pensamento com um orçamento de token específico
disabledtypeDesativa pensamento
O campo opcional display controla se o texto de pensamento é retornado "summarized" ou "omitted". No Claude Opus 4.7 e posterior, o padrão da API é "omitted", então defina "summarized" para receber conteúdo de pensamento em saídas ThinkingBlock. Como estas são classes TypedDict, são dicts simples em tempo de execução. Construa-as como literais de dict ou chame a classe como um construtor; ambos produzem um dict. Acesse campos com config["budget_tokens"], não 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 literal para recursos beta do SDK.
SdkBeta = Literal["context-1m-2025-08-07"]
Use com o campo betas em ClaudeAgentOptions para ativar recursos beta.
O beta context-1m-2025-08-07 foi descontinuado a partir de 30 de abril de 2026. Passar este cabeçalho com Claude Sonnet 4.5 ou Sonnet 4 não tem efeito, e solicitações que excedem a janela de contexto padrão de 200k-token retornam um erro. Para usar uma janela de contexto de 1M-token, migre para Claude Sonnet 4.6, Claude Opus 4.6, ou Claude Opus 4.7, que incluem contexto de 1M a preços padrão sem cabeçalho beta necessário.

McpSdkServerConfig

Configuração para servidores MCP do SDK criados com create_sdk_mcp_server().
class McpSdkServerConfig(TypedDict):
    type: Literal["sdk"]
    name: str
    instance: Any  # MCP Server instance

McpServerConfig

Tipo de união para configurações de servidor 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

A configuração de um servidor MCP conforme relatado por get_mcp_status(). Esta é a união de todas as variantes de transporte McpServerConfig mais uma variante de saída apenas claudeai-proxy para servidores proxied através de claude.ai.
McpServerStatusConfig = (
    McpStdioServerConfig
    | McpSSEServerConfig
    | McpHttpServerConfig
    | McpSdkServerConfigStatus
    | McpClaudeAIProxyServerConfig
)
McpSdkServerConfigStatus é a forma serializável de McpSdkServerConfig com apenas campos type ("sdk") e name (str); a instance em processo é omitida. McpClaudeAIProxyServerConfig tem campos type ("claudeai-proxy"), url (str), e id (str).

McpStatusResponse

Resposta de ClaudeSDKClient.get_mcp_status(). Envolve a lista de status de servidor sob a chave mcpServers.
class McpStatusResponse(TypedDict):
    mcpServers: list[McpServerStatus]

McpServerStatus

Status de um servidor MCP conectado, contido em 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]]
CampoTipoDescrição
namestrNome do servidor
statusstrUm de "connected", "failed", "needs-auth", "pending", ou "disabled"
serverInfodict (opcional)Nome e versão do servidor ({"name": str, "version": str})
errorstr (opcional)Mensagem de erro se o servidor falhou ao conectar
configMcpServerStatusConfig (opcional)Configuração do servidor. Mesma forma que McpServerConfig (stdio, SSE, HTTP, ou SDK), mais uma variante claudeai-proxy para servidores conectados através de claude.ai
scopestr (opcional)Escopo de configuração
toolslist (opcional)Ferramentas fornecidas por este servidor, cada uma com campos name, description, e annotations

SdkPluginConfig

Configuração para carregar plugins no SDK.
class SdkPluginConfig(TypedDict):
    type: Literal["local"]
    path: str
CampoTipoDescrição
typeLiteral["local"]Deve ser "local" (apenas plugins locais atualmente suportados)
pathstrCaminho absoluto ou relativo para o diretório do plugin
Exemplo:
plugins = [
    {"type": "local", "path": "./my-plugin"},
    {"type": "local", "path": "/absolute/path/to/plugin"},
]
Para informações completas sobre criação e uso de plugins, veja Plugins.

Tipos de Mensagem

Message

Tipo de união de todas as mensagens possíveis.
Message = (
    UserMessage
    | AssistantMessage
    | SystemMessage
    | ResultMessage
    | StreamEvent
    | RateLimitEvent
)

UserMessage

Mensagem de entrada do usuário.
@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
CampoTipoDescrição
contentstr | list[ContentBlock]Conteúdo da mensagem como texto ou blocos de conteúdo
uuidstr | NoneIdentificador único de mensagem
parent_tool_use_idstr | NoneID de uso de ferramenta se esta mensagem é uma resposta de resultado de ferramenta
tool_use_resultdict[str, Any] | NoneDados de resultado de ferramenta se aplicável

AssistantMessage

Mensagem de resposta do assistente com blocos de conteúdo.
@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
CampoTipoDescrição
contentlist[ContentBlock]Lista de blocos de conteúdo na resposta
modelstrModelo que gerou a resposta
parent_tool_use_idstr | NoneID de uso de ferramenta se esta é uma resposta aninhada
errorAssistantMessageError | NoneTipo de erro se a resposta encontrou um erro
usagedict[str, Any] | NoneUso de token por mensagem (mesmas chaves que ResultMessage.usage)
message_idstr | NoneID de mensagem da API. Múltiplas mensagens de um turno compartilham o mesmo ID

AssistantMessageError

Possíveis tipos de erro para mensagens do assistente.
AssistantMessageError = Literal[
    "authentication_failed",
    "billing_error",
    "rate_limit",
    "invalid_request",
    "server_error",
    "max_output_tokens",
    "unknown",
]

SystemMessage

Mensagem do sistema com metadados.
@dataclass
class SystemMessage:
    subtype: str
    data: dict[str, Any]

ResultMessage

Mensagem de resultado final com informações de custo e uso.
@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
O dict usage contém as seguintes chaves quando presentes:
ChaveTipoDescrição
input_tokensintTotal de tokens de entrada consumidos.
output_tokensintTotal de tokens de saída gerados.
cache_creation_input_tokensintTokens usados para criar novas entradas de cache.
cache_read_input_tokensintTokens lidos de entradas de cache existentes.
O dict model_usage mapeia nomes de modelo para uso por modelo. As chaves do dict interno usam camelCase porque o valor é passado sem modificação do processo CLI subjacente, correspondendo ao tipo TypeScript ModelUsage:
ChaveTipoDescrição
inputTokensintTokens de entrada para este modelo.
outputTokensintTokens de saída para este modelo.
cacheReadInputTokensintTokens de leitura de cache para este modelo.
cacheCreationInputTokensintTokens de criação de cache para este modelo.
webSearchRequestsintSolicitações de busca na web feitas por este modelo.
costUSDfloatCusto estimado em USD para este modelo, computado no lado do cliente. Veja Rastrear custo e uso para ressalvas de faturamento.
contextWindowintTamanho da janela de contexto para este modelo.
maxOutputTokensintLimite máximo de token de saída para este modelo.

StreamEvent

Evento de fluxo para atualizações de mensagem parcial durante streaming. Apenas recebido quando include_partial_messages=True em ClaudeAgentOptions. Importe via from claude_agent_sdk.types import StreamEvent.
@dataclass
class StreamEvent:
    uuid: str
    session_id: str
    event: dict[str, Any]  # The raw Claude API stream event
    parent_tool_use_id: str | None = None
CampoTipoDescrição
uuidstrIdentificador único para este evento
session_idstrIdentificador de sessão
eventdict[str, Any]Os dados brutos do evento de fluxo da API Claude
parent_tool_use_idstr | NoneID de uso de ferramenta pai se este evento é de um subagente

RateLimitEvent

Emitido quando o status do limite de taxa muda (por exemplo, de "allowed" para "allowed_warning"). Use isso para avisar usuários antes de atingirem um limite rígido, ou para recuar quando o status é "rejected".
@dataclass
class RateLimitEvent:
    rate_limit_info: RateLimitInfo
    uuid: str
    session_id: str
CampoTipoDescrição
rate_limit_infoRateLimitInfoEstado de limite de taxa atual
uuidstrIdentificador único de evento
session_idstrIdentificador de sessão

RateLimitInfo

Estado de limite de taxa carregado por 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)
CampoTipoDescrição
statusRateLimitStatusStatus atual. "allowed_warning" significa aproximando-se do limite; "rejected" significa que o limite foi atingido
resets_atint | NoneTimestamp Unix quando a janela de limite de taxa é redefinida
rate_limit_typeRateLimitType | NoneQual janela de limite de taxa se aplica
utilizationfloat | NoneFração do limite de taxa consumido (0.0 a 1.0)
overage_statusRateLimitStatus | NoneStatus do uso de excedente pré-pago, se aplicável
overage_resets_atint | NoneTimestamp Unix quando a janela de excedente é redefinida
overage_disabled_reasonstr | NonePor que o excedente está indisponível, se o status é "rejected"
rawdict[str, Any]Dict bruto completo do CLI, incluindo campos não modelados acima

TaskStartedMessage

Emitido quando uma tarefa de fundo começa. Uma tarefa de fundo é qualquer coisa rastreada fora do turno principal: um comando Bash em fundo, um watch de Monitor, um subagente gerado via ferramenta Agent, ou um agente remoto. O campo task_type diz qual. Esta nomenclatura não está relacionada à renomeação de ferramenta Task-para-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
CampoTipoDescrição
task_idstrIdentificador único para a tarefa
descriptionstrDescrição da tarefa
uuidstrIdentificador único de mensagem
session_idstrIdentificador de sessão
tool_use_idstr | NoneID de uso de ferramenta associado
task_typestr | NoneQue tipo de tarefa de fundo: "local_bash" para Bash em fundo e watches de Monitor, "local_agent", ou "remote_agent"

TaskUsage

Dados de token e tempo para uma tarefa de fundo.
class TaskUsage(TypedDict):
    total_tokens: int
    tool_uses: int
    duration_ms: int

TaskProgressMessage

Emitido periodicamente com atualizações de progresso para uma tarefa de fundo em execução.
@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
CampoTipoDescrição
task_idstrIdentificador único para a tarefa
descriptionstrDescrição de status atual
usageTaskUsageUso de token para esta tarefa até agora
uuidstrIdentificador único de mensagem
session_idstrIdentificador de sessão
tool_use_idstr | NoneID de uso de ferramenta associado
last_tool_namestr | NoneNome da última ferramenta que a tarefa usou

TaskNotificationMessage

Emitido quando uma tarefa de fundo é concluída, falha ou é parada. Tarefas de fundo incluem comandos Bash run_in_background, watches de Monitor e subagentes em fundo.
@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
CampoTipoDescrição
task_idstrIdentificador único para a tarefa
statusTaskNotificationStatusUm de "completed", "failed", ou "stopped"
output_filestrCaminho para o arquivo de saída da tarefa
summarystrResumo do resultado da tarefa
uuidstrIdentificador único de mensagem
session_idstrIdentificador de sessão
tool_use_idstr | NoneID de uso de ferramenta associado
usageTaskUsage | NoneUso de token final para a tarefa

Tipos de Bloco de Conteúdo

ContentBlock

Tipo de união de todos os blocos de conteúdo.
ContentBlock = TextBlock | ThinkingBlock | ToolUseBlock | ToolResultBlock

TextBlock

Bloco de conteúdo de texto.
@dataclass
class TextBlock:
    text: str

ThinkingBlock

Bloco de conteúdo de pensamento (para modelos com capacidade de pensamento).
@dataclass
class ThinkingBlock:
    thinking: str
    signature: str

ToolUseBlock

Bloco de solicitação de uso de ferramenta.
@dataclass
class ToolUseBlock:
    id: str
    name: str
    input: dict[str, Any]

ToolResultBlock

Bloco de resultado de execução de ferramenta.
@dataclass
class ToolResultBlock:
    tool_use_id: str
    content: str | list[dict[str, Any]] | None = None
    is_error: bool | None = None

Tipos de Erro

ClaudeSDKError

Classe de exceção base para todos os erros do SDK.
class ClaudeSDKError(Exception):
    """Base error for Claude SDK."""

CLINotFoundError

Levantado quando Claude Code CLI não está instalado ou não é encontrado.
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

Levantado quando a conexão com Claude Code falha.
class CLIConnectionError(ClaudeSDKError):
    """Failed to connect to Claude Code."""

ProcessError

Levantado quando o processo Claude Code falha.
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

Levantado quando a análise JSON falha.
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

Tipos de Hook

Para um guia abrangente sobre o uso de hooks com exemplos e padrões comuns, veja o Hooks guide.

HookEvent

Tipos de evento de hook suportados.
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
]
O SDK TypeScript suporta eventos de hook adicionais não disponíveis ainda em Python: SessionStart, SessionEnd, Setup, TeammateIdle, TaskCompleted, ConfigChange, WorktreeCreate, WorktreeRemove, PostToolBatch e MessageDisplay.

HookCallback

Definição de tipo para funções de callback de hook.
HookCallback = Callable[[HookInput, str | None, HookContext], Awaitable[HookJSONOutput]]
Parâmetros:
  • input: Entrada de hook fortemente tipada com uniões discriminadas baseadas em hook_event_name (veja HookInput)
  • tool_use_id: Identificador de uso de ferramenta opcional (para hooks relacionados a ferramentas)
  • context: Contexto de hook com informações adicionais
Retorna um HookJSONOutput que pode conter:
  • decision: "block" para bloquear a ação
  • systemMessage: Mensagem de aviso mostrada ao usuário
  • hookSpecificOutput: Dados de saída específicos do hook

HookContext

Informações de contexto passadas para callbacks de hook.
class HookContext(TypedDict):
    signal: Any | None  # Future: abort signal support

HookMatcher

Configuração para corresponder hooks a eventos ou ferramentas específicas.
@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 de união de todos os tipos de entrada de hook. O tipo real depende do campo hook_event_name.
HookInput = (
    PreToolUseHookInput
    | PostToolUseHookInput
    | PostToolUseFailureHookInput
    | UserPromptSubmitHookInput
    | StopHookInput
    | SubagentStopHookInput
    | PreCompactHookInput
    | NotificationHookInput
    | SubagentStartHookInput
    | PermissionRequestHookInput
)

BaseHookInput

Campos base presentes em todos os tipos de entrada de hook.
class BaseHookInput(TypedDict):
    session_id: str
    transcript_path: str
    cwd: str
    permission_mode: NotRequired[str]
CampoTipoDescrição
session_idstrIdentificador de sessão atual
transcript_pathstrCaminho para o arquivo de transcrição da sessão
cwdstrDiretório de trabalho atual
permission_modestr (opcional)Modo de permissão atual

PreToolUseHookInput

Dados de entrada para eventos de hook PreToolUse.
class PreToolUseHookInput(BaseHookInput):
    hook_event_name: Literal["PreToolUse"]
    tool_name: str
    tool_input: dict[str, Any]
    tool_use_id: str
    agent_id: NotRequired[str]
    agent_type: NotRequired[str]
CampoTipoDescrição
hook_event_nameLiteral["PreToolUse"]Sempre “PreToolUse”
tool_namestrNome da ferramenta prestes a ser executada
tool_inputdict[str, Any]Parâmetros de entrada para a ferramenta
tool_use_idstrIdentificador único para este uso de ferramenta
agent_idstr (opcional)Identificador de subagente, presente quando o hook dispara dentro de um subagente
agent_typestr (opcional)Tipo de subagente, presente quando o hook dispara dentro de um subagente

PostToolUseHookInput

Dados de entrada para eventos de hook PostToolUse.
class PostToolUseHookInput(BaseHookInput):
    hook_event_name: Literal["PostToolUse"]
    tool_name: str
    tool_input: dict[str, Any]
    tool_response: Any
    tool_use_id: str
    agent_id: NotRequired[str]
    agent_type: NotRequired[str]
CampoTipoDescrição
hook_event_nameLiteral["PostToolUse"]Sempre “PostToolUse”
tool_namestrNome da ferramenta que foi executada
tool_inputdict[str, Any]Parâmetros de entrada que foram usados
tool_responseAnyResposta da execução da ferramenta
tool_use_idstrIdentificador único para este uso de ferramenta
agent_idstr (opcional)Identificador de subagente, presente quando o hook dispara dentro de um subagente
agent_typestr (opcional)Tipo de subagente, presente quando o hook dispara dentro de um subagente

PostToolUseFailureHookInput

Dados de entrada para eventos de hook PostToolUseFailure. Chamado quando uma execução de ferramenta falha.
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]
CampoTipoDescrição
hook_event_nameLiteral["PostToolUseFailure"]Sempre “PostToolUseFailure”
tool_namestrNome da ferramenta que falhou
tool_inputdict[str, Any]Parâmetros de entrada que foram usados
tool_use_idstrIdentificador único para este uso de ferramenta
errorstrMensagem de erro da execução falhada
is_interruptbool (opcional)Se a falha foi causada por uma interrupção
agent_idstr (opcional)Identificador de subagente, presente quando o hook dispara dentro de um subagente
agent_typestr (opcional)Tipo de subagente, presente quando o hook dispara dentro de um subagente

UserPromptSubmitHookInput

Dados de entrada para eventos de hook UserPromptSubmit.
class UserPromptSubmitHookInput(BaseHookInput):
    hook_event_name: Literal["UserPromptSubmit"]
    prompt: str
CampoTipoDescrição
hook_event_nameLiteral["UserPromptSubmit"]Sempre “UserPromptSubmit”
promptstrO prompt enviado pelo usuário

StopHookInput

Dados de entrada para eventos de hook Stop.
class StopHookInput(BaseHookInput):
    hook_event_name: Literal["Stop"]
    stop_hook_active: bool
CampoTipoDescrição
hook_event_nameLiteral["Stop"]Sempre “Stop”
stop_hook_activeboolSe o hook de parada está ativo

SubagentStopHookInput

Dados de entrada para eventos de hook SubagentStop.
class SubagentStopHookInput(BaseHookInput):
    hook_event_name: Literal["SubagentStop"]
    stop_hook_active: bool
    agent_id: str
    agent_transcript_path: str
    agent_type: str
CampoTipoDescrição
hook_event_nameLiteral["SubagentStop"]Sempre “SubagentStop”
stop_hook_activeboolSe o hook de parada está ativo
agent_idstrIdentificador único para o subagente
agent_transcript_pathstrCaminho para o arquivo de transcrição do subagente
agent_typestrTipo do subagente

PreCompactHookInput

Dados de entrada para eventos de hook PreCompact.
class PreCompactHookInput(BaseHookInput):
    hook_event_name: Literal["PreCompact"]
    trigger: Literal["manual", "auto"]
    custom_instructions: str | None
CampoTipoDescrição
hook_event_nameLiteral["PreCompact"]Sempre “PreCompact”
triggerLiteral["manual", "auto"]O que acionou a compactação
custom_instructionsstr | NoneInstruções personalizadas para compactação

NotificationHookInput

Dados de entrada para eventos de hook Notification.
class NotificationHookInput(BaseHookInput):
    hook_event_name: Literal["Notification"]
    message: str
    title: NotRequired[str]
    notification_type: str
CampoTipoDescrição
hook_event_nameLiteral["Notification"]Sempre “Notification”
messagestrConteúdo da mensagem de notificação
titlestr (opcional)Título da notificação
notification_typestrTipo de notificação

SubagentStartHookInput

Dados de entrada para eventos de hook SubagentStart.
class SubagentStartHookInput(BaseHookInput):
    hook_event_name: Literal["SubagentStart"]
    agent_id: str
    agent_type: str
CampoTipoDescrição
hook_event_nameLiteral["SubagentStart"]Sempre “SubagentStart”
agent_idstrIdentificador único para o subagente
agent_typestrTipo do subagente

PermissionRequestHookInput

Dados de entrada para eventos de hook PermissionRequest. Permite que hooks manipulem decisões de permissão programaticamente.
class PermissionRequestHookInput(BaseHookInput):
    hook_event_name: Literal["PermissionRequest"]
    tool_name: str
    tool_input: dict[str, Any]
    permission_suggestions: NotRequired[list[Any]]
CampoTipoDescrição
hook_event_nameLiteral["PermissionRequest"]Sempre “PermissionRequest”
tool_namestrNome da ferramenta solicitando permissão
tool_inputdict[str, Any]Parâmetros de entrada para a ferramenta
permission_suggestionslist[Any] (opcional)Atualizações de permissão sugeridas do CLI

HookJSONOutput

Tipo de união para valores de retorno de callback de hook.
HookJSONOutput = AsyncHookJSONOutput | SyncHookJSONOutput

SyncHookJSONOutput

Saída de hook síncrona com campos de controle e decisão.
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]
Use continue_ (com underscore) no código Python. É automaticamente convertido para continue quando enviado para o CLI.

HookSpecificOutput

Um TypedDict contendo o nome do evento de hook e campos específicos do evento. A forma depende do valor hookEventName. Para detalhes completos sobre campos disponíveis por evento de hook, veja Control execution with hooks. Uma união discriminada de tipos de saída específicos do evento. O campo hookEventName determina quais campos são válidos.
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

Saída de hook assíncrona que adia a execução do hook.
class AsyncHookJSONOutput(TypedDict):
    async_: Literal[True]  # Set to True to defer execution
    asyncTimeout: NotRequired[int]  # Timeout in milliseconds
Use async_ (com underscore) no código Python. É automaticamente convertido para async quando enviado para o CLI.

Exemplo de Uso de Hook

Este exemplo registra dois hooks: um que bloqueia comandos bash perigosos como rm -rf /, e outro que registra todo o uso de ferramenta para auditoria. O hook de segurança funciona apenas em comandos Bash (via matcher), enquanto o hook de registro funciona em todas as ferramentas.
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)

Tipos de Entrada/Saída de Ferramenta

Documentação de schemas de entrada/saída para todas as ferramentas Claude Code integradas. Embora o SDK Python não exporte esses como tipos, eles representam a estrutura de entradas e saídas de ferramenta em mensagens.

Agent

Nome da ferramenta: Agent (anteriormente Task, que ainda é aceito como alias) Entrada:
{
    "description": str,  # Uma descrição breve (3-5 palavras) da tarefa
    "prompt": str,  # A tarefa para o agente executar
    "subagent_type": str,  # O tipo de agente especializado a usar
}
Saída:
{
    "result": str,  # Resultado final do subagente
    "usage": dict | None,  # Estatísticas de uso de tokens
    "total_cost_usd": float | None,  # Custo total estimado em USD
    "duration_ms": int | None,  # Duração da execução em milissegundos
}

AskUserQuestion

Nome da ferramenta: AskUserQuestion Faz perguntas de esclarecimento ao usuário durante a execução. Veja Lidar com aprovações e entrada do usuário para detalhes de uso. Entrada:
{
    "questions": [  # Perguntas a fazer ao usuário (1-4 perguntas)
        {
            "question": str,  # A pergunta completa a fazer ao usuário
            "header": str,  # Rótulo muito breve exibido como chip/tag (máx 12 caracteres)
            "options": [  # As escolhas disponíveis (2-4 opções)
                {
                    "label": str,  # Texto de exibição para esta opção (1-5 palavras)
                    "description": str,  # Explicação do que esta opção significa
                }
            ],
            "multiSelect": bool,  # Defina como true para permitir múltiplas seleções
        }
    ],
    "answers": dict[str, str | list[str]] | None,
    # Respostas do usuário preenchidas pelo sistema de permissões. Respostas
    # de múltipla seleção podem ser uma lista de rótulos ou uma string separada por vírgula
}
Saída:
{
    "questions": [  # As perguntas que foram feitas
        {
            "question": str,
            "header": str,
            "options": [{"label": str, "description": str}],
            "multiSelect": bool,
        }
    ],
    "answers": dict[str, str],  # Mapeia texto da pergunta para string de resposta
    # Respostas de múltipla seleção são separadas por vírgula
}

Bash

Nome da ferramenta: Bash Entrada:
{
    "command": str,  # O comando a executar
    "timeout": int | None,  # Tempo limite opcional em milissegundos (máx 600000)
    "description": str | None,  # Descrição clara e concisa (5-10 palavras)
    "run_in_background": bool | None,  # Defina como true para executar em segundo plano
}
Saída:
{
    "output": str,  # Saída combinada de stdout e stderr
    "exitCode": int,  # Código de saída do comando
    "killed": bool | None,  # Se o comando foi interrompido devido ao tempo limite
    "shellId": str | None,  # ID do shell para processos em segundo plano
}

Monitor

Nome da ferramenta: Monitor Executa um script de fundo e entrega cada linha stdout para Claude como um evento para que ele possa reagir sem polling. Monitor segue as mesmas regras de permissão que Bash. Veja a referência da ferramenta Monitor para comportamento e disponibilidade de provedor. Entrada:
{
    "command": str,  # Script de shell; cada linha stdout é um evento, exit encerra a observação
    "description": str,  # Descrição breve mostrada em notificações
    "timeout_ms": int | None,  # Interromper após este prazo (padrão 300000, máx 3600000)
    "persistent": bool | None,  # Executar pela vida útil da sessão; parar com TaskStop
}
Saída:
{
    "taskId": str,  # ID da tarefa de monitor de fundo
    "timeoutMs": int,  # Prazo de tempo limite em milissegundos (0 quando persistente)
    "persistent": bool | None,  # True quando executando até TaskStop ou fim da sessão
}

Edit

Nome da ferramenta: Edit Entrada:
{
    "file_path": str,  # O caminho absoluto do arquivo a modificar
    "old_string": str,  # O texto a substituir
    "new_string": str,  # O texto para substituir por
    "replace_all": bool | None,  # Substituir todas as ocorrências (padrão False)
}
Saída:
{
    "message": str,  # Mensagem de confirmação
    "replacements": int,  # Número de substituições realizadas
    "file_path": str,  # Caminho do arquivo que foi editado
}

Read

Nome da ferramenta: Read Entrada:
{
    "file_path": str,  # O caminho absoluto do arquivo a ler
    "offset": int | None,  # O número da linha para começar a ler
    "limit": int | None,  # O número de linhas a ler
}
Saída (Arquivos de texto):
{
    "content": str,  # Conteúdo do arquivo com números de linha
    "total_lines": int,  # Número total de linhas no arquivo
    "lines_returned": int,  # Linhas realmente retornadas
}
Saída (Imagens):
{
    "image": str,  # Dados de imagem codificados em Base64
    "mime_type": str,  # Tipo MIME da imagem
    "file_size": int,  # Tamanho do arquivo em bytes
}

Write

Nome da ferramenta: Write Entrada:
{
    "file_path": str,  # O caminho absoluto do arquivo a escrever
    "content": str,  # O conteúdo a escrever no arquivo
}
Saída:
{
    "message": str,  # Mensagem de sucesso
    "bytes_written": int,  # Número de bytes escritos
    "file_path": str,  # Caminho do arquivo que foi escrito
}

Glob

Nome da ferramenta: Glob Entrada:
{
    "pattern": str,  # O padrão glob para corresponder arquivos
    "path": str | None,  # O diretório a pesquisar (padrão cwd)
}
Saída:
{
    "matches": list[str],  # Array de caminhos de arquivo correspondentes
    "count": int,  # Número de correspondências encontradas
    "search_path": str,  # Diretório de pesquisa usado
}

Grep

Nome da ferramenta: Grep Entrada:
{
    "pattern": str,  # O padrão de expressão regular
    "path": str | None,  # Arquivo ou diretório a pesquisar
    "glob": str | None,  # Padrão glob para filtrar arquivos
    "type": str | None,  # Tipo de arquivo a pesquisar
    "output_mode": str | None,  # "content", "files_with_matches", ou "count"
    "-i": bool | None,  # Pesquisa insensível a maiúsculas/minúsculas
    "-n": bool | None,  # Mostrar números de linha
    "-B": int | None,  # Linhas a mostrar antes de cada correspondência
    "-A": int | None,  # Linhas a mostrar após cada correspondência
    "-C": int | None,  # Linhas a mostrar antes e depois
    "head_limit": int | None,  # Limitar saída às primeiras N linhas/entradas
    "multiline": bool | None,  # Ativar modo multilinha
}
Saída (modo content):
{
    "matches": [
        {
            "file": str,
            "line_number": int | None,
            "line": str,
            "before_context": list[str] | None,
            "after_context": list[str] | None,
        }
    ],
    "total_matches": int,
}
Saída (modo files_with_matches):
{
    "files": list[str],  # Arquivos contendo correspondências
    "count": int,  # Número de arquivos com correspondências
}

NotebookEdit

Nome da ferramenta: NotebookEdit Entrada:
{
    "notebook_path": str,  # Caminho absoluto para o notebook Jupyter
    "cell_id": str | None,  # O ID da célula a editar
    "new_source": str,  # A nova fonte para a célula
    "cell_type": "code" | "markdown" | None,  # O tipo da célula
    "edit_mode": "replace" | "insert" | "delete" | None,  # Tipo de operação de edição
}
Saída:
{
    "message": str,  # Mensagem de sucesso
    "edit_type": "replaced" | "inserted" | "deleted",  # Tipo de edição realizada
    "cell_id": str | None,  # ID da célula que foi afetada
    "total_cells": int,  # Total de células no notebook após edição
}

WebFetch

Nome da ferramenta: WebFetch Entrada:
{
    "url": str,  # A URL para buscar conteúdo
    "prompt": str,  # O prompt a executar no conteúdo buscado
}
Saída:
{
    "bytes": int,  # Tamanho do conteúdo buscado em bytes
    "code": int,  # Código de resposta HTTP
    "codeText": str,  # Texto do código de resposta HTTP
    "result": str,  # Resultado processado da aplicação do prompt ao conteúdo
    "durationMs": int,  # Tempo para buscar e processar o conteúdo, em milissegundos
    "url": str,  # URL que foi buscada
}

WebSearch

Nome da ferramenta: WebSearch Entrada:
{
    "query": str,  # A consulta de pesquisa a usar
    "allowed_domains": list[str] | None,  # Incluir apenas resultados desses domínios
    "blocked_domains": list[str] | None,  # Nunca incluir resultados desses domínios
}
Saída:
{
    "query": str,  # A consulta de pesquisa
    "results": list[str | {"tool_use_id": str, "content": list[{"title": str, "url": str}]}],
    "durationSeconds": float,  # Duração da pesquisa em segundos
}

TodoWrite

Nome da ferramenta: TodoWrite
A partir do Claude Code v2.1.142, TodoWrite está desabilitado por padrão. Use TaskCreate, TaskGet, TaskUpdate e TaskList em seu lugar. Veja Migrar para ferramentas Task para atualizar seu código de monitoramento, ou defina CLAUDE_CODE_ENABLE_TASKS=0 para reverter para TodoWrite.
Entrada:
{
    "todos": [
        {
            "content": str,  # A descrição da tarefa
            "status": "pending" | "in_progress" | "completed",  # Status da tarefa
            "activeForm": str,  # Forma ativa da descrição
        }
    ]
}
Saída:
{
    "message": str,  # Mensagem de sucesso
    "stats": {"total": int, "pending": int, "in_progress": int, "completed": int},
}

TaskCreate

Nome da ferramenta: TaskCreate Entrada:
{
    "subject": str,  # Título breve da tarefa
    "description": str,  # Corpo detalhado da tarefa
    "activeForm": str | None,  # Rótulo em tempo presente mostrado enquanto em progresso
    "metadata": dict | None,  # Metadados arbitrários do chamador
}
Saída:
{
    "task": {"id": str, "subject": str},  # Tarefa criada com ID atribuído
}

TaskUpdate

Nome da ferramenta: TaskUpdate Entrada:
{
    "taskId": str,  # ID da tarefa a corrigir
    "status": Literal["pending", "in_progress", "completed", "deleted"] | None,
    "subject": str | None,
    "description": str | None,
    "activeForm": str | None,
    "addBlocks": list[str] | None,  # IDs de tarefas que esta tarefa agora bloqueia
    "addBlockedBy": list[str] | None,  # IDs de tarefas que agora bloqueiam esta tarefa
    "owner": str | None,
    "metadata": dict | None,
}
Saída:
{
    "success": bool,
    "taskId": str,
    "updatedFields": list[str],  # Nomes dos campos que mudaram
    "error": str | None,
    "statusChange": {"from": str, "to": str} | None,
}

TaskGet

Nome da ferramenta: TaskGet Entrada:
{
    "taskId": str,  # ID da tarefa a ler
}
Saída:
{
    "task": {
        "id": str,
        "subject": str,
        "description": str,
        "status": Literal["pending", "in_progress", "completed"],
        "blocks": list[str],
        "blockedBy": list[str],
    } | None,  # None quando o ID não é encontrado
}

TaskList

Nome da ferramenta: TaskList Entrada:
{}
Saída:
{
    "tasks": [
        {
            "id": str,
            "subject": str,
            "status": Literal["pending", "in_progress", "completed"],
            "owner": str | None,
            "blockedBy": list[str],
        }
    ],
}

BashOutput

Nome da ferramenta: BashOutput Entrada:
{
    "bash_id": str,  # O ID do shell de fundo
    "filter": str | None,  # Regex opcional para filtrar linhas de saída
}
Saída:
{
    "output": str,  # Nova saída desde a última verificação
    "status": "running" | "completed" | "failed",  # Status atual do shell
    "exitCode": int | None,  # Código de saída quando concluído
}

KillBash

Nome da ferramenta: KillBash Entrada:
{
    "shell_id": str  # O ID do shell de fundo a interromper
}
Saída:
{
    "message": str,  # Mensagem de sucesso
    "shell_id": str,  # ID do shell interrompido
}

ExitPlanMode

Nome da ferramenta: ExitPlanMode Entrada:
{
    "plan": str  # O plano a executar pelo usuário para aprovação
}
Saída:
{
    "message": str,  # Mensagem de confirmação
    "approved": bool | None,  # Se o usuário aprovou o plano
}

ListMcpResources

Nome da ferramenta: ListMcpResourcesTool Entrada:
{
    "server": str | None  # Nome de servidor opcional para filtrar recursos por
}
Saída:
{
    "resources": [
        {
            "uri": str,
            "name": str,
            "description": str | None,
            "mimeType": str | None,
            "server": str,
        }
    ],
    "total": int,
}

ReadMcpResource

Nome da ferramenta: ReadMcpResourceTool Entrada:
{
    "server": str,  # O nome do servidor MCP
    "uri": str,  # A URI do recurso a ler
}
Saída:
{
    "contents": [
        {"uri": str, "mimeType": str | None, "text": str | None, "blob": str | None}
    ],
    "server": str,
}

Recursos Avançados com ClaudeSDKClient

Construindo uma Interface de Conversa Contínua

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

Usando Hooks para Modificação de 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())

Monitoramento de Progresso em Tempo Real

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

Uso de Exemplo

Operações básicas de arquivo (usando query)

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


async def create_project():
    options = Cl audeAgentOptions(
        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())

Tratamento de erros

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

Modo de streaming com cliente

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

Usando ferramentas personalizadas com 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())

Configuração de Sandbox

SandboxSettings

Configuração para comportamento de sandbox. Use isso para ativar sandboxing de comando e configurar restrições de rede programaticamente.
class SandboxSettings(TypedDict, total=False):
    enabled: bool
    autoAllowBashIfSandboxed: bool
    excludedCommands: list[str]
    allowUnsandboxedCommands: bool
    network: SandboxNetworkConfig
    ignoreViolations: SandboxIgnoreViolations
    enableWeakerNestedSandbox: bool
PropriedadeTipoPadrãoDescrição
enabledboolFalseAtiva modo sandbox para execução de comando
autoAllowBashIfSandboxedboolTrueAuto-aprova comandos bash quando sandbox está ativado
excludedCommandslist[str][]Comandos que sempre contornam restrições de sandbox (por exemplo, ["docker"]). Esses executam sem sandbox automaticamente sem envolvimento do modelo
allowUnsandboxedCommandsboolTruePermite que o modelo solicite executar comandos fora do sandbox. Quando True, o modelo pode definir dangerouslyDisableSandbox na entrada da ferramenta, que volta para o sistema de permissões
networkSandboxNetworkConfigNoneConfiguração de sandbox específica de rede
ignoreViolationsSandboxIgnoreViolationsNoneConfigure quais violações de sandbox ignorar
enableWeakerNestedSandboxboolFalseAtiva um sandbox aninhado mais fraco para compatibilidade
O sandbox depende do suporte de plataforma e, no Linux, de ferramentas como bubblewrap e socat. Por padrão, quando enabled é True mas o sandbox não consegue iniciar, comandos executam sem sandbox com um aviso em stderr. Este padrão difere do SDK TypeScript, onde failIfUnavailable tem padrão true.Defina "failIfUnavailable": True nas suas configurações de sandbox para parar em vez disso. A chave ainda não está declarada em SandboxSettings, mas o SDK a encaminha para Claude Code, que a honra. query() então relata uma ResultMessage com subtype="error_during_execution" e a razão em errors. Observe esse subtipo em vez de esperar que query() lance antes de ceder mensagens.

Exemplo de uso

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)
Segurança de socket Unix: A opção allowUnixSockets pode conceder acesso a serviços de sistema poderosos. Por exemplo, permitir /var/run/docker.sock efetivamente concede acesso completo ao sistema host através da API Docker, contornando isolamento de sandbox. Apenas permita sockets Unix que são estritamente necessários e entenda as implicações de segurança de cada um.

SandboxNetworkConfig

Configuração específica de rede para modo sandbox. Essas configurações se aplicam a comandos Bash em sandbox quando enabled é True na SandboxSettings pai. Elas não restringem a ferramenta WebFetch, que usa regras de permissão em vez disso.
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
PropriedadeTipoPadrãoDescrição
allowedDomainslist[str][]Nomes de domínio que processos em sandbox podem acessar
deniedDomainslist[str][]Nomes de domínio que processos em sandbox não podem acessar. Tem precedência sobre allowedDomains
allowManagedDomainsOnlyboolFalseApenas configurações gerenciadas: quando definido em configurações gerenciadas, ignore allowedDomains de fontes de configurações não gerenciadas. Não tem efeito quando definido via opções SDK
allowUnixSocketslist[str][]Caminhos de socket Unix que processos podem acessar (por exemplo, socket Docker)
allowAllUnixSocketsboolFalsePermite acesso a todos os sockets Unix
allowLocalBindingboolFalsePermite que processos se vinculem a portas locais (por exemplo, para servidores dev)
allowMachLookuplist[str][]Apenas macOS: nomes de serviço XPC/Mach para permitir. Suporta um curinga à direita
httpProxyPortintNonePorta de proxy HTTP para solicitações de rede
socksProxyPortintNonePorta de proxy SOCKS para solicitações de rede
O proxy de sandbox integrado aplica a lista de permissões de rede com base no nome de host solicitado e não encerra ou inspeciona tráfego TLS, portanto técnicas como domain fronting podem potencialmente contorná-lo. Veja Limitações de segurança de Sandboxing para detalhes e Implantação segura para configurar um proxy que encerra TLS.

SandboxIgnoreViolations

Configuração para ignorar violações de sandbox específicas.
class SandboxIgnoreViolations(TypedDict, total=False):
    file: list[str]
    network: list[str]
PropriedadeTipoPadrãoDescrição
filelist[str][]Padrões de caminho de arquivo para ignorar violações
networklist[str][]Padrões de rede para ignorar violações

Fallback de Permissões para Comandos Sem Sandbox

Quando allowUnsandboxedCommands está ativado, o modelo pode solicitar executar comandos fora do sandbox definindo dangerouslyDisableSandbox: True na entrada da ferramenta. Essas solicitações voltam para o sistema de permissões existente, significando que seu manipulador can_use_tool será invocado, permitindo que você implemente lógica de autorização personalizada.
excludedCommands vs allowUnsandboxedCommands:
  • excludedCommands: Uma lista estática de comandos que sempre contornam o sandbox automaticamente (por exemplo, ["docker"]). O modelo não tem controle sobre isso.
  • allowUnsandboxedCommands: Permite que o modelo decida em tempo de execução se deve solicitar execução sem sandbox definindo dangerouslyDisableSandbox: True na entrada da ferramenta.
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)
Este padrão permite que você:
  • Audite solicitações de modelo: Registre quando o modelo solicita execução sem sandbox
  • Implemente listas de permissão: Apenas permita comandos específicos executarem sem sandbox
  • Adicione fluxos de trabalho de aprovação: Exija autorização explícita para operações privilegiadas
Comandos executando com dangerouslyDisableSandbox: True têm acesso completo ao sistema. Certifique-se de que seu manipulador can_use_tool valida essas solicitações cuidadosamente.Se permission_mode está definido para bypassPermissions e allow_unsandboxed_commands está ativado, o modelo pode autonomamente executar comandos fora do sandbox sem qualquer prompt de aprovação. Esta combinação efetivamente permite que o modelo escape do isolamento de sandbox silenciosamente.

Veja também