4

Guia Prático: Harness no Desenvolvimento com AI (Guardrails, Evals e Claude Code)

English summary (PT-BR article): A long-form practical guide to agent harnesses in AI development, using Claude Code as the reference model for workflow design, guardrails, evals, and context management. It also explains when a harness-oriented approach can outperform rigid Spec-Driven Development and includes practical TypeScript snippets and Mermaid diagrams.

Harness no Desenvolvimento com AI: Como Implementar Guardrails, Evals e Claude Code Passo a Passo

O termo harness saiu do nicho de pesquisa e entrou de vez no vocabulário de quem constrói produto com modelos grandes.

Isso não aconteceu por acaso.

Em 2025, muita gente tratava o modelo como o produto. Em 2026, a ficha começou a cair: o modelo importa, claro, mas o resultado real depende muito da camada operacional em volta dele. É essa camada que define:

  • que ferramentas o agente vê;
  • que contexto ele carrega;
  • o que ele pode fazer sem aprovação;
  • o que precisa de confirmação;
  • o que é auditável;
  • o que vira memória;
  • o que é descartado;
  • e como você mede se o sistema está realmente melhorando.

Essa camada é o harness.

No artigo oficial "Harnessing Claude’s intelligence", publicado pela Anthropic em 2 de abril de 2026, a empresa coloca isso de forma muito elegante: agent harnesses encode assumptions about what Claude can’t do on its own. Em português claro:

um harness é a forma como você empacota as suas suposições sobre o que o modelo precisa de ajuda para fazer.

E aí mora o problema mais interessante.

Quando o modelo melhora, parte dessas suposições envelhece. O que fazia sentido com uma versão anterior do modelo pode virar peso morto com a versão atual. Você acaba mantendo filtros, resets, prompts inchados, ferramentas hiper-especializadas e fluxos de aprovação que já não aumentam qualidade na mesma proporção em que aumentam latência, custo e atrito.

É por isso que esse tema ficou tão importante.

Este artigo vai em quatro direções ao mesmo tempo:

  1. explicar o que é um agent harness de verdade;
  2. mostrar por que ele virou um dos conceitos centrais do desenvolvimento com AI;
  3. explicar por que essa abordagem pode ser uma alternativa melhor do que um SDD rígido em muitos cenários;
  4. e mostrar um caminho prático, com exemplos em TypeScript, para implementar guardrails, evals e um fluxo inspirado em Claude Code.

Vou assumir aqui que SDD significa Spec-Driven Development, que é o sentido mais comum dessa sigla no contexto atual de AI-assisted development. Se você usa a sigla em outro sentido na sua equipe, adapte essa comparação.

A tese do texto é simples:

em times que trabalham com modelos capazes, o diferencial não está em escrever uma spec cada vez mais longa; está em construir um harness que deixe o modelo forte onde ele já é forte, restrinja o que precisa ser restrito e meça continuamente o que realmente funciona.

Esse é o ponto.

O que é um harness no desenvolvimento com AI

Se você quiser a definição mais prática possível, use esta:

um harness é a camada de orquestração, contexto, ferramentas, memória, segurança e avaliação que fica em volta do modelo.

O modelo gera texto, código, tool calls e decisões. O harness define o ambiente em que isso acontece.

Na prática, um harness pode incluir:

  • system prompt;
  • ferramentas declarativas;
  • sandbox de execução;
  • políticas de aprovação;
  • memória e arquivos persistentes;
  • contexto carregado sob demanda;
  • subagentes;
  • logs e traces;
  • cache;
  • evals;
  • critérios de parada;
  • UX de interação.

Isso significa que Claude Code não é só um cliente bonito para Claude. Ele é um exemplo muito concreto de agent harness maduro.

Ele combina:

  • ferramentas amplas como shell e editor;
  • CLAUDE.md como memória hierárquica;
  • subagentes;
  • modos de permissão;
  • contexto progressivo;
  • verificação via comandos reais;
  • e uma interface que deixa o modelo agir sem perder completamente os limites.

Ou seja, quando você usa Claude Code, você já está usando um harness.

O que este artigo propõe é aprender com esse design para construir fluxos melhores nos seus próprios produtos e times.

Por que harness virou um tema central em 2026

O artigo da Anthropic traz três padrões principais:

  1. use o que Claude já sabe;
  2. pergunte "o que eu posso parar de fazer?";
  3. defina os limites com cuidado.

