Hook chains no Verboo Code: automatizar a recuperação quando uma tarefa falha
Voltar para o Blog
Artigodev toolshow toverboo codetutorialautomação

Hook chains no Verboo Code: automatizar a recuperação quando uma tarefa falha

Mafra11 de setembro de 20265 min de leitura

Uma tarefa falha de madrugada, sem ninguém olhando o terminal: hoje, no Verboo Code, ela fica falha até alguém entrar e mandar rodar de novo. Hook chains resolvem exatamente isso. É uma camada de recuperação orientada a evento que, quando um hook de falha dispara, avalia regras declarativas e executa uma ação, como recuperar a tarefa com um agente novo ou avisar o time. É um recurso real, desligado por padrão. Este artigo mostra o comando exato pra ligar e o arquivo de configuração completo, verificado direto no código-fonte de verbeux-ai/code (src/utils/hookChains.ts, docs/hook-chains.md).

O que dispara uma hook chain?

Hoje, dois eventos. PostToolUseFailure, quando uma tool falha durante a execução, e TaskCompleted com outcome: "failed", quando uma tarefa termina sem sucesso. Cada regra declara a qual evento e a qual resultado ela reage; o resultado aceita um valor único em outcome ou uma lista em outcomes (nunca os dois ao mesmo tempo, o próprio schema rejeita).

Como eu ligo hook chains no Verboo Code?

Duas coisas. Primeiro, a variável de ambiente que liga o recurso inteiro, porque ele vem desligado por padrão mesmo que exista um arquivo de configuração:

export CLAUDE_CODE_ENABLE_HOOK_CHAINS=1
# aceita tambem: true, yes, on

Segundo, o arquivo de regras. O caminho padrão é .verboo/hook-chains.json, na raiz do projeto. Pra usar outro caminho:

export CLAUDE_CODE_HOOK_CHAINS_CONFIG_PATH=/caminho/para/hook-chains.json

Sem a variável de ativação, o Verboo Code nem chega a ler o arquivo: a checagem de enabled acontece antes de qualquer tentativa de carregar a configuração do disco.

Qual é o formato do arquivo de configuração?

Um objeto com quatro campos de controle geral e uma lista de regras. Pode vir direto na raiz do JSON ou envolvido numa chave hookChains, as duas formas são aceitas.

CampoTipoPadrão
versionnúmero1
enabledbooleanotrue
maxChainDepthinteiro, 1 a 102
defaultCooldownMsinteiro30000
defaultDedupWindowMsinteiro30000
ruleslista[]

Um exemplo mínimo que recupera uma tarefa falha rodando um agente novo:

{
  "version": 1,
  "enabled": true,
  "maxChainDepth": 2,
  "defaultCooldownMs": 30000,
  "defaultDedupWindowMs": 30000,
  "rules": [
    {
      "id": "retry-task-via-fallback",
      "trigger": { "event": "TaskCompleted", "outcome": "failed" },
      "cooldownMs": 60000,
      "actions": [
        {
          "type": "spawn_fallback_agent",
          "id": "spawn-retry-agent",
          "description": "Retry failed task with fallback agent",
          "promptTemplate": "A task failed. Recover it safely.\nTask=${TASK_SUBJECT}\nError=${ERROR}",
          "agentType": "general-purpose",
          "model": "sonnet"
        }
      ]
    }
  ]
}

Como eu miro a regra só em erros específicos?

Com o bloco condition, dentro da regra. Ele é opcional, mas sem ele a regra reage a qualquer ocorrência do evento e do outcome declarados.

CampoO que faz
toolNameslista de nomes de tool que a regra aceita (bate com tool_name/toolName do evento)
taskStatuseslista de status de tarefa aceitos
errorIncludessubstring, sem diferenciar maiúscula de minúscula, contra a mensagem de erro
eventFieldEqualsigualdade exata por caminho de campo, por exemplo "meta.source": "scheduler"
"condition": {
  "toolNames": ["Edit", "Write", "Bash"],
  "errorIncludes": ["timeout", "permission denied"]
}

Dá pra só avisar o time, sem rodar agente nenhum?

Dá, com a ação notify_team no lugar de spawn_fallback_agent. Ela lê o time configurado no projeto e escreve a mensagem sem precisar disparar um agente novo:

{
  "type": "notify_team",
  "id": "notify-ops",
  "recipients": ["*"],
  "summary": "Hook chain ${RULE_ID} fired",
  "messageTemplate": "Event=${EVENT_NAME} outcome=${OUTCOME}\nTask=${TASK_ID}\nError=${ERROR}"
}

Se não houver arquivo de time configurado, a ação não quebra a cadeia: ela é pulada, com o motivo registrado. As duas ações, e uma terceira (warm_remote_capacity, que avisa o runtime pra preparar capacidade de execução remota com antecedência), aceitam os mesmos placeholders de texto:

PlaceholderPreenchido com
${EVENT_NAME}o evento que disparou a regra
${OUTCOME}o resultado do evento
${RULE_ID}o id da regra que bateu
${TASK_SUBJECT}o assunto da tarefa
${TASK_DESCRIPTION}a descrição da tarefa
${TASK_ID}o identificador da tarefa
${ERROR}a mensagem de erro
${PAYLOAD_JSON}o payload completo do evento, em JSON

warm_remote_capacity é seguro deixar configurado mesmo sem usar execução remota: ela é pulada sem erro quando a política do projeto bloqueia sessão remota, ou quando não há nenhuma sessão remota ativa pra preparar.

O que impede um loop de recuperação sem fim?

Três travas, e elas se somam. maxChainDepth corta o disparo quando a profundidade da cadeia atual já alcançou o limite (padrão 2, teto 10): uma ação de hook chain que dispara outro evento não gera uma cadeia infinita. cooldownMs impede que a mesma regra dispare de novo antes do tempo configurado passar (30 segundos por padrão, ajustável por regra). dedupWindowMs suprime a repetição da mesma combinação de evento e ação dentro da janela, então uma rajada do mesmo erro não dispara o mesmo agente várias vezes seguidas. Some a isso o comportamento seguro por padrão: se o sinal atual já foi abortado, a ação é pulada sem tentar rodar em cima de um estado que não existe mais.

Fluxograma de uma hook chain no Verboo Code: evento de falha, regra batendo pela condition, ação disparada, e a trava de segurança que impede disparo repetido
Do evento à ação, com a trava que impede loop. Verificado em verbeux-ai/code, src/utils/hookChains.ts, 11/09/2026.

Cada vez que uma regra dispara spawn_fallback_agent, um agente roda do zero pra tentar recuperar a tarefa. Numa madrugada em que o mesmo erro se repete algumas vezes antes do cooldownMs deixar a regra quieta, isso significa vários agentes de recuperação seguidos. Na Verboo Code, cada um deles roda com token ilimitado, então a quinta tentativa de recuperação custa o mesmo que a primeira.

Gostou deste artigo?
Compartilhe conhecimento com sua rede.
// Leia também

Artigos relacionados