Tu pipeline de agentes falla en cascada. Sin aviso.
Desplegaste el pipeline hace tres días. Todo aparece verde en los logs. Esta mañana un cliente te llama: los datos de 47 registros están mal.
Revisas los logs de nuevo. No hubo ninguna excepción. Ningún timeout. Ningún error visible. El Agente 1 pasó un JSON con un campo vacío al Agente 2. El Agente 2 lo procesó tal cual. El Agente 3 también. Y el Agente 4 escribió ese JSON corrupto en la base de datos, convencido de que estaba haciendo exactamente lo que debía hacer.
Esto es un fallo en cascada en un pipeline de agentes IA. Y es el tipo de error más difícil de detectar en producción porque nunca lanza una excepción — simplemente propaga silencio.
Por qué los pipelines de agentes fallan de forma diferente a un monolito
En un sistema monolítico clásico, un error es local. Si una función falla, lanza una excepción, el stack trace te dice exactamente dónde y por qué. El daño está contenido en ese punto.
En un pipeline multi-agente, la arquitectura cambia radicalmente la naturaleza del fallo. Cada agente es un proceso independiente que confía en el output del agente anterior. Si el Agente 1 devuelve algo estructuralmente válido pero semánticamente incorrecto — un JSON con el campo correcto pero un valor vacío —, el Agente 2 no tiene forma de detectarlo. Procesa lo que recibe. Lo mismo el Agente 3. El Agente 4 escribe en base de datos.
Resultado: un error pequeño en el nodo 1 se convierte en corrupción de datos en el nodo 4, sin que ningún sistema de alertas se haya disparado.
Esto se vuelve especialmente grave cuando los agentes tienen acceso a herramientas de escritura: bases de datos, APIs externas, sistemas de email, CRMs. Una sola entrada incorrecta puede generar decenas de registros erróneos antes de que alguien lo detecte — normalmente porque un cliente llama.
Patrón 1: Validación de schema en cada frontera de agente
El primer patrón defensivo es tratar cada transición entre agentes como si fuera una frontera de sistema externa. Igual que validamos los inputs de una API REST antes de procesarlos, hay que validar lo que entra en cada agente.
import { z } from "zod";
const CustomerSchema = z.object({
id: z.string().uuid(),
email: z.string().email(),
plan: z.enum(["free", "pro", "enterprise"]),
metadata: z.record(z.string()).optional(),
});
type Customer = z.infer<typeof CustomerSchema>;
async function agente2EnrichCustomer(raw: unknown): Promise<EnrichedCustomer> {
// Validar ANTES de procesar — nunca confiar en el agente anterior
const customer = CustomerSchema.parse(raw);
// Si parse() lanza, el error se captura aquí, no 2 nodos después
return await enrichFromCRM(customer);
}
Con Zod (o cualquier librería de validación de schemas), si el Agente 1 devuelve un campo vacío donde se espera un UUID, el error se lanza exactamente en el punto de transición, con un stack trace que apunta directamente al problema — no 3 nodos después cuando el daño ya está hecho.
Esta validación parece obvia. Está ausente en la mayoría de los pipelines que auditamos. La justificación siempre es la misma: "el agente anterior ya valida eso". No. Cada agente debe asumir que su input puede estar corrupto.
Patrón 2: Dead letter queue para mensajes fallidos
La validación captura el error en el punto de transición, pero ¿qué haces con el mensaje fallido? Si simplemente lanzas una excepción y detienes el pipeline, los mensajes que venían detrás también se bloquean.
El patrón correcto es una dead letter queue (DLQ): una cola separada donde van los mensajes que no pudieron procesarse, sin bloquear el flujo principal.
type PipelineMessage = {
id: string;
payload: unknown;
attempts: number;
lastError?: string;
};
async function processWithDLQ(
message: PipelineMessage,
processor: (payload: unknown) => Promise<void>,
dlqWriter: (msg: PipelineMessage, err: Error) => Promise<void>
): Promise<void> {
try {
await processor(message.payload);
} catch (error) {
const err = error instanceof Error ? error : new Error(String(error));
if (message.attempts >= 3) {
// Tras 3 intentos, va a la DLQ para revisión manual
await dlqWriter({ ...message, lastError: err.message }, err);
} else {
// Reintento con backoff exponencial
await scheduleRetry({ ...message, attempts: message.attempts + 1 });
}
}
}
Con este patrón, los mensajes problemáticos se aparcan en la DLQ sin bloquear el flujo. El equipo puede inspeccionar qué falló, corregir el mensaje y reintroducirlo si es necesario.
Si usas Supabase como base de datos en tu proyecto de integración IA, una tabla agent_dlq con los campos payload, error, created_at y resolved_at te da un registro completo de todos los fallos sin infraestructura adicional.
Patrón 3: Compensación de estado para acciones irreversibles
Los dos patrones anteriores evitan que el error se propague. Pero ¿qué pasa con lo que ya se ejecutó antes de que se detectara el fallo?
En transacciones de base de datos clásicas, puedes hacer rollback. En pipelines de agentes que interactúan con sistemas externos — envían emails, llaman a APIs de terceros, modifican CRMs —, no hay rollback posible. El email ya salió. El pedido ya se creó en el sistema del proveedor.
La solución es el patrón de compensación: en lugar de deshacer, ejecutar acciones opuestas explícitas para cada paso que se completó antes del fallo.
type PipelineStep = {
execute: () => Promise<void>;
compensate: () => Promise<void>; // acción opuesta si falla un paso posterior
};
async function executePipelineWithCompensation(
steps: PipelineStep[]
): Promise<void> {
const executed: PipelineStep[] = [];
try {
for (const step of steps) {
await step.execute();
executed.push(step);
}
} catch (error) {
// Ejecutar compensaciones en orden inverso
for (const completedStep of [...executed].reverse()) {
await completedStep.compensate().catch(console.error);
}
throw error;
}
}
Este patrón no es complejo de entender, pero es muy costoso de implementar bien a posteriori. Cada step necesita tener su compensación definida desde el diseño inicial. Añadido como afterthought, suele quedar incompleto — exactamente el escenario donde los fallos en cascada hacen más daño porque los sistemas externos ya tienen el estado incorrecto.
Lo que cuesta construir esto cuando el sistema ya está en producción
Los tres patrones son fáciles de entender. Son difíciles de añadir a un pipeline que ya procesa mensajes reales.
Encajar validación de schema en un pipeline existente sin romper los contratos entre agentes lleva entre 2 y 4 semanas de trabajo especializado. Añadir una DLQ con retry logic y las dashboards necesarias para operarla: otras 2 semanas. El patrón de compensación, dependiendo de cuántos sistemas externos toca el pipeline, puede extenderse a un mes completo.
En DAILYMP diseñamos pipelines de agentes IA con estos patrones desde el inicio — no como hardening posterior, sino como parte de la arquitectura base. El motivo es práctico: construirlo bien desde el principio cuesta 5 veces menos que remediarlo cuando el cliente ya llamó y los datos ya están corruptos.
Si tienes un pipeline de agentes en producción y no sabes exactamente cómo se comporta cuando un nodo falla, esa es la pregunta correcta que hacerse antes de escalar el sistema.
El fallo silencioso es el más caro
Un error que lanza una excepción es fácil de resolver. Un error que procesa datos incorrectos en silencio durante 72 horas cuesta la confianza de un cliente y semanas de trabajo correctivo.
Los pipelines de agentes IA no se gestionan igual que los sistemas tradicionales. Los contratos de validación entre nodos, las colas de mensajes fallidos y los patrones de compensación no son optimizaciones: son la diferencia entre un sistema que escala y uno que falla en producción sin avisarte.