Esses três pontos são muito mais profundos do que parecem.

1. Use o que o modelo já sabe

A Anthropic argumenta que vale a pena construir aplicações usando ferramentas que Claude entende bem. O exemplo central é excelente: bash e um editor de texto já foram suficientes para resultados de ponta em benchmarks como SWE-bench Verified, e o próprio Claude Code se apoia nessa base.

O insight aqui é poderoso:

quanto mais você tenta esconder a complexidade do mundo atrás de abstrações artificiais demais, mais corre o risco de engessar o agente.

Ferramentas gerais, quando o modelo as domina bem, envelhecem melhor.

2. Pergunte o que você pode parar de fazer

Esse talvez seja o ponto mais importante de todo o artigo.

Harnesses acumulam decisões de projeto:

  • sempre passar todo output de ferramenta de volta pelo modelo;
  • sempre pré-carregar instruções no prompt;
  • sempre resumir contexto de um jeito específico;
  • sempre criar uma ferramenta dedicada para cada ação;
  • sempre exigir intervenção humana em cada etapa.

O problema é que parte dessas decisões nasceu para compensar limitações antigas do modelo. Quando o modelo melhora, você precisa reavaliar quais compensações ainda fazem sentido.

3. Defina limites com cuidado

Nem tudo deve ser "bash livre".

A Anthropic também mostra o outro lado: em ações com impacto real, ferramentas tipadas e declarativas podem ser superiores por motivos de:

  • segurança;
  • UX;
  • observabilidade;
  • auditoria;
  • reversibilidade.

É aqui que guardrails entram com força.

O que Claude Code ensina sobre agent harnesses

Se você observar Claude Code como produto, ele é praticamente uma aula de design de harness.

Ele parte de uma hipótese simples:

  • dar ao modelo ferramentas gerais e úteis;
  • deixar o próprio modelo decidir quando ler mais contexto;
  • dar caminhos para persistir ou resumir contexto;
  • permitir isolamento com subagentes;
  • e colocar segurança e permissão como uma camada operacional, não como um sermão no prompt.

Isso é muito importante.

Muita gente ainda tenta resolver quase tudo com:

  • prompt gigante;
  • checklist no system prompt;
  • e medo operacional.

Só que prompt não substitui ambiente.

Claude Code mostra outra direção. Em vez de tentar forçar o modelo a "ser bonzinho", ele combina:

  • ferramentas;
  • memória;
  • contexto;
  • permissões;
  • e verificações.

Essa combinação é o harness.

Por que um harness pode ser uma alternativa ao SDD

Aqui vale nuance.

Eu não estou argumentando que Spec-Driven Development morreu ou ficou inútil. Em vários cenários, SDD continua excelente, especialmente quando você tem:

  • requisitos regulatórios fortes;
  • times grandes com handoffs formais;
  • contratos de integração sensíveis;
  • necessidade alta de previsibilidade documental;
  • mudanças caras de reverter.

Mas existe um limite muito claro para SDD quando o assunto é desenvolvimento com agentes.

O problema do SDD rígido

Num fluxo de SDD rígido, você frequentemente assume que a melhor forma de controlar o sistema é:

  1. especificar tudo antes;
  2. reduzir variação durante execução;
  3. usar a spec como fonte principal de verdade;
  4. medir aderência à spec.

Isso funciona quando:

  • o espaço de solução é relativamente estável;
  • a implementação é mais previsível;
  • o executor não muda de capacidade toda semana.

Só que modelos mudam rápido.

E mais: a própria maneira como um agente bom resolve o problema pode melhorar entre uma versão e outra. Então um harness centrado em observação, limites e avaliação costuma ser mais adaptativo do que um fluxo excessivamente centrado em uma spec fixa.

Onde o harness ganha

Um bom harness ganha quando o trabalho depende de:

  • autonomia controlada;
  • exploração do ambiente;
  • capacidade do modelo de escolher a próxima ação;
  • recomposição dinâmica de contexto;
  • e melhoria contínua baseada em evals.

Nesse tipo de cenário, a pergunta mais valiosa deixa de ser:

"a implementação seguiu a spec?"

e passa a ser:

"o harness está produzindo resultados confiáveis, auditáveis e melhores ao longo do tempo?"

A formulação mais honesta

Então a melhor forma de dizer isso é:

