Harness engineering en 12 pasos: guía completa para tu agente de código

(actualizado )

Tabla de contenidos

Agente = modelo + harness.

Esa suma explica por qué dos personas con la misma suscripción a Claude Code obtienen resultados que no se parecen en nada. El modelo es idéntico. Lo que cambia es todo lo demás: el fichero de instrucciones, las skills, los hooks, los tests que se ejecutan solos, los subagentes que exploran sin ensuciar el contexto.

A esa capa se la llama harness, y si todavía no tienes claro el concepto aquí está explicado despacio: qué es el AI harness y por qué pesa más que el modelo. Una parte de ella ya viene de fábrica —el system prompt de la herramienta, su bucle de tool calls, su orquestación interna—, pero la otra la construyes tú. Birgitta Böckeler, de Thoughtworks, la llama harness de usuario, y es de lo único que va esta guía.

Harness de usuario · lo que construyes tú Guías: AGENTS.md, skills, docs/, reglas por ruta, CLIs Sensores: tests, linters, hooks, revisor, evaluador Entra por un fallo real. Sale cuando el modelo la vuelve innecesaria. Harness de la herramienta system prompt, bucle de tool calls, orquestación interna ya viene de fábrica: no lo tocas Modelo Agente

En este artículo vas a encontrar:

  • El modelo mental de dos ejes que ordena todas las piezas: guías y sensores
  • Los 12 pasos, en el orden en el que compensa construirlos, con lo que hay que montar en cada uno
  • Dónde va cada pieza en Claude Code, Codex, OpenCode y Cursor, ruta por ruta
  • Una estructura de repositorio portable y nueve plantillas copiables
  • Lo que ningún harness resuelve todavía, y las cosas que se repiten por ahí y ya no son ciertas

🧭 Todo lo que hay aquí sale de fuentes públicas en inglés publicadas entre febrero y septiembre de 2026 y está contrastado contra la documentación oficial de cada herramienta. Las rutas cambian rápido: los hooks de Codex, por ejemplo, no existían en marzo y hoy vienen activados por defecto.

¿Qué es exactamente el harness de usuario y en qué dos ejes se ordena?

Un buen harness de usuario persigue dos cosas: que el agente acierte más a la primera y que se autocorrija antes de que tengas que revisar tú. Böckeler lo organiza en dos ejes que conviene tener en la cabeza durante el resto de la guía.

Guías (feedforward). Orientan al agente antes de actuar. AGENTS.md, skills, documentación, reglas, codemods, servidores de lenguaje.

Sensores (feedback). Observan después de actuar y dan señal para corregir. Tests, linters, revisores, logs, navegador.

Y cada uno de los dos puede ser de dos naturalezas:

Computacional. Determinista, rápido y fiable. Se puede ejecutar en cada cambio sin pensárselo.

Inferencial. Juicio semántico con un LLM. Más caro y no determinista, pero ve lo que un linter no ve.

Guías (feedforward) orientan antes de actuar Sensores (feedback) corrigen después de actuar Computacional determinista y barato, se ejecuta en cada cambio Inferencial juicio de un LLM, más caro y no determinista — Servidores de lenguaje (LSP) — Codemods — Hooks que bloquean — CLIs finas propias — Tests y typecheck — Linters con mensaje útil — Reglas de dependencias — Mutation testing — AGENTS.md y CLAUDE.md — Skills — docs/ y ARCHITECTURE.md — Reglas por ruta — Skill de revisión de diff — Evaluador separado — Revisiones programadas — Subagente revisor Solo sensores: repite errores. Solo guías: nunca sabe si funcionaron.

Los dos ejes se necesitan. Con solo sensores tienes un agente que repite los mismos errores una y otra vez; con solo guías, uno que sigue reglas sin saber nunca si funcionaron.

Tu papel es dirigir iterando sobre el harness. El principio que popularizó Mitchell Hashimoto resume la disciplina: cada vez que el agente comete un error, dedicas tiempo a diseñar una solución para que no vuelva a cometerlo. Cuando un problema se repite, mejoras una guía o un sensor para hacerlo menos probable, o directamente imposible.

Hay una regla que evita que esto engorde sin control, y Anthropic la formuló en su artículo de marzo de 2026: cada componente del harness codifica una suposición sobre lo que el modelo no puede hacer solo, y esas suposiciones caducan cuando llegan modelos mejores. Añade piezas por fallos reales y quítalas cuando dejen de hacer falta. El paso 12 vuelve sobre esto con un ejemplo de hace dos meses.

Curso gratis · paso a paso

Antes de montar el arnés, aprende a escribir el encargo

Los sensores atrapan lo estructural, pero si la especificación está mal ninguno puede salvarte. Este curso gratis te hace recorrer un ciclo completo de Spec Driven Development con OpenSpec sobre un proyecto real: del documento al código, que es justo la guía que ningún hook sustituye.

Entra en el curso gratis →

¿Por qué el paso 0 es registrar fallos y no configurar nada?

Es la lección que más se repite en todas las fuentes, y la que más gente se salta.

HumanLayer, tras cientos de sesiones sobre código empresarial, publicó la lista de lo que no les funcionó: diseñar la configuración ideal antes de haber sufrido fallos reales, instalar decenas de skills y servidores MCP por si acaso, ejecutar la suite completa de más de cinco minutos al final de cada sesión y micro-optimizar qué herramientas ve cada subagente.

Lo que sí funcionó: empezar simple, añadir configuración solo cuando el agente fallaba, probar, y tirar lo que no ayudaba.

Addy Osmani lo llama ratchet, un trinquete: solo añades una restricción cuando has visto un fallo real, y solo la quitas cuando un modelo capaz la ha vuelto innecesaria. (La misma palabra aparece en el sprint en el que Anthropic dejó claude.ai 3 veces más rápido, aplicada a benchmarks de rendimiento que solo pueden bajar en CI.) Dicho de otra forma, cada línea de tu AGENTS.md debería poder trazarse hasta algo concreto que salió mal.

Qué construyes: un registro de fallos del agente, en un fichero del repo o como issues etiquetadas. Para cada fallo: qué pasó, cuántas veces, qué pieza lo evitará (una guía o un sensor, computacional o inferencial) y cuándo revisarás si sigue haciendo falta.

