← Voltar ao Blog

CLAUDE.md pede, hook impõe: os 3 níveis de contrato que separam 90% de 100%

Escrevi uma regra no CLAUDE.md do meu projeto principal, deixei lá por três meses, e medi. A IA seguiu em 90% das vezes. Nove em dez. Numa conversa de bar, 90% soa ótimo: quase sempre acerta.

Passei essa mesma regra para um hook. Foi 100%. Cem em cem. E aqui está a parte que eu levei uns dois meses para admitir: 90% e 100% não são o mesmo tipo de coisa. Eles não estão na mesma linha reta. Um é um pedido educado com uma boa taxa de resposta. O outro é um contrato. Confundir os dois é o principal motivo pelo qual o harness da maior parte dos times de IA parece funcionar até o dia em que não funciona.

Este texto é sobre os três níveis de contrato que separam esses dois números, e por que você provavelmente está operando no nível errado agora.

O experimento que me forçou a olhar

Faz um ano e pouco desde que a Anthropic publicou o padrão do AGENTS.md / CLAUDE.md. A ideia é simples e sedutora: você escreve as regras do seu projeto em um arquivo de markdown, o agente lê, e a partir daí sabe como se comportar. “Documente o comportamento esperado” é uma frase que qualquer engenheiro assina sem pensar.

O problema é que eu assinei sem medir. Coloquei no meu CLAUDE.md, entre outras coisas, esta linha:

Antes de commitar, rode `npm test` e confirme que passa.

Simples. Direto. A IA leu, concordou, e por três meses fez basicamente isso. Basicamente. Fui rastrear os commits recentes um dia: 47 commits no branch principal, feitos por sessões do Claude Code no último mês. Cinco desses commits estavam com testes quebrados. Não descobertos no git blame, descobertos porque o CI reprovou o merge do PR e o job voltou para mim.

Cinco em 47 é aproximadamente 10,6%. Dez por cento de falha silenciosa em uma regra que eu tinha escrito. E o mais incômodo: eu não notei durante três meses. O CI cobriu, então eu nunca senti o custo. O harness “funcionava” porque tinha uma rede de segurança que eu esqueci que existia.

Movi a mesma regra para um hook pre-commit. Do dia seguinte em diante, zero falhas silenciosas. O hook bloqueou cinco tentativas de commit nos primeiros dez dias, todas porque um teste realmente estava quebrado e o Claude Code tentou fazer commit mesmo assim (com toda a boa intenção, claro). O hook segurou. Eu corrigi os testes. Os commits saíram limpos.

O que mudou foi o tipo de contrato. A IA continua a mesma.

Os três níveis

Depois desse tropeço, comecei a separar mentalmente três níveis de contrato no meu harness. Eu escolho pelo custo do erro. A importância da regra não entra na conta.

Nível 1 — Restrição leve (documentação)

Onde fica: CLAUDE.md, AGENTS.md, prompts iniciais, comentários no código.

Como funciona: você escreve o comportamento esperado em linguagem natural. A IA lê no início da sessão, incorpora, e tenta seguir.

Taxa de execução real: 85–95%. Depende do modelo, do tamanho do arquivo, da posição da regra dentro dele (a IA segue regras no topo com mais consistência do que as regras no final), e de quantos outros pedidos competem pela atenção.

Nível 2 — Restrição negociada (skill / subagent)

Onde fica: um skill dedicado (por exemplo, um verify-before-commit skill), um subagent chamado no fim da tarefa, uma checagem estruturada dentro do próprio prompt.

Como funciona: em vez de escrever “rode os testes antes de fazer commit” e torcer, você invoca uma sub-rotina que faz a verificação e reporta o resultado. A IA principal continua no controle, mas delega a execução da regra para algo que sempre a executa da mesma forma.

Taxa de execução real: 96–99%. A diferença para o nível 1 é que a IA principal ainda pode escolher pular a sub-rotina se achar que “essa mudança é trivial demais para rodar testes.” Ela nunca deveria fazer isso. Ela faz.

Nível 3 — Restrição rígida (hook)

Onde fica: .claude/hooks/pre-commit.sh, um webhook do CI, um pre-push do git, uma checagem no próprio wrapper que invoca o Claude Code.

Como funciona: a IA não pode pular. O código do hook roda em um contexto que a IA não controla: quem executa é o harness. Se o hook falhar, o commit não sai. Ponto.

Taxa de execução real: 100%. Sem exceção.

A frase que uso para lembrar da diferença veio de uma discussão no SmartScope sobre governança de IA:

Escrever “rode o linter” no CLAUDE.md versus impor via hook é a diferença entre “quase sempre” e “sem exceção”.

Você pode continuar dizendo às pessoas “lavem as mãos”, ou pode colocar um sensor na torneira. O sensor vence.

