Engineering the Agentic Stack · Parte 6

Harness Engineering para AI Agents: diseño de bucles de control

Traducción automática Este artículo se tradujo automáticamente a partir de la versión original en inglés.

Actualización del artículo

Publicado originalmente el 22 de julio de 2026. Revisado y actualizado el 6 de septiembre de 2026. La actualización añade evidencias más recientes de benchmarks de harness y casos de intervención del proveedor, y aclara qué demuestran los resultados publicados.

Un agent puede terminar su turno mientras el trabajo sigue incompleto. Para un coding agent, las evidencias útiles son el artefacto modificado y los resultados de los tests requeridos. Un mensaje final que diga «hecho» no demuestra ninguna de las dos cosas.

El harness es el código de control que rodea al reasoning loop. Proporciona contexto, valida y autoriza los tool calls, registra los resultados y decide si las evidencias son suficientes para aceptar el trabajo. El runtime mantiene la ejecución y el estado activos por debajo de esta capa.

Al revisar un harness, plantearía dos preguntas: ¿qué impide que acepte trabajo incompleto y qué fallos justifican añadir controles? En este artículo se recorren los acceptance checks, los reintentos y los handoffs, y después se muestra cómo comparar un control con una baseline fija. Los ejemplos de la tienda son ficticios; el lab complementario es una simulación determinista, no una medición de un agent en producción.

El acceptance check más sencillo es fácil de escribir para un pequeño research agent como el que se ha construido en esta serie: un agent de LangGraph que obtiene datos de mercado y redacta un informe de analista. Un hook externo al model valida el informe contra un schema y comprueba que realmente contiene tickers bursátiles; un informe mal formado mantiene abierta la ejecución. Doce líneas de código convencional, y el model no puede declarar que su propia salida está bien formada. El repo utiliza un check más flexible: un evaluator con fresh context emite su voto y después una persona revisa el resultado. (La parte 4 esboza la versión determinista).

Lo que ese ejemplo no puede mostrar es la parte interesante: qué ocurre cuando las evidencias son ambiguas, cuando un retry podría cobrar dos veces a alguien o cuando el trabajo dura más que la sesión que lo inició. Para eso hace falta una tarea con un límite de aprobado/suspenso más claro que el de un informe de investigación. El research agent se mantiene como ejemplo de acceptance check; un pequeño repositorio ficticio de una tienda se incorpora para los casos de retry y handoff. La tarea de coding consiste en bajar el umbral para aplicar un descuento automático del 10 % de $100 a $75 en src/checkout.py. El repositorio tiene dos checks requeridos:

  • pytest tests/test_checkout.py verifica el cálculo del descuento.
  • pnpm playwright test tests/checkout_discount.spec.ts añade un artículo de $80 en una tienda de pruebas local y comprueba que la página de checkout muestra un descuento de $8.

El ejemplo es un fixture didáctico, no una aplicación real ni un benchmark. Cada intento parte del mismo commit y de los mismos datos de prueba inicializados. El harness solo puede aceptar el cambio cuando ambos comandos terminan correctamente y un registro de aceptación duradero vincula ambos resultados a un candidato commiteado limpio o a un digest de la snapshot completa probada, incluidos los archivos sin seguimiento relevantes.

El diagrama sigue el cambio del descuento desde la propuesta hasta las evidencias. El harness proporciona la tarea y los archivos, comprueba los argumentos y los permisos propuestos para edit_file y despacha el call aceptado. Después de que el runtime aplique la edición, el harness ejecuta los tests de unidad y de aceptación en el navegador indicados. Un comando fallido vuelve al model como evidencia para otro turno; dos comandos correctos hacen que el cambio pueda aceptarse.

Un cambio de descuento a través del bucle de control del harnessUn cambio de descuento a través del bucle de control del harness


Qué controla el harness

El recorrido del bucle de Codex de OpenAI describe el ciclo básico. El harness ensambla un prompt, pide al model la siguiente acción, envía un tool call aceptado al runtime y añade el resultado. Después vuelve a preguntar. El ciclo se repite hasta que el harness acepta el resultado o devuelve el control al usuario.

Las implementaciones pueden agrupar varias responsabilidades en un mismo proceso. Los límites de fallo siguen siendo distintos:

TérminoFunciónEjemplo en un coding agent
ModelPropone texto, un tool call o una respuesta finalSugiere una edición en src/checkout.py
Reasoning loopElige el siguiente movimiento a partir del contexto disponibleInspeccionar, editar, probar, volver a inspeccionar
HarnessProporciona contexto, valida propuestas, las autoriza, despacha calls aceptados, registra resultados y comprueba el finPermite editar bajo src/ y exige ambos tests indicados
RuntimeEjecuta calls aceptados y mantiene el estado fuera del proceso workerLog de sesión, sandbox, almacén de checkpoints, backend de trazas

