28 de junho de 20269 min de leitura

Harness Engineering: por que seu agente falha (e não é culpa do modelo)

Quando o agente entrega pela metade ou quebra o projeto, o problema costuma ser o harness — não o modelo. Veja os cinco subsistemas que fazem a diferença.

Para economizar seu tempo:

Harness é toda a infraestrutura fora dos pesos do modelo — aquilo que evita você pedir uma coisa, o agente entregar pela metade, quebrar o build e, na sessão seguinte, começar do zero como se nada tivesse acontecido.

Consiste em cinco subsistemas:

  • InstruçõesAGENTS.md, regras do IDE, docs/
  • Ferramentas — shell, leitura/escrita de arquivos
  • Ambienteinit.sh, versões, comando para rodar o projeto
  • Estadoprogress.md, feature_list.json, commits
  • Feedback — test, lint, build

Fiz a skill harness-modular para você implementar ou melhorar o harness no seu projeto agora mesmo. Instale com:

Bash
npx skills add ErikBarroso/skills@harness-modular -g -y

Depois, peça ao agente para criar ou auditar o harness.

O restante deste artigo mostra como cada subsistema resolve uma causa real de falha.

Quando os modelos falham

Quando pedimos para o agente fazer algo e ele cria bugs, quebra testes, adiciona algo nada a ver ou entrega algo pela metade, logo pensamos que o modelo não é bom o suficiente e achamos que testar um mais caro vai resolver. Bom, talvez o problema não seja o modelo.

A Anthropic fez um teste usando o mesmo prompt ("crie um editor de jogos retrô 2D"), mesmo modelo (Opus 4.5), duas execuções. A primeira custou US$9 e 20 minutos; as principais funcionalidades do jogo não funcionaram. A segunda custou US$200 e o jogo ficou totalmente jogável.

Perceba que o modelo usado foi o mesmo. O que trouxe a diferença foi o harness. Vamos analisar alguns motivos:

1. Requisitos vagos

Se você pede algo muito vago, o agente precisa adivinhar. E adivinhar nada mais é do que sorte. Se ele errar, o retrabalho vai sair mais caro do que se você tivesse sido específico desde o início.

Subsistema que resolve: Instruções (AGENTS.md, docs/).

2. Convenções implícitas não documentadas

Você acha que seu código tem que ter early return, e suas rotas no plural, /products não /product , mas isso está apenas na sua cabeça. O agente não tem como seguir, porque ele simplesmente não faz ideia disso.

Subsistema que resolve: Instruções + Fonte de verdade no repositório.

3. Ausência de métodos de verificação

O agente vai considerar a task concluída quando ele achar que terminou. Se você não tiver um comando de verificação e não comunicar isso ao agente, ele vai escrever o código, revisar superficialmente e concluir.

A Anthropic observou um comportamento e o chamou de "ansiedade de contexto": quando o contexto está acabando, o agente acelera para terminar, pulando etapas de verificação e escolhendo soluções simples em vez das melhores.

Subsistema que resolve: Feedback (init.sh, lint, test, build).

4. Perda de estado entre sessões

Toda nova sessão começa do zero. O agente precisa redescobrir a organização do código, decisões tomadas, qual a próxima tarefa, como testar, buildar e rodar o projeto. Isso aumenta o número de falhas em tarefas maiores.

Subsistema que resolve: Estado (progress.md, feature_list.json, git log).

Ainda neste artigo, vamos ver como resolver cada um deles.


Primeiros passos no harness engineering

Primeiro de tudo: um arquivo na raiz do repositório chamado AGENTS.md. Se você usa Claude Code, o equivalente é CLAUDE.md. A função desse arquivo é dizer como operar o projeto.

Vai ser a primeira leitura que o agente faz em cada sessão. Então, ela deve conter um mapa do repositório, definition of done e restrições obrigatórias. Trate-o como um índice (~100 linhas), não enciclopédia.

Ele serve como mapa para a base de conhecimento do repositório, que ficará em uma pasta docs/:

AGENTS.md
docs/
├── design-docs/
│   ├── index.md
│   ├── core-beliefs.md
│   └── ...
├── generated/
│   └── db-schema.md
├── product-specs/
│   ├── index.md
│   ├── new-user-onboarding.md
│   └── ...

