Verboo

Hooks

Hooks são handlers executados automaticamente em resposta a eventos do ciclo de vida do agente. Com hooks você pode:

  • Formatar código após edições
  • Bloquear operações perigosas antes de executar
  • Enviar notificações quando o agente termina
  • Fazer recovery automático em caso de falhas
  • Auditar todas as ferramentas chamadas

Configurar hooks

Hooks são definidos em settings.json ou settings.local.json:

json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write|FileWrite",
        "hooks": [
          {
            "type": "command",
            "command": "prettier --write {{file}}"
          }
        ]
      }
    ]
  }
}

Use /update-config para configurar hooks com verificação automática em 7 passos.

Eventos disponíveis

Evento Quando dispara
PermissionRequest Antes de solicitar permissão ao usuário para uma ferramenta
PreToolUse Imediatamente antes de executar qualquer ferramenta
PostToolUse Imediatamente após a ferramenta retornar (sucesso ou falha)
PreCompact Antes de compactar o contexto da conversa
PostCompact Após compactação concluída
Stop Quando o agente termina a resposta
Notification Quando o agente precisa notificar o usuário
SessionStart No início de uma nova sessão
UserPromptSubmit Quando o usuário envia um prompt

Tipos de hook

`command` — shell script

Executa um comando shell. O hook recebe um JSON via stdin e pode retornar um JSON via stdout para influenciar o comportamento do agente.

json
{
  "type": "command",
  "command": "bash /home/user/.verboo/hooks/lint-on-edit.sh"
}

Formato de entrada (stdin):

json
{
  "event": "PostToolUse",
  "tool_name": "Edit",
  "tool_input": { "file_path": "/src/main.ts", "... " },
  "tool_result": { "... " }
}

Formato de saída (stdout) — opcional:

json
{
  "continue": true,
  "decision": "approve",
  "reason": "Arquivo formatado com sucesso"
}

`prompt` — avaliação por LLM

Usa um modelo de linguagem para avaliar se a operação deve continuar:

json
{
  "type": "prompt",
  "prompt": "O comando abaixo é seguro de executar? Responda apenas 'allow' ou 'deny'.\n\nComando: {{command}}"
}

`http` — POST para URL

Faz um POST HTTP para uma URL externa:

json
{
  "type": "http",
  "url": "https://hooks.slack.com/services/XXX/YYY/ZZZ",
  "headers": {
    "Content-Type": "application/json",
    "Authorization": "Bearer ${SLACK_TOKEN}"
  },
  "body": {
    "text": "Agente finalizou: {{TASK_SUBJECT}}"
  }
}

Variáveis de ambiente são expandidas com ${VAR}. Template variables do contexto são expandidas com {{VAR}}.

`agent` — verificação agêntica

Invoca um sub-agente para verificar a operação:

json
{
  "type": "agent",
  "prompt": "Verifique se a edição em {{file_path}} não introduz vulnerabilidades de segurança."
}

Campos do hook

Campo Tipo Descrição
type string command, prompt, http, agent
command string Comando shell (apenas command)
url string URL do endpoint (apenas http)
prompt string Prompt do modelo (apenas prompt, agent)
headers object Headers HTTP (apenas http)
body object Body da requisição (apenas http)
timeout number Timeout em ms (padrão: 10000)
statusMessage string Mensagem exibida enquanto o hook roda
once bool Executa apenas uma vez por sessão
async bool Executa em background sem bloquear o agente
asyncRewake bool Rewake o agente quando o hook async terminar
if string Condição para execução (sintaxe de permission rule)

Hook matchers

O campo matcher é um padrão que filtra em qual ferramenta o hook dispara:

json
{
  "matcher": "Bash|Edit|Write",
  "hooks": [...]
}

Padrões suportados:

  • Nome exato: "Edit"
  • Alternância: "Edit|Write|FileWrite"
  • Wildcard: "*" (todos os tools)
  • Negação com if: "if": "not tool_name:Bash"

Saída do hook (decisão)

Hooks do tipo command podem retornar um JSON para controlar o agente:

json
{
  "continue": false,
  "decision": "block",
  "reason": "Operação bloqueada: destino fora do diretório autorizado",
  "stopReason": "Política de segurança violada"
}
Campo Valores Descrição
continue true/false Se false, aborta a operação
decision approve, deny, block Decisão explícita
reason string Explicação exibida ao usuário
stopReason string Mensagem de parada (quando continue: false)

Exemplos práticos

Formatar código após edição

json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "prettier --write \"{{tool_input.file_path}}\" 2>/dev/null || true",
            "async": true
          }
        ]
      }
    ]
  }
}

Bloquear comandos rm perigosos

json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "bash -c 'echo $HOOK_INPUT | jq -r .tool_input.command | grep -qE \"rm -rf /\" && echo \\'{ \"continue\": false, \"reason\": \"rm -rf / bloqueado\" }\\' || echo \\'{ \"continue\": true }\\''"
          }
        ]
      }
    ]
  }
}

Notificação Slack ao finalizar

json
{
  "hooks": {
    "Stop": [
      {
        "matcher": "*",
        "hooks": [
          {
            "type": "http",
            "url": "https://hooks.slack.com/services/T.../B.../XXX",
            "body": {
              "text": "Verboo Code finalizou: {{TASK_SUBJECT}}"
            }
          }
        ]
      }
    ]
  }
}

Auditoria de comandos bash

json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "echo \"$(date): $HOOK_INPUT\" >> ~/.verboo-audit.log",
            "async": true
          }
        ]
      }
    ]
  }
}

Hook Chains

Hook Chains são regras de recovery automático disparadas por outcomes de ferramentas ou tarefas.

Configuração

json
{
  "hookChains": {
    "version": 1,
    "enabled": true,
    "maxChainDepth": 2,
    "defaultCooldownMs": 30000,
    "rules": [
      {
        "id": "retry-on-bash-fail",
        "enabled": true,
        "trigger": {
          "event": "PostToolUse",
          "outcome": "failed"
        },
        "condition": {
          "toolNames": ["Bash"],
          "errorIncludes": "ECONNREFUSED"
        },
        "actions": [
          {
            "type": "spawn_fallback_agent",
            "prompt": "O comando falhou com ECONNREFUSED. Verifique se o serviço está rodando e tente novamente."
          }
        ]
      }
    ]
  }
}

Campos da regra

Campo Descrição
id Identificador único da regra
enabled Liga/desliga a regra
trigger.event Evento que dispara (ex: PostToolUse, TaskCompleted)
trigger.outcome success, failed, timeout, unknown
condition.toolNames Lista de ferramentas que ativam a regra
condition.errorIncludes Substring no erro
cooldownMs Mínimo de ms entre disparos (padrão: 30000)
dedupWindowMs Janela de deduplicação (padrão: 30000)
maxDepth Profundidade máxima de chains (padrão: 2, máx: 10)
actions Array de ações a executar

Tipos de ação

Tipo Descrição
spawn_fallback_agent Dispara um agente de recuperação
notify_team Notifica o time configurado
warm_remote_capacity Pré-aquece capacidade remota

Template variables nas ações

Variável Valor
{{EVENT_NAME}} Nome do evento
{{OUTCOME}} Outcome do evento
{{RULE_ID}} ID da regra
{{TASK_SUBJECT}} Assunto da tarefa
{{ERROR}} Mensagem de erro
{{PAYLOAD_JSON}} JSON completo do evento

Hook Chains são desabilitados por padrão. Habilite gradualmente por ambiente após validar o comportamento.