um harness não substitui toda forma de SDD, mas é uma alternativa mais adaptativa ao SDD rígido em fluxos agentic, especialmente quando a capacidade do modelo evolui rápido e o ambiente importa tanto quanto a especificação inicial.

A arquitetura de um harness moderno

Antes de falar de implementação, vale deixar clara a arquitetura conceitual.

flowchart TD
    A[Usuario ou sistema chama o agente] --> B[Harness aplica contexto estavel]
    B --> C[Harness expoe ferramentas e politicas]
    C --> D[Modelo decide proxima acao]
    D --> E{Acao permitida?}
    E -- Nao --> F[Guardrail bloqueia, pede aprovacao ou substitui fluxo]
    E -- Sim --> G[Ferramenta executa acao]
    G --> H[Resultado filtrado, resumido ou persistido]
    H --> I[Modelo continua ou encerra]
    I --> J[Logs, traces e evals medem a qualidade]

Essa arquitetura tem algumas propriedades importantes:

  • o modelo não está sozinho;
  • o harness não precisa decidir tudo;
  • guardrails ficam fora do prompt quando possível;
  • o sistema é medível.

Os componentes essenciais de um bom harness

1. Ferramentas amplas o suficiente

Uma das principais lições da Anthropic é evitar criar abstrações desnecessárias cedo demais.

Se o modelo já sabe usar bem:

  • shell;
  • editor;
  • execução de código;
  • leitura de arquivos;
  • busca;

então comece por aí.

Ferramentas muito granulares podem parecer seguras, mas frequentemente criam:

  • rigidez excessiva;
  • mais manutenção;
  • menos adaptabilidade;
  • e um modelo pior aproveitado.

2. Guardrails fora do prompt

Esse é um ponto central.

Prompt diz comportamento desejado.

Guardrail define comportamento permitido.

Essas coisas não são a mesma coisa.

Se você quer impedir:

  • exclusão destrutiva;
  • chamadas externas irreversíveis;
  • deploy acidental;
  • escrita em áreas sensíveis;
  • vazamento de segredo;

não delegue isso ao "bom senso" do modelo.

Coloque na camada operacional.

3. Contexto progressivo

Outro aprendizado importante do artigo oficial é não pré-carregar tudo.

Contexto demais também é um problema:

  • aumenta custo;
  • diminui atenção útil;
  • polui decisões;
  • e envelhece rápido.

Por isso, skills, memory folders, context editing e subagentes são boas ideias. O modelo deve conseguir buscar contexto quando precisar, e descartar o que ficou obsoleto.

4. Observabilidade

Se você não consegue responder:

  • quais ferramentas o agente usou;
  • por que usou;
  • onde falhou;
  • quando pediu aprovação;
  • qual output foi crítico para a decisão;

então você não tem um harness maduro. Você tem um sistema opaco.

5. Evals

Sem evals, toda melhoria vira opinião.

E esse é exatamente o tipo de coisa que torna sistemas de AI frágeis em produção.

Como implementar um harness passo a passo

Agora vamos para a parte prática.

Vou usar TypeScript para ilustrar uma implementação simplificada. O objetivo aqui não é reproduzir Claude Code internamente, mas capturar seus princípios.

Passo 1: defina o contrato do harness

Antes de plugar qualquer modelo, defina o que o harness realmente controla.

Você precisa de pelo menos:

  • registro de ferramentas;
  • política de guardrails;
  • camada de execução;
  • política de persistência de contexto;
  • camada de logs;
  • camada de eval.

Um ponto de partida simples pode ser este:

export type ToolCall = {
  name: string;
  input: unknown;
};

export type ToolResult = {
  ok: boolean;
  output: string;
  metadata?: Record<string, unknown>;
};

export type GuardrailDecision =
  | { type: "allow" }
  | { type: "deny"; reason: string }
  | { type: "require_approval"; reason: string };

export interface ToolDefinition<TInput = unknown> {
  name: string;
  description: string;
  isSensitive?: boolean;
  execute(input: TInput): Promise<ToolResult>;
}

export interface GuardrailPolicy {
  evaluate(call: ToolCall): Promise<GuardrailDecision>;
}

export interface ExecutionTrace {
  stepId: string;
  toolName: string;
  input: unknown;
  decision: GuardrailDecision;
  result?: ToolResult;
  startedAt: string;
  finishedAt?: string;
}

