Guía completa de harness engineering: cómo construir agentes de IA al estilo Claude Code
Un buen prompt no basta para dominar un LLM. Aprende a entrelazar herramientas, contexto y bucles de control en un harness, con código funcional y la arquitectura de Claude Code como guía.
La era de «lanzar un prompt a ChatGPT y ya está» terminó. Desde 2025, el centro de gravedad de la ingeniería de IA se ha desplazado rápidamente hacia el harness engineering. Es una de las palabras clave que más se repiten en los blogs internos de Anthropic y en la investigación sobre agentes de OpenAI.
Y aun así, pregunta a alguien «¿qué es un harness?» y pocas personas dan una respuesta contundente. En este artículo desentrañamos el harness engineering con código ejecutable y la arquitectura de Claude Code como caso de estudio. Al terminar tendrás todo lo necesario para montar tu propio agente desde cero.
Un harness es el «andamiaje» que rodea a la IA
«Harness» significaba originalmente arnés para un caballo o cinturón de seguridad para un escalador. En software pensamos en el «test harness»: la estructura externa que permite que algo funcione.
En IA, un harness es la capa envolvente alrededor del LLM. De forma concreta, agrupa todo lo que el modelo necesita para resolver tareas reales:
- Herramientas: leer archivos, ejecutar comandos, llamar APIs, etc.
- Gestión del contexto: qué recordar, qué olvidar, qué comprimir
- Bucle de control: cuándo invocar, cuándo detener, cuándo reintentar
- Permisos y salvaguardas: evitar que operaciones destructivas se ejecuten solas
- Memoria: conocimiento que persiste entre sesiones
El prompt es solo una entrada a este harness. Con un harness débil, incluso el prompt más ingenioso choca con un techo de rendimiento. Por eso se oye cada vez más: «la ingeniería de prompts ya no es suficiente».
Por qué importa el harness: piénsalo como un bucle OODA
Un LLM por sí solo únicamente puede «generar el siguiente token». Para resolver tareas reales hay que girar un bucle OODA (Observe → Orient → Decide → Act), tomado de la estrategia militar.
| Fase | Contenido | Responsable |
|---|---|---|
| Observe (Observar) | Leer el entorno (archivos, consultas a BD) | Harness |
| Orient (Orientar) | Organizar la información y pasarla al LLM | Harness |
| Decide (Decidir) | Elegir el siguiente paso | LLM |
| Act (Actuar) | Ejecutar (comandos, llamadas a API) | Harness |
Como ves, tres de las cuatro fases corresponden al harness. El LLM solo brilla en la decisión. La calidad del andamiaje que lo rodea determina la calidad del agente completo.
Tres niveles de harness, con ejemplos
Resolvamos la misma tarea, «generar un artículo de blog», en tres niveles crecientes.
Nivel 1: llamada cruda a la API (casi sin harness)
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
const res = await client.messages.create({
model: "claude-opus-4-6",
max_tokens: 4096,
messages: [{ role: "user", content: "Escribe un artículo de blog" }],
});
console.log(res.content[0].text);
Resultado: texto genérico y vacío. Tema y estructura cambian en cada ejecución.
Nivel 2: añadir herramientas (harness intermedio)
const tools = [
{
name: "read_existing_posts",
description: "Obtiene la lista de artículos existentes con sus títulos",
input_schema: { type: "object", properties: {} },
},
{
name: "write_post",
description: "Escribe un archivo MDX",
input_schema: {
type: "object",
properties: {
slug: { type: "string" },
frontmatter: { type: "object" },
body: { type: "string" },
},
required: ["slug", "frontmatter", "body"],
},
},
];
async function runAgent(userGoal: string) {
let messages = [{ role: "user", content: userGoal }];
while (true) {
const res = await client.messages.create({
model: "claude-opus-4-6",
max_tokens: 4096,
tools,
messages,
});
if (res.stop_reason === "end_turn") break;
// El harness ejecuta la llamada a la herramienta
const toolUse = res.content.find((c) => c.type === "tool_use");
const result = await executeTool(toolUse.name, toolUse.input);
messages.push({ role: "assistant", content: res.content });
messages.push({
role: "user",
content: [{ type: "tool_result", tool_use_id: toolUse.id, content: result }],
});
}
}
Resultado: se escoge un tema no duplicado y se produce un MDX con formato correcto. Solo añadir herramientas cambia radicalmente la calidad.
Nivel 3: un harness completo al nivel de Claude Code
- Bucle autónomo (aprobación del usuario, reintentos ante errores)
- Compresión de contexto (resumir conversaciones largas para ahorrar tokens)
- Delegación a subagentes (traducir en contexto aislado)
- Prompt caching (no reenviar la parte estática)
- Hooks (lint automático antes del commit)
Armar todo esto a mano es un proyecto mayor. Por eso estudiar Claude Code como implementación de referencia resulta tan valioso.
Desmontando el harness de Claude Code
Claude Code es el harness de agente más pulido dentro de Anthropic. Se descompone en estas cinco capas.
Capa 1: diseño de herramientas
De fábrica vienen Read, Edit, Write, Bash, Glob, Grep, Agent, etc. Presta atención a la granularidad:
Grepno es un simplegrep, sino un envoltorio de ripgrep: preciso y velozEditno reescribe el archivo completo, sino que sustituye cadenas concretas: diff mínimoAgentcrea un subagente con contexto aislado
La calidad de las herramientas se refleja directamente en la del agente. «Con que funcione basta» no vale. Diseña las herramientas con idempotencia, mensajes de error claros y una única responsabilidad.
Capa 2: contexto por capas
~/.claude/CLAUDE.md ← reglas globales
./CLAUDE.md ← reglas del proyecto (carga automática)
~/.claude/memory/ ← memoria a largo plazo (entre sesiones)
├── user_profile.md
├── feedback_xxx.md
└── project_xxx.md
historial de la conversación ← turnos recientes
tareas/plan ← progreso de la sesión actual
Cada capa tiene una vida útil y un rol distintos. Escribir donde no toca hace que la información se pierda o, peor aún, que datos obsoletos sobrevivan. «Solo esta sesión» va en tareas; «se usará siempre» va en memoria.
Capa 3: delegación a subagentes
Con la herramienta Agent puedes lanzar otro agente en un contexto propio.
# El principal solo da instrucciones; el trabajo pesado va al subagente
Agent(
subagent_type: "general-purpose",
prompt: "Traduce blog/harness.mdx al inglés y a otros 8 idiomas,
guarda cada versión en blog-{lang}/ y reporta"
)
Así el contexto principal no se contamina con logs ruidosos. Logs de compilación, traducciones intermedias, volcados de búsqueda… cualquier trabajo del que solo necesitas el resultado final se delega sin problema.
Capa 4: hooks (procesamiento determinista)
En .claude/settings.json puedes enganchar comandos de shell antes y después de las llamadas a herramientas.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{ "type": "command", "command": "npx tsc --noEmit" }
]
}
]
}
}
Tras cada edición se ejecuta automáticamente la comprobación de tipos. Todo lo que deba gestionarse de forma determinista en lugar de pedírselo al LLM cada vez pertenece a un hook.
Capa 5: modos de permisos
{
"permissions": {
"allow": ["Read", "Grep", "Glob"],
"deny": ["Bash(rm -rf*)", "Bash(git push --force*)"],
"ask": ["Write", "Edit", "Bash"]
}
}
Deniega de forma explícita los comandos destructivos y exige aprobación para las escrituras. Los accidentes ocurren cuando algo se ejecuta sin supervisión, así que esta capa define tu seguridad operativa.
Cinco trampas frecuentes
1. Demasiadas herramientas Si le das 30 herramientas al modelo se pierde al elegir y la precisión cae. Regla empírica: entre 5 y 15. Lo que sobre, llévalo a subagentes.
2. No aprovechar el prompt caching
Sin usar cache_control de la API de Claude, reenvías el system prompt largo completo en cada turno y la factura se dispara. Ten presente el TTL de 5 minutos y cachea la parte estática.
messages: [{
role: "system",
content: [
{ type: "text", text: longStaticInstructions,
cache_control: { type: "ephemeral" } }, // ← esto
{ type: "text", text: dynamicContext },
],
}]
3. Mensajes de error que el LLM no puede interpretar
Si una herramienta devuelve únicamente Error: undefined, el modelo no puede autocorregirse. Explica qué falló y cómo arreglarlo.
throw new Error(
`El archivo '${path}' no existe. ` +
`Archivos actualmente en scripts/: ${list.join(", ")}`
);
4. Saltarse la aprobación humana Autorizar de manera automática acciones destructivas (borrar, force push, actualizaciones de BD) garantiza un desastre tarde o temprano. Por defecto: preguntar para escritura, denegar borrados.
5. No ordenar la memoria
La información vieja empuja al agente hacia suposiciones erróneas. La memoria también necesita limpiezas periódicas (en Claude Code mediante /compact o edición manual).
Pon a correr tu mini harness
Para terminar, un harness mínimo en Node.js + TypeScript.
// mini-harness.ts
import Anthropic from "@anthropic-ai/sdk";
import { readFileSync, writeFileSync } from "fs";
const client = new Anthropic();
const tools = [
{ name: "read_file",
description: "Leer un archivo de texto",
input_schema: { type: "object", properties: { path: { type: "string" } }, required: ["path"] } },
{ name: "write_file",
description: "Escribir un archivo de texto",
input_schema: { type: "object", properties: { path: { type: "string" }, content: { type: "string" } }, required: ["path", "content"] } },
];
const executors = {
read_file: ({ path }) => readFileSync(path, "utf-8"),
write_file: ({ path, content }) => { writeFileSync(path, content); return `written ${path}`; },
};
async function loop(goal: string, maxSteps = 10) {
const messages: any[] = [{ role: "user", content: goal }];
for (let i = 0; i < maxSteps; i++) {
const res = await client.messages.create({
model: "claude-opus-4-6", max_tokens: 4096, tools, messages,
});
messages.push({ role: "assistant", content: res.content });
if (res.stop_reason === "end_turn") return res.content;
const toolUse = res.content.find((c: any) => c.type === "tool_use") as any;
if (!toolUse) return res.content;
const result = executors[toolUse.name](toolUse.input);
messages.push({
role: "user",
content: [{ type: "tool_result", tool_use_id: toolUse.id, content: String(result) }],
});
}
}
await loop("Lee README.md y guarda un resumen de 3 líneas en TL;DR.md");
Con esto ya tienes un miniagente que puede leer un archivo existente y escribir otro nuevo. Añade herramientas como Grep, Bash y Agent, y tendrás una versión reducida de Claude Code.
Conclusión: del redactor de prompts al arquitecto de harness
| Enfoque anterior | Enfoque actual |
|---|---|
| Buen prompt, buen resultado | Buen harness, buen resultado |
| Elegir un modelo | Diseñar modelo + herramientas + contexto + permisos |
| Preguntas puntuales | Operación continua en bucle |
Claude Code es el mejor material didáctico para asimilar este cambio de perspectiva. No te limites a usarlo: desmóntalo e incorpora las ideas a tu propio agente. Esa es la actitud que se exige a los ingenieros de IA desde 2026.
Copia y pega el mini harness de arriba y ejecútalo. Diez minutos después habrás dado el primer paso hacia tu agente personal.
Artículos relacionados
- 10 patrones de subagentes en Claude Code
- Buenas prácticas de CLAUDE.md
- Técnicas de optimización de tokens en Claude Code
- Guía de permisos de Claude Code
Referencias
Lleva tu flujo con Claude Code al siguiente nivel
50 plantillas de prompts probadas en producción, listas para copiar y pegar en Claude Code.
PDF gratuito: Hoja de trucos de Claude Code en 5 minutos
Solo deja tu correo y te enviaremos al instante la hoja de trucos en una página A4.
Cuidamos tus datos personales y nunca enviamos spam.
Sobre el autor
Masa
Ingeniero apasionado por Claude Code. Dirige claudecode-lab.com, un medio tecnológico en 10 idiomas con más de 2.000 páginas.
Artículos relacionados
Guía Completa de Seguridad para Claude Code: Claves API, Permisos y Protección en Producción
Guía práctica de seguridad para usar Claude Code de forma segura. Desde la gestión de claves API hasta la configuración de permisos, automatización con Hooks y protección del entorno de producción — con ejemplos de código funcionales.
7 Casos de Fallo de Seguridad con Claude Code | Incidentes Reales y Prevención
Siete incidentes de seguridad reales con Claude Code: filtraciones de .env, eliminación de BD en producción, explosiones de facturación y más — con análisis de causa raíz y código de prevención.
Guía completa de permisos de Claude Code | settings.json, Hooks y Allowlist explicados
Guía completa de permisos de Claude Code. Aprende a usar allow/deny/ask, automatización con Hooks, settings.json por entorno y patrones prácticos, todo con código funcional.