Las cinco capas de un agente de cumplimiento, con código que falla sin ellas.
Las cinco capas de un arnés de agente, cada una con código que falla sin ella: límite de ejecución, aislamiento en sandbox, memoria, bucles de verificación y la tubería de contexto.
Fuentes: `The Complete Guide to Agent Harnesses (With Code)`
Imagínese un equipo que agrega una línea a la configuración de un agente: no se realiza ninguna modificación sin la aprobación del humano. La redacción es clara, la línea está cerca de la parte superior y el agente la carga al inicio de cada sesión.
Luego llega una tarde en la que una sola sesión supera esa línea once veces y introduce alrededor de setenta y seis cambios no aprobados en el documento para el cliente. No aparece ningún error. Nada se detiene para preguntar. Dos horas después, alguien revisa el documento, resalta cada línea que el agente reescribió por su cuenta y encuentra cuarenta y seis, dentro de un archivo que lleva el nombre del cliente.
La instrucción en sí estaba bien. Estaba en el lugar equivocado.
Lo que funciona en su lugar es un gancho, un pequeño script que el harness ejecuta justo antes de enviar una solicitud de herramienta. Este inspecciona la solicitud pendiente y puede responder con un rechazo. El agente aún puede querer realizar la edición, pero esta nunca se aplica al archivo. Un gancho de este tipo a veces fallará, generalmente porque la regla se definió de forma demasiado restrictiva, y la diferencia es que se puede abrir el código y señalar la condición exacta que causó el error. Una oración en una instrucción no deja nada a lo que apuntar.
La distancia entre una regla que se anuncia y una regla que se aplica es el harness. Este abarca cinco áreas:
- Las acciones que puede tomar el agente
- Los lugares a los que puede acceder
- El estado que persiste después de un reinicio
- Quien revisa su salida
- El costo de lo que se le muestra
Cada área recibe el código a continuación. Existe un conjunto de demostraciones ejecutables en las que cada capa falla en tu propio portátil antes de que pueda fallar en producción. Esto está dirigido a personas que ya han lanzado un agente y han visto que fallaba.
Qué te ofrece realmente un harness
Comencemos con algo casi demasiado sencillo como para mencionarlo. El bucle principal de un agente de programación consta de seis líneas:
while agent.turns < max_turns:
call = agent.next_call(observations)
if call is None:
break
result = execute(call)
observations.append(result)
Esas líneas representan al agente. Con manejo de errores y reintentos, la cifra se acerca a veinte. Cualquiera que sea el framework que hayas evaluado, este envuelve este bucle, y el punto interesante es execute. Esa función determina qué puede hacer el modelo, a qué puede acceder, qué conserva, quién lo audita y qué termina frente a él.
Juntas, esas decisiones constituyen el marco de trabajo, y muchos comentarios afirman que esto supera en importancia la elección del modelo. Los datos respaldan una afirmación más limitada, que resulta ser más práctica.
El arnés gana en costo. Un preimpreso de junio de 2026 comparó tres arneses (Goose, OpenCode, OpenHands-SDK) en dos modelos utilizando una muestra estratificada de 50 tareas de Terminal-Bench Pro, la variante más exigente del conjunto de agentes Terminal-Bench. El uso de tokens por tarea resuelta varió hasta 40 veces entre los arneses. Al cambiar a un modelo mejor, esa cifra solo aumentó entre 1.0 y 1.3 veces.
No gana en capacidad. Las tasas de acierto variaron entre los arneses entre 0 y 8 puntos, y con intervalos de confianza de tipo bootstrap, todos los valores excepto el de la mayor diferencia estuvieron cerca de cero. Los propios autores califican los resultados de precisión como descriptivos, dada la muestra de n=50.
En términos sencillos, una tarea en un modelo con una tasa de éxito determinada puede costar cuarenta veces más bajo un sistema que bajo otro. Todo lo que sigue sirve para reducir costos y sorpresas, y nada de ello añade inteligencia a un modelo débil.
Transformar la regla en código
Establecer una regla en una instrucción del sistema equivale a apostar a que el modelo la recordará, la interpretará como se pretende y se atendrá a ella cuando el contexto se vuelva complejo. Por lo general, el modelo gana. Esa tasa de éxito es precisamente lo que lo hace arriesgado, ya que la gente deja de verificarlo.
Las reglas a nivel de código se activan en cada llamada, incluso cuando el modelo ya no las recuerda.
Un bucle de agente cuenta con cinco puntos en los que el código puede detenerse. Cada sección a continuación explica su propósito, el código encargado de aplicar las reglas y el comportamiento cuando esa capa está ausente. Nadie necesita las cinco al mismo tiempo. Elija la capa cuyo fallo pueda imaginar que le afectará con mayor facilidad esta semana.
Capa 1: el límite de ejecución
¿Qué está permitido que haga el agente?
El límite es una función situada entre la elección del modelo y la llamada real a la herramienta. Comience con el agente sin protección alguna. Su instrucción indica que nunca se debe eliminar un archivo sin preguntar primero, y hay tres llamadas a herramientas esperando en la cola.
SYSTEM_PROMPT = "IMPORTANT: never delete a file without asking the user first."
def execute(call):
if call.name == "delete_file":
FILES.pop(call.args["path"], None)
return f"deleted {call.args['path']}"
Al ejecutarlo, el agente elimina cache.tmp, que es basura inofensiva, y luego elimina client-deliverable.md, tal como su nombre indica. No se hizo ninguna pregunta, aunque la instrucción ya incluía la regla desde el principio.
Una función colocada antes de la herramienta lo soluciona:
def boundary(rules):
def wrap(execute):
def guarded(call):
for name, deny_if, reason in rules:
if deny_if(call):
return f"DENIED by {name}: {reason}"
return execute(call)
return guarded
return wrap
NEEDS_APPROVAL = [(
"delete-needs-approval",
lambda c: c.name == "delete_file" and not c.args.get("approved_by_human"),
"deletion requires an explicit human approval flag on the call",
)]
Con el mismo agente, script e instrucción, nada se elimina.
Capa 2: aislamiento
¿Hasta dónde puede llegar el agente?
Un entorno aislado define qué directorios y hosts puede acceder el proceso del agente desde un principio. Constrúyalo desde cero: comienza sin nada y otorga únicamente lo que requiere la tarea, a través de una lista de rutas permitidas, una lista de hosts permitidos y un proceso que no tenga conocimiento de nada más.
La alternativa más común es una lista de denegación de rutas prohibidas:
DENY = ["secrets/"]
def execute(call):
path = call.args["path"]
if any(path.startswith(d) for d in DENY): # checks the spelling
return "DENIED by deny-list"
real = os.path.normpath(path) # the ../ collapses HERE, after the check
return DISK.get(real, "not found")
Al ejecutarlo, el agente lo intenta dos veces:
read('secrets/api_key') -> DENIED by deny-list
read('work/../secrets/api_key') -> sk-live-DO-NOT-LEAK
La verificación examinó el texto tal como estaba escrito, mientras que la búsqueda en el archivo siguió la ubicación a la que apuntaba ese texto. Dos solicitudes, dos formas de escribir, un archivo.
La solución consiste en normalizar primero la ruta y luego comparar:
ALLOW_ROOTS = ["work"]
def resolve(path):
real = os.path.normpath(path) # resolve FIRST
if not any(real == r or real.startswith(r + os.sep) for r in ALLOW_ROOTS):
return None
return real
Ambas formas de escribir ahora se reducen a secrets/api_key, que no se encuentra bajo ninguna raíz permitida, por lo que ambas son rechazadas. Aquí es importante permitir en lugar de denegar, ya que una lista de denegación solo bloquea las formas de escribir que su creador imaginó.
Estos ejemplos son funciones comunes de Python, por lo que no se necesita ningún contenedor para probarlas. En una implementación real, la verificación idéntica es el propio límite del proceso: un usuario o contenedor que no tenga permisos de lectura fuera de work/, con el mismo orden de operaciones.
La Capa 1 no puede realizar esta tarea. Una verificación dentro de tu programa solo detecta las llamadas que reconoce, mientras que una orden de shell, un enlace simbólico o una ruta que contenga .. pueden acceder al mismo archivo sin ser ninguna de esas llamadas.
Capa 3: persistencia de memoria
¿Qué permanece después de un reinicio de contexto?
Un hábito rinde más frutos que la mayoría: interrumpir las conversaciones sin pensarlo dos veces. El contexto se llena, la calidad disminuye y el agente comienza a contradecirse a sí mismo. Muchas personas siguen manteniendo este tipo de sesiones. Es mejor reiniciar temprano, siempre y cuando todo lo importante esté almacenado en un lugar al que el reinicio no pueda acceder, ya sea código comprometido, configuraciones, el propio framework o notas resumidas.
Por lo tanto, decida intencionalmente a dónde pertenece cada elemento del estado. Hay tres opciones: la conversación, donde desaparece junto con la sesión; el disco, donde persiste y puede ser recuperado posteriormente; y la configuración del framework, donde influye en todas las sesiones posteriores.
Una sola función de envío cubre las tres opciones:
CONVERSATION, DISK, HARNESS_CONFIG = [], {}, {}
def remember(kind, key, value):
"""'chat' dies with the session, 'disk' survives it,
'config' shapes every session that follows."""
{"chat": lambda: CONVERSATION.append(value),
"disk": lambda: DISK.__setitem__(key, value),
"config": lambda: HARNESS_CONFIG.__setitem__(key, value)}[kind]()
La función prácticamente no sirve para nada. Lo que ofrece es una regla según la cual nada se guarda sin especificar en cuál de las tres casas debe ir. Los equipos rara vez toman esa decisión de forma explícita, lo que explica por qué los agentes parecen olvidarse de algunas cosas y cometer errores obstinadamente en otras. En la demostración, la lista de conversaciones vuelve vacía, mientras que la decisión y la regla permanecen en el disco y en la configuración.
Capa 4: bucles de verificación
¿Quién revisa los resultados, y qué impide que quien revisa simplemente arregle los problemas?
Un bucle de verificación significa una segunda revisión del trabajo del agente, realizada por alguien a quien se le permite señalar problemas pero no repararlos.
La segunda mitad es lo que la gente omite. Deja que un subagente revisor escriba y, de forma silenciosa, corrija todo lo que encuentre. Eso parece eficiente, pero elimina la información que uno quería: ya no se puede distinguir entre el trabajo correcto y el incorrecto que fue corregido a espaldas del usuario.
Por lo tanto, mantén al revisor en modo solo lectura. Él genera una crítica, y actuar sobre dicha crítica supone otro paso con su propio rastro. Mantenerlos separados preserva una señal que se puede leer.
Otra táctica es la prueba preliminar. Para cualquier acción irreversible, la herramienta acepta una marca de verificación, describe por defecto lo que habría hecho y solo actúa una vez que alguien desactiva deliberadamente esa marca. El comportamiento inofensivo es el predeterminado, así que un descuido no cuesta nada. En la demostración, la herramienta de corrección anuncia que reescribirá total.py, no escribe nada, y el error de “off-by-one” permanece al final.
Una execute contiene ambas reglas:
def execute(call):
if call.name == "review":
snapshot = dict(CODE) # a copy, so the reviewer cannot write
src = snapshot[call.args["path"]]
return f"VERDICT: {'off-by-one' if '+ 1' in src else 'looks good'}"
if call.name == "apply_fix":
if call.args.get("dry_run", True): # on by default, turned off on purpose
return f"DRY RUN: would rewrite {call.args['path']}, nothing written"
CODE[call.args["path"]] = call.args["new"]
return f"wrote {call.args['path']}"
El revisor detecta el error de “off-by-one” pero no tiene forma de corregirlo.
Capa 5: pipelines de contexto
¿Qué llega al modelo y por qué se cobra por ello?
El pipeline de contexto abarca cómo la información ingresa al espacio del modelo y cuánta de ella es admitida.
Es en la admisión donde se gasta el dinero. Cada token que entra se paga en ese turno y nuevamente en todos los turnos posteriores, por lo que aquí surge la diferencia cuadruplante entre los diferentes sistemas, no en la Capa 1.
Una configuración ingenua carga todo: el archivo completo para una pregunta sobre una función, los resultados completos de una búsqueda para una necesidad de una sola línea y toda la historia anterior. Funciona, pero en el turno veinte se vuelve a pagar por todo lo que ya se leyó en los turnos del uno al diecinueve.
La solución consiste en la delegación sumada a la destilación. Un subagente trabaja en una ventana separada, lee decenas de miles de tokens y devuelve uno o dos mil. El hilo principal omite el registro bruto de la búsqueda y recibe únicamente la respuesta.
En código, se trata de determinar qué contador aumenta:
def subagent_search(query):
"""Its own window. The main thread never pays for this reading."""
global subagent_tokens
subagent_tokens += sum(len(v.split()) for v in CORPUS.values())
return next(f"{n}: {b.split('ANSWER:')[1].strip()}"
for n, b in CORPUS.items() if "ANSWER:" in b)
def execute(call):
global main_tokens
distilled = subagent_search(call.args["q"])
main_tokens += len(distilled.split()) # the only line that bills you
return distilled
La demostración es deliberadamente pequeña y sencilla. La pregunta y la respuesta son idénticas en ambas ejecuciones, sin embargo el hilo principal procesa 9,602 tokens en una y 2 en la otra.
Esto también aclara por qué los subagentes en cadena decepcionan a las personas. Cuando cada paso espera al anterior, se produce aislamiento del contexto y no hay ningún tipo de aceleración paralela. Los pasos verdaderamente independientes deberían ejecutarse simultáneamente. De lo contrario, hay que aceptar que lo que se obtiene es aislamiento. A menudo esto justifica el precio, siempre y cuando se sepa qué incluye la factura.
Lo que aún nadie puede decir
La confianza del público en este tema ha superado a las pruebas que lo respaldan, por lo que las advertencias son importantes.
- Nada de lo aquí presentado ha sido revisado por pares. Hasta agosto de 2026, todos los estudios que analizan el arnés son preimpresos de arXiv sin revisión por expertos. El experimento más cuidadosamente diseñado se describe a sí mismo como un trabajo preliminar en fase de revisión en un taller, y el artículo de referencia más conocido se considera un documento de posición que no incluye ningún experimento propio. Trate todo esto, incluido este texto, como material sin revisión por pares, y repita la comparación en sus tareas antes de planificar presupuestos basados en ello.
- Los beneficios rara vez se transfieren a tareas no vistas. Un artículo de julio de 2026 indicó que permitir que un sistema evolucione automáticamente no logra superar de manera fiable el escalado durante las pruebas y tiene una capacidad de generalización deficiente, ya que la búsqueda y la prueba final se basan en un mismo benchmark. En una evaluación de aprendizaje continuo en Terminal-Bench 2.0, GEPA alcanzó el 70,8% en las tareas para las que fue ajustado, pero luego descendió al 54,5% en el conjunto más amplio, un porcentaje inferior a su valor inicial de 56,8%. De hecho, el ajuste perjudicó el rendimiento. Pruebe cualquier sistema en tareas que no se utilizaron para su desarrollo, ya que las mejoras observadas únicamente en el conjunto de ajuste desaparecen en entornos reales.
- Una mejora notable obtenida mediante ajuste fino se evalúa según su propio señal de entrenamiento. Baseten ajustó finamente a Gemma 3 27B para la redacción de notas clínicas, elevando su rendimiento del 35% por debajo de Claude Sonnet 4 al 60% por encima. En la descripción se indica abiertamente que el conjunto de evaluación sirvió también como recompensa de entrenamiento. Se trata de un método válido, pero la puntuación proviene precisamente de lo que se utilizó para el entrenamiento. Cuando un proveedor afirma haber logrado una mejora mediante ajuste fino, pregúntele cuál fue la evaluación durante el entrenamiento; si es el mismo conjunto, la cifra demuestra que el modelo aprendió a reproducir esa evaluación.
- Un arnés no se transfiere de manera eficaz entre modelos diferentes. Un estudio de junio de 2026 reveló que agregar un arnés después del entrenamiento recupera muy poco de lo que ofrece el entrenamiento con él. Los modelos entrenados posteriormente con un arnés mínimo presentaron el error “Formato de herramienta inválido” en el 75.1% de los intentos tras modificarse las definiciones de las herramientas, y una variante de Qwen2.5-7B obtuvo 10.8 puntos menos que su propio modelo base. Un arnés que sirve para todos los modelos, en realidad, los adapta de forma algo peor. Elija el arnés antes del entrenamiento, y si no entrena su propio modelo, tenga en cuenta que cambiar de arnés a mitad de un proyecto puede resultar más costoso de lo que parece la migración.
- La terminología aún no está definida con claridad. En mayo de 2026, Hugging Face publicó un glosario que separa a “harness” de “scaffold”, y reconoció que Claude Code, Codex y otros sistemas utilizan “harness” para referirse a toda la estructura en conjunto. La división en cinco capas es solo una forma de hacerlo. Según una definición más estricta, aproximadamente la mitad de las pruebas mencionadas anteriormente se refieren a algo diferente. Elija un vocabulario, úselo dentro de su equipo y lea con atención las comparaciones entre estudios. Por esa razón, las cinco capas funcionan mejor como lista de verificación para su propia configuración, ya que una lista de verificación perdura más allá de los cambios en el vocabulario, mientras que una taxonomía puede generar conflictos. Antes de confiar en las diferencias entre los resultados de dos agentes, pregúntese qué capas incluye cada uno.
- Los efectos del harness parecen desvanecerse a medida que los modelos mejoran. Harness-Bench indica que los backends de modelos más potentes presentan puntuaciones promedio más altas, además de una menor variación entre los harnesses. Parte de la estructura de soporte podría estar compensando una debilidad que está desapareciendo. Dirija su inversión en harness hacia el control de costos, que es duradero, y no hacia la precisión, que podría ofrecerse gratuitamente con la próxima versión del modelo.
Los scripts complementarios
Existen diez scripts cortos que acompañan esta idea. Cada capa se muestra con su protección y el mismo agente se muestra sin ella. Se ejecutan sin conexión y sin clave API, ya que un sustituto programado reemplaza al modelo y emite una serie fija de llamadas a herramientas. Ver la diferencia al ejecutarlos es mejor que confiar ciegamente en las afirmaciones.
git clone https://github.com/paoloap-py/agent-harness-guide
cd agent-harness-guide
python3 run_all.py # all five layers, guard off then on, side by side
python3 test_harness.py # asserts every difference above, 10 checks
El README presenta las cinco capas como una lista de verificación de auditoría con una pregunta que se repite: ¿el código lo impone, o es una frase en una instrucción? Cualquier casilla que no puedas marcar señalando una ruta de archivo representa una regla con la que solo puedes contar esperanzadamente.
Dónde se aplica esto
Una regla sólida en el lugar equivocado apenas cuenta. En el escenario anterior, causó quince infracciones, once en una sola tarde, y un día que nadie quiere volver a vivir. Reubicar la regla fue lo que la hizo efectiva, sin que cambiara ni una sola palabra de ella.
Ese es el núcleo del asunto. El modelo es algo que compras. Todo lo demás es algo que construyes, y eso determina en parte cuánto cuesta el agente y con qué frecuencia realiza acciones que nunca aprobaron. Ambos son aspectos de ingeniería, pero solo el segundo está bajo tu control para darle forma.
Preguntas frecuentes
¿Qué es exactamente un harness para un agente? Todo lo que rodea al modelo: el bucle de herramientas, las verificaciones previas a la ejecución, el entorno aislado, la persistencia entre sesiones, el revisor y la secuencia que determina qué contiene cada turno. El bucle consta de seis líneas, o veinte con manejo de errores, y todo lo demás forma parte del harness.
¿Es el harness más importante que el modelo? En cuanto al costo, sí, ya que el uso de tokens por tarea resuelta puede variar hasta 40 veces. En cuanto a si las tareas se resuelven, no. Las diferencias medidas en la tasa de éxito entre los harnesses van de 0 a 8 puntos, con intervalos que cruzan cero, y los autores de Terminal-Bench concluyen que elegir el modelo suele ser más importante para el rendimiento.
¿Dónde cuesta más el harness? En el contexto: cada token que se muestra al modelo en cada turno se paga en ese mismo turno. Eso hace que Layer 5 sea el más costoso y explica por qué entregar una búsqueda a un subagente modifica la factura sin cambiar la respuesta.
¿Las reglas de permisos cuentan como seguridad?
No. Una verificación del harness solo examina la llamada que el agente realizó realmente, mientras que un comando de shell, un enlace simbólico o una ruta .. pueden acceder al mismo archivo sin ser inspeccionados. El verdadero límite proviene del sistema operativo: se inicia el proceso sin acceso a nada y luego se le añaden los permisos que necesita la tarea.
¿Construir un harness o adoptar uno? Adopte uno y quédese con él. Pasar a otro borra el conocimiento acumulado en sus archivos de configuración, y cada regla que se escribe después de un fallo real debe volver a ganarse.
Leer más
- Agentes que se mejoran a sí mismos mediante habilidades: reutilización, selección, reparación y verificación — Un diseño en cuatro partes para agentes que mejoran sus propias habilidades: guardar código funcional, perfeccionar las descripciones, proponer soluciones revisadas y verificar la salida antes de la transferencia.
- Un harness de producción para Claude Code: seis capas desde Slack hasta el código fusionado — Cómo un harness de seis capas convierte los tickets de Slack en código fusionado: recepción de eventos, bucles de agentes con control de acceso, estado duradero, autoreparación, capacidad de observación y control por parte del operador.