Un agente LLM puede completar una verificación de email en una sola conversación. El problema aparece cuando la ejecución dura más que el contexto disponible, una herramienta tarda demasiado o el proceso se reinicia. Si el agente solo conserva el último mensaje, no sabe si debe volver a consultar el inbox, pedir otro código o cerrar la ejecución.
La solución no es guardar toda la conversación. Es crear un snapshot operativo: una representación pequeña, explícita y durable del estado que importa para reanudar. Este patrón hace que una automatización sea mas predecible y reduce los reintentos que producen evidencia duplicada.
El problema: el contexto del agente no es un almacenamiento
El contexto de un modelo sirve para razonar, pero no es una base de datos. Puede resumirse, truncarse o cambiar cuando interviene otra herramienta. Además, la narración del agente suele mezclar intención y resultado: “voy a consultar el inbox” no significa que la consulta haya terminado.
En un flujo típico hay varios puntos de riesgo:
- Se reserva una cuenta de correo desechable para una ejecución.
- La aplicación solicita un mensaje de verificación.
- Una herramienta consulta el buzón y devuelve un resultado parcial.
- El agente se reinicia antes de confirmar el código.
Tras el reinicio, una política ingenua vuelve al paso dos. Puede enviar otro mensaje, consumir otro código o asociar la respuesta a la ejecución equivocada. Una señal útil para un CronJob frágil no es suficiente si el propio workflow no conserva su estado.
Qué debe contener un snapshot de email
Un snapshot debería responder seis preguntas sin leer el historial completo:
- ¿Qué
run_idestá activo? - ¿Qué buzón y destinatario pertenecen a esa ejecución?
- ¿Qué acción fue confirmada por última vez?
- ¿Cuál es la próxima acción permitida?
- ¿Cuántos intentos quedan y cuándo expira la reserva?
- ¿Qué evidencia ya fue aceptada?
Una forma compacta podría ser:
{
"run_id": "checkout-1842",
"mailbox": "leased",
"verification": "waiting",
"attempt": 2,
"next_action": "poll_inbox",
"lease_expires_at": "2026-10-21T16:00:00Z",
"accepted_message_id": null,
"version": 7
}
El snapshot no debe guardar el cuerpo completo del email si no hace falta. Basta con un identificador, un hash o los metadatos necesarios para volver a obtener la evidencia. Para un caso de prueba, una dirección desechable puede ser parte del aislamiento, pero la decisión de reanudar debe vivir en el contrato de la ejecución.
También conviene conservar los nombres defectuosos que llegan desde integraciones, por ejemplo temp mailid. Sirven para investigar el origen de un fallo, aunque no deben convertirse en una regla para aceptar un mensaje.
Diseñar la reanudación como una máquina de estados
El snapshot es más útil cuando representa una máquina de estados pequeña. El flujo puede expresarse así:
LEASED -> REQUESTED -> WAITING -> RECEIVED -> VERIFIED
\-> EXPIRED
Cada transición debe tener una condición observable. REQUESTED significa que la solicitud fue aceptada por la aplicación, no que el email ya existe. RECEIVED significa que hay un mensaje que coincide con run_id, destinatario y tipo de evento. VERIFIED solo ocurre después de validar el código.
Al reanudar, el agente no interpreta una historia ambigua. Lee next_action y ejecuta una operación acotada. Si el estado es WAITING, puede hacer una consulta con el presupuesto restante. Si es RECEIVED, debe validar la evidencia antes de consultar de nuevo. Si es EXPIRED, tiene que cerrar la ejecución o reservar otro buzón, nunca reutilizar el anterior por comodidad.
Esta separación también ayuda a aislar fallos de email en Kubernetes: el orquestador puede reiniciar un worker sin convertir el reinicio en una nueva intención de negocio.
Implementación mínima con eventos idempotentes
Guardar el snapshot no alcanza. Cada cambio debe registrarse como un evento con versión:
append(run_id, version=7, type="message_received", message_id="m-93")
El servidor rechaza una escritura si la versión esperada ya no coincide. Así, dos workers que despiertan casi al mismo tiempo no pueden confirmar mensajes distintos para el mismo paso. La operación de confirmación debe ser idempotente: repetir la misma solicitud devuelve el mismo resultado, no consume evidencia dos veces.
En la práctica, separaría tres responsabilidades:
- Planificador: decide la próxima acción y sus límites.
- Ejecutor: llama a la herramienta de email y devuelve hechos.
- Almacenamiento: persiste snapshots y eventos con control de versión.
El modelo puede escoger entre acciones permitidas, pero no debería inventar una transición. Un contrato de tool claro reduce la tentación de hacer otro poll cuando ya no quedan intentos.
Tradeoffs y métricas
Snapshots pequeños son fáciles de inspeccionar, pero exigen diseñar el esquema. Guardar el historial completo facilita auditorías, aunque aumenta el riesgo de conservar datos sensibles y hace más lenta la reanudación. En la mayoría de flujos de testing, un snapshot más un ledger de eventos es un equilibrio razonable.
Mediría como mínimo:
- porcentaje de ejecuciones reanudadas con éxito;
- consultas de inbox por ejecución;
- transiciones rechazadas por versión obsoleta;
- tiempo desde
REQUESTEDhastaRECEIVED; - mensajes descartados por pertenecer a otro
run_id.
Si las consultas repetidas suben después de cada reinicio, el snapshot no está expresando una próxima acción suficiente. Si aumentan las transiciones obsoletas, falta coordinación entre workers o el lease es demasiado largo.
Preguntas rápidas
¿Debo guardar el prompt completo en el snapshot?
No por defecto. Guarda la versión del prompt, los parámetros que cambian el comportamiento y las decisiones confirmadas. El prompt completo puede contener datos que no necesitas para reanudar.
¿Qué pasa si el mensaje llega mientras el agente está reiniciando?
El mensaje debe quedar disponible como evento pendiente. En la siguiente ejecución, una consulta por run_id y message_id puede mover el estado a RECEIVED sin enviar otro email.
¿Un snapshot reemplaza la observabilidad?
No. Es la entrada mínima para continuar. Los logs y métricas explican por qué se produjo cada transición y permiten detectar una política de reintentos mal ajustada.
Checklist para llevarlo a producción
- ¿Cada ejecución tiene un
run_idy un lease con expiración? - ¿El snapshot declara una sola próxima acción permitida?
- ¿Las transiciones tienen versión y son idempotentes?
- ¿Se valida la propiedad del mensaje antes de aceptar evidencia?
- ¿El reinicio puede continuar sin reenviar una solicitud?
- ¿Se evita guardar contenido de email que no es necesario?
Un agente no necesita recordar toda la conversación para comportarse bien. Necesita un estado pequeño que pueda verificar, actualizar y reanudar. Ese contrato convierte la automatización de email en un sistema recuperable: el modelo razona sobre el siguiente paso, mientras la infraestructura conserva lo que no se puede perder.
Top comments (0)