Cada documento de tópico deve ter entre 50 e 150 linhas, organizado por assunto dentro de docs/ ou ao lado do módulo correspondente. (Falaremos mais sobre isso na seção Fonte de verdade.)

Isso faz com que os agentes comecem com um ponto de entrada pequeno e sejam instruídos sobre onde procurar em seguida, em vez de serem sobrecarregados consumindo a janela de contexto.

Estrutura de documentação do projeto

Exemplo de AGENTS.md

MARKDOWN
# AGENTS.md
 
## Visão Geral do Projeto
 
API REST em TypeScript com Express.
 
## Antes de escrever código
 
1. Confirme o diretório com `pwd`.
2. Leia `progress.md` e `feature_list.json` (estado atual e feature ativa).
3. Revise commits recentes: `git log --oneline -5`.
4. Execute `./init.sh` (lint + build + test).
 
Se o baseline já estiver quebrado, corrija antes de implementar feature nova.
 
## Restrições obrigatórias
 
- Early return; evitar `else`.
- Rotas REST no plural (`/products`, não `/product`).
- Todas as APIs devem utilizar autenticação OAuth 2.0
  
## Documentos Temáticos
- Padrões de Design de API (`docs/api-patterns.md`) — Leitura obrigatória ao adicionar endpoints
- Regras de Banco de Dados (`docs/database-rules.md`) — Obrigatório ao modificar operações de banco
- Padrões de Teste (`docs/testing-standards.md`) — Referência ao escrever testes
  
## Definição de concluído
Uma feature só está concluída quando:
 
- o comportamento alvo foi implementado
- `./init.sh` passa (lint + build)
- requests relevantes do `test.http` do módulo foram exercitados
- `feature_list.json` atualizado com status + evidência
- `progress.md` atualizado ao fim da sessão
 
Não marque feature como `passing` só porque o código foi escrito.
 
## Fim de sessão
 
1. Atualizar `feature_list.json` (status + evidência).
2. Atualizar `progress.md` (o que foi feito, bloqueios, próximo passo).
3. Commit descritivo quando o repo estiver em estado seguro.
4. Próxima sessão deve conseguir rodar `./init.sh` imediatamente.

Uma vez que tenhamos essa estrutura estabelecida, o agente vai:

  • Identificar o diretório para que as alterações se limitem a ele
  • Ler os logs de git e arquivos de progresso para saber o trabalho recente
  • Ler o arquivo de funcionalidades para saber a próxima tarefa
  • Executar ./init.sh para confirmar que a aplicação não está quebrada

Essa abordagem economiza tokens, já que o agente não precisa, a cada sessão, redescobrir o que fazer, como testar, rodar o app e qual contexto está ativo.

Fortalecendo seu harness

Existem mais alguns passos que você pode fazer para melhorar o harness.

init.sh

O init.sh é um script que o agente roda antes de alterar algo no projeto. Essa etapa valida que o projeto está saudável, passando em lint, build e tests.

Se o agente adiciona código em cima de um projeto já quebrado, o estrago pode ser maior. Então ele verifica o baseline, corrige se necessário, implementa a feature e roda o script de novo para garantir que nada quebrou.

Subsistema: Ambiente + Feedback.

feature_list.json

O feature_list.json diz quais features terminaram (com evidência) e quais são os próximos passos.

Apenas adicionar código não significa que uma task foi concluída. Para uma task ser considerada concluída, precisamos verificar que o comportamento foi aprovado. Toda tarefa precisa de um critério objetivo de conclusão. Se o agente não sabe o que significa "concluído", ele entrega coisas pela metade.

Não precisa ser complexo. A Anthropic recomenda JSON porque o modelo tende a alterar menos campos indevidamente do que em Markdown. Existem dois formatos comuns:

Formato A — comportamento + evidência (bom para APIs e fluxos verificáveis):

JSON
{
  "id": "F03",
  "behavior": "POST /cart/items with {product_id, quantity} returns 201",
  "verification": "curl -X POST http://localhost:3000/api/cart/items -H 'Content-Type: application/json' -d '{\"product_id\":1,\"quantity\":2}' | jq .status == 201",
  "state": "passing",
  "evidence": "commit abc123, test output log"
}

Formato B — steps + passes (bom para fluxos de UI ou checklists):

