Agentes LLM: un buzón con contrato de consumo
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 ante

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ó.
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:
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.
El contrato no necesita una plataforma enorme. Para cada ejecución guardaría, como mínimo:
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 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 } Enter fullscreen mode Exit fullscreen mode 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..." } Enter fullscreen mode Exit fullscreen mode 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.
Los agentes trabajan mejor con resultados explícitos que con texto ambiguo. Separaría cuatro casos:
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.
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.
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.
No. La cola ejecuta tareas; la reserva controla quién puede consumir un mensaje. Son problemas distintos y se complementan.
Empieza con 60 a 120 segundos y mide. Una ventana demasiado corta produce expiraciones falsas; una demasiado larga retiene recursos y oculta agentes atascados.
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.