Guardrails e evals respondem a perguntas diferentes. O guardrail pergunta, a cada ação: "isso pode acontecer agora?". O eval pergunta, sobre centenas de execuções: "esse agente acerta, e continua acertando depois da última mudança?". Um agente pronto pra produção precisa dos dois. Quem trata um como se fosse o outro vai pro ar sem saber se o agente funciona.
Nota: "harness" aqui é o conceito de software, a infraestrutura em volta do modelo. Se o termo é novo pra você, comece por o que é um AI harness.
Onde este post entra
Neste blog a gente já explicou harness engineering, como construir um harness a partir das falhas e por que o Claude Code é um harness. Faltava explicar como você sabe que o harness funciona. O loop de erro para regra, de Mitchell Hashimoto, pressupõe que você enxerga o erro. Guardrails e evals mostram o erro antes do deploy.
Guides e sensors: a taxonomia de Böckeler
Birgitta Böckeler (Thoughtworks) dá o vocabulário em "Harness engineering for coding agent users" (martinfowler.com, 2 de abril de 2026):
- Guides (feedforward) antecipam o comportamento do agente e tentam direcioná-lo antes de ele agir.
- Sensors (feedback) observam depois que o agente age e ajudam ele a se auto-corrigir.
Ela adiciona um segundo eixo, que é o que mais pesa na avaliação:
- Computacional. Determinístico e rápido: testes, linters, type checkers, análise estrutural.
- Inferencial. Análise semântica, revisão por IA, "LLM as judge". Mais lento, mais caro e não-determinístico.
Com esses dois eixos dá pra classificar guardrails e evals. Um guardrail é um sensor (às vezes um gate) que roda dentro do loop do agente, em cada ação. Um eval é um sensor que roda fora do loop, sobre um conjunto de tarefas, pra medir o comportamento agregado.
Guardrails: o sensor que roda antes da ação
Um guardrail não mede qualidade. Ele impõe um limite: "nunca rode git push --force", "pare tudo quando eu mandar".
Um bom guardrail é computacional sempre que possível. Uma regra no prompt ("não apague arquivos") é um guide inferencial: ajuda, mas degrada conforme o contexto enche. Um hook que bloqueia a chamada funciona igual no primeiro minuto e na décima sessão. É o princípio do capivaOS: regra que precisa valer sempre vira hook, não frase no prompt.
Claude Code Mods: guardrails como código TypeScript
Em 1º de outubro de 2026, a Anthropic lançou os mods do Claude Code: pequenas funções em TypeScript (ou JavaScript) que rodam dentro do Claude Code e se penduram nos eventos que ele emite. Pra quem coloca agente em produção, o evento que interessa é o tool.call.
Segundo a documentação oficial, o evento tool.call dispara toda vez que o Claude vai rodar uma ferramenta, inclusive em subagents e ferramentas MCP. O hook pode:
- Observar. Registra e devolve
next(e), e a ferramenta roda. - Reescrever. Chama
nextcom argumentos alterados. - Responder no lugar. Devolve
{ deny: motivo }sem chamarnext. A ferramenta não roda, e o Claude lê o motivo como resultado da ferramenta.
Na taxonomia de Böckeler, um hook em tool.call que bloqueia é um sensor computacional posicionado antes da execução: ele observa a ação que o agente já decidiu tomar e devolve um sinal legível pelo modelo. A própria Böckeler descreve mensagens de sensor escritas pra consumo do LLM como "a positive kind of prompt injection", uma forma positiva de prompt injection. O texto do deny é isso, e a doc recomenda escrevê-lo como uma instrução que o Claude consegue seguir.
Já um hook em prompt.submit ou prompt.section, que reescreve o que o modelo lê, é um guide: atua antes de o agente decidir qualquer coisa.
Exemplo: um kill switch em um arquivo
O exemplo mais simples é um interruptor que para todas as ferramentas quando existe .claude/KILL no projeto. Um humano (ou um alerta) cria o arquivo, e o agente para na próxima chamada.
O código abaixo segue a API documentada: on('tool.call', ...), $.fs.exists (que resolve para boolean nas declarações de tipos oficiais) e o .catch pra falhar fechado. A Anthropic avisa que os eventos podem mudar entre versões e que os tipos gerados para o seu build prevalecem sobre qualquer página, então confira contra a sua versão (mods exigem Claude Code v2.1.287 ou posterior no terminal).
kill-switch/
├── .claude-plugin/plugin.json
└── hooks/
├── hooks.json → { "modules": ["./register.ts"] }
└── register.ts// kill-switch/hooks/register.ts
import type { On } from 'claude-code'
// Caminho relativo: resolve contra o diretório de trabalho da sessão
const KILL_FILE = '.claude/KILL'
export function register(on: On) {
// Sem matcher: roda antes de TODA chamada de ferramenta,
// inclusive de subagents e de ferramentas MCP
on('tool.call', async ($, e, next) => {
if (await $.fs.exists(KILL_FILE)) {
// Não chama next(): a ferramenta não roda e o Claude lê o motivo
return {
deny:
'Kill switch ativo (.claude/KILL existe). Pare a tarefa, ' +
'não tente outra ferramenta e aguarde instruções de um humano.',
}
}
return next(e)
}).catch(async ($, e, next) => {
// Sem este handler, um hook que falha antes de next() é pulado
// e a chamada segue (fail open). Aqui, falhamos fechado.
if (next.called) return next(e)
return { deny: 'Kill switch indisponível (' + next.error.kind + '). Chamada bloqueada por segurança.' }
})
}E o guardrail também ganha teste. O kit claude-code/testing dispara eventos sem sessão, sem login e sem rede, com stubs no lugar das chamadas da API dos mods (Test a mod):
// kill-switch/tests/kill-switch.test.ts
import { expect, test } from 'claude-code/testing'
test('bloqueia toda ferramenta quando o arquivo KILL existe', async ($, on) => {
on('fs.exists', () => ({ value: true }))
const r = await $.tool.call({ tool: 'Bash', command: 'ls' })
expect(r.deny).toContain('Kill switch ativo')
})
test('deixa passar quando o arquivo não existe', async ($, on) => {
on('fs.exists', () => ({ value: false }))
on('tool.call', () => ({ result: 'ok' }))
const r = await $.tool.call({ tool: 'Bash', command: 'ls' })
expect(r.result).toBe('ok')
})
test('falha fechado quando não dá pra checar o arquivo', async ($, on) => {
on('fs.exists', () => ({ deny: 'EACCES' }))
const r = await $.tool.call({ tool: 'Bash', command: 'ls' })
expect(r.deny).toContain('Kill switch indisponível')
})O terceiro teste simula o $.fs.exists falhando: um stub que devolve { deny } faz a chamada rejeitar dentro do mod, como a documentação descreve. Rodei os dois arquivos acima com o Claude Code 2.1.296 no Linux, sem login e sem chave de API, a partir da pasta kill-switch/:
$ claude plugin validate .
...
Validating hooks: .../kill-switch/hooks/hooks.json
❯ ./register.ts hooks: tool.call
❯ ./register.ts gating hook with .catch: tool.call
❯ ./register.ts calls: $.fs.exists
✔ Validation passed with warnings
$ claude plugin test
tests/kill-switch.test.ts:
(pass) bloqueia toda ferramenta quando o arquivo KILL existe [47.36ms]
(pass) deixa passar quando o arquivo não existe [14.61ms]
(pass) falha fechado quando não dá pra checar o arquivo [12.10ms]
3 pass
0 fail
Ran 3 tests across 1 file. [0.20s]O único aviso do validate foi a falta do campo author no plugin.json. Pra ver o fail open acontecer, apaguei o .catch do register.ts e rodei de novo. O terceiro teste falhou, e o motor mostra por quê:
(fail) falha fechado quando não dá pra checar o arquivo [15.84ms]
HooksError: no implementation for tool.call
...
the engine reported:
kill-switch's tool.call hook was skipped: kill-switch: $.fs.exists: EACCESSem o .catch, o hook foi pulado e a chamada seguiu adiante; no teste, não havia nada embaixo pra respondê-la, por isso o no implementation. Numa sessão real, a ferramenta teria rodado. claude plugin test saiu com status 1 nesse caso, então isso roda no CI como qualquer suíte.
Os limites que a documentação deixa claros
Um guardrail honesto vem com a lista do que ele não cobre. Pela documentação:
- Mods não rodam em sandbox. Têm as permissões do seu usuário. Instale só de fontes confiáveis e revise com
claude plugin validate. - Sem
.catch, a falha é aberta. Hook que lança erro ou estoura o tempo antes denexté pulado. O próprio.catchtem limite de 1 segundo; se falhar, o hook é pulado também. - Ferramentas executadas pelo servidor da API (como o advisor) não disparam
tool.call. - Política corporativa vem primeiro. Hooks
PreToolUsedas managed settings rodam antes de qualquer mod, e o bloqueio deles é final. Regra obrigatória mora ali. - Casar texto de comando é lembrete, não segurança. Pra proteger a
mainde verdade, proteja no Git host.
Guardrail limita o estrago possível. Ele não diz se o agente faz um bom trabalho. Pra isso existe o eval.
Evals: o sensor que mede o agente inteiro
A Anthropic define, em "Demystifying evals for AI agents" (janeiro de 2026): um eval é um teste para um sistema de IA. Você dá uma entrada, aplica uma lógica de avaliação à saída e mede o sucesso.
Em agentes, o sistema avaliado é modelo, harness, ferramentas e ambiente. Avalie, de preferência, o resultado no ambiente (o teste passou? o registro existe?) em vez do texto final, porque o agente pode anunciar que terminou sem ter terminado.
(O "eval harness", runner que executa e pontua, não é o "agent harness". A distinção está em AI harness e benchmark.)
Offline e online
- Evals offline. Rodam antes do deploy, sobre um conjunto fixo de tarefas, sem usuário real. São o que roda no CI a cada mudança de prompt, de ferramenta ou de modelo.
- Evals online. Rodam sobre tráfego de produção: monitoramento, amostras de transcripts avaliadas automaticamente, feedback de usuário, testes A/B.
A Anthropic usa a imagem do queijo suíço: nenhuma camada pega tudo. Evals automatizados são a primeira linha no CI/CD; o monitoramento de produção pega drift e falhas imprevistas; a revisão humana periódica calibra o resto.
Golden set: comece com poucas tarefas, mas reais
Golden set é o conjunto curado de tarefas, com critério de sucesso inequívoco, que representa o que o agente precisa acertar. O erro comum é adiar porque "precisamos de centenas de casos". A Anthropic recomenda começar com 20 a 50 tarefas simples, tiradas de falhas reais.
Teste de qualidade da tarefa: dois especialistas chegariam sozinhos ao mesmo veredito? Se não, o problema está na tarefa, não no agente.
Três tipos de avaliador
O mesmo artigo separa três tipos de grader, que mapeiam direto nos eixos de Böckeler:
| Avaliador | Tipo na taxonomia | Quando usar |
|---|---|---|
| Baseado em código (testes, checagem de estado, análise estática) | Sensor computacional | Sempre que existir um resultado verificável |
| Baseado em modelo (rubrica, comparação par a par) | Sensor inferencial | Qualidade aberta: tom, completude, aderência à instrução |
| Humano (especialista, amostragem) | Calibração | Pra validar os avaliadores automáticos |
LLM-as-judge: útil, desde que calibrado
O artigo de referência é "Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena" (Zheng et al., 2023). Os autores mostram que juízes fortes (no estudo, GPT-4) chegaram a mais de 80% de concordância com preferências humanas, o mesmo nível de concordância entre humanos. E documentam três vieses: de posição (preferir a primeira resposta), de verbosidade (preferir a mais longa) e de autopromoção (preferir as próprias respostas).
Na prática, isso vira regra de engenharia:
- Troque a ordem das respostas e só declare vencedor quando o veredito se mantiver nas duas ordens.
- Use rubricas estruturadas e avalie cada dimensão com um juiz isolado, como recomenda a Anthropic.
- Dê ao juiz uma saída: permitir "Unknown" quando faltar informação reduz alucinação.
- Calibre contra humanos antes de confiar, e de novo quando trocar o modelo juiz.
Regressão: o eval que protege o que já funciona
A Anthropic separa dois tipos de suíte. Evals de capacidade perguntam "o que esse agente consegue fazer?" e devem começar com taxa de acerto baixa: é ali que você melhora. Evals de regressão perguntam "ele ainda faz tudo o que fazia?" e devem passar perto de 100%. Queda ali é sinal de que algo quebrou.
O ciclo fecha com o loop de Hashimoto: cada falha de produção vira tarefa nova no golden set, e tarefas de capacidade já dominadas "se formam" na suíte de regressão.
Uma métrica que gestor precisa entender: pass@k e pass^k
Agentes são não-determinísticos, então uma execução por tarefa não basta. A Anthropic usa duas métricas. pass@k é a chance de acertar ao menos uma vez em k tentativas. pass^k é a chance de acertar todas as k. Com 75% de acerto por tentativa e 3 tentativas, pass^3 é 0,75³, cerca de 42%.
Pra uma ferramenta interna em que basta uma resposta boa, use pass@k. Pra um agente que atende cliente, use pass^k.
Guardrails vs. evals, lado a lado
| Guardrail | Eval | |
|---|---|---|
| Pergunta | "Esta ação pode acontecer?" | "O agente acerta, e continua acertando?" |
| Quando roda | Em cada ação, em tempo de execução | No CI (offline) e sobre tráfego real (online) |
| Unidade | Uma chamada de ferramenta, um prompt | Uma distribuição de tarefas |
| Tipo ideal | Computacional e determinístico | Misto: código, juiz LLM calibrado, humano |
| Falha típica | Falhar aberto sem ninguém perceber | Medir o texto final em vez do resultado |
| Exemplo | Kill switch em tool.call | Golden set de 30 tarefas reais no CI |
Guardrail sem eval dá um agente que não causa desastre, mas que talvez não entregue nada. Eval sem guardrail dá um agente que acerta quase sempre, sem controle sobre o resto.
Checklist antes de ir para produção
- Critério de sucesso escrito e verificável no ambiente.
- Golden set com 20 a 50 tarefas reais, cada uma com veredito inequívoco.
- Avaliadores por código primeiro. Juiz LLM só onde não houver resultado verificável.
- Juiz LLM calibrado contra amostra humana, com troca de ordem e rubrica por dimensão.
- Várias tentativas por tarefa, reportando
pass^kquando consistência importa. - Suíte de regressão no CI, rodando a cada mudança de prompt, ferramenta ou modelo.
- Guardrails determinísticos para as ações irreversíveis: deleção, push, pagamento, envio externo.
- Kill switch testado, com falha fechada, e alguém que sabe acioná-lo.
- Política corporativa em managed settings, não em extensão instalada por usuário.
- Monitoramento online definido: o que amostrar, quem lê os transcripts e com que frequência.
- Toda falha de produção vira tarefa nova no golden set.
Perguntas frequentes
Qual a diferença entre guardrail e eval?▼
O guardrail age em cada ação, em tempo de execução, e decide se ela pode acontecer. O eval mede o comportamento do agente sobre um conjunto de tarefas, antes do deploy (offline) e em produção (online). Guardrail limita; eval mede.
O que são Claude Code Mods?▼
São funções em TypeScript ou JavaScript, distribuídas como plugins, que rodam dentro do Claude Code e se penduram nos eventos dele. A Anthropic lançou em 1º de outubro de 2026. Um hook em tool.call vê cada ferramenta antes de ela rodar e pode bloquear, reescrever ou responder no lugar.
LLM-as-judge é confiável?▼
Pode ser, se calibrado. Zheng et al. (2023) mediram mais de 80% de concordância entre juízes fortes e humanos, mas também vieses de posição, verbosidade e autopromoção. Prefira avaliadores por código quando o resultado for verificável.
Onde a Capiva entra
É isso que a fase de Validação Técnica da Capiva faz antes do investimento maior: definir critério de sucesso mensurável, montar o golden set com seus dados reais, medir o agente e desenhar os guardrails que a operação exige. Você sai com um go ou no-go baseado em números medidos.
Se você tem um agente funcionando em piloto e não sabe dizer se ele está pronto pra produção, vale uma conversa.