La fila del runtime cubre cuatro elementos: sesión, sandbox, checkpoint y trace. Los cuatro almacenan estado o limitan la ejecución. El model propone la acción y el reasoning loop elige el siguiente movimiento. El harness decide si un call propuesto puede ejecutarse y si las evidencias bastan para terminar, por eso tiene su propio artículo. La parte 5 cuenta el harness junto a esos cuatro elementos como uno de los cinco primitives que hay que situar antes de poner el sistema en producción; este artículo lo separa de nuevo.

Cuando aparece un fallo, diagnostica el límite que debería responder. Un plan deficiente puede requerir mejores instrucciones o mejor reasoning del model. Si edit_file apunta a una ruta fuera de src/, el harness debe rechazarlo. Un proceso de sandbox que muere antes de ejecutar la edición pertenece al runtime, que debe reiniciar el worker o informar del crash.

Dónde encajan las partes anteriores

La fila del harness de la tabla anterior hace la mayor parte del trabajo, y ahí es donde desembocan las partes 2, 3 y 4. Cada una decide una cosa sobre un único turno:

Parte anteriorQué decide para este turnoDónde actúa en el recorrido de la siguiente sección
Parte 2 — memoriaQué estado previo entra en el promptPaso 1, el constructor de contexto
Parte 3 — tool useQué acciones existen y cómo es un resultado validadoValidación de argumentos del paso 3 y forma del resultado en el paso 4
Parte 4 — seguridadSi este call concreto puede ejecutarse ahoraPaso 3, comprobación de ruta y decisión de aprobación
Parte 6 — este artículoSi las evidencias resultantes terminan la ejecuciónPasos 5 a 7, acceptance checks y trace

Dónde se sitúa cada parte de la serie Engineering the Agentic StackDónde se sitúa cada parte de la serie Engineering the Agentic Stack

Las partes 3 y 4 comparten el paso 3, y ese solapamiento es precisamente el argumento para tratarlas como un único programa. La misma capa de código del harness que rechaza un argumento mal formado también rechaza un call permitido pero aún no aprobado. Si la validación y la autorización se ejecutan en servicios separados, conserva los argumentos validados a través de ese límite para que la decisión de autorización se aplique al call que se va a ejecutar.

La separación sigue siendo importante para depurar: una edición en el archivo equivocado es una regla de ruta de la parte 4, no un problema de retrieval de la parte 2. Una sección cercana al final de este artículo lo convierte en una tabla de routing.

El propio caso práctico de harness engineering de OpenAI describe una instancia de aplicación arrancable para cada worktree. El equipo también integró browser automation en el entorno del agent y expuso logs, métricas y trazas.

Una tarea como «ningún span de estos cuatro recorridos críticos de usuario supera los dos segundos» se volvió comprobable porque el agent podía ejecutar la aplicación y consultar las mismas señales que inspeccionaría un ingeniero. El caso práctico es específico del producto. Lo que se puede transferir es la condición que explica el resultado: la aplicación y sus señales de rendimiento tenían que estar disponibles dentro del entorno del agent.

Lopopolo, autor de ese caso práctico, mantiene una guía de campo sobre harness engineering. En ella identifica las dos palancas que utiliza este artículo: mantener el model y el coding agent fijos como una caja negra, e idear el contexto y las tools que los rodean. Su planteamiento también explica por qué gran parte del harness acaba siendo código convencional.

El umbral de calidad de una organización, sus procedimientos, el historial de excepciones y sus relaciones de autoridad quedan fuera de lo que un model general puede conocer. El harness los expone como instrucciones del repositorio, reglas de permisos y acceptance checks. Cada ejecución aceptada puede devolver sus lecciones a esos artefactos, en lugar de confiar en que la siguiente sesión las redescubra.


Sigue el cambio del descuento desde la propuesta hasta la aceptación

Para la tarea de descuento definida anteriormente, el model propone cambiar calculate_discount en src/checkout.py. Antes de que esa edición cuente como progreso, ocurren varias cosas:

  1. El constructor de contexto proporciona la tarea, las instrucciones del repositorio, los archivos relevantes, los resultados anteriores de los tools y el plan actual.
  2. El model propone un call a edit_file con una ruta y el texto de sustitución.
  3. El límite de la tool (el código del harness entre la propuesta y la ejecución) valida los argumentos, comprueba la ruta frente al ámbito permitido y solicita aprobación si la operación la necesita.
  4. El runtime aplica la edición en el sandbox y devuelve un resultado estructurado.
  5. El harness ejecuta pytest tests/test_checkout.py, seguido de pnpm playwright test tests/checkout_discount.spec.ts, y lee ambos exit codes. El test de navegador comprueba el descuento visible de $8 en el carrito inicializado de $80.
  6. El harness decide qué significan los resultados. Un check fallido se convierte en contexto nuevo para el siguiente turno del model, y una ejecución correcta hace que la tarea sea candidata a completarse.
  7. Un resultado correcto solo se convierte en evidencia de finalización después de que el harness registre de forma duradera el comando, el exit code, la snapshot probada, el grader y las versiones del entorno; un trace puede enlazar con ese registro.

