Pular para o conteúdo principal
Hooks são funções de callback que executam seu código em resposta a eventos do agente, como uma ferramenta sendo chamada, uma sessão iniciando ou a execução parando. Com hooks, você pode:
  • Bloquear operações perigosas antes de serem executadas, como comandos shell destrutivos ou acesso a arquivos não autorizado
  • Registrar e auditar cada chamada de ferramenta para conformidade, depuração ou análise
  • Transformar entradas e saídas para sanitizar dados, injetar credenciais ou redirecionar caminhos de arquivo
  • Exigir aprovação humana para ações sensíveis como gravações em banco de dados ou chamadas de API
  • Rastrear ciclo de vida da sessão para gerenciar estado, limpar recursos ou enviar notificações
Este guia cobre como hooks funcionam e como configurá-los, com exemplos para padrões comuns como bloquear ferramentas, modificar entradas e encaminhar notificações.

Como hooks funcionam

1

Um evento é disparado

Algo acontece durante a execução do agente e o SDK dispara um evento: uma ferramenta está prestes a ser chamada (PreToolUse), uma ferramenta retornou um resultado (PostToolUse), um subagente iniciou ou parou, o agente está ocioso ou a execução terminou. Veja a lista completa de eventos.
2

O SDK coleta hooks registrados

O SDK verifica se há hooks registrados para esse tipo de evento. Isso inclui hooks de callback que você passa em options.hooks e hooks de comando shell de arquivos de configuração quando a entrada settingSources ou setting_sources correspondente está habilitada, o que é o padrão para opções query().
3

Matchers filtram quais hooks são executados

Se um hook tem um padrão matcher (como "Write|Edit"), o SDK o testa contra o alvo do evento (por exemplo, o nome da ferramenta). Hooks sem um matcher são executados para cada evento desse tipo.
4

Funções de callback são executadas

Cada função de callback do hook correspondente recebe informações sobre o que está acontecendo: o nome da ferramenta, seus argumentos, o ID da sessão e outros detalhes específicos do evento.
5

Seu callback retorna uma decisão

Após realizar qualquer operação (registro, chamadas de API, validação), seu callback retorna um objeto de saída que diz ao agente o que fazer: permitir a operação, bloqueá-la, modificar a entrada ou injetar contexto na conversa.
O exemplo a seguir reúne essas etapas. Ele registra um hook PreToolUse (etapa 1) com um matcher "Write|Edit" (etapa 3) para que o callback seja acionado apenas para ferramentas de escrita de arquivo. Quando acionado, o callback recebe a entrada da ferramenta (etapa 4), verifica se o caminho do arquivo tem como alvo um arquivo .env e retorna permissionDecision: "deny" para bloquear a operação (etapa 5):

Hooks disponíveis

O SDK fornece hooks para diferentes estágios de execução do agente. Alguns hooks estão disponíveis em ambos os SDKs, enquanto outros são apenas para TypeScript.

Configurar hooks

Para configurar um hook, passe-o no campo hooks de suas opções de agente (ClaudeAgentOptions em Python, o objeto options em TypeScript):
A opção hooks é um dicionário em Python ou um objeto em TypeScript, onde:

Matchers

