Pular para o conteúdo
· 9 min de leitura

Hooks como contrato: automatizando guardrails para agentes

Hooks são onde a politicagem do time vira código. O que precisa rodar antes, depois e ao redor do agente - e o que deve falhar barulhento.

Victor Dantas Comitê de IA · Bamse

Toda regra do time que vive só na cabeça das pessoas vai ser quebrada mais cedo ou mais tarde. "Sempre roda o prettier antes de commitar." "Nunca deixa subir direto pra main." "Lint antes de declarar pronto." Com gente isso já vazava. Com um agente que toma dezenas de decisões por minuto, vaza na primeira sessão distraída. Hooks são onde essas regras param de ser folclore e viram contrato executável.

Hook, no Claude Code, é um comando de shell que o harness dispara automaticamente em eventos do ciclo de vida da sessão. Eles ficam no settings.json, não no julgamento do modelo. Essa é a parte que importa: o agente não decide se vai rodar o hook. O harness roda, toda vez, independente do que o modelo "lembrou" de fazer. É justamente por serem determinísticos e fora da discrição do agente que eles servem de guardrail.

Antes: validar e bloquear

O evento mais poderoso é o PreToolUse. Ele roda antes de uma ferramenta executar e pode barrar a ação. Um hook que sai com código de saída 2, ou que devolve um JSON com permissionDecision: "deny", impede a chamada de acontecer e ainda diz ao agente por quê. É aqui que mora o "nunca deixa subir pra main": um matcher no Bash que inspeciona o comando e nega qualquer git push que aponte pra branch protegida. Não é uma sugestão no prompt. É uma porta trancada.

"Um guardrail que depende do modelo lembrar não é um guardrail - é uma esperança."

A diferença prática é brutal. Pedir "por favor não dê push na main" no CLAUDE.md funciona até a sessão ficar longa o suficiente pra aquela instrução sair de foco. O PreToolUse não esquece, não fica distraído e não negocia. Ou o comando passa no filtro, ou ele simplesmente não roda.

Depois: formatar e verificar

O PostToolUse roda depois que a ferramenta já executou - então ele não bloqueia, ele reage. O caso clássico é o auto-format: um matcher em Write|Edit que pega o arquivo recém-editado e roda o prettier nele. O agente nem precisa saber que isso existe; o código sai formatado do jeito do time, toda vez. É exatamente o padrão que uso aqui no portfólio, com a formatação amarrada num hook de pós-edição.

O mesmo evento serve pra verificação barulhenta. Editou um arquivo de teste? Roda o teste e injeta o resultado de volta no contexto. Mexeu num schema? Dispara o type-check. O ponto não é deixar bonito - é fechar o loop sem depender do agente "lembrar" de validar antes de dizer que terminou.

* Regra de Bolso

Guardrail bom falha barulhento e determinístico. Se a única coisa que segura uma regra é o modelo se lembrar dela, ela não é uma regra - é um detalhe de implementação esperando pra dar errado.

Ao redor: preparar o terreno

Tem ainda os eventos que cercam a sessão inteira. O SessionStart roda quando a conversa começa e é ótimo pra carregar contexto que o agente vai precisar de qualquer jeito: a branch atual, as issues abertas, o estado do banco local. O Stop roda quando o agente acha que terminou - e pode impedir que ele pare se um gate não passou, devolvendo a bola: "o lint ainda está falhando, continua". Antes, depois e ao redor: os três cercam a autonomia do agente sem amarrar o que ele faz no meio.

No fim, hooks são a forma de codificar a cultura do time num arquivo versionado - e uma das peças centrais do harness em volta do agente. As regras que antes viviam num canal do Slack, num onboarding mal documentado ou na memória de quem está há mais tempo viram um contrato que o agente assina sem ter escolha. E contrato que não depende de boa vontade é o único que aguenta produção.

Gostou desse escrito?

Posso passar essas e outras notas para o seu time num formato de workshop ou de mentoria recorrente pelo programa de Mentoria de IA da Bamse.

Conversar sobre mentoria
Próximo Escrito

O que descobrimos no Comitê de IA da Bamse no início de 2026