Después del paso 2 no ha cambiado ningún archivo. El harness puede rechazar ../../secrets.env, exigir aprobación para un comando destructivo o detener una ejecución que haya agotado su presupuesto. Ese es el último momento barato que tienes. Después de ejecutar los tests, el harness lee por sí mismo sus exit codes. El model no puede marcar su propia edición como correcta.

El registro de aceptación debe identificar la snapshot probada, ambos comandos y sus resultados, así como las versiones del grader y del entorno; los traces pueden enlazar con ese registro. Mantén los tests requeridos fuera del ámbito de escritura del agent o aprueba los cambios de forma independiente antes de hacer el grading. Cualquier edición posterior de un archivo invalida el resultado. Estos checks implementan los principios de entorno estable y grader resistente a bypass de la guía de evaluación de Anthropic. Un mensaje final de done sin esos registros no demuestra que este cambio haya superado sus checks requeridos.


Decide dónde se aplica cada regla

El requisito de que tests/checkout_discount.spec.ts termine correctamente pertenece al código determinista, no al prompt. El harness despacha el comando de Playwright al runtime, lee su exit code y se niega a terminar la ejecución mientras falle. Un prompt puede recordar al model que ejecute el test. No puede impedir que el model declare que ha terminado sin evidencias.

Otras reglas encajan en capas distintas:

Situar la regla enEncaja bien conEjemplo
Prompt o skillOrden de búsqueda, convenciones de coding y formato del planLeer AGENTS.md antes de editar código de checkout
Límite de la toolValidación de argumentos, rutas permitidas, aprobaciones y acceso a toolsPermitir escrituras solo bajo src/
Código deterministaPresupuestos, timeouts, reintentos, exit codes de tests y requisitos de releaseMantener abierta la ejecución mientras falle el test de Playwright
Evaluator con fresh contextRevisión visual o criterios que requieren juicio similar al humanoComparar un diagrama generado con una rúbrica escrita

Los contratos de tools separan propuesta y permiso

La tarea de descuento solo necesita ediciones de archivos y comandos de tests. Una API que cambia estado tiene un modo de fallo distinto, así que cambiaremos de ejemplo en esta sección. Supón que el agent puede llamar a create_test_order contra un servicio de pedidos de staging mientras prepara datos de prueba. Esta tool no es uno de los acceptance checks de la tarea de descuento. Resulta útil aquí porque un timeout puede ocultar si el servicio ha creado un pedido.

El límite de la tool necesita más que una descripción en lenguaje natural. Necesita un contrato explícito de tool. La parte 3 defendía uno desde el lado del model: acciones claras, feedback compacto y errores recuperables. El harness necesita el mismo contrato por otro motivo. Tiene que decidir, sin preguntar al model, si un call puede ejecutarse y si un call fallido puede repetirse. Para create_test_order, eso significa un contrato con:

  • argumentos validados, para rechazar las entradas mal formadas antes de la ejecución
  • un resultado estructurado como { "order_id": "123", "created": true }, para que los checks posteriores no tengan que analizar texto libre
  • una categoría de efecto que registre si el call solo obtiene información o cambia un archivo, un registro de base de datos o un servicio externo. También registra si repetir el call es seguro. Esta etiqueta indica al harness si un retry automático podría duplicar trabajo. El harness puede reintentar get_order_status cuando el servicio define esa consulta como de solo lectura. No debe reintentar a ciegas create_test_order, porque el primer call podría haber creado ya el pedido
  • una política de timeout y retry, para que una respuesta perdida no active una secuencia ilimitada de calls
  • una regla de permisos que indique qué aprobación se necesita. Consultar el estado de un pedido puede ejecutarse automáticamente, mientras que crear un pedido puede requerir confirmación

La descripción en lenguaje natural es el texto que se muestra al model. Podría decir: «Crea un pedido de prueba para verificar el checkout». Esa frase ayuda al model a decidir cuándo proponer create_test_order. No autoriza el call. En este ejemplo, el cliente de Model Context Protocol (MCP) del harness valida los argumentos, aplica sus propias reglas y comprueba la confianza en el servidor, los requisitos de aprobación y la seguridad del retry antes de despachar nada. Esto combina las reglas de permisos y los checks previos a la tool tratados en la parte 4, con una pregunta adicional: si un call que ya ha fallado puede volver a enviarse.

Un servidor MCP publica descripciones de tools y anotaciones opcionales de comportamiento para el cliente. Un servidor defectuoso o malicioso podría describir una tool que cambia estado como inofensiva. Un cliente que aceptara automáticamente esa afirmación podría ejecutar o reintentar create_test_order sin aprobación y crear un duplicado. Por eso la especificación de MCP exige que los clientes traten las anotaciones de tools como no fiables salvo que el propio servidor sea de confianza.

