Cuando un flujo con agentes mezcla planificacion, aprobacion y ejecucion en la misma bandeja, depurarlo se vuelve raro muy rapido. El correo llega, si, pero ya no queda claro que etapa emitio el mensaje ni que worker debe retomarlo. En varios pipelines internos he visto que el problema no era el prompt ni el modelo; era la topologia de notificaciones, que quedaba demasiado plana para un sistema con estados distintos.
Mi regla ahora es simple: un inbox por etapa critica. No significa una direccion por cada microservicio. Significa separar los puntos donde una persona o un worker toman decisiones distintas. Parece un detalle pequeno, pero evita bastante confucion cuando toca revisar runs horas despues.
El problema aparece cuando todo cae en una sola bandeja
Piensalo como un diagrama en palabras:
- Un agente prepara el plan.
- Otro proceso redacta el mensaje de aprobacion.
- Un cron espera la respuesta.
- Un worker retoma la ejecucion.
Si esas cuatro piezas usan el mismo destino, empiezan tres fallos comunes:
- el asunto ya no dice mucho;
- los replies correctos se mezclan con pruebas viejas;
- el operador no sabe si mira evidencia de plan, de retry o de entrega.
En LLMs eso duele mas porque los pasos suelen ser asincronos y reanudables. Una cola puede esperar 10 minutos o 10 horas, y mientras tanto entran mensajes de otros runs. El sistema sigue "funcionando", pero el costo de entenderlo sube un monton. Es el tipo de deuda que no rompe hoy, aunque luego castiga feo.
Algo parecido se nota cuando en Kubernetes diseñas correos utiles en cambios de red: si no separas bien la causa, el cambio y el impacto, el correo existe pero orienta poco.
Un inbox por etapa reduce ambiguedad
Yo suelo dividir el flujo en tres bandejas logicas:
-
plan@...para borradores, manifiestos y aprobaciones. -
exec@...para confirmaciones de ejecucion y errores terminales. -
qa@...para pruebas de rendering, parsing y latencia.
No siempre son tres cuentas reales. A veces basta con aliases o rutas distintas dentro del provider. Lo importante es que cada inbox responda una pregunta concreta:
-
plan@...: que se aprobo? -
exec@...: que corrio de verdad? -
qa@...: que estabamos probando?
Ese corte hace que el operador lea menos contexto implicito. Tambien simplifica la automatizacion, porque el worker ya no necesita adivinar intenciones a partir de un hilo larguisimo. Queda mas aburrido, y eso aca es bueno.
Como mapear etapas, workers y asuntos
El patron que mejor me ha servido es este:
type Stage = "plan" | "exec" | "qa";
function routeInbox(stage: Stage) {
const map = {
plan: "plan@example.com",
exec: "exec@example.com",
qa: "qa@example.com",
};
return map[stage];
}
Y despues fijo el asunto con tres piezas estables:
run_id- nombre de la etapa
- accion esperada
Ejemplo:
[run 20260817T082222Z] plan -> aprobar articulo
No es glamoroso, pero vuelve trivial filtrar, agrupar y reenviar. Si ademas guardas el run_id dentro del cuerpo y en el artefacto congelado, el reanudador puede validar que esta leyendo el hilo correcto antes de actuar.
Donde mas se nota la mejora es en los retries. Si una respuesta tarda, no quieres que el worker lea accidentalmente un mensaje de QA o una aprobacion anterior. Separar bandejas reduce esa superficie sin meter una capa exotica. Para backend, este tipo de recorte se parece bastante a depurar reintentos de correo sin ruido: menos ambiguedad, menos ramas raras, menos tiempo perdido.
Donde si encaja un correo temporal
Un correo temporal o un dummy e mail tiene sentido en la etapa de QA, no en aprobacion real. Lo uso para tres cosas:
- probar rendering en distintos clientes;
- medir cuanto tarda en llegar un mensaje;
- verificar que el parser de replies aguanta variaciones normales.
Si un tester quiere disparar diez corridas seguidas con un temp mailid, perfecto. Ahi ganas velocidad y no contaminas bandejas de operacion. Pero yo no mezclaria ese entorno con aprobaciones humanas reales ni con evidencia de auditoria. El tradeoff es clarito: ganas friccion baja, pierdes historial estable.
Tambien conviene recordar que las bandejas temporales sirven para laboratorio, no para identidad. Si tu run depende de saber exactamente quien aprobo y cuando, necesitas una ruta mas fuerte que un inbox efimero. Parece obvio, pero aveces se olvida cuando el sistema crece rapido.
Checklist para montarlo sin sobreingenieria
Si tuviera que implementarlo esta semana, haria esto:
- Definir solo tres etapas visibles: plan, exec y qa.
- Derivar alias o rutas por etapa en vez de crear cuentas nuevas primero.
- Incluir
run_idy etapa en asunto y cuerpo. - Rechazar replies que lleguen al inbox equivocado.
- Guardar el inbox objetivo dentro de
plan.jsono del manifiesto. - Medir cuantas veces un retry toca un hilo que no corresponde.
Con eso ya puedes ver si el problema era real antes de invertir mas. Si el flujo sigue siendo pequeno, probablemente no necesitas nada mas. Si el volumen sube, luego puedes sumar TTL por hilo, recibos firmados o colas separadas. La clave es no empezar por la version heroica del sistema.
Preguntas frecuentes
Esto no multiplica demasiado la complejidad?
Un poco, pero la complejidad cambia de lugar. Quitas complejidad interpretativa del operador y la pones en reglas de ruteo bastante simples. Para mi, es un cambio sano.
Hace falta una cuenta por etapa?
No. Muchas veces con aliases basta. Lo importante no es la infraestructura exacta, sino que cada mensaje tenga un destino coherente con la accion que dispara.
Sirve solo para articulos o tambien para otros cron jobs?
Sirve para casi cualquier Automation con pausas humanas: aprobaciones, QA, tareas de soporte y workers que reanudan horas despues. Si el flujo tiene etapas con decisiones distintas, separar inboxes suele ayudar mas de lo que parece.
Mi conclusion es corta: si un sistema de agentes necesita que alguien relea correos para entender que paso, la topologia de inboxes probablemente esta pidiendo un rediseño pequeno. No muy sexy, pero muy rentable.
Top comments (0)