DEV Community

Silviu Technology
Silviu Technology

Posted on

Agentes LLM: un contrato para emails de prueba

Cuando un agente LLM ejecuta una prueba de email, no basta con decirle “espera el mensaje y comprueba el enlace”. Esa instrucción mezcla varias decisiones: qué identidad usar, cuánto tiempo esperar, qué mensaje pertenece a la ejecución y qué hacer si el proveedor tarda.

El resultado suele ser una prueba difícil de repetir. A veces encuentra un mensaje viejo, otras veces crea una cuenta que ya existe y, en el peor caso, termina usando una bandeja compartida para un flujo que debía ser aislado. El problema no es que el agente no sea inteligente; es que le falta un contrato operativo.

En este artículo propongo una arquitectura pequeña para agentes LLM que automatizan pruebas de email. La idea central es separar la decisión del agente, la evidencia de la bandeja y el estado de la ejecución.

El problema: un agente no entiende una bandeja por intuición

Un agente puede leer una interfaz y reconocer que llegó un correo. Pero “llegó un correo” no prueba que sea el correcto. Debe responder, como mínimo, estas preguntas:

  • ¿La bandeja pertenece a esta ejecución?
  • ¿El destinatario coincide con la identidad creada por el sistema?
  • ¿El mensaje fue generado después del evento que estamos probando?
  • ¿El enlace lleva al entorno correcto?
  • ¿La evidencia se puede conservar sin exponer un token?

Si el flujo usa un correo temporal para Facebook como dato de prueba, la bandeja sigue siendo una dependencia externa y no una fuente absoluta de identidad. El agente debe conocer esa limitación desde el principio.

Hay una diferencia importante entre un agente que decide y un adaptador que observa. El agente puede decidir “esperar un mensaje de verificación”; el adaptador debe devolver hechos estructurados, no una interpretación ambigua de la pantalla.

El contrato mínimo de una prueba de email

Un contrato útil convierte la ejecución en una serie de estados observables. Por ejemplo:

{
  "run_id": "signup-agent-1842",
  "mailbox_id": "mbx-1842",
  "recipient": "qa-1842@example.test",
  "event": "signup.verification_requested",
  "expected_subject": "Confirma tu cuenta",
  "expires_at": "2026-10-30T03:35:00Z"
}
Enter fullscreen mode Exit fullscreen mode

El run_id relaciona el evento de la aplicación con la evidencia de email. mailbox_id identifica el recurso aislado sin obligar al agente a manipular credenciales. expires_at evita que una espera indefinida se transforme en un bucle caro.

La respuesta del adaptador debería tener una forma estable, aunque no encuentre nada:

{
  "status": "found",
  "message_id": "msg-91a2",
  "received_at": "2026-10-30T03:22:11Z",
  "recipient_matches": true,
  "correlation_matches": true,
  "links": ["https://staging.example.test/verify?token=redacted"]
}
Enter fullscreen mode Exit fullscreen mode

Los estados found, pending, expired y invalid son más útiles que devolver texto libre. Sin este contrato, el agente puede confundir “no hay mensajes” con “la aplicación falló”, o volver a intentar una operación que ya fue completada.

Separar decisión del agente y evidencia externa

El agente LLM debería controlar el plan: crear identidad, iniciar el flujo, pedir una lectura y evaluar la evidencia. No debería construir consultas arbitrarias contra la bandeja ni decidir que un mensaje parecido es suficiente.

Una separación razonable se ve así:

  1. El sistema crea una identidad de prueba y asigna un run_id.
  2. La aplicación emite el evento de verificación con esa correlación.
  3. El adaptador consulta únicamente la bandeja asociada al mailbox_id.
  4. El adaptador normaliza el resultado y redacta tokens.
  5. El agente evalúa el contrato y elige continuar, esperar o fallar.

Este diseño reduce el espacio de decisiones. También hace más simple revisar los logs: se puede ver qué recibió el adaptador y qué decisión tomó el agente, sin guardar el cuerpo completo del mensaje.

La identidad visual también importa. Un formulario accesible facilita que una prueba automatizada distinga entre error de validación y estado de confirmación; un signup accesible para pruebas reales ofrece un buen punto de comparación para ese tipo de flujo.

Reintentos, aislamiento y trazabilidad

Los emails llegan tarde, pero un retry ciego empeora el diagnóstico. Cada intento debe conservar el mismo run_id y registrar una razón: pending_delivery, provider_timeout o invalid_message. No conviene crear una nueva cuenta en cada intento, porque así la prueba deja de medir el flujo original.

El aislamiento tiene tres capas:

  • Identidad: una cuenta de prueba por ejecución o por worker.
  • Bandeja: un recurso que no se comparte entre ejecuciones paralelas.
  • Evidencia: un artefacto con datos redactados y una vida limitada.

Una bandeja de prueba puede llamarse tepm mail com o tamp mail com en un fixture antiguo, pero esos nombres ambiguos no deben definir la lógica del sistema. Los alias confunden al agente y al humano que mantiene el repositorio; es más mejor usar nombres que expresen el nivel de aislamiento.

Cuando el proveedor falla, el agente debe terminar con una causa clara. Cuando el mensaje llega, debe validar destinatario, correlación, entorno y propósito. El enlace puede ser válido y aun así pertenecer a otra ejecución.

Checklist de implementación

  • Asigna un run_id antes de crear la cuenta.
  • Relaciona identidad, evento y bandeja mediante ese ID.
  • Expone estados estructurados al agente, no solo texto de la UI.
  • Define un timeout y un número de reintentos explícito.
  • Redacta tokens, códigos y URLs sensibles en los artefactos.
  • Comprueba destinatario, asunto, correlación y entorno.
  • Conserva un recibo pequeño de cada decisión del agente.
  • Elimina o expira la identidad después de la prueba, sin depender del cleanup para declarar el resultado.

El contrato no tiene que ser grande. Debe ser suficiente para que otro proceso pueda reconstruir qué se esperaba, qué se observó y por qué el agente continuó o falló. Esa trazabilidad vale más que una instrucción muy larga en el prompt.

Preguntas frecuentes

¿Un agente LLM puede leer directamente la bandeja?

Puede, pero no es la opción más robusta. Un adaptador con permisos limitados y salida estructurada reduce errores de interpretación y facilita la auditoría.

¿Debo crear una bandeja nueva en cada reintento?

Normalmente no. Mantén la misma ejecución y cambia solo la operación de lectura. Crea una nueva identidad únicamente si el contrato define que la ejecución anterior quedó irrecuperable.

¿Qué hago con un mensaje que tiene el asunto correcto?

No lo aceptes todavía. Valida también destinatario, correlación, timestamp razonable y dominio del entorno. Un asunto correcto por sí solo es evidencia muy débil.

¿Dónde encaja la automatización?

En el orquestador: debe preparar recursos, invocar el adaptador y guardar el recibo. El modelo puede decidir el siguiente paso, pero las reglas de seguridad y expiración deben permanecer en código determinista.

Con ese límite, los modelos LLM aportan flexibilidad para diagnosticar estados, mientras que el contrato conserva las propiedades que una prueba necesita: repetibilidad, aislamiento y una explicación verificable.

Top comments (0)