JSON
{
  "category": "functional",
  "description": "New chat button creates a fresh conversation",
  "steps": [
    "Navigate to main interface",
    "Click the 'New Chat' button",
    "Verify a new conversation is created",
    "Check that chat area shows welcome state",
    "Verify conversation appears in sidebar"
  ],
  "passes": false
}

No formato B, a ideia é o agente alterar apenas o campo passes, evitando mudar requisitos indevidamente.

Cada item deve ter escopo concluível em uma única sessão. "O usuário pode adicionar itens ao carrinho" é boa granularidade. "Implementar o carrinho de compras" é amplo demais. "Criar o campo name no modelo Cart" é detalhado demais.

Para evitar que o agente tente muitas features de uma vez ou considere o projeto concluído precocemente, o feature_list lista tudo que falta para entregar o escopo. A cada nova sessão, o agente sabe onde paramos e qual o próximo passo.

Subsistema: Estado + Feedback.

progress.md

O progress.md (ou claude-progress.md) registra o que foi feito na sessão: decisões tomadas, mudanças de regras, erros e como foram resolvidos.

Imagine um projeto onde engenheiros trabalham em turnos. Cada novo engenheiro assume sem saber o que aconteceu no turno anterior. É exatamente isso que acontece em projetos complexos que não cabem em uma única sessão, cada nova sessão começa sem memória do que ocorreu antes.

É aí que entra o progress.md. Ele registra as ações dos agentes para que a próxima sessão compreenda rapidamente o estado do trabalho, mesmo com janela de contexto vazia.

Subsistema: Estado.


Fonte de verdade

Decisões tomadas no Slack, reuniões, Jira e até na sua cabeça são comuns. Para nós humanos já é difícil consultar depois. Imagine para o agente.

A OpenAI afirma isso de forma direta: informações que não existem no repositório não existem para o agente.

O repositório precisa ser a fonte de verdade. Qualquer coisa que o agente não consiga enxergar, na prática, não existe.

Abra uma sessão completamente nova do agente no seu projeto (sem contexto verbal), permita que ele veja apenas o repositório e faça cinco perguntas:

  • O que é este sistema?
  • Como ele está organizado?
  • Como eu executo isso?
  • Como eu verifico isso?
  • Qual é o progresso atual?

Se você não tiver o mínimo de harness, o agente nunca terá essas respostas — ou vai gastar muito mais contexto e tempo do que deveria.

Fonte de verdade no repositório

Como desenhar um bom mapa

    1. O conhecimento vive ao lado do código: coloque um documento curto em cada diretório de módulo explicando responsabilidades e restrições. Quando o agente chega ao código, encontra as regras sem precisar procurar.
    1. Seja objetivo: se remover uma regra não altera a qualidade das decisões do agente, essa regra não deveria existir. Busque equilíbrio, nada demais, nem de menos.
    1. Atualize a doc junto com o código: cada vez que modificar o código, revise a documentação naquele diretório e atualize se necessário.
project/
├── AGENTS.md              # Entrada: visão geral, comandos e restrições rígidas
├── src/
│   ├── api/
│   │   ├── ARCHITECTURE.md  # Decisões arquiteturais da camada de API
│   │   └── ...
│   ├── db/
│   │   ├── CONSTRAINTS.md   # Restrições com MUST / MUST NOT para operações críticas
│   │   └── ...
│   └── ...
├── PROGRESS.md             # Progresso: concluído, em andamento, bloqueado
└── Makefile                # Comandos padronizados: setup, teste, lint e verificação

Como manter o contexto vivo entre sessões?

Com progress.md + histórico do git, as próximas sessões sabem o progresso e o que foi feito.

Você também pode ter um decisions.md com registros de decisões importantes:

MARKDOWN
# Decisões de Design
 
## 15/01/2026: Utilizar Redis para cache de preferências do usuário
 
- **Motivo:** Alta frequência de leitura (praticamente todas as chamadas da API) e pequeno volume de dados.
- **Alternativa rejeitada:** *Materialized View* no PostgreSQL (a alta frequência de alterações não justifica o custo de manutenção).
- **Restrição:** TTL do cache de 5 minutos, com invalidação ativa sempre que ocorrer uma escrita.

Você precisa testar na prática para comprovar que Harness Engineering não é algo a ignorar se quer trabalhar de forma séria com IA.

Já passamos da fase de culpar modelos e prompts. Lembre-se: se seu prompt falhar, veja isso como uma forma de perceber que seu harness tem defeitos.