¿Cómo debe ser tu fichero de instrucciones raíz para que sirva de algo?

Hay más datos de los que parece sobre este fichero, y todos apuntan en la misma dirección.

El estudio de ETH Zurich (Gloaguen y otros, febrero de 2026) concluye que, en general, los ficheros de contexto no mejoran la tasa de éxito y encarecen la inferencia más de un 20%. Los generados automáticamente bajaron el éxito en torno a un 3%; los escritos por los desarrolladores lo subieron en torno a un 4%. Las vistas generales del código y los árboles de directorios no ayudaron, porque el agente descubre la estructura por su cuenta. En cambio, las herramientas mencionadas en el fichero se usaron mucho más, lo que confirma que el agente sí obedece lo que pones ahí.

OpenAI llegó a lo mismo por la vía práctica. Probó un AGENTS.md enorme y falló: desplazaba la tarea del contexto, todo parecía importante, se quedaba obsoleto enseguida y no se podía verificar mecánicamente. Ahora usan uno de unas 100 líneas que funciona como índice con punteros a documentación más profunda.

La documentación de Claude Code da cifras concretas: apunta a menos de 200 líneas por fichero, porque los más largos consumen contexto y reducen la adherencia. Su comando /doctor propone recortar lo que Claude puede deducir del código —estructura de carpetas, listas de dependencias, resúmenes de arquitectura— y conservar trampas, razones y convenciones que difieren de lo habitual.

Y hay un detalle que cambia cómo escribes el fichero: la misma documentación deja claro que CLAUDE.md es contexto, no configuración que se imponga. Se entrega como mensaje de usuario después del system prompt. Si algo tiene que bloquearse pase lo que pase, eso no va aquí: va en un hook (paso 6).

⚠️ Si usas Claude Opus 5, borra las instrucciones de verificación genéricas. La guía oficial de Anthropic indica que este modelo verifica su propio trabajo sin que se lo pidas, y que las instrucciones heredadas del tipo “revisa tu trabajo al final” o “haz un doble chequeo” provocan sobreverificación y gastan tokens sin mejorar la calidad. Recomienda eliminarlas, no reescribirlas. Los comandos concretos de test y lint siguen siendo útiles; lo que sobra es la orden genérica de comprobar.

Qué construyes:

  • Un AGENTS.md de 40 a 100 líneas con comandos de build, test y lint, herramientas no estándar (pnpm, uv, bun), convenciones que se salen de lo habitual, trampas conocidas y punteros a docs/.
  • Nada de árbol de carpetas, lista de dependencias ni resumen de arquitectura en prosa.
  • Para Claude Code, nada más si no necesitas instrucciones propias: lee el AGENTS.md cuando no hay CLAUDE.md. Si las necesitas, un CLAUDE.md que importe el anterior con @AGENTS.md y añada solo lo específico de Claude.

¿Dónde vive el conocimiento que el agente no puede ver?

El AGENTS.md corto solo funciona si los punteros llevan a algún sitio.

En el equipo de OpenAI ese conocimiento vive en un directorio docs/ tratado como sistema de registro: documentos de diseño, planes de ejecución activos y completados, un registro de deuda técnica, specs de producto, referencias en formato llms.txt y un ARCHITECTURE.md con el mapa de dominios y capas. Los planes complejos se versionan con su progreso y sus decisiones.

La razón de fondo es sencilla: para el agente, lo que no puede ver mientras trabaja no existe. Una conversación de Slack que alineó al equipo sobre un patrón es tan invisible para el agente como para alguien que entre en el equipo dentro de tres meses.

OpenAI además impone la calidad de esa documentación: linters y jobs de CI comprueban que está al día y bien enlazada, y un agente de “jardinería” busca documentos obsoletos y abre PRs para corregirlos.

Para lo que solo aplica a una parte del código, las herramientas ya ofrecen carga condicional. En Claude Code, las reglas de .claude/rules/ con campo paths solo entran en contexto al tocar ficheros que coinciden. En Cursor, las reglas .mdc se pueden limitar por patrón y los AGENTS.md anidados se combinan con los del directorio padre.

Qué construyes:

  • docs/ARCHITECTURE.md con dominios, capas y dirección permitida de dependencias.
  • docs/plans/active/ y docs/plans/completed/ con registro de decisiones, más specs y referencias.
  • Reglas por ruta para convenciones que solo afectan a una zona del código.

¿Para qué sirven las skills y cuántas necesitas de verdad?

Las skills son hoy la pieza más portable del harness. Nacieron en Claude Code, se publicaron como estándar abierto y ya las soportan Codex, OpenCode y Cursor (el formato, los campos del SKILL.md y los errores típicos están al detalle en la guía completa de Agent Skills).

Su ventaja es la divulgación progresiva: el agente solo ve el nombre y la descripción de cada skill, y carga las instrucciones completas cuando decide usarla. Codex, por ejemplo, limita la lista inicial al 2% de la ventana de contexto (u 8.000 caracteres) y recorta primero las descripciones si hay muchas skills. Conclusión práctica: pon el caso de uso y las palabras disparadoras al principio de la descripción, no al final.

Una skill es un directorio con SKILL.md y, opcionalmente, scripts/, references/ y assets/. No puede empaquetar un servidor MCP, pero sí un ejecutable o una CLI que el agente invoque. Böckeler señala dos usos que se olvidan con frecuencia: una skill con instrucciones y un script para arrancar proyectos (guía mixta) y una skill que describe cómo revisar código (sensor inferencial).

🔒 Aviso de seguridad que subraya HumanLayer: ya se han detectado registros que distribuían cientos de skills maliciosas. Una skill instalada de un tercero merece exactamente la misma desconfianza que un paquete npm desconocido.

Qué construyes: entre tres y cinco skills salidas de tu registro de fallos. Candidatas típicas: cómo verificar un cambio con pasos y comandos concretos, cómo añadir una feature siguiendo las convenciones, cómo revisar un diff y cómo preparar una release. Colócalas en .agents/skills/ para Codex, OpenCode y Cursor, y hazlas visibles en .claude/skills/ para Claude Code.