La especificación no prescribe una única configuración de confianza universal, así que necesitas una política de confianza explícita para tu despliegue; un servidor no puede hacer fiables sus propias anotaciones. Esa política decide qué metadatos pueden influir en las decisiones de permisos o retry y qué anotaciones siguen siendo meramente informativas.

Reintentar un call que cambia estado requiere protección frente a replay

La parte 5 exige una identidad de operación duradera para los efectos secundarios que pueden duplicarse al reintentar. El harness es quien decide cuándo esa clave debe soportar esa carga. create_test_order crea el pedido, pero se pierde su respuesta HTTP. El harness ve un timeout y no puede saber si el servidor completó la petición. Repetir el call podría crear un segundo pedido.

Persiste un ID de operación propiedad de la aplicación antes del dispatch y vincúlalo a los argumentos aprobados. Reutilízalo al recuperar el mismo pedido previsto, aunque el model genere un ID de tool call nuevo; conserva los IDs del model por separado para la correlación. Reconcilia los payloads modificados o las ventanas de deduplicación del proveedor expiradas en lugar de reenviar a ciegas. El contrato de Stripe, por ejemplo, permite eliminar las keys después de al menos 24 horas.

Una consulta de estado puede reintentarse cuando el servicio la define como de solo lectura. Un call de creación necesita la key: el cliente adjunta un identificador de petición único y el servicio devuelve el primer resultado en lugar de crear otro pedido cuando vuelve a ver ese identificador. Sin esta protección, el harness debe comprobar si el pedido existe o solicitar una decisión humana antes de otro intento. AWS documenta este patrón en su guía sobre APIs idempotentes.

La aceptación necesita evidencias independientes

Una respuesta correcta de create_test_order solo demuestra que la tool ha devuelto datos. No demuestra que una tarea de coding haya superado sus tests. Si un test de navegador posterior depende del pedido preparado, el harness debe validar el schema de la respuesta y ejecutar igualmente ese test antes de aceptar el cambio de código.

Algunos criterios no pueden reducirse a un exit code. Para una tarea independiente de diseño visual, un evaluator con fresh context puede comparar una página renderizada o un diagrama con una rúbrica escrita —«fresh context» significa una segunda sesión del model que empieza sin historial de la ejecución y lee los artefactos producidos en lugar del transcript. Compara ese evaluator con revisiones humanas antes de permitir que su resultado decida si la tarea ha terminado.


Una migración del adaptador de pagos necesita un handoff

Volvamos a cambiar de tarea, pero mantengámonos en el repositorio ficticio de la tienda. Ahora el agent tiene que migrar el checkout del adaptador de pagos v1 al v2. El trabajo abarca el handler de checkout, el cliente de pagos, la configuración y los tests, por lo que puede durar más que una sesión de model: un tramo continuo de contexto del model, terminado por un reinicio o por un nuevo comienzo deliberadamente limpio, en lugar de prolongarse.

Antes de que la primera sesión alcance su límite de contexto, ha modificado varios archivos, ha iniciado un sandbox local de pagos y ha dejado tests/payment_migration.spec.ts fallando. Ese test de aceptación en el navegador completa un pago mediante el adaptador v2 y verifica el ID del proveedor registrado. Un resumen de la conversación puede orientar a la siguiente sesión del model, pero no puede reiniciar el sandbox ni demostrar qué archivos están modificados actualmente.

La siguiente sesión tiene que recuperar tres cosas:

Qué debe recuperarseQué incluyeCómo puede fallar
Historial de la conversaciónMensajes, tool calls y resultados devueltosLos detalles antiguos desplazan la tarea actual
Entorno de trabajoArchivos, sandbox de pagos y estado del test de navegadorEl transcript dice que un servicio está activo después de que haya muerto
Progreso de la tareaPlan, checks completados, aprobación pendiente y siguiente acciónLa siguiente sesión repite trabajo terminado

La compaction sustituye los mensajes antiguos por un resumen más corto para que la sesión actual pueda continuar. Un progress handoff registra lo que necesita la siguiente sesión: la branch actual, los archivos modificados, el último comando de test y su salida, y el siguiente paso no resuelto.

Un archivo de handoff es document memory para la siguiente sesión del model. Un checkpoint puede conservar ya el plan, los pasos completados, los resultados y el trabajo pendiente. Añade un handoff cuando esos detalles no estén presentes o no sean utilizables en el siguiente contexto, y verifica los archivos y los servicios en ejecución frente al entorno real.

Si la conversación antigua contiene suposiciones obsoletas, el harness puede iniciar una sesión nueva del model con ese handoff y el workspace actual. Sustituir un worker caído y restaurar sus procesos es una tarea independiente de recovery del runtime.