Use matchers para filtrar quando seus callbacks são acionados. O campo matcher corresponde a um valor diferente dependendo do tipo de evento de hook. Por exemplo, hooks baseados em ferramentas correspondem ao nome da ferramenta, enquanto hooks Notification correspondem ao tipo de notificação. Veja a referência de hooks do Claude Code para a lista completa de valores de matcher para cada tipo de evento. Os matchers do SDK seguem as mesmas regras que matchers em arquivos de configuração. Um matcher contendo apenas letras, dígitos, _, -, espaços, , e | é comparado como uma string exata, com alternativas separadas por | ou , e espaço em branco opcional ao redor, então Write|Edit e Write, Edit correspondem exatamente a essas duas ferramentas e code-reviewer corresponde apenas a esse tipo de agente. Um matcher de *, uma string vazia, ou omitir o matcher inteiramente corresponde a cada ocorrência do evento. Um matcher contendo qualquer outro caractere é avaliado como uma expressão regular sem âncora, então ^mcp__ corresponde a cada ferramenta MCP e Edit.* corresponde tanto a Edit quanto a NotebookEdit. Envolva uma expressão regular em ^ e $ quando você precisar de uma correspondência de string inteira. Um matcher como mcp__memory ou mcp__brave-search contém apenas caracteres de correspondência exata, então é comparado como uma string exata e não corresponde a nenhuma ferramenta; use mcp__memory__.* para corresponder a cada ferramenta desse servidor. Hífens no conjunto de correspondência exata requerem um runtime do Claude Code v2.1.195 ou posterior. Em versões anteriores, um nome com hífen como code-reviewer é avaliado como uma expressão regular sem âncora e deve ser ancorado como ^code-reviewer$ para corresponder exatamente. Use o padrão matcher para direcionar ferramentas específicas sempre que possível. Um matcher com 'Bash' é executado apenas para comandos Bash, enquanto omitir o padrão executa seus callbacks para cada ocorrência do evento. Para hooks baseados em ferramentas, matchers filtram apenas pelo nome da ferramenta, não por caminhos de arquivo ou outros argumentos. Para filtrar por caminho de arquivo, verifique tool_input.file_path dentro de seu callback.
Descobrindo nomes de ferramentas: Veja Tipos de Entrada de Ferramenta para a lista completa de nomes de ferramentas integradas, ou adicione um hook sem um matcher para registrar todas as chamadas de ferramenta que sua sessão faz.Nomenclatura de ferramentas MCP: Ferramentas MCP sempre começam com mcp__ seguido pelo nome do servidor e ação: mcp__<server>__<action>. Por exemplo, se você configurar um servidor chamado playwright, suas ferramentas serão nomeadas mcp__playwright__browser_screenshot, mcp__playwright__browser_click e assim por diante. O nome do servidor vem da chave que você usa na configuração mcpServers.

Funções de callback

Entradas

Cada callback de hook recebe três argumentos:
  • Dados de entrada: um objeto tipado contendo detalhes do evento. Cada tipo de hook tem sua própria forma de entrada. Por exemplo, PreToolUseHookInput inclui tool_name e tool_input, enquanto NotificationHookInput inclui message. Veja as definições de tipo completas nas referências do SDK TypeScript e Python.
    • Todas as entradas de hook compartilham session_id, cwd e hook_event_name.
    • agent_id e agent_type são preenchidos quando o hook é acionado dentro de um subagente. Em TypeScript, estes estão na entrada de hook base e disponíveis para todos os tipos de hook. Em Python, eles são campos opcionais em PreToolUse, PostToolUse, PostToolUseFailure e PermissionRequest, e campos obrigatórios em SubagentStart e SubagentStop.
  • ID de uso de ferramenta (str | None / string | undefined): correlaciona eventos PreToolUse e PostToolUse para a mesma chamada de ferramenta.
  • Contexto: em TypeScript, contém uma propriedade signal (AbortSignal) para cancelamento. Em Python, este argumento é reservado para uso futuro.

Saídas

Seu callback retorna um objeto com duas categorias de campos:
  • Campos de nível superior funcionam da mesma forma em cada evento: systemMessage mostra uma mensagem ao usuário, e continue (continue_ em Python) determina se o agente continua executando após este hook.
  • hookSpecificOutput controla a operação atual. Os campos dentro dependem do tipo de evento de hook. Para hooks PreToolUse, é aqui que você define permissionDecision ("allow", "deny", "ask" ou "defer"), permissionDecisionReason e updatedInput. Retornar "defer" encerra a consulta para que você possa retomá-la depois. Para hooks PostToolUse, você pode definir additionalContext para anexar informações ao resultado da ferramenta. Para substituir a saída da ferramenta antes de Claude vê-la, defina updatedToolOutput, que funciona para qualquer ferramenta em ambos os SDKs. O campo mais antigo updatedMCPToolOutput substitui apenas a saída de ferramentas MCP e está descontinuado.
Retorne {} para permitir a operação sem alterações. Hooks de callback do SDK usam o mesmo formato de saída JSON que hooks de comando shell do Claude Code, que documenta cada campo e opção específica do evento. Para as definições de tipo do SDK, veja as referências do SDK TypeScript e Python.
Quando múltiplos hooks ou regras de permissão se aplicam, deny tem prioridade sobre defer, que tem prioridade sobre ask, que tem prioridade sobre allow. Se qualquer hook retornar deny, a operação é bloqueada independentemente de outros hooks.