Las rutas y los protocolos de estas herramientas cambian cada pocas semanas: lo que hoy es .codex/skills mañana es .agents/skills. Cada domingo seleccionamos 12 recursos para que no se te escape nada del sector. Ya somos +7.200 developers y es gratis desde 2018.

Suscríbete gratis →

¿Cuántas herramientas y servidores MCP deberías conectar?

Cada servidor MCP que conectas mete en el prompt la lista de herramientas, sus descripciones y sus argumentos. Eso tiene dos costes.

El primero es de seguridad: un MCP en el que no confías es un vector de prompt injection, y los que se ejecutan en local con npx o uvx pueden ejecutar código en tu máquina. El segundo es de contexto: demasiadas herramientas llenan la ventana antes de que hayas empezado a trabajar.

HumanLayer da una regla práctica que funciona muy bien: si un MCP duplica algo que ya existe como CLI conocida por el modelo (GitHub, Docker, la mayoría de bases de datos), es mejor pedir al agente que use la CLI, que además se combina con grep o jq. Ellos sustituyeron el MCP de Linear por una CLI propia con respuestas compactas y seis ejemplos de uso en su CLAUDE.md, y se ahorraron miles de tokens.

Otra forma de contener el coste es asignar un MCP de nicho solo al agente que lo necesita. La documentación de Codex muestra un subagente de documentación que declara su propio servidor MCP en su fichero TOML, sin cargarlo en la sesión principal.

Böckeler añade a este paso las guías computacionales que no son MCP y que casi nadie cuenta: servidores de lenguaje (LSP) y codemods.

Qué construyes:

  • Un inventario de los MCP activos y la desactivación de los que no usas a diario.
  • CLIs finas propias para tus APIs internas, con salida corta y pensada para el agente.
  • MCP solo cuando no hay alternativa razonable, y asignado al subagente concreto si es de nicho.

¿Cómo se escribe un sensor que el agente entienda?

HumanLayer lo considera lo de mayor retorno de todo el harness: la probabilidad de que el agente resuelva un problema está muy ligada a su capacidad de verificar su propio trabajo.

Pero los sensores tienen que ser eficientes en contexto. Al principio ejecutaban toda la suite tras cada cambio; 4.000 líneas de tests que pasaban inundaban el contexto y el agente perdía el hilo. Ahora ocultan la salida y solo muestran errores. El éxito es silencioso; el fallo, detallado.

El segundo truco es escribir los mensajes de error como instrucciones. OpenAI impone su arquitectura en capas con linters y tests estructurales hechos a medida, y como los linters son suyos redactan los mensajes para inyectar la forma de corregir el problema. También fijan “invariantes de gusto”: logging estructurado, convenciones de nombres, tamaño máximo de fichero.

Böckeler probó esto a fondo con ESLint, dependency-cruiser y Stryker, y sus conclusiones son de las más aprovechables de toda la investigación:

  • Los fallos típicos de la IA más fáciles de atrapar son el número de argumentos, la longitud de fichero y de función y la complejidad ciclomática, y ninguno venía activado en el preset por defecto de ESLint.
  • Reescribió los mensajes con un formateador propio. Para no-explicit-any, por ejemplo, explicaba el criterio y permitía suprimir el aviso dejando la razón en un comentario. Las excepciones que creaba el agente resultaron ser el mejor punto de partida para revisar.
  • El único umbral que el agente subía con frecuencia en lugar de refactorizar fue el de complejidad ciclomática, justo el que no tenía mensaje con criterio. Con un empujón, proponía buenos refactors. Los mensajes marcan la diferencia.
  • Las reglas de dependencias, con un recordatorio de las capas en el propio error, sustituyeron con ventaja a describir la estructura en markdown.
  • La cobertura engañaba: un fichero con 100% de sentencias cubiertas no tenía tests unitarios y sobrevivían 13 mutantes. Si dejas los tests a la IA, el mutation testing pasa a ser imprescindible.

Qué construyes:

  • Un único punto de entrada, por ejemplo scripts/checks/fast.sh, que ejecute typecheck, lint, reglas de dependencias y tests afectados en pocos segundos, sin salida si todo pasa.
  • Mensajes de lint personalizados que expliquen el criterio y cómo corregir o suprimir con razón.
  • Mutation testing incremental para el código crítico, ejecutado bajo demanda y no en cada cambio.

¿Cuándo hay que dejar de pedir y pasar a imponer con hooks?

Aquí está la frontera entre pedir y exigir, y es la que más resultados cambia.

La documentación de Claude Code lo dice sin rodeos: para bloquear una acción independientemente de lo que decida Claude, usa un hook PreToolUse. Y lo que tenga que ocurrir en un punto fijo —antes de cada commit, tras cada edición— debe ser un hook, no una línea en un markdown.

Böckeler lo comprobó por el lado contrario: pedir en AGENTS.md que el agente consultara sus sensores era lo más fácil de montar y lo menos fiable de todo; tuvo que preguntarle muchas veces por qué no lo había hecho ni una sola vez.

Los usos más comunes que describe HumanLayer son notificaciones cuando el agente termina o espera aprobación, aprobaciones con reglas más expresivas que los permisos por defecto (por ejemplo, denegar cualquier migración y pedir que la lance una persona), integraciones con Slack o GitHub, y verificación al terminar el turno. Su hook de verificación ejecuta formateo y typecheck: si todo va bien no deja rastro en el contexto, y si falla devuelve solo los errores con código de salida 2 para que el agente siga trabajando.

El agente intenta terminar el turno Hook Stop scripts/checks/fast.sh exit 0 · silencio Cero líneas en el contexto. El turno termina limpio. exit 2 · solo los errores El agente ve qué falló y sigue trabajando. El éxito es silencioso; el fallo, detallado.

