Cómo funciona Agents Never Sleep

Un recorrido por una ejecución desatendida, de principio a fin — el mecanismo, no un discurso de ventas.

Definición

¿Qué es la ejecución desatendida de agentes?

La ejecución desatendida de agentes es un agente de código que avanza por un backlog de tickets sin nadie vigilando cada paso — sin un humano presente para responder una pregunta aclaratoria. Solo funciona si el agente tiene una regla permanente para el momento en que no está seguro: asumir y continuar, aplazar esa única decisión y pasar al siguiente ticket, o detener toda la ejecución. Agents Never Sleep (ANS) es la capa de gobernanza que suministra esa regla como un contrato duradero y aplicado, de modo que un ticket ambiguo a las 2 de la madrugada nunca congela a los otros treinta y nueve.

1. Preflight de lanzamiento — antes de gastar ningún token

Una ejecución headless empieza a través del lanzador (bin/ans-run), un gate determinista de GO/NO-GO que se ejecuta antes de que arranque el CLI del agente — porque para cuando se ejecutan los propios chequeos de preflight del agente, los primeros tokens ya se han gastado en una ejecución que podría estar condenada.

El lanzador comprueba, en orden: la confianza de la configuración (el .claude/agents-never-sleep.json del repositorio debe estar explícitamente aprobado una vez por usuario, indexado por su SHA-256 — una configuración nueva o cambiada sin nadie alrededor para aprobarla es un NO-GO); la identidad (un usuario objetivo configurado, nunca una ejecución desatendida dejada corriendo como root); la selección de agente (un preset con nombre, verificado con una prueba real de --version para detectar la deriva de flags antes del gasto, no después); y un bloqueo del árbol de trabajo — un flock(2) no bloqueante para que dos lanzamientos simultáneos sobre el mismo repositorio siempre produzcan exactamente un ganador, liberado automáticamente por el kernel ante cualquier caída.

Los códigos de salida son simples: 0 iniciado, 64 NO-GO, 65 el árbol de trabajo ya está ocupado. Los flags de autonomía — el modo de permisos que permite que una ejecución desacoplada avance realmente sin detenerse en un aviso de aprobación — nunca son un valor por defecto; un preset solo se vuelve lanzable una vez que un humano ha confirmado exactamente lo que ese flag concede.

Los tickets avanzan por la máquina, punto de control a punto de control.
Los tickets avanzan por la máquina, punto de control a punto de control.

2. La máquina de estados por ticket

Una vez en marcha, el agente conduce un bucle de dos comandos contra el harness: next pide un ticket para trabajar, complete registra lo ocurrido. Cada llamada es un subproceso nuevo sobre un estado duradero y escrito de forma atómica — una caída entre los dos no pierde nada, porque nada vive solo en memoria.

Cada ticket termina en exactamente uno de siete estados de resultado, elegidos para que la respuesta a la mañana siguiente nunca sea ambigua:

  • DONE — implementado, gate determinista en verde.
  • DONE_LOW_CONFIDENCE — gate en verde, pero la revisión delegada de un diff de alto riesgo planteó dudas, dio error, o nunca se ejecutó; necesita revisión a la luz del día.
  • PARKED_DECISION — una decisión aplazada a un humano; la ejecución siguió adelante.
  • PARKED_FOUNDATIONAL — una ambigüedad fundacional; los tickets dependientes quedan en cuarentena hasta que se resuelva.
  • BLOCKED_ENV — el entorno bloqueó el progreso (un bloqueo de git, un gate que no puede ejecutarse) — no es culpa del agente.
  • FAILED_RETRYABLE — un gate detectó un bug introducido por el diff; la edición se revirtió; seguro para reintentar.
  • FAILED_BUG_IN_AGENT — fallos repetidos sugieren un problema sistemático; necesita revisión humana.

3. Decidir — luego implementar

Antes de tocar un archivo, el harness clasifica el radio de impacto del ticket y decide PROCEED, PARK o HALT. Solo un ticket PROCEED llega al agente para su implementación; un PARK se registra antes de cualquier edición, porque la decisión en sí es el producto del trabajo.

Una vez que se entrega un ticket PROCEED, el agente — el trabajador en este diseño — edita exactamente los archivos de ese ticket. El harness toma primero un snapshot del árbol de trabajo, así que lo que haga el agente puede deshacerse.

La puerta decide: el sello solo cae cuando pasan las pruebas.
La puerta decide: el sello solo cae cuando pasan las pruebas.

4. El gate determinista — el único bloqueo estricto

Un gate es un comando de shell — tu suite de tests — ejecutado después de la edición. Salida 0 es verde; distinto de cero es rojo. Esto es lo único en toda la ejecución que puede bloquear estrictamente un ticket; todo lo demás (una revisión delegada a un modelo, una lente especializada) es consultivo y solo puede retener un sello de confianza, nunca revertir el trabajo ni detener la ejecución.

Un gate en rojo se clasifica, no solo se reporta: un fallo que el diff claramente introdujo revierte al último commit en verde y registra FAILED_RETRYABLE; un fallo que parece preexistente, inestable o del entorno reduce la confianza pero conserva el trabajo; un gate que no puede ejecutarse en absoluto (un bloqueo, un timeout, un aviso no interactivo que no puede responder) registra BLOCKED_ENV — nunca una parada silenciosa. ANS nunca elimina ni omite un test que falla para forzar el verde.

