O que é harness engineering? Guia testado para Codex e Claude Code
Entenda harness engineering com o caso do Codex, limites entre IA e pessoas, código seguro e testes executáveis.
Uma equipe pede a um agente de IA para organizar um repositório. O agente encontra arquivos parecidos, altera configurações que não faziam parte da tarefa e termina dizendo que “deu tudo certo”. Sem um comando registrado, um teste ou um limite claro de arquivos, ninguém sabe se o resultado é realmente seguro.
O problema não se resolve apenas escrevendo um prompt mais detalhado. Também é preciso definir o que o agente pode enxergar, quais ferramentas pode usar, quando deve parar e qual prova será aceita como conclusão. Harness engineering é o trabalho de projetar esse sistema ao redor do agente. Em português, pense em um conjunto de apoio e contenção: a estrutura que permite trabalhar sem entregar todas as decisões à IA.
Este guia parte do caso publicado pela OpenAI sobre o Codex e monta um exemplo mínimo que serve para Claude Code e outros agentes. O código restringe o acesso a arquivos, impede sobrescrita e inclui testes que podem ser executados sem consumir créditos de API.
Principais pontos
- Um harness não é apenas um script. Ele combina contexto, ferramentas, permissões, testes, logs, recuperação e aprovação humana.
- No caso do Codex, a OpenAI tornou a estrutura do repositório, o comportamento do aplicativo e as regras de qualidade compreensíveis e verificáveis pelos agentes.
- A IA pode pesquisar, preparar rascunhos e repetir tarefas. Exclusões, produção, comunicação externa e gastos devem continuar sob decisão humana.
- Verificar apenas o prefixo textual de um caminho não cria uma sandbox completa. Links simbólicos, sobrescritas e permissões do sistema operacional também importam.
- “Testado” deve indicar comando, resultado e escopo. A mensagem de sucesso do modelo não é uma prova.
O que harness engineering significa na prática
O prompt descreve o pedido de uma execução. O harness define o ambiente em que esse pedido será tentado.
| Camada | Pergunta que responde | Exemplo mínimo |
|---|---|---|
| Contexto | O que o agente pode aprender? | AGENTS.md, pasta limitada, especificação versionada |
| Ferramentas | O que ele pode fazer? | Ler, testar e criar um rascunho |
| Permissões | Onde ele precisa parar? | Aprovação humana para excluir ou enviar |
| Verificação | O que significa “concluído”? | npm test termina com código 0 |
| Observabilidade | Como investigar uma falha? | Comando, diff e trecho relevante do erro |
| Recuperação | Como desfazer uma execução ruim? | Commits pequenos, dry-run e rollback |
Trocar o modelo não revela uma regra de negócio que existe apenas na memória de alguém. Por outro lado, um agente se torna mais previsível quando encontra a informação certa no repositório e quando os critérios de aceitação podem ser executados por uma máquina.
Por que o tema ganhou força em 2026: o caso do Codex
Uma das principais referências para a discussão atual é o artigo da OpenAI publicado em 11 de fevereiro de 2026, Harness engineering: leveraging Codex in an agent-first world.
Segundo a OpenAI, três engenheiros usaram o Codex para produzir cerca de 1.500 pull requests em aproximadamente cinco meses. O número chama atenção, mas não é a parte mais útil do relato. A equipe redesenhou o ambiente partindo do princípio de que agentes, e não pessoas digitando cada linha, fariam grande parte da implementação.
O artigo descreve práticas como:
- manter planos e decisões de arquitetura em artefatos versionados no repositório;
- permitir que o agente inspecione interface, logs, métricas e traces;
- aplicar direção de dependências e outras regras com testes estruturais e linters próprios;
- interpretar uma falha como sinal de que falta uma ferramenta, regra ou abstração, em vez de apenas pedir ao modelo para tentar de novo;
- executar limpezas recorrentes para localizar documentação antiga e desvios acumulados.
Isso não significa colocar toda a empresa em um prompt enorme. A proposta é oferecer uma entrada pequena e estável, com links para fontes específicas, e transformar restrições importantes em verificações obrigatórias.
Claude Code permite aplicar o mesmo raciocínio. A documentação oficial de hooks do Claude Agent SDK mostra como inspecionar uma solicitação de ferramenta, negar a operação, alterar a entrada ou registrar a ação. Os controles variam entre produtos, mas o harness continua responsável pelo limite e pelo ciclo de feedback.
O que delegar à IA e o que manter com uma pessoa
Não comece com autonomia total. Automatize primeiro as operações reversíveis e exija aprovação quando houver impacto em clientes, dinheiro ou produção.
| Bom primeiro passo | Delegar com condições | Decisão humana |
|---|---|---|
| Buscar arquivos | Editar arquivos existentes | Excluir dados de produção |
| Executar testes | Adicionar uma dependência | Enviar e-mail a um cliente |
| Resumir um diff | Publicar em staging | Alterar cobrança ou contrato |
| Criar um rascunho | Fazer push de uma branch | Processar dados pessoais sensíveis |
Use duas perguntas para classificar uma ação: ela pode ser desfeita com baixo custo? Ela afeta alguém fora da equipe? Comece com leitura e saída temporária. Só automatize uma operação depois que os casos de sucesso e de falha estiverem visíveis.
Como montar um harness mínimo
O exemplo oferece apenas duas capacidades ao modelo:
- ler texto dentro de
sandbox; - criar um arquivo de texto novo dentro de
sandbox.
Não há ferramenta para excluir, sobrescrever, executar shell ou acessar a rede. O exemplo foi verificado com Node.js 22, e a versão do SDK foi fixada conforme a verificação.
mkdir harness-demo
cd harness-demo
npm init -y
npm install @anthropic-ai/[email protected]
mkdir sandbox
echo "# meeting notes" > sandbox/note.md
Crie policy.json:
{
"workspace": "./sandbox",
"maxSteps": 6,
"maxToolResultChars": 4000
}
1. Aplique o limite de arquivos no código
Crie safe-files.mjs. Uma verificação como candidate.startsWith(root) não basta sozinha: uma pasta de nome semelhante também pode corresponder, e um link simbólico dentro do workspace pode apontar para fora. A leitura abaixo confere o destino real; a escrita aceita apenas arquivos novos.
import { open, readFile, realpath } from "node:fs/promises";
import path from "node:path";
function assertInside(root, candidate) {
if (candidate !== root && !candidate.startsWith(root + path.sep)) {
throw new Error(`outside workspace: ${candidate}`);
}
}
export async function createFileGate(workspace) {
const root = await realpath(path.resolve(workspace));
async function readText(relativePath) {
const requested = path.resolve(root, relativePath);
assertInside(root, requested);
const actual = await realpath(requested);
assertInside(root, actual);
return readFile(actual, "utf8");
}
async function createText(relativePath, content) {
const requested = path.resolve(root, relativePath);
assertInside(root, requested);
const actualParent = await realpath(path.dirname(requested));
assertInside(root, actualParent);
let handle;
try {
handle = await open(requested, "wx", 0o600);
await handle.writeFile(content, "utf8");
} catch (error) {
if (error.code === "EEXIST") {
throw new Error(`refusing to overwrite: ${relativePath}`);
}
throw error;
} finally {
await handle?.close();
}
return "created";
}
return { readText, createText };
}
Esse é um controle da aplicação, não uma barreira de segurança completa. Quando for necessária uma separação mais forte, use também container, máquina virtual, permissões do sistema operacional ou a sandbox do produto. Uma checagem em JavaScript não neutraliza um processo com privilégios administrativos.
2. Exponha apenas duas ferramentas ao modelo
Crie agent.mjs. O nome do modelo vem de ANTHROPIC_MODEL porque os modelos disponíveis e o acesso de cada conta podem mudar.
import Anthropic from "@anthropic-ai/sdk";
import { readFile } from "node:fs/promises";
import { createFileGate } from "./safe-files.mjs";
const model = process.env.ANTHROPIC_MODEL;
if (!model) throw new Error("Set ANTHROPIC_MODEL to a model available to your account.");
const policy = JSON.parse(await readFile("./policy.json", "utf8"));
const gate = await createFileGate(policy.workspace);
const client = new Anthropic();
const tools = [
{
name: "read_file",
description: "Read a UTF-8 text file inside the workspace",
input_schema: {
type: "object",
properties: { path: { type: "string" } },
required: ["path"],
additionalProperties: false
}
},
{
name: "create_file",
description: "Create a new UTF-8 file; existing files cannot be overwritten",
input_schema: {
type: "object",
properties: {
path: { type: "string" },
content: { type: "string" }
},
required: ["path", "content"],
additionalProperties: false
}
}
];
async function runTool(name, input) {
if (name === "read_file") return gate.readText(input.path);
if (name === "create_file") return gate.createText(input.path, input.content);
throw new Error(`unknown tool: ${name}`);
}
const prompt = process.argv.slice(2).join(" ") ||
"Read note.md and create summary.md with a three-line summary.";
const messages = [{ role: "user", content: prompt }];
for (let step = 0; step < policy.maxSteps; step += 1) {
const response = await client.messages.create({
model,
max_tokens: 1200,
system: "Use only the supplied tools. Never claim a file was created unless the tool succeeded.",
tools,
messages
});
messages.push({ role: "assistant", content: response.content });
const calls = response.content.filter((block) => block.type === "tool_use");
if (calls.length === 0) {
console.log(response.content.find((block) => block.type === "text")?.text ?? "done");
process.exit(0);
}
const results = [];
for (const call of calls) {
try {
const value = await runTool(call.name, call.input);
results.push({
type: "tool_result",
tool_use_id: call.id,
content: String(value).slice(0, policy.maxToolResultChars)
});
} catch (error) {
results.push({
type: "tool_result",
tool_use_id: call.id,
is_error: true,
content: error.message
});
}
}
messages.push({ role: "user", content: results });
}
throw new Error(`step limit exceeded: ${policy.maxSteps}`);
3. Teste o limite antes de chamar um modelo
O controle mais importante pode ser testado localmente, sem gasto de API. Crie safe-files.test.mjs:
import assert from "node:assert/strict";
import test from "node:test";
import { mkdtemp, mkdir, rm, symlink, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import path from "node:path";
import { createFileGate } from "./safe-files.mjs";
test("file gate blocks traversal, overwrite, and outside symlinks", async () => {
const base = await mkdtemp(path.join(tmpdir(), "harness-test-"));
const root = path.join(base, "sandbox");
const outside = path.join(base, "outside.txt");
try {
await mkdir(root);
await writeFile(path.join(root, "note.md"), "hello", "utf8");
await writeFile(outside, "secret", "utf8");
const gate = await createFileGate(root);
assert.equal(await gate.readText("note.md"), "hello");
await assert.rejects(() => gate.readText("../outside.txt"), /outside workspace/);
await assert.rejects(() => gate.createText("note.md", "replace"), /refusing to overwrite/);
try {
await symlink(outside, path.join(root, "outside-link.txt"), "file");
await assert.rejects(() => gate.readText("outside-link.txt"), /outside workspace/);
} catch (error) {
if (error.code !== "EPERM") throw error;
}
assert.equal(await gate.createText("summary.md", "safe"), "created");
} finally {
await rm(base, { recursive: true, force: true });
}
});
Execute as verificações offline:
node --test safe-files.test.mjs
node --check agent.mjs
Somente depois configure ANTHROPIC_API_KEY e ANTHROPIC_MODEL e execute node agent.mjs. Não grave credenciais no código-fonte nem em policy.json.
Três casos de uso
1. Desenvolvimento: implementar e validar um pull request
Entregue ao agente uma issue específica, as pastas relevantes e os comandos de teste. “Escrevi o código” não é critério de aceite. Exija uma reprodução que falhe antes da correção, o teste passando depois e um diff legível. Deploy em produção e migração de banco continuam sujeitos à aprovação humana.
2. Operação de conteúdo: impedir uma publicação fraca
Separe a criação do artigo das verificações de tema repetido, profundidade, sintaxe do código, links e layout móvel. Se uma regra falhar, o pipeline deve interromper a publicação e devolver uma mensagem que indique o ajuste necessário. Assim, a afirmação do redator de que “está pronto” não substitui a inspeção.
3. Atendimento: classificar uma solicitação e preparar a resposta
O agente pode classificar a mensagem e redigir uma resposta com justificativa. Uma pessoa aprova a alteração do cadastro e o envio. Forneça apenas os dados pessoais necessários e evite copiar a mensagem inteira para logs permanentes.
Como calcular o ROI
Meça tempo humano economizado e retrabalho evitado, não a quantidade de tokens gerados. Imagine 15 tarefas semanais que exigem 20 minutos de revisão cada: são cinco horas por semana. Se a construção inicial do harness consumir seis horas e a manutenção cair para uma hora semanal, o investimento inicial será recuperado em cerca de uma semana e meia.
É uma simulação, não uma promessa. Registre por duas semanas antes e depois:
- minutos humanos por tarefa;
- taxa de retrabalho;
- falhas detectadas antes da produção;
- quantidade de escalonamentos para aprovação humana.
Muitos pedidos de aprovação podem indicar que uma operação já comprovada e de baixo risco pode ser automatizada dentro de limites menores. Mais falhas ou retrabalho indicam que falta contexto ou verificação; não são motivo para ampliar a autonomia.
Pitfalls: erros comuns e como corrigir
Tratar um teste de nome de pasta como sandbox
Um caminho pode parecer interno enquanto um link simbólico aponta para fora. Resolva o destino real, recuse sobrescritas e adicione permissões do sistema operacional como segunda barreira.
Escrever “não faça nada perigoso” no prompt
Texto orienta, mas não impõe uma fronteira. Não disponibilize a ferramenta perigosa ou bloqueie-a em um hook antes da execução. O guia de permissões do Claude Code apresenta uma configuração concreta.
Aceitar a frase “os testes passaram”
Registre comando, código de saída e escopo. Mudanças de interface também precisam de interação direta ou screenshot. O fluxo de recibo de verificação mostra como preservar essas evidências.
Enviar todos os documentos em toda execução
Contexto longo pode esconder justamente a restrição mais importante. Use uma entrada pequena que aponte para fontes focadas e versionadas. Mantenha data e estado de verificação para que documentos antigos sejam encontrados.
Próximo passo
Escolha um fluxo reversível e escreva quatro linhas: entrada, ações permitidas, comando de aceite e ações que exigem aprovação. Para aplicar permissões, verificações e revisão em um repositório real, use o treinamento e a consultoria de implementação do Claude Code.
O que foi testado de verdade
Em 21 de julho de 2026, os blocos safe-files.mjs e safe-files.test.mjs deste artigo foram extraídos para uma pasta temporária e executados com Node.js. O teste confirmou leitura normal, criação de arquivo novo, bloqueio de ../ e recusa de sobrescrita. Nos sistemas em que o processo consegue criar link simbólico, o teste também verifica o bloqueio de um link que aponta para fora. agent.mjs passou por verificação de sintaxe.
Uma chamada real à API da Anthropic não faz parte deste escopo, pois acesso a modelos e custos variam entre contas. “Código publicado”, “sintaxe verificada”, “teste offline executado” e “API paga chamada” são afirmações diferentes; um harness confiável registra qual delas é verdadeira.
Artigos relacionados
Prompt engineering avançado para Claude Code e Codex: briefs práticos que resistem ao trabalho real
Crie prompts Claude Code/Codex com brief, critérios de aceite, verificação e iteração segura.
Claude Code ou Codex, afinal? A solução realista pra usar os dois sem acidente
Codex e Claude Code: qual é bom em quê? A divisão de trabalho e o fluxo pra usar os dois com segurança.
Funciona mesmo sem ser dev: como empurrar “aquela tarefa” da sua área pra IA
Vendas, suporte, administrativo, marketing: como aliviar aquela tarefa chata de cada área com IA, mesmo sem ser dev.
PDF grátis: cheatsheet do Claude Code
Informe seu e-mail e baixe uma página com comandos, hábitos de revisão e workflows seguros.
Cuidamos dos seus dados e não enviamos spam.
Sobre o autor
Masa
Engenheiro focado em workflows práticos com Claude Code.