Quando cada nível é a escolha certa

Nem toda regra merece um hook. Se você impuser 40 hooks em um projeto, o Claude Code passa mais tempo esperando checagens do que escrevendo código. A questão é combinar o nível de contrato ao custo do erro.

Documentação (nível 1) é suficiente quando:

  • A consequência de errar é reversível em segundos (formatação estética, escolha de nome de variável, ordem de imports que o editor arruma sozinho).
  • Você tem uma rede de segurança em nível superior (o CI vai bloquear se o npm test não rodar localmente, então perder isso 10% das vezes só custa tempo).
  • A regra depende do julgamento e você não quer bloquear a criatividade da IA (por exemplo, “prefira funções pequenas, mas não force” é impossível de codificar como hook).

Skill / subagent (nível 2) é a escolha certa quando:

  • A regra requer checagem contextual que muda por tarefa (rodar apenas os testes do módulo tocado, verificar se a mudança precisa de migration, decidir se a alteração merece um novo teste).
  • A execução da regra tem várias etapas e você quer que a IA principal continue sabendo o que aconteceu (o resultado do skill volta para o contexto).
  • O custo de rodar a checagem em toda operação seria alto, e você quer que a IA escolha quando invocar.

Hook (nível 3) é obrigatório quando:

  • A consequência de errar é irreversível (apagar tabela em produção, força-push em main, deletar arquivo não versionado).
  • O erro é caro de detectar depois do fato (teste quebrado que só o CI acha, secret vazado em commit, migração que quebra o deploy).
  • Você não quer que o julgamento da IA participe da decisão. “Nunca faça commit com teste quebrado” não é negociável, então não faz sentido colocar em um lugar onde a IA pode negociar.

O erro mais comum que vejo em harnesses recém-montados é usar nível 1 (documentação) para regras que pedem nível 3 (hook). “Anthropic recomenda escrever regras no AGENTS.md” vira “eu escrevi lá, então está resolvido”. Não está. Você escreveu um pedido educado com 90% de taxa de resposta em uma questão onde 90% é o pior número possível, porque parece funcionar até o dia em que não funciona.

O exemplo mínimo de hook (Claude Code)

Para materializar, o hook que substituiu minha linha do CLAUDE.md:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "if echo \"$TOOL_INPUT\" | grep -qE 'git commit'; then npm test || exit 2; fi"
          }
        ]
      }
    ]
  }
}

Traduzindo: sempre que o Claude Code for rodar um comando Bash que contenha git commit, executa npm test primeiro. Se os testes falharem, o hook retorna exit code 2, o que faz o Claude Code abortar a chamada da ferramenta e trazer a saída de volta para o contexto. A IA vê que os testes falharam, corrige, e tenta o commit de novo. O commit só sai quando os testes passam. Sem exceção.

Comparação lado a lado dos dois “contratos”:

Restrição leve (CLAUDE.md):
  "Antes de commitar, rode `npm test`."
  → o agente esquece às vezes (~90% de execução)

Restrição rígida (hook):
  PreToolUse Bash matcher: bloqueia git commit a menos que npm test passe
  → 100% de execução (sem exceção)

Vinte linhas de JSON, e o resultado muda de categoria. Não é magia, e não é sofisticado. Só é uma camada acima da negociação com o modelo.

Por que 90% é o pior número

Vou terminar com o ponto que eu queria ter entendido três meses antes.

Uma regra com 100% de execução gera um sistema que você entende. Ou passa, ou o hook bloqueia, ou o hook explode com barulho. Você calibra o resto do harness a partir dessa garantia.

Uma regra com 0% de execução também gera um sistema que você entende, embora ruim. Você sabe que a regra não está funcionando, então ou você a implementa em outro lugar, ou você a remove, ou você aceita o risco explicitamente. É um problema visível.

Uma regra com 90% de execução é o pior dos mundos. Você acredita que ela funciona porque na maior parte das observações ela funciona. Você calibra o resto do harness assumindo que a regra vale. E aí, 10% das vezes, a regra falha em silêncio, e o harness gera um resultado que passa por cima de uma premissa que você achava garantida.

Nove em dez commits com testes verdes te fazem confiar. Foi o décimo que me acordou.

Documentação é uma ferramenta. É boa para regras de julgamento e para comunicar intenção. Mas ela não é um contrato. E se você escreveu algo importante no CLAUDE.md sem um hook por trás, você tem uma taxa de execução de 90% em um lugar onde provavelmente precisava de 100%. Vale a hora que leva para separar os dois.


ken imoto · WebRTC & Voice AI engineer · kenimoto.dev · TabNews

Harness Engineering Livro relacionado Harness Engineering Tutorial de Harness Engineering | design de AGENTS.md · implementação de hooks · operação de agentes de IA Ver a página do livro →