Saída assíncrona

Por padrão, o agente aguarda seu hook retornar antes de prosseguir. Se seu hook realiza um efeito colateral, como registro ou envio de webhook, e não precisa influenciar o comportamento do agente, você pode retornar uma saída assíncrona. Isso diz ao agente para continuar imediatamente sem aguardar o hook terminar:
Saídas assíncronas não podem bloquear, modificar ou injetar contexto na operação, pois o agente já avançou. Use-as apenas para efeitos colaterais como registro, métricas ou notificações.

Exemplos

Modificar entrada de ferramenta

Este exemplo intercepta chamadas de ferramenta Write e reescreve o argumento file_path para prepender /sandbox, redirecionando todas as gravações de arquivo para um diretório em sandbox. O callback retorna updatedInput com o caminho modificado e permissionDecision: 'allow' para aprovar automaticamente a operação reescrita:
Ao usar updatedInput, você também deve incluir permissionDecision: 'allow' para aprovar automaticamente a entrada modificada ou permissionDecision: 'ask' para mostrá-la ao usuário. Com 'defer', updatedInput é ignorado. Sempre retorne um novo objeto em vez de mutar o tool_input original.

Adicionar contexto e bloquear uma ferramenta

Este exemplo bloqueia gravações no diretório /etc e explica o motivo tanto para o modelo quanto para o usuário:
  • permissionDecision: 'deny' interrompe a chamada de ferramenta.
  • permissionDecisionReason informa ao modelo por que, para que ele evite tentar novamente.
  • systemMessage mostra ao usuário o que aconteceu.

Aprovar automaticamente ferramentas específicas

Por padrão, o agente pode solicitar permissão antes de usar certas ferramentas. Este exemplo aprova automaticamente ferramentas de sistema de arquivos somente leitura (Read, Glob, Grep) retornando permissionDecision: 'allow', permitindo que sejam executadas sem confirmação do usuário enquanto deixa todas as outras ferramentas sujeitas a verificações de permissão normais:

Registrar múltiplos hooks

Quando um evento é disparado, todos os hooks correspondentes são executados em paralelo. Para decisões de permissão, o resultado mais restritivo vence: um único deny bloqueia a chamada de ferramenta independentemente do que os outros hooks retornam. Como a ordem de conclusão é não-determinística, escreva cada hook para agir independentemente em vez de depender de outro hook ter sido executado primeiro. O exemplo abaixo registra três verificações independentes para cada chamada de ferramenta:

Filtrar com matchers de múltiplas ferramentas

Use matchers de múltiplas ferramentas para compartilhar um callback entre ferramentas relacionadas. Este exemplo registra três matchers com escopos diferentes:
  • Uma lista exata separada por pipe (Write|Edit|Delete) dispara file_security_hook apenas para ferramentas de modificação de arquivo.
  • Uma regex (^mcp__) dispara mcp_audit_hook para qualquer ferramenta MCP cujo nome começa com mcp__.
  • Um matcher omitido dispara global_logger para cada chamada de ferramenta independentemente do nome.

Rastrear atividade de subagente

Use hooks SubagentStop para monitorar quando subagentes terminam seu trabalho. Veja o tipo de entrada completo nas referências do SDK TypeScript e Python. Este exemplo registra um resumo cada vez que um subagente é concluído:

Fazer requisições HTTP a partir de hooks

Hooks podem realizar operações assíncronas como requisições HTTP. Capture erros dentro de seu hook em vez de deixá-los se propagar, pois uma exceção não tratada pode interromper o agente. Este exemplo envia um webhook após cada ferramenta ser concluída, registrando qual ferramenta foi executada e quando. O hook captura erros para que um webhook falhado não interrompa o agente:

Encaminhar notificações para Slack

Use hooks Notification para receber notificações do sistema do agente e encaminhá-las para serviços externos. Notificações são disparadas para tipos de evento como:
  • permission_prompt quando Claude precisa de permissão
  • idle_prompt quando Claude está aguardando entrada
  • auth_success quando a autenticação é concluída
  • elicitation_dialog, elicitation_complete e elicitation_response para fluxos de elicitação de entrada do usuário
Cada notificação inclui um campo message com uma descrição legível por humanos e opcionalmente um title. Este exemplo encaminha cada notificação para um canal Slack. Requer uma URL de webhook de entrada do Slack, que você cria adicionando um app ao seu espaço de trabalho Slack e habilitando webhooks de entrada:

