Guía completa de harness engineering: agentes de IA al estilo Claude Code
Aprende harness engineering con Claude Code, policy JSON, código Node.js ejecutable y workflows reales.
La idea de “escribe un buen prompt y deja que la IA haga el resto” ya no alcanza para crear agentes útiles. Lo que está ganando importancia es el harness engineering: diseñar el andamiaje que rodea al modelo. Si conoces el concepto de test harness en testing de software, piensa en su equivalente para agentes: herramientas, contexto, permisos, verificación y un bucle de control alrededor del LLM.
Claude Code es una referencia excelente porque no es solo una interfaz de chat. Integra herramientas de archivos, comandos shell, CLAUDE.md, hooks, modos de permiso, subagents y memoria. En esta guía veremos por qué el tema está en tendencia, cómo implementar un mini harness en Node.js con un policy JSON, y cómo aplicarlo a content automation, code review, SaaS integration, cloud operations y security boundaries.
Por Qué Se Habla Tanto De Harness Engineering
Un LLM decide bien el siguiente paso, pero el trabajo real exige observar el entorno, elegir contexto, ejecutar herramientas, manejar errores, limitar acciones peligrosas y demostrar que el resultado sirve. Todo eso vive fuera del modelo.
La documentación de Claude Agent SDK explica que puede cargar features de Claude Code como project instructions, skills, hooks y permissions. La documentación de permissions detalla allow rules, deny rules, permission modes y callbacks. La de prompt caching muestra cómo reutilizar contexto estático largo. Esas son piezas de harness, no trucos de prompt.
El OODA loop lo resume bien:
| Fase | Qué ocurre | Responsable |
|---|---|---|
| Observe | leer archivos, logs, URLs, tickets y estado de APIs | Harness |
| Orient | ordenar y comprimir el contexto | Harness |
| Decide | elegir la próxima acción | LLM |
| Act | ejecutar tool, escribir archivo, llamar API o parar | Harness |
Tres de las cuatro fases dependen sobre todo del harness. Por eso incluso un modelo fuerte se queda corto con un harness débil.
Qué Debe Contener Un Harness
Antes de empezar, un harness práctico responde cuatro preguntas: qué puede leer el agente, qué artefacto debe producir, qué checks prueban el éxito y qué acciones son automáticas, ask-first o prohibidas.
En un workflow de blog, no basta con “escribe un artículo”. El harness lee slugs existentes, elige un tema no duplicado, escribe MDX, valida frontmatter, revisa code fences, añade enlaces oficiales e internos, coloca CTAs a /products/ y /training/, ejecuta build y revisa la URL pública.
| Capa | Ejemplo | pitfall |
|---|---|---|
| Contexto | reglas de proyecto, estilo, fallos previos | supuestos viejos sobreviven |
| Herramientas | read, grep, write, test, API call | demasiadas herramientas confunden |
| Política | allow, ask, deny, sandbox | acciones destructivas sin supervisión |
| Verificación | test, diff, screenshot, public URL | salida plausible pero rota |
| Memoria | preferencias reutilizables | una nota temporal se vuelve regla permanente |
Diagrama Conceptual
El harness es la capa de control antes y después del modelo. El prompt importa, pero policy, context, tools, permission gate y verification loop deciden si el workflow es confiable.
flowchart LR
A["Goal"] --> B["Harness policy"]
B --> C["Context"]
B --> D["Tools"]
B --> E["Permissions"]
C --> F["LLM decision"]
D --> F
E --> G["Safe action"]
F --> G
G --> H["Verification"]
H --> I["Artifact"]
H --> B
Mini Harness Ejecutable En Node.js
Este ejemplo mínimo incluye modelo, dos herramientas, policy, bucle, límites de path y errores legibles. Define ANTHROPIC_API_KEY antes de ejecutarlo.
mkdir harness-demo
cd harness-demo
npm init -y
npm install @anthropic-ai/sdk
node -e "const fs=require('node:fs');fs.mkdirSync('sandbox',{recursive:true});fs.writeFileSync('sandbox/README.md','# Demo\nShip a safer agent workflow.\nKeep writes inside sandbox.\n');"
Guarda esto como policy.json.
{
"workspace": "./sandbox",
"maxSteps": 6,
"tools": {
"read_file": {
"allow": true,
"risk": "Read UTF-8 text only inside workspace"
},
"write_file": {
"allow": true,
"risk": "Write UTF-8 text only inside workspace"
}
}
}
Guarda esto como mini-harness.mjs.
import Anthropic from "@anthropic-ai/sdk";
import { mkdir, readFile, writeFile } from "node:fs/promises";
import path from "node:path";
const client = new Anthropic();
const policy = JSON.parse(await readFile(new URL("./policy.json", import.meta.url), "utf8"));
const model = process.env.ANTHROPIC_MODEL || "claude-sonnet-4-6";
const workspace = path.resolve(policy.workspace);
function safePath(requestedPath) {
const resolved = path.resolve(workspace, requestedPath);
const inside = resolved === workspace || resolved.startsWith(workspace + path.sep);
if (!inside) {
throw new Error(`Path escapes workspace: ${requestedPath}. Use a path under ${policy.workspace}.`);
}
return resolved;
}
function ensureAllowed(toolName) {
const rule = policy.tools?.[toolName];
if (!rule?.allow) {
throw new Error(`Tool '${toolName}' is not allowed by policy.json.`);
}
}
const tools = [
{
name: "read_file",
description: "Read a UTF-8 text file from the allowed workspace.",
input_schema: {
type: "object",
properties: { path: { type: "string" } },
required: ["path"],
additionalProperties: false
}
},
{
name: "write_file",
description: "Write a UTF-8 text file inside the allowed workspace.",
input_schema: {
type: "object",
properties: {
path: { type: "string" },
content: { type: "string" }
},
required: ["path", "content"],
additionalProperties: false
}
}
];
async function executeTool(name, input) {
ensureAllowed(name);
if (name === "read_file") {
return await readFile(safePath(input.path), "utf8");
}
if (name === "write_file") {
const target = safePath(input.path);
await mkdir(path.dirname(target), { recursive: true });
await writeFile(target, input.content, "utf8");
return `written ${input.path}`;
}
throw new Error(`Unknown tool: ${name}`);
}
async function run(goal) {
const messages = [{ role: "user", content: goal }];
for (let step = 0; step < policy.maxSteps; step++) {
const response = await client.messages.create({
model,
max_tokens: 1200,
tools,
system: "You are a careful file assistant. Use tools when needed. Keep writes under policy workspace.",
messages
});
messages.push({ role: "assistant", content: response.content });
const toolUses = response.content.filter((block) => block.type === "tool_use");
if (toolUses.length === 0) {
const text = response.content
.filter((block) => block.type === "text")
.map((block) => block.text)
.join("\n");
console.log(text);
return;
}
const results = [];
for (const toolUse of toolUses) {
try {
const output = await executeTool(toolUse.name, toolUse.input);
results.push({ type: "tool_result", tool_use_id: toolUse.id, content: String(output).slice(0, 8000) });
} catch (error) {
results.push({
type: "tool_result",
tool_use_id: toolUse.id,
is_error: true,
content: error instanceof Error ? error.message : String(error)
});
}
}
messages.push({ role: "user", content: results });
}
throw new Error(`Max steps reached: ${policy.maxSteps}`);
}
const goal = process.argv.slice(2).join(" ") || "Read README.md and write summary.md with three bullet points.";
await run(goal);
Ejecuta:
node mini-harness.mjs
Aunque sea pequeño, ya contiene el patrón esencial: schema de herramientas, policy, sandbox, límite de pasos, errores útiles y artefacto verificable. Añade grep, tests, approval UI, APIs SaaS y hooks para acercarte a Claude Code.
Cinco Use Cases Concretos
1. content automation
Un prompt débil pide “escribe un post”. Un harness fuerte lee artículos existentes, evita duplicados, escribe MDX, valida frontmatter y code fences, añade enlaces oficiales e internos, inserta CTAs a /products/ y /training/, ejecuta build y revisa la URL pública. El pitfall es producir traducciones delgadas y repetitivas por ir demasiado rápido.
2. code review
Un review harness lee git diff, resultados de tests, archivos modificados y reglas locales. Debe responder findings-first: bugs, risk, regresiones y tests faltantes antes del resumen. El riesgo es que el modelo describa el cambio sin encontrar fallos.
3. SaaS integration Con Notion, HubSpot, Stripe o CRM, separa read-only lookup, dry-run mutation y approved write. Puedes clasificar leads y preparar un update, pero la escritura real debe pedir aprobación. El pitfall es actualizar clientes, facturación o notas en producción por una mala clasificación.
4. cloud operations Operar cloud no es solo lanzar deploy. El harness debe revisar variables de entorno, build, diff, target, plan de rollback, health endpoint y public URL. El risk es arreglar la última línea visible del log sin tocar la causa raíz.
5. security boundaries
Las security boundaries se diseñan al principio. Read puede ser amplio, pero Write debe limitarse al workspace. Shell debe usar allow-list. rm, force push, DB de producción, billing y secrets van a deny o ask-first. El harness evita confiar demasiado.
Qué Copiar De Claude Code
Primero, separar contexto por vida útil: reglas estables en CLAUDE.md, progreso de sesión en plan y preferencias duraderas en memory.
Segundo, usar hooks para lo determinista. Format, lint, tests, link checks y screenshots deben ejecutarse como comandos. Claude interpreta fallos y propone cambios.
Tercero, aislar trabajo ruidoso. Logs largos, búsquedas amplias, traducciones y refactors grandes encajan mejor en subagents o etapas separadas.
Pitfalls Frecuentes
Demasiadas herramientas reducen precisión. Empieza con 5 a 10 herramientas claras.
Errores ilegibles bloquean la autocorrección. No devuelvas Error: failed; explica qué falta y qué se puede intentar.
Ignorar prompt caching encarece workflows largos. Separa contexto estático y dinámico.
Sin verificación, un output pulido puede romper producción. Artículos necesitan checks de frontmatter y code fence; código necesita tests; cloud necesita health checks; SaaS necesita audit log.
Los permisos se ensanchan con facilidad. Revisa allow, ask y deny de forma periódica.
Siguiente Paso
Para empezar por seguridad, lee la guía de permisos de Claude Code. Para contexto de proyecto, sigue con buenas prácticas de CLAUDE.md. Para dividir trabajo pesado, revisa patrones de subagents en Claude Code. Para coste, usa optimización de tokens en Claude Code.
Como referencia rápida, guarda el Claude Code Quick Reference Cheatsheet. Para plantillas y playbooks, empieza en /products/. Si tu equipo necesita diseñar permisos, review gates, verificación, publicación y revenue workflow, usa /training/.
Lo Que Verifiqué
En ClaudeCodeLab, el mayor beneficio del harness es que hace visibles los fallos. Un prompt puede crear un artículo; un harness comprueba profundidad, code fences, frontmatter, links, CTAs y public URL. Eso cambia la operación: ya no se trata de confiar en el output, sino de ver qué puerta de control lo aceptó o lo frenó.
Resumen
Harness engineering consiste en decidir qué puede ver el modelo, qué puede hacer, dónde debe detenerse y cómo se verifica el resultado. Claude Code es un gran ejemplo porque su valor no está solo en el modelo, sino en el scaffold que lo rodea. Ejecuta el mini harness de arriba y añade una boundary y un check para tu propio use case.
Referencias
PDF gratis: cheatsheet de Claude Code
Introduce tu email y descarga una hoja con comandos, hábitos de revisión y flujos seguros.
Cuidamos tus datos y no enviamos spam.
Sobre el autor
Masa
Ingeniero enfocado en workflows prácticos con Claude Code.
Artículos relacionados
Escalera de permisos de Claude Code para ampliar acceso sin perder control
Pasa de read-only a ediciones limitadas, comandos de prueba y checks de deploy con menos riesgo.
Claude Code Small PR Proof Pack: cambios pequeños que sí se pueden revisar
Un paquete de prueba para PRs de Claude Code: diff, checks, URL pública, CTA y rollback.
Gate de revisión antes del commit con Claude Code
Cómo revisar con Claude Code antes del commit: diff, build, URL pública, Gumroad, consultoría, tests y archivos ajenos.