Cuando un agente con IA empieza a enviar correos, mucha gente mira primero el prompt. Yo casi nunca empiezo ahi. En equipos que trabajan con LLMs y automatización, el punto frágil suele estar en el contrato entre la decisión del agente, la herramienta que ejecuta la acción y la forma en que verificas el resultado. Si ese borde queda borroso, el sistema parece listo en demo pero luego falla de formas muy poco elegantes.
El patrón que más me funciona es pensar el flujo como un diagrama en palabras: evento de negocio, reducción determinista de contexto, decisión del agente, comando normalizado, envío de correo y verificación final. No suena muy sexy, pero sí evita bastante dolor operativo.
El contrato entre agente y herramienta manda
El error común es dejar que el agente describa libremente qué correo quiere mandar y confiar en que la herramienta "entenderá". Ese enfoque produce integraciones fragiles. Un LLM puede devolver una intención razonable, pero la infraestructura necesita campos concretos: plantilla, destinatario, alcance, ventana de tiempo, idempotencia y trace_id.
Yo prefiero limitar la salida del agente a acciones permitidas. Algo como send_review_request o send_retry_notice. Después, un ejecutor determinista arma el comando final. Esa separación parece un paso extra, pero hace que el sistema sea mucho más facil de operar y tambien más facil de probar.
Un esquema minimo que suelo pedir incluye:
action_typerecipient_scopetemplate_versiontrace_id
Si falta uno de esos campos, la investigación posterior se vuelve rara. El equipo empiesa a discutir si "falló el modelo" cuando en realidad faltaba contexto o habia un mapeo medio roto.
Un flujo verificable para correos disparados por IA
La mejor versión de este sistema no intenta probarlo todo en una sola capa. Lo divide:
- El backend reduce el evento a datos seguros.
- El agente elige una acción dentro de un esquema fijo.
- La herramienta valida permisos y campos requeridos.
- El servicio de correo registra el envío con el mismo
trace_id. - La prueba end to end abre una bandeja aislada y valida contenido, destinatario y efecto final.
Ese diseño hereda una idea util de probar emails de referidos en tu SaaS: la evidencia debe quedar separada por escenario, no mezclada en una bandeja comun. Cuando dos flujos comparten inbox, los asserts terminan siendo blandos y el debugging se vuelve lentisimo.
En una herramienta de ejecución, el código puede ser bastante corto:
def execute_agent_action(action, trace_id):
if action["type"] != "send_review_request":
return {"ok": False, "reason": "unsupported"}
command = {
"template": "review_request_v3",
"recipient": action["recipient"],
"trace_id": trace_id,
}
return send_email(command)
Lo importante no es Python, Node o Go. Lo importante es que el comando final quede cerrado antes de tocar la infraestructura de email. Así tu prueba describe el contrato, no un detalle accidental del proveedor. Incluso si el equipo usa un generador de cuentas de correo temporal para revisar mensajes en staging, ese componente debería ser solo una ayuda de validación, no el centro del diseño.
También conviene nombrar bien las cosas. En varios equipos vi texto heredado como dummy e mail en tickets, seeds o variables. No es grave, pero sí señala que el flujo creció con parches. Cuando eso pasa, revisar nombres y contratos suele dar una mejora bastante real, aunqe no sea la parte más vistosa del roadmap.
Qué medir cuando falla el email
Cuando una prueba falla, yo busco cuatro evidencias en orden:
- La decisión original del agente.
- El comando normalizado que produjo la herramienta.
- El mensaje que llegó a la bandeja aislada.
- El efecto final tras abrir el enlace o aceptar la acción.
Si una de esas cuatro piezas no existe, el equipo empieza a adivinar. Y adivinar en Automation sale caro. También ayuda mucho registrar estados pequeños y legibles. Esto se parece bastante a depurar reintentos de correo en FastAPI: no necesitas miles de líneas de logs si puedes ver una secuencia corta como "acción aceptada", "correo emitido", "mensaje recibido" y "enlace validado".
Hay un dato util para justificar esta disciplina: el informe 2024 de Accelerate encontró que la calidad de entrega mejora cuando los equipos reducen handoffs ambiguos y aumentan la observabilidad de flujo, no solo la velocidad bruta de release source. No habla de agentes de correo en específico, pero el principio encaja bastante bien.
Tradeoffs para equipos pequeños
Este enfoque agrega estructura. Hay ids, validaciones, estados y una capa extra entre el agente y el envío. A cambio ganas algo muy valioso: explicar por qué un correo salió, por qué no salió y qué componente tomó cada decisión. Para equipos pequeños, esa claridad vale mucho más que una demo impresionanate.
Los tradeoffs que suelo ver son estos:
- Menos libertad del agente, pero mejor auditabilidad.
- Más pasos de integración, pero menos debugging raro.
- Pruebas un poco más lentas, pero mucha mejor señal.
- Menos "magia", pero un sistema que sí se deja mantener.
Mi checklist corto:
- Cada ejecución tiene
trace_idúnico. - El agente solo pide acciones dentro de un esquema válido.
- La herramienta revalida destinatario, plantilla y contexto.
- Cada escenario usa su propia bandeja.
- El assert final revisa efecto de negocio, no solo "email enviado".
No hace falta una plataforma enorme. Hace falta disciplina de contratos, y un poco de paciencia para no mezclar inteligencia probabilística con partes que deberían ser aburridas. Suena simple, pero aveces eso es justo lo que salva una semana fea.
Preguntas frecuentes
¿Debo dejar que el LLM redacte el correo completo?
Solo si el riesgo es bajo. Para mensajes sensibles, prefiero plantillas controladas y que el modelo rellene campos o bloques acotados.
¿Qué reviso primero si el usuario recibió el correo equivocado?
Compara la acción propuesta por el agente con el comando final del ejecutor. Ese salto concentra muchisimos errores silenciosos.
¿Necesito pruebas reales si ya tengo unit tests del agente?
Sí. Los unit tests te dicen si la lógica local parece correcta. No te dicen si el sistema completo mantiene el contrato hasta el inbox y el estado final.
Top comments (0)