Un agente LLM que prueba un flujo de registro suele parecer sencillo: crea una cuenta, espera un correo, extrae el enlace y confirma el acceso. El problema aparece cuando el agente puede repetir una herramienta, dos workers observan el mismo mensaje o el buzón conserva correos de una ejecución anterior.
En ese punto, leer un email ya no es una operación inocente. Es una operación con estado. El agente necesita saber qué mensaje puede reclamar, durante cuánto tiempo y qué evidencia debe devolver al siguiente paso. Sin ese contrato, una prueba puede pasar por haber consumido un correo viejo, o fallar porque otro intento ya lo tomó.
El problema no es leer, es reclamar un mensaje
Un buzón de pruebas es parecido a una cola, aunque normalmente se trate como una simple bandeja de entrada. Un flujo típico tiene estas etapas:
- El agente solicita una identidad de prueba.
- La aplicación envía un enlace de verificación.
- Una herramienta consulta el buzón.
- El agente extrae el mensaje y ejecuta la acción.
La carrera está entre los pasos 3 y 4. Si dos llamadas hacen list_messages y después intentan abrir el mismo email, las dos pueden creer que tienen permiso. También hay una carrera temporal: llega un mensaje correcto, pero la búsqueda devuelve primero uno antiguo con un asunto parecido.
Por eso conviene pensar en un correo de usar y tirar como un recurso de ejecución, no como un dato permanente. Un generador de correo temporal puede crear el buzón, pero el sistema de pruebas aún debe decidir quién es dueño de cada lectura.
Un contrato mínimo para el buzón
El contrato no necesita una plataforma enorme. Para cada ejecución guardaría, como mínimo:
-
run_id: identifica la prueba y evita mezclar sesiones. -
mailbox_id: apunta al buzón aislado. -
message_id: identifica el mensaje reclamado. -
expected_recipient: dirección que debía recibirlo. -
received_after: límite temporal desde el que el mensaje es válido. -
lease_until: momento en que expira la reserva de lectura. -
status:waiting,claimed,consumedoexpired.
La dirección y el asunto sirven para encontrar candidatos, pero no son una identidad suficiente. Dos mensajes pueden compartirlos. El agente debería confirmar también el run_id cuando la aplicación lo pueda incluir en un encabezado, un token de prueba o un campo de metadata.
Este criterio encaja bien con un flujo de validar correos con evidencia útil: no basta con decir “encontré un email”; hay que explicar por qué ese email pertenece a la ejecución.
La ventana de consumo evita carreras
La operación importante no es get_message, sino claim_message. Reclamar cambia el estado de forma atómica y entrega una ventana breve para que el agente procese el mensaje.
{
"operation": "claim_message",
"mailbox_id": "mbx_42",
"run_id": "run_20261014_001",
"filters": {
"recipient": "qa@example.test",
"subject_contains": "Verifica tu cuenta",
"received_after": "2026-10-14T06:00:00Z"
},
"lease_seconds": 90
}
La respuesta positiva debe incluir un identificador estable y la expiración de la reserva:
{
"status": "claimed",
"message_id": "msg_884",
"lease_until": "2026-10-14T06:02:11Z",
"body_excerpt": "Confirma tu cuenta..."
}
Una segunda llamada para la misma ejecución debería devolver already_claimed, no otro mensaje. Si el agente termina correctamente, llama a consume_message. Si se cae o tarda demasiado, la reserva expira y una política controlada puede permitir otro intento. Ese límite es mejor que dejar reintentos sin fin, que luego parece un fallo del proveedor.
Qué debe devolver la herramienta al agente
Los agentes trabajan mejor con resultados explícitos que con texto ambiguo. Separaría cuatro casos:
-
waiting: todavía no hay mensaje válido; incluyeretry_after_seconds. -
claimed: hay un mensaje reservado y listo para extraer. -
already_consumed: el flujo ya procesó el mensaje; no debe repetir el clic. -
expired: el mensaje o la reserva ya no es confiable.
No devolvería el buzón completo en cada llamada. Además de ser costoso para el contexto, hace más probable que el modelo elija una evidencia equivocada. Un resumen con el mensaje candidato, la edad, el destinatario y el estado es mucho más facil de razonar.
El agente tampoco debería inventar que un enlace fue verificado. La herramienta debe devolver un recibo, por ejemplo message_id, run_id, claimed_at y consumed_at. Ese recibo se puede adjuntar al resultado de la prueba y revisar despues.
Implementación y checkpoints
En una API real pondría la transición waiting -> claimed detrás de una operación condicional: UPDATE ... WHERE status = 'waiting'. En Redis, un SET con expiración y una llave por run_id puede cubrir una ventana corta. La tabla SQL da mejor auditoría; Redis ofrece menor latencia. La elección depende de cuánto necesites investigar una ejecución fallida.
Mis checkpoints serían estos:
- Crear un buzón nuevo o limpiar el anterior antes de iniciar la prueba.
- Registrar
received_afterjusto antes de disparar el email. - Rechazar mensajes sin destinatario o ejecución coincidente.
- Hacer que reclamar sea idempotente para el mismo
run_id. - Consumir el mensaje solo después de completar la acción del flujo.
- Guardar el recibo junto con los logs de la prueba.
En datos de QA aparecen a veces valores humanos poco cuidados, como tempail mail o temp gamil com, especialmente en fixtures viejos. No deberían romper el parser ni convertirse en criterios de búsqueda. Conviene tratarlos como datos de prueba y marcar su origen, nada mas.
Este aislamiento también ayuda a probar onboarding sin ensuciar métricas. Si el agente consume cuentas y correos separados del tráfico real, los resultados son más faciles de explicar.
Preguntas frecuentes
¿La reserva reemplaza a una cola?
No. La cola ejecuta tareas; la reserva controla quién puede consumir un mensaje. Son problemas distintos y se complementan.
¿Cuánto debe durar la ventana?
Empieza con 60 a 120 segundos y mide. Una ventana demasiado corta produce expiraciones falsas; una demasiado larga retiene recursos y oculta agentes atascados.
¿Hay que borrar cada email después de usarlo?
No siempre. Marcarlo como consumido conserva evidencia. Borrarlo puede ser útil por privacidad, pero hazlo después de guardar el recibo mínimo y aplicar la retención definida.
La idea central es pequeña: un agente no necesita “mirar el inbox”, necesita adquirir evidencia con límites. Cuando el buzón expone estado, lease y recibo, los reintentos dejan de ser misterio y la automatización se vuelve mucho más predecible.
Top comments (0)