Las cuatro herramientas tienen ya este mecanismo, con matices que conviene conocer:

  • En Codex los hooks están activados por defecto (se estabilizaron en abril), viven en hooks.json o en tablas [hooks] de config.toml, y los que no están gestionados por la organización hay que revisarlos y darles confianza antes de que se ejecuten.
  • En Cursor, un código de salida 2 bloquea la acción, pero los fallos y timeouts dejan pasar la acción por defecto: para hooks de seguridad conviene marcar failClosed: true. Cursor también admite hooks que evalúan una condición con un LLM.
  • En OpenCode, este papel lo cumplen los plugins.

Qué construyes:

  • Un hook que bloquee antes de ejecutar comandos destructivos o sensibles (migraciones, push --force, borrados masivos).
  • Un hook de verificación rápida al final del turno que llame a scripts/checks/fast.sh y solo hable si falla.
  • Un hook de notificación cuando el agente espera aprobación.
  • Los tres apuntan a los mismos scripts desde el fichero de hooks de cada herramienta, así solo mantienes la lógica una vez.

¿Para qué sirven de verdad los subagentes?

La intuición lleva a crear subagentes con personaje: el de frontend, el de backend, el analista de datos. HumanLayer probó exactamente eso y no funcionó.

Lo que sí funciona es usarlos para controlar el contexto. El agente principal solo ve el prompt que escribe para el subagente y su respuesta final; todas las lecturas, búsquedas y llamadas intermedias se quedan fuera. Así la sesión principal se mantiene mucho más tiempo en la zona donde el modelo razona bien.

Sin subagente queda un 15% Lecturas, búsquedas y ficheros enteros, todo dentro Con subagente queda un 75% para razonar Solo el prompt y la respuesta condensada con ruta:línea Subagente 14 lecturas 6 búsquedas 9 ficheros leídos todo esto se descarta al terminar Las barras son la ventana de contexto de la sesión principal.

Los buenos encargos tienen una pregunta sencilla y una respuesta sencilla que requieren mucho trabajo intermedio: localizar una implementación, analizar patrones, trazar un flujo entre servicios, investigar documentación. La respuesta debe ser condensada y citar referencias en formato ruta:línea para que el agente principal pueda ampliar si lo necesita.

Y permiten ahorrar: modelo caro para planificar y orquestar, modelo barato para cada subagente. Al definirlos, especifica qué deben hacer y qué no, qué devuelven y en qué formato, y qué herramientas tienen.

Cómo se comportan en cada herramienta:

  • Codex trae los agentes default, worker y explorer, y solo lanza subagentes cuando se lo pides explícitamente. Los propios se definen como ficheros TOML en .codex/agents/ con name, description y developer_instructions, y pueden fijar modelo, sandbox de solo lectura y MCP propios. Por defecto admite 6 hilos concurrentes y un nivel de anidamiento; su documentación desaconseja subir la profundidad salvo necesidad real.
  • OpenCode distingue agentes primary, subagent y all, e incluye los subagentes General y Explore.
  • Claude Code incluye subagentes como Explore, y los propios van en .claude/agents/. Con Opus 5 conviene vigilar el coste: la guía oficial destaca que delega en subagentes con más facilidad que modelos anteriores y recomienda limitar cuántos lanza en tareas pequeñas.

Qué construyes: dos o tres subagentes de solo lectura con encargo estrecho: un explorador de código, un investigador de documentación y un revisor. Formato de respuesta corto con referencias, modelo más barato donde la calidad aguante, y límites de concurrencia y profundidad.

¿Por qué hay que separar a quien hace de quien juzga?

Es el hallazgo central del artículo de Anthropic de marzo de 2026: cuando se pide a un agente que evalúe lo que ha producido, tiende a elogiarlo aunque la calidad sea mediocre. Separar al generador del evaluador no elimina del todo esa indulgencia, pero afinar un evaluador independiente para que sea escéptico resulta mucho más manejable que conseguir que el generador sea crítico consigo mismo.

Su arquitectura final tenía tres agentes:

  1. Un planificador convertía un prompt de una a cuatro frases en una spec de producto, centrada en el qué y no en detalles técnicos que pudieran arrastrar errores.
  2. Un generador construía.
  3. Un evaluador usaba Playwright para usar la aplicación como lo haría una persona y la puntuaba con criterios con umbral mínimo.

Antes de cada bloque de trabajo, generador y evaluador negociaban un contrato con lo que significaba “terminado”, y se comunicaban mediante ficheros.

contrato previo: qué significa «terminado» Planificador prompt de 1 a 4 frases → spec de producto el qué, no el cómo Generador construye si se juzga a sí mismo, se aprueba Evaluador usa la app con Playwright y puntúa con umbrales hay que afinarlo a mano no llega al umbral → vuelve al trabajo Se comunican mediante ficheros, no por conversación.

Tres matices que suelen perderse cuando se cuenta este experimento:

  • El evaluador no sale bien a la primera. Por defecto Claude era un mal QA: detectaba problemas reales y se convencía de que no eran graves. Lo afinaron leyendo sus logs y corrigiendo el prompt donde su juicio divergía del humano.
  • Cuesta dinero. Una ejecución individual tardó 20 minutos y 9 dólares; el harness completo, 6 horas y 200 dólares, con un resultado mucho mejor.
  • Al llegar Opus 4.6 simplificaron quitando piezas de una en una. El planificador siguió siendo imprescindible, pero el evaluador solo compensa cuando la tarea está por encima de lo que el modelo resuelve bien solo.

⚠️ Evaluador sí, instrucción genérica de verificar no. La guía de Opus 5 incluye “usa un subagente para verificar” entre las instrucciones heredadas que causan sobreverificación. La lección de Anthropic sigue siendo válida, pero como diseño explícito del harness, con criterios concretos y herramientas reales, reservado a las tareas donde el modelo falla solo. No como una línea refleja en CLAUDE.md.

Qué construyes: una rúbrica escrita por tipo de trabajo, con lo que significa “terminado” y un umbral por criterio, y un agente revisor independiente que la aplica con herramientas reales (tests, navegador, métricas). Actívalo solo en el tipo de tarea donde tu registro de fallos muestra que el modelo se queda corto.

¿Cómo se monta un bucle que sabe cuándo parar?

Lo que a principios de año era un bucle de bash hecho a mano —el famoso “Ralph loop”— ya es una primitiva nativa.