Una pequeña edición de documentación puede no necesitar ninguno de estos mecanismos. La migración de pagos necesita un handoff si su estado guardado no conserva un progreso de tarea utilizable, porque la siguiente sesión del model debe reconstruir tanto el workspace como el estado de la tarea.

Los experimentos de Anthropic con coding agents de larga duración utilizaron el historial de git y un archivo de progreso entre sesiones. El posterior informe sobre diseño de harness separa la compaction del handoff con fresh context e indica que los handoffs añaden orquestación, uso de tokens y tiempo de pared, sin publicar cifras que atribuyan ninguno de esos costes al handoff en sí.


Utiliza traces para distinguir tres fallos

Las tres filas siguientes son esquemas ilustrativos de traces, no ejecuciones medidas ni salidas del lab complementario. Cada fila muestra un fallo distinto y, por tanto, una respuesta distinta del harness.

Qué registra el traceQué ocurrióRespuesta correcta
El call de solo lectura get_order_status devuelve 503; no hay ningún call que cambie estado en cursoFalló una consulta transitoriaReintentar la consulta con límite y backoff
create_test_order termina por timeout y después una consulta de estado encuentra el pedido 123 bajo la key de idempotencia checkout-42El servicio creó el pedido, pero se perdió la respuestaDevolver el pedido existente; no crear otro
La edición y el test de unidad pasan, pero el trace no tiene resultado para tests/checkout_discount.spec.ts en la snapshot probadaFalta una evidencia de aceptación requeridaMantener abierta la ejecución y despachar el test de aceptación en el navegador

Un fallo que parece transitorio no hace que todos los calls sean seguros de reintentar. La primera fila es una consulta de solo lectura. La segunda es una petición que cambia estado, por lo que la key de idempotencia y el estado del servidor deciden si se permite otro intento de creación. La tercera no es un fallo de una tool; el harness todavía no ha recopilado las evidencias necesarias para aceptar el cambio de descuento.

Un transcript de chat registra lo que vio el model. No puede demostrar si el servicio de pedidos confirmó una petición antes de que desapareciera la respuesta. Un trace solo puede aportar esa evidencia si incluye el resultado relevante del servidor o la consulta de estado; un timeout del cliente por sí solo deja el resultado sin resolver. Los registros duraderos de operación y aceptación deben unir el call del cliente, la decisión de aprobación, la identidad de operación, el resultado del servidor o la consulta de estado, la snapshot probada y el resultado del test de aceptación. Los traces pueden exponer esos vínculos para depurar sin convertirse en el ledger de recovery. Esos campos indican al harness en cuál de las tres rutas se encuentra.

Síntoma repetidoPequeño cambio que probarQué medir
Las consultas de solo lectura fallan de forma transitoriaRetry acotado con backoffTasa de recuperación, calls adicionales y tiempo de pared
Las sesiones reanudadas repiten trabajo completadoProgress handoff estructuradoAcciones de tools duplicadas tras reanudar
Faltan tests requeridos al completarRechazar la finalización hasta que pase cada check requeridoTareas aceptadas sin todos los checks requeridos
Los defectos visuales sobreviven a los checks deterministasEvaluator con fresh context y una rúbricaDefectos detectados, rechazos falsos y tiempo de revisión
El agent edita fuera de su ámbitoPermisos más restrictivos para las toolsCalls bloqueados y overrides manuales
La memoria recuperada desplaza la tarea actualLimitar los datos recuperados; clasificarlos antes de inyectarlosTokens dedicados a recuperar información, tareas completadas y coste por tarea

Para la asistencia opcional, como ayudas de planificación, resúmenes y evaluators adicionales, identifica el fallo y mide si el componente compensa su coste. La autorización, el aislamiento, los requisitos de privacidad y los acceptance checks obligatorios siguen vigentes aunque las tareas normales pasen sin ellos. Prueba esas restricciones con casos adversariales e invariantes explícitos; un benchmark pequeño de éxito no justifica eliminarlas.

Convertir esos fallos repetidos en una suite de regresión versionada es una tarea propia. La expliqué por separado en Evaluación de AI Agents en producción.


Mide un cambio cada vez

Una ablation mide si un componente del harness produce el efecto esperado cambiándolo o eliminándolo mientras el resto del experimento permanece fijo. Por ejemplo: ¿el linting del editor ayuda a este model en esta suite de tareas?

Utiliza el siguiente protocolo:

  1. Fija la versión del model, las instancias de tareas, el entorno, el grader y los prompts fuera del componente que se está probando.
  2. Da a ambas variantes el mismo presupuesto total de tokens, tiempo y dinero.
  3. Elige el número de trials o la regla de parada antes de ejecutar la comparación.
  4. Ejecuta las mismas instancias de tareas en ambas variantes. Como las salidas del model varían, repite cada tarea varias veces.
  5. Publica la media junto con la dispersión o el intervalo de confianza.
  6. Cuenta cada trial iniciado, incluidos los timeouts, las paradas por políticas, los crashes del harness y los fallos del evaluator.