Esse contrato já faz uma coisa importante: ele separa claramente:

  • intenção do agente;
  • política de permissão;
  • execução real;
  • e rastreabilidade.

Passo 2: trate guardrails como código

Se guardrail é só texto no prompt, ele é frágil.

Trate guardrail como política executável.

const SENSITIVE_TOOLS = new Set([
  "deploy_production",
  "delete_records",
  "call_billing_api",
  "write_secret",
]);

export class DefaultGuardrailPolicy implements GuardrailPolicy {
  async evaluate(call: ToolCall): Promise<GuardrailDecision> {
    if (SENSITIVE_TOOLS.has(call.name)) {
      return {
        type: "require_approval",
        reason: `A ferramenta ${call.name} tem side effects irreversiveis ou sensiveis.`,
      };
    }

    if (call.name === "bash") {
      const command = String((call.input as { command?: string })?.command ?? "");

      if (command.includes("rm -rf /") || command.includes("drop database")) {
        return {
          type: "deny",
          reason: "Comando bloqueado por politica de seguranca.",
        };
      }
    }

    return { type: "allow" };
  }
}

Esse exemplo é simples, mas já mostra o princípio correto:

  • o prompt pode pedir cautela;
  • o guardrail decide de fato.

Passo 3: promova ações sensíveis para ferramentas tipadas

Esse é um dos melhores pontos do artigo da Anthropic.

Uma ferramenta ampla como bash dá poder para o modelo, mas pouco contexto para o harness. Já uma ferramenta tipada dá:

  • intenção estruturada;
  • melhor logging;
  • melhor UX;
  • melhor auditoria;
  • melhores pontos de interceptação.
type DeployInput = {
  environment: "staging" | "production";
  service: string;
  version: string;
};

export const deployTool: ToolDefinition<DeployInput> = {
  name: "deploy_service",
  description: "Faz deploy de um servico em staging ou production",
  isSensitive: true,
  async execute(input) {
    return {
      ok: true,
      output: `Deploy iniciado para ${input.service}@${input.version} em ${input.environment}`,
      metadata: input,
    };
  },
};

Repare no ganho.

Agora o harness pode:

  • bloquear production;
  • permitir staging;
  • pedir confirmação contextual;
  • renderizar um modal claro para o usuário;
  • e guardar auditoria estruturada.

Isso é muito melhor do que tentar inferir tudo a partir de uma string shell.

Passo 4: deixe o modelo orquestrar o que pode ser orquestrado

Uma das críticas mais importantes do texto da Anthropic é ao padrão em que o harness força cada resultado de ferramenta a voltar inteiro para a janela de contexto.

Isso é caro e, muitas vezes, inútil.

O modelo pode decidir melhor do que o harness quando:

  • resumir;
  • filtrar;
  • processar localmente;
  • encadear uma chamada em outra;
  • ou ignorar parte do output.

Na prática, isso quer dizer que ferramentas de execução de código ou shell continuam muito valiosas.

Você não quer um harness que microgerencia demais. Você quer um harness que:

  • libera o modelo para operar;
  • mas não o deixa atravessar fronteiras erradas.

Passo 5: implemente uma camada de memória e contexto progressivo

Claude Code e a documentação da Anthropic insistem no mesmo princípio: nem todo contexto deve estar sempre carregado.

Crie um contexto em camadas:

  • contexto estável;
  • contexto da tarefa;
  • contexto recuperável;
  • contexto descartável.
export type MemoryRecord = {
  key: string;
  content: string;
  kind: "stable" | "task" | "learned";
  updatedAt: string;
};

export class MemoryStore {
  private records = new Map<string, MemoryRecord>();

  upsert(record: MemoryRecord) {
    this.records.set(record.key, record);
  }

  get(key: string) {
    return this.records.get(key);
  }

  listByKind(kind: MemoryRecord["kind"]) {
    return [...this.records.values()].filter((record) => record.kind === kind);
  }
}

O ponto aqui não é a sofisticação do storage. O ponto é a política.

Pergunte sempre:

  • isso precisa estar no contexto inicial?
  • isso precisa ser buscável?
  • isso precisa ser resumido?
  • isso precisa ser esquecido?

Harness bom também sabe tirar contexto.

Um fluxo inspirado em Claude Code

Se você quiser transformar essas ideias num fluxo real de engenharia, uma boa aproximação é esta:

flowchart TD
    A[Brief inicial da tarefa] --> B[Harness injeta contexto estavel]
    B --> C[Modelo escolhe ler arquivos, usar shell ou chamar ferramentas]
    C --> D[Guardrails avaliam a acao]
    D --> E{Permitido?}
    E -- Nao --> F[Bloqueio ou pedido de aprovacao]
    E -- Sim --> G[Execucao da ferramenta]
    G --> H[Output filtrado, resumido ou persistido]
    H --> I{Precisa de mais contexto?}
    I -- Sim --> J[Skills, memoria ou subagente]
    I -- Nao --> K[Continuar execucao]
    J --> K
    K --> L[Verificacao via testes, logs ou checks]
    L --> M[Resumo final com risco residual]

Esse fluxo não é bom porque é bonito. Ele é bom porque reflete uma realidade importante:

o trabalho não é só "pensar". O trabalho é pensar dentro de um ambiente operacional bom.

Como usar Claude Code como exemplo prático

Se você não pretende construir um produto agente do zero, ainda assim vale usar Claude Code como referência operacional para o time.

Padrões que valem copiar

1. Memória hierárquica com CLAUDE.md

Isso é útil porque separa:

  • regras amplas do projeto;
  • instruções do diretório local;
  • preferências do usuário;
  • e contexto específico.

2. Ferramentas gerais como base

shell, editor, busca e leitura de arquivos continuam excelentes ferramentas-base quando o modelo sabe usá-las bem.

3. Subagentes para isolamento

Subagente não é firula. É uma forma de não poluir a thread principal com exploração lateral demais.

4. Modos de permissão

Permissão não é só segurança. É ergonomia operacional. Ela define quando vale pedir confirmação e quando a autonomia é aceitável.

5. Verificação no ambiente real

Essa talvez seja a maior diferença entre um chat e um harness de verdade.

No chat, o modelo descreve.

No harness, o modelo:

  • lê;
  • executa;
  • verifica;
  • falha;
  • corrige;
  • mede.

Onde guardrails realmente importam

Guardrail virou buzzword. Vale separar o que é sério do que é cosmético.

Guardrails de verdade

São os que:

  • bloqueiam ações erradas;
  • pedem aprovação em ações sensíveis;
  • restringem escopo;
  • forçam checagens;
  • evitam destruição;
  • criam trilha de auditoria.

Guardrails cosméticos

São os que apenas dizem coisas como:

  • "seja cuidadoso";
  • "não faça besteira";
  • "aja com responsabilidade".

Isso pode até ajudar um pouco no prompt, mas não substitui nenhuma barreira séria.

Categorias úteis de guardrail

TipoO que protegeExemplo
Escopoevita acesso indevidobloquear escrita fora do workspace
Reversibilidadeprotege ações caras de desfazerexigir aprovação para deploy ou delete
Integridadeevita sobrescrever estado divergentestaleness check em arquivos
Dadosprotege PII, segredo e ambientes sensíveisnegar leitura de .env ou tokens
UXprotege experiência do usuáriomodal de confirmação com argumentos claros
Auditoriamelhora rastreiolog estruturado por ferramenta e argumento

Exemplo prático de guardrail com aprovação humana

Carregando publicação patrocinada...
1

Meus 2 cents,

Parar de tentar forcar o modelo a se comportar bem apenas com textao e colocar essas regras na camada de execucao ajuda um bocado.

Ainda gosto do uso de SDD (principamente quanto a orientacoes especificas sobre banco de dados, entidades, atributos e detalhes sobre a stack que estou usando) e sobre os testes a serem implementados, mas entendo o ponto de vista que voce colocou.

Apesar de um pouco artesanal, tenho usado a tecnica de "ativar" agents/claude/skills dependendo da tarefa que vou fazer (para plan, implementacao e manutencao, p.ex.) via script bash antes de chamar o agente (tentando evitar lixo em tarefas nao relacionadas).

E guardrails ainda sao um mal necessario, principalmente no nivel operacional - nao consigo fazer nada com agentes sem usar containers (ate agora nao vazaram, como diversas noticias vira-e-mexe informam).

voce tem visto/usado algum framework especifico para gerenciar essa memoria e contexto progressivo no dia a dia, ou so delega ao agente ?

Saude e Sucesso !


Este post foi favoritado via extensão TABNEWS FAVORITOS

Tem curiosidade sobre IA ? Da uma olhada no meu LIVRO: IA PARA ENGENHEIROS