Según el equipo de Claude Code, /goal define qué significa terminado: cada vez que Claude intenta parar, un modelo evaluador comprueba la condición y lo devuelve al trabajo hasta cumplirla o agotar los turnos que fijes. Por eso los criterios deterministas funcionan tan bien: un número de tests en verde, una puntuación mínima. /loop repite un prompt a intervalos, es de sesión y caduca a los siete días; /schedule lo lleva a la nube.

Osmani añade tres advertencias que evitan disgustos:

  • El evaluador de /goal no juzga si el resultado es bueno, solo comprueba en la transcripción si se cumplen las reglas que pusiste.
  • Si no sabes describir el estado final (“hasta que el diseño quede bien”), no es tarea para un bucle.
  • La señal de que un bucle gira en vacío es el mismo comando repetido sin cambio en el resultado.

En OpenAI el equivalente es que Codex revise sus propios cambios, pida revisiones a otros agentes y siga iterando hasta que todos queden satisfechos.

Qué construyes: una plantilla de objetivo con tres partes (condición medible, restricciones, límite de turnos) y una lista de trabajo recurrente candidato a bucle programado: triaje de issues, PRs con CI roto, actualizaciones de dependencias.

¿Quién limpia la deriva que se acumula sola?

Los pasos anteriores actúan sobre cada cambio. Este vigila lo que se pudre poco a poco.

En OpenAI dedicaban todos los viernes —el 20% de la semana— a limpiar código mediocre generado por IA, y no escalaba. Lo sustituyeron por “principios dorados” escritos en el repo y tareas de Codex en segundo plano que buscan desviaciones, actualizan notas de calidad y abren PRs de refactor pequeños; la mayoría se revisan en menos de un minuto y se integran automáticamente.

Böckeler ejecutaba con cadencia lenta una revisión de seguridad basada en la checklist de su equipo de AppSec, una revisión de manejo de datos, un informe de antigüedad de dependencias y una revisión de modularidad. Esta última, hecha con skills especializadas, encontró problemas serios que habían pasado desapercibidos: rutas duplicadas, formas inconsistentes de llamar al backend y un cambio de parámetros que obligaba a tocar más de 40 ficheros. Además, repetir el análisis sin el contexto de la primera pasada sacó a la luz un problema nuevo.

Qué construyes: un documento de principios dorados, dos o tres revisiones programadas (modularidad, seguridad, documentación desfasada) que abran PRs pequeños y acotados, y un criterio escrito para decidir qué se puede integrar sin revisión humana.

¿Cómo empaquetas y compartes tu harness?

Lo primero es versionar la configuración en el repo, que es lo que le funcionó a HumanLayer para compartirla con todo el equipo. Cuando algo se repite entre proyectos, toca empaquetarlo.

Codex lo explica bien: las skills son el formato de autoría y los plugins la unidad de distribución, que puede incluir varias skills, configuración MCP y hooks. Por eso un plugin no es texto inofensivo: puede traer ejecutables y acceso a herramientas externas, y un marketplace es un canal de distribución de software con todo lo que eso implica. OpenCode y Cursor tienen su propio sistema de plugins con la misma lógica.

Böckeler apunta más lejos: las plantillas de servicio que ya tienen muchas empresas podrían convertirse en plantillas de harness por tipo de proyecto (API de negocio, procesador de eventos, dashboard), con sus guías y sensores. Advierte del mismo problema que las plantillas clásicas: en cuanto se instancian, se desincronizan del original.

Qué construyes: primero, todo versionado en el repo del proyecto. Después, un repositorio plantilla o un plugin por herramienta con las skills, subagentes, hooks y scripts de sensores que ya hayan demostrado su valor en más de un proyecto.

¿Cómo sabes qué piezas del harness sobran?

Anthropic lo aprendió por las malas. Su primer intento de simplificar el harness fue un recorte drástico que no igualó el rendimiento y, peor todavía, les impidió saber qué piezas sostenían el resultado. Pasaron a quitar un componente cada vez y medir el impacto. Su recomendación general: revisar el harness cada vez que sale un modelo nuevo, quitar lo que ya no aporta y añadir lo que ahora es posible.

Opus 5 es el ejemplo vivo. Las instrucciones de verificación que tenían sentido con modelos anteriores ahora son coste sin beneficio, y la guía oficial pide borrarlas. Es exactamente el tipo de pieza que caduca.

Para medir, Böckeler registra el estado de cada sensor en cada comprobación. Un sensor que nunca falla quizá sobra; uno que falla a menudo señala una guía que mejorar. Un pipeline siempre en verde es sospechoso, y uno siempre en rojo indica sensores demasiado sensibles o código muy por debajo del estándar.

A nivel de equipo, Faros propone métricas que ya puedes sacar de tus sistemas: coste por PR integrada, tiempo hasta integrar PRs asistidas por agentes, velocidad de revisión en relación con el tamaño y gasto de cómputo por desarrollador.

Qué construyes: un histórico de disparos de sensores, una revisión del harness en cada cambio de modelo quitando piezas de una en una, y tres o cuatro métricas de coste y tiempo que revises cada mes.

💡 Si solo te llevas una idea de este post: el harness no se diseña, se acumula por cicatrices. Cada pieza entra por un fallo real y sale cuando el modelo la vuelve innecesaria.

Y si lo que te interesa es el otro lado del asunto, el de la carrera y no el de la configuración, está contado aquí: cómo ser Harness Engineer, la ruta en 7 preguntas.

¿Dónde va cada pieza en Claude Code, Codex, OpenCode y Cursor?

Los conceptos son los mismos en las cuatro herramientas; cambian las rutas y algunos comportamientos. Esta tabla está contrastada con la documentación oficial en septiembre de 2026.