---
id: fix-flaky-webhook-retry
title: Retry webhook delivery on 5xx with backoff
blast_radius: medium      # optional hint — the harness auto-classifies from the diff
gate: pytest tests/webhooks/ -x
---

The webhook sender should retry on 5xx responses with exponential backoff
(max 3 attempts). Cover it with a test that simulates two 500s then a 200.

Ejemplo ilustrativo — un ticket es un archivo Markdown con un bloque opcional de front-matter YAML; el cuerpo es la única parte obligatoria, y gate nombra el comando que decide el éxito o fracaso de ese ticket.

5. ASK / PARK / HALT — los puntos de decisión

Tres respuestas distintas a la incertidumbre, nunca colapsadas en una sola. ASK está prohibido en el momento en que una ejecución es desatendida — no hay nadie ahí para responder, así que se convierte automáticamente en PARK. Eso deja dos opciones reales:

  • PARK — aplazar este ticket o decisión concreta, y pasar directamente al siguiente ticket independiente. Esto es normal y saludable, no una parada. Un aparcado siempre registra por qué, las interpretaciones candidatas, y la decisión humana exacta que espera por la mañana. Ejemplos reales que se aparcan de forma estricta (Hard-PARK): en qué dirección debería ir una migración de base de datos, un cambio a un contrato de API público o compartido, cualquier cosa que toque un límite de seguridad o de aislamiento entre tenants, y cualquier cosa relacionada con dinero, facturación o precios.
  • HALT — detener toda la ejecución. Reservado para peligros genuinamente irreversibles sin ninguna red de seguridad — por ejemplo, sin control de versiones presente y sin posibilidad de crearlo. HALT es raro por diseño; la mayor parte de la incertidumbre es un PARK, no un HALT.

La disciplina detrás de la elección es el radio de impacto: el nombrado, la estructura interna, la redacción de logs, o una elección entre dos implementaciones locales equivalentes pueden seguir con PROCEED (asumir, registrar, continuar, de forma reversible). Cualquier cosa con un radio de impacto grande, o cualquier cosa genuinamente inclasificable, se aparca. Un elemento pequeño aparcado por error cuesta una decisión matutina de cinco segundos; uno grande asumido por error cuesta una noche entera de trabajo equivocado en la dirección equivocada.

El vigilante vela; una ejecución congelada se reinicia de forma reanudable.
El vigilante vela; una ejecución congelada se reinicia de forma reanudable.

6. El watchdog — congelación, luego un reinicio reanudable

Un cuelgue es un fallo distinto de una parada: el proceso está vivo, sin hacer nada, y ningún hook que vigile una parada prematura puede verlo. Una ola sostenida de sobrecarga del proveedor es la causa realista — la ejecución sigue ahí, pero su heartbeat se ha quedado obsoleto.

El watchdog es un sidecar que ejecuta el comando desatendido como un proceso hijo y sondea su archivo de heartbeat. Cuando el heartbeat se queda obsoleto más allá de un umbral configurado, mata al hijo y lo reinicia — y como el estado de ANS es duradero, el reinicio retoma exactamente donde estaba la ejecución; las ediciones parciales del ticket en curso se revierten a su último snapshot, así que nada se pierde ni se cuenta dos veces. Tras un número limitado de reinicios, lanza una alerta y termina, en lugar de reiniciar indefinidamente. ans-run envuelve por defecto cada lanzamiento desacoplado en el watchdog.

El mismo sidecar también recoge sus propios procesos hijos filtrados — por ejemplo un servidor MCP que el agente lanzó y nunca cerró — estrictamente por linaje de cadena de padres a partir del propio ID de proceso de la ejecución, nunca haciendo coincidir un nombre de proceso (una coincidencia de nombre podría matar una ejecución no relacionada en la misma máquina). Límite honesto: si el propio supervisor es forzado a terminar, no puede recoger después del hecho, así que esto reduce la fuga de procesos, no la elimina.

7. Drain — ejecutar hasta que no quede nada por hacer

El agente sigue llamando a next y luego a complete hasta que next devuelve un estado terminal: DRAINED (el backlog está vacío), HALTED (se dio una condición de HALT), o LOW_YIELD (un disyuntor saltó porque la mayoría de los tickets recientes están aparcando o bloqueándose en lugar de completarse — una señal de que algo en el propio backlog necesita revisión humana, no más intentos). Los topes de intentos y de bucles fuerzan el aparcado de cualquier ticket individual que de otro modo consumiría toda la ejecución, para que un elemento maldito no pueda repetir exactamente el fallo que todo este diseño existe para evitar.

8. El informe matutino

Cuando la ejecución termina, escribe un único informe ordenado por prioridad (night-report.md) en lugar de dejarte reconstruir lo ocurrido a partir de logs. Indica: qué está hecho y es de confianza, qué está hecho pero necesita revisión a la luz del día (un cambio de alto riesgo cuya revisión delegada no lo aprobó), qué está aparcado — cada uno con sus interpretaciones candidatas y la próxima acción exacta — qué está bloqueado por el entorno, y cualquier punto ciego: una garantía degradada, una capacidad que no estaba disponible, una credencial que la ejecución no pudo leer. Una noche de bajo rendimiento se señala claramente en el informe, para que "la ejecución terminó" nunca se confunda con "el trabajo se hizo".