Cuando tu agente falla a mitad: el patrón Saga
Tu agente de pedidos funciona. Ejecuta tres pasos en secuencia: actualiza el estado en el CRM, crea la factura en el sistema de billing, y envía el email de confirmación al cliente. Nueve de cada diez veces, perfecto.
El décimo falla al enviar el email. El servidor SMTP de tu proveedor devuelve un 503.
El CRM ahora muestra la orden como "confirmada". La factura existe en el sistema de billing. El cliente no ha recibido nada. Tres sistemas con estados que no se corresponden entre sí — y ningún error visible en los logs del agente.
Este es el problema de las transacciones distribuidas en agentes IA, y ocurre en producción antes de lo que esperas.
Por qué los agentes crean problemas de consistencia
En una base de datos relacional, tienes BEGIN TRANSACTION y ROLLBACK. Si algo falla, todo vuelve al estado anterior. Los agentes IA no tienen nada de eso.
Cada tool call es una operación independiente contra un sistema externo. El CRM tiene su API. El sistema de billing tiene la suya. El SMTP también. Cuando el agente ejecuta estos pasos en secuencia, no hay ningún mecanismo nativo que deshaga los anteriores si el último falla.
El patrón más común que ves en equipos que implementan agentes por primera vez:
// Lo que muchos equipos hacen — y lo que falla en producción
async function processOrder(orderId: string) {
await crmTool.updateStatus(orderId, "confirmed"); // paso 1
await billingTool.createInvoice(orderId); // paso 2
await emailTool.sendConfirmation(orderId); // paso 3 → falla
// Si paso 3 falla, pasos 1 y 2 ya están escritos en sistemas externos
}
El error se captura, se loggea, quizás se reintenta. Pero nadie deshace los pasos anteriores.
El patrón Saga: compensaciones explícitas
El patrón Saga viene de los sistemas distribuidos. La idea es simple: cada paso que puede escribir datos también define una operación de compensación que deshace ese efecto.
No es un rollback automático. Es una función que tú defines por cada paso: "si algo falla después de mí, ejecuta esto para volver al estado anterior".
La estructura básica en TypeScript:
type SagaStep<T> = {
execute: () => Promise<T>;
compensate: () => Promise<void>;
description: string;
};
async function runSaga<T>(steps: SagaStep<T>[]): Promise<T[]> {
const executed: SagaStep<T>[] = [];
const results: T[] = [];
for (const step of steps) {
try {
const result = await step.execute();
results.push(result);
executed.push(step);
} catch (err) {
// Ejecutar compensaciones en orden inverso
for (const done of [...executed].reverse()) {
try {
await done.compensate();
} catch (compErr) {
// Loggear fallo de compensación — necesita atención humana
console.error(`Compensation failed for: ${done.description}`, compErr);
}
}
throw err; // Propagar el error original
}
}
return results;
}
Aplicado al caso de la orden
Con este patrón, cada paso del agente queda así:
const orderSaga: SagaStep<unknown>[] = [
{
description: "CRM: update order status",
execute: () => crmTool.updateStatus(orderId, "confirmed"),
compensate: () => crmTool.updateStatus(orderId, "pending"),
},
{
description: "Billing: create invoice",
execute: () => billingTool.createInvoice(orderId),
compensate: () => billingTool.cancelInvoice(orderId),
},
{
description: "Email: send confirmation",
execute: () => emailTool.sendConfirmation(orderId),
compensate: async () => {
// El email ya enviado no se puede reenviar,
// pero si no se envió, no hay nada que compensar
},
},
];
try {
await runSaga(orderSaga);
} catch (err) {
// Las compensaciones ya se ejecutaron automáticamente
// El sistema queda en estado consistente
await alertingTool.notifyOps(orderId, err);
}
Si el paso del email falla, runSaga ejecuta automáticamente billingTool.cancelInvoice() y luego crmTool.updateStatus(orderId, "pending"). Los tres sistemas vuelven al estado anterior.
Lo que muchos equipos ignoran: compensaciones idempotentes
Una trampa habitual: las compensaciones también pueden fallar. Si cancelInvoice falla porque el sistema de billing está caído, tienes el problema original más uno nuevo.
Dos reglas para compensaciones robustas:
Idempotencia obligatoria. Ejecutar cancelInvoice(orderId) dos veces debe producir el mismo resultado que ejecutarla una vez. Usa IDs de operación únicos y verifica el estado antes de actuar:
compensate: async () => {
const invoice = await billingTool.getInvoice(orderId);
if (invoice.status !== "cancelled") {
await billingTool.cancelInvoice(orderId);
}
// Si ya está cancelada, no hacer nada — idempotente
},
Log de compensaciones fallidas. Cuando una compensación falla, el sistema necesita intervención humana. Ese log es el rastro de auditoría que permite resolver el problema manualmente. Sin él, el incidente es invisible.
El servicio de observabilidad para agentes IA incluye este tipo de registro de compensaciones como parte del contrato de producción.
Cuándo aplicar el patrón Saga
No todos los agentes lo necesitan. Aplica Saga cuando:
- El agente escribe en más de un sistema externo en una misma ejecución
- Los pasos no son reversibles de forma natural (una factura creada, un email enviado)
- El estado inconsistente tiene consecuencias reales: el cliente cobra dos veces, el operador ve datos erróneos, el inventario se descuadra
Si tu agente solo lee datos, o solo escribe en un sistema, puedes omitirlo sin problema.
El error que cuesta más caro
Los equipos que llegan con este problema llevaban semanas notando "anomalías" en los datos: órdenes confirmadas sin factura, facturas sin orden asociada, clientes que llaman preguntando por confirmaciones que nunca llegaron.
El fallo original lleva días o semanas sin detectarse porque el agente no lanza ningún error visible. Los datos inconsistentes se acumulan en silencio hasta que alguien los cruza manualmente.
Implementar Saga al principio cuesta dos o tres horas. Implementarlo después de un incidente de datos cuesta semanas de limpieza manual y revisión de historiales.
Si estás construyendo un agente que toca varios sistemas de tu empresa y quieres una arquitectura que no genere deuda técnica desde el día uno, hablemos directamente.
También puedes ver cómo está estructurado el servicio de integración IA en empresas — el patrón Saga es parte del diseño base para cualquier agente que opere sobre sistemas de producción.