La tasa de éxito por sí sola puede ocultar un componente caro. Como mínimo, registra las tareas rotas aceptadas como completas, el coste y el tiempo de pared por tarea completada, los errores de tools, los pedidos duplicados, los minutos de revisión y los overrides manuales de permisos. Elige la métrica que refleje el coste real de tu producto. Aumentar en dos puntos las tareas completadas es un mal intercambio si duplica tu cola de revisión.

Un experimento emparejado de la migración de pagos hace medible el progress handoff. Cada par control/tratamiento parte del mismo commit del repositorio y del mismo checkpoint inicializado, con el mismo model, tarea, grader y presupuesto total. El handoff es el único interruptor. La métrica principal cuenta las acciones de tools duplicadas después de reanudar: una acción es duplicada cuando su operación y artefacto coinciden con un paso que la sesión anterior ya había completado.

Una prueba de ablation emparejada del progress handoffUna prueba de ablation emparejada del progress handoff

El artículo de SWE-agent fija GPT-4 Turbo en la división de 300 tareas de SWE-bench Lite e informa de un 18,0 % de tareas resueltas con su interfaz completa, frente al 11,0 % de un agent con solo shell al que se proporcionó una demostración guiada y el 7,3 % del mismo agent sin ella. La diferencia destacada de 10,7 puntos del artículo se mide frente a la baseline del 7,3 %; la parte 3 trabaja los mismos tres números desde el punto de vista del diseño de interfaces. El artículo también cambió features individuales de la interfaz:

Cambio de interfazResueltas
Interfaz completa de SWE-agent (referencia, sin cambios)18,0 %
Editor sin linting15,0 %
Archivo completo en lugar de un viewer de 100 líneas12,7 %
Historial completo de observaciones en lugar de las cinco últimas15,0 %

Estas cifras corresponden a ese model, benchmark y límite de $4 por tarea. Las tres filas inferiores a la referencia son las pruebas útiles de una sola feature: cada una cambió una feature de la interfaz mientras el model y la configuración de evaluación permanecían fijos.

LangChain publicó una comparación más amplia con el model fijo para deepagents-cli. Informa de un aumento en Terminal-Bench 2.0 del 52,8 % al 66,5 % con gpt-5.2-codex fijo, mientras su equipo cambiaba el system prompt, las tools y el middleware. El post agrupa varios cambios y omite un intervalo de confianza, una comparación con presupuesto total fijo y una tabla de ablations por cambio. Ese resultado no puede identificar qué cambio ayudó. Los nombres de los modelos de esta sección son los que cada estudio fijó en el momento de ejecutarse; lo transferible es el protocolo, no la lista de modelos.

Una comparación más reciente muestra por qué la configuración de la API pertenece a la baseline congelada. En su informe de ARC-AGI-3 del 29 de julio de 2026, OpenAI informa de que la puntuación de GPT-5.6 Sol en el conjunto público subió del 13,3 % al 38,3 % cuando su harness conservó el reasoning y utilizó compaction en lugar de eliminar el reasoning y truncar el historial. La métrica es Relative Human Action Efficiency, no la fracción de tareas resueltas. Se trata de una comparación agrupada comunicada por el proveedor; no aísla las dos configuraciones ni establece un tamaño de efecto en producción. Para una actualización, registra la API, la conservación del reasoning, la política de compaction y los presupuestos junto al ID del model. De lo contrario, una aparente regresión del model podría ser una capacidad ausente en el adaptador.

Incluye la intervención del proveedor en la suite de fallos. Un misalignment_policy_violation debe llegar a una ruta de parada y revisión incluso después de haber emitido output en streaming; no es un caso de retry transitorio. La parte 4 cubre su ámbito dependiente de la API. Comprueba que el harness detiene el dispatch y registra los efectos ya completados.

El informe de Anthropic sobre aplicaciones de larga duración es un caso práctico cualitativo y específico del producto, no un benchmark controlado. La aplicación es RetroForge, un creador de juegos retro 2D; en el Sprint 3, el evaluator del harness comprobó 27 criterios que cubrían su editor de niveles. El trabajo comenzó con modelos Opus anteriores y, cuando se lanzó Opus 4.6, el equipo eliminó componentes del harness uno a uno para comprobar cuáles había vuelto redundantes el nuevo model. Informa de que los calls del evaluator se convirtieron en overhead en tareas que Opus 4.6 podía completar de forma fiable por sí solo, aunque seguían ayudando cerca del límite del model. El ejemplo justifica volver a validar el scaffolding antiguo cuando cambia el model; no estima un tamaño de efecto general.


Mantén el harness editable después de justificarlo