Pieza Claude Code Codex OpenCode Cursor
Instrucciones raíz CLAUDE.md o .claude/CLAUDE.md. Lee AGENTS.md si no hay CLAUDE.md; si hay los dos, impórtalo con @AGENTS.md AGENTS.md AGENTS.md. La versión 1 usa CLAUDE.md si no hay AGENTS.md; la V2 solo reconoce AGENTS.md AGENTS.md en raíz y subdirectorios, o reglas .cursor/rules/*.mdc
Instrucciones por zona .claude/rules/ con paths; CLAUDE.md anidados cargados bajo demanda AGENTS.md en subdirectorios AGENTS.md anidados; campo instructions en opencode.json Reglas .mdc con globs; AGENTS.md anidados
Skills .claude/skills/ .agents/skills/ en el repo; ~/.agents/skills de usuario .opencode/skills/, .agents/skills/ y .claude/skills/ .cursor/skills/; también lee .agents, .claude y .codex
Subagentes .claude/agents/*.md .codex/agents/*.toml; límites globales en [agents] de config.toml En opencode.json o Markdown, con mode: subagent .cursor/agents/*.md
Hooks .claude/settings.json .codex/hooks.json o [hooks] en config.toml Plugins en JavaScript o TypeScript .cursor/hooks.json; fallan en abierto salvo failClosed
MCP .mcp.json mcp_servers en config.toml o en el TOML de un subagente opencode.json .cursor/mcp.json
Permisos permissions en settings sandbox_mode y perfiles de permisos permission con allow, ask o deny, también por skill Hooks de permiso como beforeShellExecution
Distribución Plugins Plugins con .codex-plugin/plugin.json Plugins Plugins

Lo realmente portable: AGENTS.md lo leen Codex, OpenCode y Cursor, y Claude Code mediante import. .agents/skills/ lo leen Codex, OpenCode y Cursor, pero no Claude Code, que sigue usando .claude/skills/. Hooks, subagentes y MCP hay que declararlos en cada herramienta, así que la estrategia sensata es mantener la lógica en scripts compartidos y que cada configuración solo apunte a ellos.

¿Cómo queda la estructura del repositorio?

Una propuesta que combina los 12 pasos con el mapa anterior. Los nombres de docs/ y scripts/ son sugerencias; lo importante es que la lógica de los sensores y las skills exista una sola vez.

repo/
├── AGENTS.md                      # mapa corto: comandos, trampas, punteros
├── CLAUDE.md                      # @AGENTS.md + lo específico de Claude Code
├── docs/
│   ├── ARCHITECTURE.md            # dominios, capas, dependencias permitidas
│   ├── golden-principles.md       # reglas para la recolección de basura
│   ├── harness-log.md             # registro de fallos del agente (paso 0)
│   ├── plans/active/  plans/completed/
│   └── specs/  references/
├── scripts/checks/
│   ├── fast.sh                    # typecheck + lint + deps + tests afectados
│   ├── guard-command.sh           # bloquea comandos peligrosos
│   └── lint-messages/             # mensajes de error con instrucciones
├── .agents/skills/                # fuente única de skills
│   ├── verify-change/SKILL.md
│   └── review-diff/SKILL.md
├── .claude/
│   ├── skills/                    # un symlink o copia por skill
│   ├── agents/explorer.md
│   └── settings.json              # hooks → scripts/checks
├── .codex/
│   ├── agents/explorer.toml
│   └── hooks.json                 # hooks → scripts/checks
├── .cursor/
│   ├── agents/explorer.md
│   └── hooks.json                 # hooks → scripts/checks
└── .opencode/
    └── plugins/guard.ts           # plugin → scripts/checks

⚠️ Cuidado con enlazar la carpeta entera de skills. Hay reportes de que hacer symlink de .claude/skills/ completo hacia .agents/skills/ da problemas porque Claude Code escribe ficheros internos en esa carpeta. Proyectos como Chromium mantienen la fuente en un directorio común y enlazan o copian skill a skill. Un pequeño script de sincronización te evita la sorpresa.

Plantillas para copiar y pegar

Puntos de partida mínimos. Los protocolos de entrada y salida de los hooks cambian entre versiones, así que valida cada plantilla contra la documentación de tu versión antes de confiar en ella para algo crítico.

AGENTS.md como mapa

# Proyecto
Monorepo pnpm. Backend Node/TypeScript, frontend React.

## Comandos
- Instalar: `pnpm install` (no uses npm ni yarn)
- Verificación rápida: `scripts/checks/fast.sh`
- Tests de un paquete: `pnpm --filter <pkg> test`

## Trampas conocidas
- Las migraciones las lanza una persona. No ejecutes `db:migrate`.
- `src/generated/` se regenera: no lo edites a mano.

## Dónde mirar
- Arquitectura y capas: docs/ARCHITECTURE.md
- Plan en curso: docs/plans/active/
- Principios de calidad: docs/golden-principles.md

CLAUDE.md que reutiliza AGENTS.md

@AGENTS.md

## Claude Code
Para cambios en `src/billing/`, usa plan mode antes de editar.

Sensor silencioso: scripts/checks/fast.sh

#!/usr/bin/env bash
# Silencioso si todo pasa; solo errores si falla. Exit 2 = pedir al agente que corrija.
cd "$(git rev-parse --show-toplevel)" || exit 0

OUT=$(pnpm -s typecheck 2>&1 && pnpm -s lint 2>&1 && pnpm -s depcruise 2>&1)
if [ $? -ne 0 ]; then
  echo "$OUT" | tail -n 60 >&2
  exit 2
fi
exit 0

Claude Code: hooks en .claude/settings.json

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/scripts/checks/guard-command.sh" }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/scripts/checks/fast.sh" }
        ]
      }
    ]
  }
}

En un hook de Stop que devuelve 2, el agente sigue trabajando. Si los errores no se pueden arreglar, eso puede convertirse en un bucle infinito: comprueba el campo stop_hook_active de la entrada, que indica que el agente ya continúa por un hook, y deja salir en ese caso.

Guardia de comandos: scripts/checks/guard-command.sh

#!/usr/bin/env bash
# Lee el JSON de la llamada por stdin y bloquea patrones peligrosos.
CMD=$(jq -r '.tool_input.command // empty')
if echo "$CMD" | grep -Eq 'db:migrate|push --force|rm -rf /'; then
  echo "Bloqueado: este comando lo ejecuta una persona. Pide al usuario que lo lance." >&2
  exit 2
fi
exit 0

Codex: subagente de exploración en .codex/agents/explorer.toml

name = "explorer_ro"
description = "Explorador de solo lectura para localizar código y reunir evidencias antes de proponer cambios."
sandbox_mode = "read-only"
model_reasoning_effort = "medium"
developer_instructions = """
Solo exploras. Sigue la ruta real de ejecución y cita ficheros y símbolos como ruta:línea.
No propongas arreglos salvo que el agente principal lo pida.
Devuelve un resumen de 10 líneas como máximo.
"""

Codex: hooks en .codex/hooks.json

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          { "type": "command", "command": "bash \"$(git rev-parse --show-toplevel)/scripts/checks/guard-command.sh\"" }
        ]
      }
    ]
  }
}

Tras añadirlo, usa /hooks en la CLI para revisarlo y darle confianza. El formato del JSON que recibe el script puede diferir del de Claude Code: comprueba los campos antes de reutilizar la guardia tal cual.

Cursor: hooks en .cursor/hooks.json

{
  "version": 1,
  "hooks": {
    "beforeShellExecution": [
      { "command": ".cursor/hooks/guard.sh", "failClosed": true }
    ]
  }
}

Cursor envía a este evento un JSON con el comando y el directorio, no el formato de Claude Code, así que guard.sh debe leer ese campo y luego llamar a la lógica compartida. Con código de salida 2 bloquea.

OpenCode: permisos de skills en opencode.json

{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "skill": {
      "*": "allow",
      "internal-*": "deny",
      "experimental-*": "ask"
    }
  }
}

Si has llegado hasta las plantillas, esto te va a gustar: cada domingo mandamos la dinamita que mereces sobre programación con IA, sin relleno y con lo que de verdad ha cambiado esa semana. +7.200 developers, gratis desde 2018.

Suscríbete gratis →

¿Qué no resuelve todavía ningún harness?

Cuatro límites que las fuentes reconocen abiertamente, y que conviene tener claros antes de invertir un mes en esto.

El comportamiento funcional. Böckeler lo llama el elefante en la habitación. Los sensores computacionales atrapan bien lo estructural y los inferenciales cubren parte de lo semántico, pero ninguno detecta de forma fiable el diagnóstico equivocado, la sobreingeniería o una instrucción malentendida. Y si no especificaste bien lo que querías, ningún sensor puede comprobar la corrección. La spec sigue siendo la guía principal y la revisión humana, el sensor que no se puede quitar. Y ese sensor se oxida si dejas crecer la deuda cognitiva que acumulas al delegar en el agente.

Sensores que se contradicen. En sus experimentos, las reglas de longitud máxima de fichero y de función empujaron al agente a trocear componentes de React hasta acabar pasando decenas de propiedades de uno a otro. La complejidad no desapareció; cambió de sitio. Nadie sabe todavía cómo mantener un harness grande y coherente.

El acoplamiento entre modelo y harness. Los modelos se entrenan dentro de su propia herramienta. OpenCode tuvo que añadir la herramienta apply_patch de Codex para que los modelos de OpenAI rindieran bien en su harness. Personalizar puede mejorar mucho el resultado, pero también puede chocar con lo que el modelo espera.

Optimizar en exceso. HumanLayer lo admite sin rodeos: es perfectamente posible pasar más tiempo afinando la configuración del agente que entregando código con ella.

¿Qué se repite por ahí sobre el harness y ya no es verdad?

Este tema se mueve rápido y hay bastante información desfasada circulando. Esto es lo que se corrigió al contrastar la investigación inicial con la documentación oficial:

“Codex guarda las skills en .codex/skills/”. La documentación oficial de Codex indica .agents/skills en cada directorio desde el actual hasta la raíz del repo, y $HOME/.agents/skills para las de usuario. La ruta antigua sigue apareciendo en guías de terceros.

“AGENTS.md más .agents/skills/ es el núcleo portable a las cuatro herramientas”. Solo a medias con Claude Code. El AGENTS.md ya lo lee cuando no hay CLAUDE.md, pero no mira dentro de .agents/: sus skills viven en .claude/skills/, y la petición de soportar .agents/skills/ sigue abierta.

“El estudio de ETH Zurich sobre 138 agentfiles”. 138 es el número de tareas del conjunto AGENTbench, no de ficheros. La conclusión del resumen es que los ficheros de contexto, en general, no mejoran el éxito y aumentan el coste más de un 20%.

“CLAUDE.md se inyecta en el system prompt”. Según la documentación actual de Claude Code, se entrega como mensaje de usuario después del system prompt. Por eso no hay garantía de cumplimiento estricto y lo imprescindible debe ir en hooks o permisos.

“Pide siempre al agente que verifique y usa un subagente verificador”. Con Claude Opus 5, la guía oficial de Anthropic dice que las instrucciones de verificación heredadas provocan sobreverificación y deben eliminarse. Los sensores externos y el evaluador separado se mantienen; las órdenes genéricas de comprobar, fuera.

“En Codex los subagentes se configuran en config.toml”. Cada agente propio es un fichero TOML independiente en .codex/agents/; en config.toml solo van los ajustes globales como max_threads (6 por defecto) y max_depth (1 por defecto). Además, Codex solo lanza subagentes cuando se lo pides.

“OpenCode funciona igual en todas sus versiones”. Tiene documentación separada para su V2, que cambia comportamientos: por ejemplo, la V2 solo reconoce AGENTS.md, mientras que la versión 1 usaba CLAUDE.md como alternativa. Comprueba qué versión usas.

“El término lo acuñó X”. Las fuentes no coinciden. Faros atribuye el concepto a Mitchell Hashimoto, HumanLayer y Osmani atribuyen el término a Viv Trivedy, y Augment Code sitúa su definición formal en el artículo de OpenAI de febrero. Lo seguro es que el principio de convertir cada error en una mejora del entorno se asocia a Hashimoto.

Preguntas frecuentes

¿Por dónde empiezo si hoy no tengo nada montado?

Por el paso 0 y el paso 1, en ese orden: un fichero donde apuntes los fallos del agente y un AGENTS.md de menos de 100 líneas con comandos, trampas y punteros. Con eso tienes la base de todo lo demás y te cuesta una tarde.

¿Cuántas líneas debe tener mi AGENTS.md?

Entre 40 y 100. OpenAI usa unas 100 líneas como índice; la documentación de Claude Code apunta a menos de 200 por fichero, porque los más largos consumen contexto y reducen la adherencia.

¿Sirve de algo un AGENTS.md generado automáticamente?

Según el estudio de ETH Zurich, los generados automáticamente bajaron la tasa de éxito en torno a un 3%, mientras que los escritos por desarrolladores la subieron alrededor de un 4%. Genera el borrador si quieres, pero reescríbelo a mano.

¿Claude Code lee AGENTS.md?

Sí, desde la versión 2.1.277, cuando no hay un CLAUDE.md o .claude/CLAUDE.md. Si lo hay, lee solo ese. Para mantener un único fichero común y añadir lo de Claude, impórtalo desde CLAUDE.md con @AGENTS.md.

¿Cuál es la diferencia entre una guía y un sensor?

La guía actúa antes (AGENTS.md, skills, reglas, documentación) y el sensor después (tests, linters, revisores, navegador). Los dos pueden ser computacionales, deterministas y baratos, o inferenciales, con juicio de un LLM.

¿Qué es mejor, un servidor MCP o una CLI?

Si el MCP duplica una CLI que el modelo ya conoce (GitHub, Docker, la mayoría de bases de datos), la CLI gana: gasta menos contexto y se combina con grep o jq. Reserva el MCP para lo que no tiene alternativa razonable.

¿Por qué mi hook de Cursor no bloquea nada?

Porque los hooks de Cursor fallan en abierto: si el script falla o agota el timeout, la acción pasa igualmente. Para hooks de seguridad hay que marcar failClosed: true.

¿Los subagentes deben tener personalidad, como “el de frontend”?

No. HumanLayer probó ese enfoque y no funcionó. Los subagentes sirven para aislar contexto: encargos con pregunta sencilla, respuesta condensada con referencias ruta:línea y mucho trabajo intermedio que no ensucia la sesión principal.

¿Cuánto cuesta montar un harness con evaluador separado?

En el experimento de Anthropic, una ejecución individual costó 20 minutos y 9 dólares, y el harness completo con planificador, generador y evaluador, 6 horas y 200 dólares, con un resultado notablemente mejor. Reserva esa arquitectura para tareas donde el modelo se queda corto solo.

¿Cada cuánto hay que revisar el harness?

Cada vez que sale un modelo nuevo. Y cuando lo simplifiques, quita una pieza cada vez y mide: Anthropic intentó un recorte drástico y no pudo saber qué componentes sostenían el resultado.

Fuentes

Marco y experiencia práctica

  • Birgitta Böckeler, “Harness engineering for coding agent users” (abril de 2026) — https://martinfowler.com/articles/harness-engineering.html
  • Birgitta Böckeler, “Maintainability sensors for coding agents” (mayo de 2026) — https://martinfowler.com/articles/sensors-for-coding-agents.html
  • HumanLayer, “Skill Issue: Harness Engineering for Coding Agents” (marzo de 2026) — https://www.humanlayer.dev/blog/skill-issue-harness-engineering-for-coding-agents
  • OpenAI, “Harness engineering: leveraging Codex in an agent-first world” (febrero de 2026) — https://openai.com/index/harness-engineering/
  • Anthropic, “Harness design for long-running application development” (marzo de 2026) — https://www.anthropic.com/engineering/harness-design-long-running-apps
  • Addy Osmani, “Agent Harness Engineering” (abril de 2026) — https://addyosmani.com/blog/agent-harness-engineering/
  • Addy Osmani, “Practical Loop Engineering” (agosto de 2026) — https://addyosmani.com/blog/practical-loop-engineering/
  • Faros, “Harness Engineering: A Guide to AI Coding Agents” (mayo de 2026) — https://www.faros.ai/blog/harness-engineering

Investigación

  • Gloaguen y otros, “Evaluating AGENTS.md: Are Repository-Level Context Files Helpful for Coding Agents?” — https://arxiv.org/abs/2602.11988

Documentación oficial

  • Claude Code, memoria, CLAUDE.md y AGENTS.md — https://code.claude.com/docs/en/memory
  • Anthropic, “Prompting Claude Opus 5” — https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-opus-5
  • Anthropic, “Prompting best practices” — https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices
  • Codex, Agent Skills — https://developers.openai.com/codex/skills
  • Codex, Subagents — https://developers.openai.com/codex/subagents
  • Codex, Hooks — https://developers.openai.com/codex/hooks
  • OpenCode, Agent Skills — https://opencode.ai/docs/skills/
  • OpenCode, Rules — https://opencode.ai/docs/rules/
  • OpenCode, Instructions (V2) — https://opencode.ai/v2/docs/instructions/
  • OpenCode, Agents (V2) — https://opencode.ai/v2/docs/agents
  • Cursor, Rules — https://cursor.com/docs/rules
  • Cursor, Hooks — https://cursor.com/docs/hooks

Incidencias y compatibilidad

  • Petición de soporte de AGENTS.md y .agents/skills en Claude Code — https://github.com/anthropics/claude-code/issues/31005
  • Configuración de Claude Code en Chromium, con skills en un directorio común — https://chromium.googlesource.com/chromium/src/+/refs/heads/main/.claude/
  • awesome-harness-engineering — https://github.com/ai-boost/awesome-harness-engineering

🧨 Última oportunidad para recibir la dinamita que mereces sobre programación con IA el próximo domingo: Suscríbete gratis a Web Reactiva en https://webreactiva.com/newsletter

Imagen de Daniel Primo
Claude, IA de Anthropic

Escrito con la ayuda de la IA generativa de Claude, fuentes fidedignas y con un human in the loop:
Dani Primo.

CEO en pantuflas de Web Reactiva. Programador y formador en tecnologías que cambian el mundo y a las personas. Activo en linkedin, en substack y canal @webreactiva en telegram

12 recursos para developers cada domingo en tu bandeja de entrada

Además de una skill práctica bien explicada, trucos para mejorar tu futuro profesional y una pizquita de humor útil para el resto de la semana. Gratis.