Corrigir problemas comuns

Hook não é disparado

  • Verifique se o nome do evento de hook está correto e sensível a maiúsculas/minúsculas (PreToolUse, não preToolUse)
  • Verifique se seu padrão de matcher corresponde exatamente ao nome da ferramenta
  • Certifique-se de que o hook está sob o tipo de evento correto em options.hooks
  • Para hooks não baseados em ferramentas que suportam matchers, como Notification e SubagentStop, matchers correspondem a campos diferentes, e Stop ignora matchers completamente (veja padrões de matcher)
  • Hooks podem não ser disparados quando o agente atinge o limite max_turns porque a sessão termina antes que hooks possam ser executados

Matcher não filtra como esperado

Matchers apenas correspondem a nomes de ferramentas, não a caminhos de arquivo ou outros argumentos. Para filtrar por caminho de arquivo, verifique tool_input.file_path dentro de seu hook:

Timeout de hook

  • Aumente o valor timeout na configuração HookMatcher
  • Use o AbortSignal do terceiro argumento de callback para lidar com cancelamento graciosamente em TypeScript
Um callback UserPromptSubmit ou UserPromptExpansion que excede seu timeout bloqueia esse prompt com uma mensagem de timeout e a sessão continua. Interromper a consulta enquanto um callback está pendente cancela a chamada de ferramenta pendente. Antes da v2.1.208, um timeout de callback nesses eventos terminava a consulta com error_during_execution, e uma interrupção durante um callback PreToolUse pendente poderia deixar a chamada de ferramenta prosseguir.

Ferramenta bloqueada inesperadamente

  • Verifique todos os hooks PreToolUse para retornos permissionDecision: 'deny'
  • Adicione registro aos seus hooks para ver qual permissionDecisionReason eles estão retornando
  • Verifique se padrões de matcher não são muito amplos: um matcher vazio corresponde a todas as ferramentas

Entrada modificada não aplicada

  • Certifique-se de que updatedInput está dentro de hookSpecificOutput, não no nível superior:
  • Retorne permissionDecision: 'allow' para aprovar automaticamente a entrada modificada, ou 'ask' para mostrá-la ao usuário para aprovação
  • Inclua hookEventName em hookSpecificOutput para identificar qual tipo de hook a saída é

Hooks de sessão não disponíveis em Python

SessionStart e SessionEnd podem ser registrados como hooks de callback do SDK em TypeScript, mas não estão disponíveis no SDK Python porque seu tipo HookEvent os omite. Em Python, eles estão disponíveis apenas como hooks de comando shell definidos em arquivos de configuração como .claude/settings.json. Para carregar hooks de comando shell de sua aplicação SDK, inclua a fonte de configuração apropriada com setting_sources ou settingSources:
Para executar lógica de inicialização como um callback do SDK Python, use a primeira mensagem de client.receive_response() como seu gatilho.

Prompts de permissão de subagente se multiplicando

Ao gerar múltiplos subagentes, cada um pode solicitar permissões separadamente. Subagentes não herdam automaticamente permissões do agente pai. Para evitar prompts repetidos, use hooks PreToolUse para aprovar automaticamente ferramentas específicas ou configure regras de permissão que se aplicam a sessões de subagente.

Loops recursivos de hook com subagentes

Um hook UserPromptSubmit que gera subagentes pode criar loops infinitos se esses subagentes acionarem o mesmo hook. Para evitar isso:
  • Verifique um indicador de subagente na entrada do hook antes de gerar
  • Use uma variável compartilhada ou estado de sessão para rastrear se você já está dentro de um subagente
  • Escopo hooks para executar apenas para a sessão de agente de nível superior

systemMessage não aparecendo na saída

O campo systemMessage mostra uma mensagem ao usuário, não ao modelo. Por padrão, o SDK expõe a saída de hook no fluxo de mensagens apenas para hooks SessionStart e Setup, portanto uma mensagem de qualquer outro evento de hook não aparece a menos que você defina includeHookEvents (include_hook_events em Python). Para passar contexto ao modelo, retorne additionalContext. Se você precisar expor decisões de hook para sua aplicação de forma confiável, registre-as separadamente ou use um canal de saída dedicado.