La ablation mantiene pequeño el harness, pero su código puede sobrevivir al model para el que se ajustó. Una petición como «enmascara los secretos en cada ruta de captura» describe un comportamiento, no un archivo. En un harness de producción, ese comportamiento puede abarcar etapas de ejecución y estado compartido. Antes de poder cambiarlo con seguridad, tienes que encontrar todos los puntos de implementación; y también debe hacerlo el coding agent al que delegues la tarea.

Una opción en fase de investigación es un preprint de 2026 de Wang et al., el Harness Handbook, que denomina a esta búsqueda localización de comportamiento. El handbook construye un mapa centrado en el comportamiento a partir del codebase del harness. El análisis estático, que no necesita calls al model, extrae un grafo del programa y después un LLM organiza sus unidades en etapas de ejecución.

El maintainer o coding agent empieza con una visión general del sistema, abre la etapa de ejecución relevante y desciende hasta entradas basadas en el código fuente para una función o un archivo. Un registro de estado anota dónde se escribe y se lee el estado compartido entre etapas. Esta jerarquía mantiene pequeño el resumen y conserva el camino hasta el código fuente.

La frescura es una regla independiente. El mapa es una ayuda de navegación; el código fuente actual establece el comportamiento. Cada locator debe resolverse contra el repositorio actual. El handbook congela las entradas obsoletas en lugar de adivinar, y cada diff no vacío vuelve a sincronizar las entradas que afecta.

El diagrama comprime el bucle de modificación: una petición centrada solo en el comportamiento desciende por los niveles del handbook, cada locator candidato se verifica contra el repositorio actual antes de escribir el plan y cada diff aplicado vuelve a sincronizar el mapa.

Enrutar un cambio de comportamiento mediante un handbook de harnessEnrutar un cambio de comportamiento mediante un handbook de harness

La evaluación del Handbook compara arms emparejados en 30 peticiones por repositorio. No establece presupuestos totales iguales, trials estocásticos repetidos ni estimaciones de incertidumbre, y sus comparaciones publicadas excluyen outputs ausentes y errores del planner. Por tanto, ilustra una parte del protocolo anterior, no todo el protocolo. Cubre dos harnesses open source: Terminus-2 (seis archivos Python) y el monorepo de Codex (2.267 archivos Rust). En cada uno, un planner de solo lectura basado en DeepSeek-V4-Pro exploró el repositorio directamente o se enrutó mediante el handbook. Las peticiones, el repositorio, los permisos de las tools y el decoding eran idénticos en ambos arms. Tres jueces (GPT-5.5, Opus 4.8 y DeepSeek-V4-Pro) puntuaron cada plan de edición en localización, control del ámbito y reasoning; observa que uno de los jueces es el mismo model que produjo los planes. Una victoria significa que la puntuación de calidad de un arm, de 0 a 100, superó la del otro en al menos tres puntos; de lo contrario, esa comparación juez-petición era un empate. La tasa publicada es el número de victorias dividido por las comparaciones juez-petición válidas:

HarnessTasa de victorias de la baselineTasa de victorias con handbookTokens del planner
Terminus-2 (6 archivos)26,7 %45,6 %−8,6 %
Monorepo de Codex (2.267 archivos)28,3 %38,3 %−12,7 %

El planner asistido por handbook ganó con mayor frecuencia y utilizó menos tokens de planner en ambos repositorios. Las condiciones siguen siendo parte de ese resultado: tres jueces LLM puntuaron planes de edición producidos por un único model planner en dos harnesses. El estudio evaluó planes, no diffs ejecutados ni tasas de defectos en producción.


Prueba el método en el lab complementario

El proyecto harness-demo en el commit 517353f3 es un pequeño ejercicio determinista con 12 tareas sintéticas genéricas que cubren cambios de código como fix-parser-edge-case, split-large-module y wire-browser-test. No implementa el repositorio ficticio de la tienda.

Cada fixture de tarea declara una dificultad y cuatro condiciones booleanas: una tool inestable, pérdida de progreso, una laguna de implementación no detectada y una finalización ambigua. El simulador deriva una quinta condición para las tareas difíciles que también necesitan un archivo de progreso: sin context_reset, la compaction conserva suposiciones obsoletas. Un grader determinista marca una tarea como superada solo cuando la configuración seleccionada gestiona todas las condiciones aplicables. No se ejecuta ningún model ni servicio externo.

Los comandos responden a preguntas distintas:

  • make check ejecuta Ruff y siete tests de unidad, incluido el validador que rechaza cualquier par de ablation que cambie más de un componente.
  • make run muestra una matriz didáctica acumulada y después cinco comparaciones válidas dejando fuera un componente cada vez.
  • make failures indica la condición no gestionada para cada tarea fallida. El harness completo debe terminar con all synthetic tasks pass.
make check
make run
make failures

La sección causal de make run tiene este aspecto:

component                 control  treatment  delta
retry_policy              8/12     12/12       +4
progress_handoff          7/12     12/12       +5
evaluator                 8/12     12/12       +4
fail_closed_acceptance    7/12     12/12       +5
context_reset            10/12     12/12       +2

Para cada fila, el control es la configuración completa con un componente eliminado; el tratamiento restaura únicamente ese componente. La matriz acumulada anterior resulta útil para orientarse, pero algunas filas adyacentes añaden varios componentes a la vez y, por tanto, no pueden identificar una causa.

El lab valida cada par declarado antes de ejecutarlo. Sus tests de regresión también incluyen un par intencionadamente inválido que cambia simultáneamente la política de retry y el evaluator; el validador lo rechaza.

El lab compara los cinco campos de componentes al validar un par. Este fragmento ejecutable muestra la misma protección en un par válido de progress handoff:

from dataclasses import dataclass, fields

@dataclass(frozen=True)
class Config:
    progress_handoff: bool = False
    evaluator: bool = False
    retry_policy: bool = False
    fail_closed_acceptance: bool = False
    context_reset: bool = False

def changed_components(control: Config, treatment: Config) -> tuple[str, ...]:
    return tuple(
        field.name
        for field in fields(control)
        if getattr(control, field.name) != getattr(treatment, field.name)
    )

control = Config(progress_handoff=False, evaluator=True, retry_policy=True)
treatment = Config(progress_handoff=True, evaluator=True, retry_policy=True)
assert changed_components(control, treatment) == ("progress_handoff",)

Qué capa debes abrir cuando algo falla

La serie avanzaba desde el reasoning loop hacia fuera. Empieza por el primer fallo que observes y después investiga el componente responsable de ese trabajo. Una ejecución puede implicar más de un componente:

Qué hizo la ejecuciónDónde vive la soluciónParte
Eligió un paso siguiente deficiente pese a tener delante la información correctaReasoning loop o model1
Repitió trabajo o perdió una decisión tomada una hora antesEnsamblado de contexto y handoffs2
No pudo expresar la acción que necesitaba o interpretó mal un resultado devueltoContrato de tool3
Hizo algo que nunca debería haber podido hacerReglas de permisos4
Lo perdió todo cuando un worker murió a mitad de un callSesión, checkpoint, sandbox5
Declaró que había terminado un trabajo que no estaba hechoAcceptance checks y traces6

Cuatro filas apuntan al código del harness, mientras que la fila 5 apunta al runtime. Las instrucciones pueden influir en el comportamiento, pero no pueden sustituir a un check de permisos, un checkpoint duradero o un test de aceptación.


Empieza con un bucle y un acceptance check

Empezaría un harness para coding agents con un model capaz, instrucciones del repositorio, unas pocas tools estrechas, un sandbox y un test de aceptación explícito. Registraría los tool calls, los resultados, los costes y ese test final en un único trace, de modo que los primeros fallos útiles fueran visibles sin tener que reconstruirlos a partir de logs del terminal y transcripts de chat. Esta es una baseline propuesta, no una evidencia de un sistema desplegado.

A partir de ahí, añade solo lo que justifique un trace. Registra quién mantiene cada componente, cuántos tokens o segundos añade y qué test de regresión justificaría eliminarlo tras una actualización del model.

Seis meses después, alguien que vea progress_handoff=True debería poder encontrar los traces fallidos que justificaron su inclusión y los casos de regresión que todavía lo mantienen. Los traces explican por qué existe el componente; un mapa actual del comportamiento explica dónde tocarlo.

Si has llegado aquí desde una búsqueda, los cinco artículos anteriores construyeron un sistema alrededor de un reasoning loop:

  1. El loop elige el siguiente movimiento.
  2. La memoria proporciona contexto y un almacén de checkpoints real de Postgres lo conserva.
  3. Los contratos de tools definen las acciones y las formas de los resultados que pueden leer los checks posteriores.
  4. La seguridad añade el deny hook y el validador del stop-hook. Ambos siguen siendo esquemas en el ejemplo, pero señalan los puntos de control.
  5. El runtime mantiene vivo el proceso entre sesiones y fallos.

La serie también añadió una superficie de servidor MCP opcional y un nodo evaluator que comprueba el borrador del informe antes de que lo vea una persona. Encaminar el worker mediante un proxy que conserve las credenciales sigue siendo una extensión propuesta. Son piezas de código convencionales alrededor de un call al model. El router es código del harness por el mismo motivo: elige el patrón de reasoning antes de que comience el reasoning loop.

Para el siguiente componente opcional de asistencia, conserva juntos el trace fallido, la regla de aceptación y la comparación con el componente desactivado. Omítelo si no puedes identificar su beneficio. Las restricciones obligatorias de seguridad y aceptación no dependen de esa comparación.


Referencias


El código de Market Analyst Agent está en GitHub.