Blog · AI Harness

Guardrails e evals para agentes de IA: o que são e como saber se o agente acertou antes da produção

Capiva · Outubro 2026 · 13 min de leitura

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 next com argumentos alterados.
  • Responder no lugar. Devolve { deny: motivo } sem chamar next. 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: EACCES

Sem 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 de next é pulado. O próprio .catch tem 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 PreToolUse das 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 main de 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:

AvaliadorTipo na taxonomiaQuando usar
Baseado em código (testes, checagem de estado, análise estática)Sensor computacionalSempre que existir um resultado verificável
Baseado em modelo (rubrica, comparação par a par)Sensor inferencialQualidade aberta: tom, completude, aderência à instrução
Humano (especialista, amostragem)CalibraçãoPra 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

GuardrailEval
Pergunta"Esta ação pode acontecer?""O agente acerta, e continua acertando?"
Quando rodaEm cada ação, em tempo de execuçãoNo CI (offline) e sobre tráfego real (online)
UnidadeUma chamada de ferramenta, um promptUma distribuição de tarefas
Tipo idealComputacional e determinísticoMisto: código, juiz LLM calibrado, humano
Falha típicaFalhar aberto sem ninguém perceberMedir o texto final em vez do resultado
ExemploKill switch em tool.callGolden 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

  1. Critério de sucesso escrito e verificável no ambiente.
  2. Golden set com 20 a 50 tarefas reais, cada uma com veredito inequívoco.
  3. Avaliadores por código primeiro. Juiz LLM só onde não houver resultado verificável.
  4. Juiz LLM calibrado contra amostra humana, com troca de ordem e rubrica por dimensão.
  5. Várias tentativas por tarefa, reportando pass^k quando consistência importa.
  6. Suíte de regressão no CI, rodando a cada mudança de prompt, ferramenta ou modelo.
  7. Guardrails determinísticos para as ações irreversíveis: deleção, push, pagamento, envio externo.
  8. Kill switch testado, com falha fechada, e alguém que sabe acioná-lo.
  9. Política corporativa em managed settings, não em extensão instalada por usuário.
  10. Monitoramento online definido: o que amostrar, quem lê os transcripts e com que frequência.
  11. 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.