Last updated on

El aviso de aprobación que antes se esfumaba a mitad de café ahora te espera


Le pides a tu agent que borre una caché de compilación que no has tocado en meses. Te pregunta si puede ejecutar la orden. Pulsas Enter y te vas a rellenar la taza de café. Cuando vuelves, el aviso ha desaparecido, la orden nunca se ejecutó y la transcripción dice una sola cosa: aprobación agotada por tiempo. No respondiste mal — simplemente el reloj fue más rápido que tú.

Actualización (2026-10-03): El cambio se revirtió esa misma noche (PR #130826: la espera infinita ya se había rechazado como dirección y dejaba colgado hermes chat -q, donde nadie puede responder). Los avisos de aprobación y de clarify en el CLI, el TUI y el Desktop vuelven a regirse por approvals.timeout y agent.clarify_timeout. Motivos completos y qué hacer en su lugar: la nota de reversión.

Ese reloj era approvals.timeout, 300 segundos por defecto. Ahora se divide según una línea muy simple: ¿hay alguien mirando la pantalla? Los avisos de CLI, TUI y Desktop se mantienen visibles hasta que respondas, interrumpas el turno o cierres la sesión. Las plataformas de mensajería conservan su plazo. Esto es lo que ha cambiado y lo que significa para tu configuración.

Primero, el muro de los cinco minutos

Las aprobaciones se rigen por una regla innegociable: un timeout no es un sí. No es «nadie respondió, así que adelante», sino «nadie respondió, así que no». Es el valor seguro por defecto, pero te cuesta una acción descartada en silencio, y en la transcripción se ve casi idéntica a «la orden ha fallado».

¿Por qué cinco minutos? Los comentarios de configuración son sorprendentemente claros al respecto: las aprobaciones en plataformas de mensajería llegan como una notificación push, y 60 segundos resultaron demasiado justos — en Telegram y Discord el aviso a menudo caducaba antes de que el usuario llegara al móvil. Así que el valor por defecto se subió a 300.

El problema es que 300 segundos tienen sentido para una notificación push y ninguno cuando la persona ya está sentada frente al aviso. Te levantaste a por un vaso de agua, y lo que encontraste al volver no fue «sigue esperando», sino «ya lo has perdido».

La nueva regla, dividida por superficie

Superficie Cuánto tiempo permanece abierto el aviso
CLI interactiva (hermes chat) hasta que respondas o interrumpas el turno
TUI igual
App de escritorio igual
Telegram / Discord / Slack y otras plataformas de mensajería sigue siendo approvals.timeout (300 s por defecto)
Editores ACP y plugins de transporte de aprobaciones sigue siendo approvals.timeout

La línea divisoria no es qué superficie es más sofisticada, sino si el usuario puede ver el aviso al instante. En una plataforma de mensajería, una aprobación es un push que puede quedarse sin leer durante horas, y los propios botones de la plataforma caducan. Esas superficies necesitan un plazo. En la CLI, la TUI y el escritorio, el aviso se dibuja en la pantalla que ya estás mirando, así que no hay nada que perder.

Un límite que conviene tener presente: no se ejecuta nada mientras espera. El contrato no ha cambiado — esto sigue siendo fail-closed, ninguna herramienta se libera mientras el aviso está en pantalla, e interrumpirlo cuenta como una denegación.

Cómo está conectado

El cambio toca varios módulos, pero el núcleo es un interruptor que se enlaza una vez por turno:

Dónde Qué hace
tools/approval_context.py añade set_prompts_wait_for_answer() / reset_prompts_wait_for_answer() tras una variable de contexto por turno, y convierte approval_wait_seconds() en el único resolutor de la ventana de aprobación integrada
agent/deadline.py MAX_SAFE_TIMEOUT_S: 365 días fuera de Windows, y en Windows el techo en milisegundos de un DWORD (unos 49,7 días) — ambos semánticamente «sin límite», dimensionados para que los límites de Lock.acquire / Thread.join derivados de él no puedan desbordarse
tools/approval_human_wait.py human_wait_ceiling() devuelve la ventana de aprobación más un margen de 60 segundos, de modo que el bucle de plazo por lotes y el lock de serialización de la puerta de autorización comparten un único techo en vez de inventarse cada uno el suyo
hermes_cli/cli_chat_turn_mixin.py enlaza el interruptor en torno a cada turno y lo restablece al desmontar
tui_gateway/prompt_turn.py la TUI y el escritorio comparten este backend: se enlaza cuando se prepara la entrada del turno y se restablece al salir

De paso se corrigió un bug sutil. El bucle de plazo por lotes podía leer el techo de espera humana desde un contexto que nunca vio el enlace, lo que haría que un aviso sin límite pareciera una ventana bloqueada y seguiría prolongando el plazo del lote. Ahora lee el techo real, y un aviso sin límite se excluye de plano en lugar de medirse mal. Las ventanas de mensajería siguen recortadas exactamente igual que antes.

La excepción que hay que recordar: el modo de consulta única

hermes chat -q "..." no tiene a nadie sentado al lado, así que deliberadamente no enlaza el interruptor y sigue usando approvals.timeout. Normalmente no espera en absoluto: approvals.single_query_mode tiene deny por defecto, de modo que una orden peligrosa se rechaza de inmediato y se empuja al agent a buscar otra vía.

Si ejecutas sesiones de consulta única en scripts o CI, no cuentes con «esperar más tiempo» — nunca hubo nadie ahí para pulsar la tecla.

Qué revisar en tu máquina

  • El uso interactivo ya no necesita un timeout elevado. Si habías subido approvals.timeout a miles de segundos solo para darte margen, puedes volver a bajarlo: ahora solo rige la mensajería y los transportes ACP y de plugins.
  • Ajusta la mensajería por separado. hermes config set approvals.timeout 600 solo afecta a esas superficies; la clave está documentada junto con el resto de la configuración en la referencia de configuración de hermes.
  • Deja de esperar que un timeout signifique sí. Para reducir las interrupciones, usa las aprobaciones inteligentes; para abrirlo todo, existen los niveles yolo; para prohibir clases enteras de órdenes, usa la lista de denegación. El panorama completo está en la guía de aprobaciones desatendidas.
  • Haz un dry-run antes de cambiar la política. Los dry-runs y las autocomprobaciones de aprobaciones muestran qué regla coincide con qué veredicto sin ejecutar nada.
  • Cron y las plataformas desatendidas siguen denegando. Sus valores por defecto no han cambiado, y eso es precisamente lo que se busca.

La conclusión

Lo que parece «el aviso deja de desaparecer» es en realidad un único parámetro dividido en dos situaciones: si hay una persona mirando, no hay plazo; si no mira nadie, tiene que haberlo. El primer caso te evita perder una acción por culpa de tu propia pausa para el café. El segundo mantiene honesta la ruta de las notificaciones push.

La regla general es lo bastante corta para memorizarla: si el aviso se dibuja en la pantalla que estás mirando, te espera; si se envió a tu móvil, tiene que caducar.