Máquina de estados IA: así se evitan pagos duplicados

En pocas palabras: Una máquina de estados IA reemplaza el bucle de prompts en memoria por un esquema persistente en base de datos: cada paso queda registrado antes de ejecutar acciones externas. Con outbox transaccional y claves de idempotencia derivadas del workflow_id, step_index y payload, un reintento de red nunca duplica una acción, como el pago doble de USD 42.000 que sufrió un agente de procurement, según el caso relatado por DusynBlog.

Un agente de procurement construido como bucle de prompts en memoria pagó dos veces una factura de USD 42.000 tras un timeout de red a las 2:17 AM, según relata DusynBlog en su análisis publicado el 29 de septiembre de 2026. El caso expone por qué una máquina de estados IA con outbox transaccional y claves de idempotencia evita que un reintento de red se convierta en una acción duplicada.

Una máquina de estados IA es un patrón de arquitectura que reemplaza el bucle de prompts en memoria (while loop más array de chat) por un esquema de estados persistente en base de datos. Cada paso del agente queda registrado de forma durable antes de ejecutar una acción externa, así el sistema sabe siempre en qué punto exacto quedó, aunque el proceso se caiga a mitad de camino.

En 30 segundos

  • Un agente de procurement pagó USD 42.000 dos veces por un timeout de red y un reintento sin control de estado, según el caso relatado por DusynBlog.
  • El análisis identifica tres fallos: saturación de recursos sin límites, presión en cascada por dependencias bloqueantes e inconsistencia de estado durante particiones de red.
  • La solución propuesta es una máquina de estados IA con patrón outbox transaccional y claves de idempotencia derivadas por SHA-256.
  • El código de ejemplo usa PostgreSQL con ON CONFLICT (idempotency_key) DO NOTHING para bloquear duplicados a nivel base de datos.
  • No hay benchmarks públicos verificables por terceros: los datos de rendimiento provienen únicamente del propio blog de Dusyn.

¿Qué pasó con el agente de IA que pagó dos veces una factura de USD 42.000?

A las 2:17 AM, un agente de procurement autónomo intentó pagar la factura de un proveedor. Un timeout de red cortó la conexión entre el worker del agente y el gateway bancario downstream, y ahí empezó el problema real.

El agente estaba construido como un while loop simple que agregaba mensajes a un array de chat en memoria, según describe el resumen técnico publicado en dev.to. Cuando el proceso se reinició tras el corte, no encontró ninguna confirmación en su contexto inmediato y volvió a ejecutar el tool de transferencia. La empresa terminó pagando USD 42.000 dos veces.

Ojo con esto: la fuente presenta el caso como ejemplo narrativo para introducir el problema arquitectónico, no como un hecho verificado por auditoría externa, medio periodístico o regulador. No hay nombre de empresa, país ni número de expediente. Tomalo como caso de estudio ilustrativo, no como noticia confirmada por terceros (que sería otra cosa completamente distinta).

¿Por qué un bucle de prompts en memoria no alcanza en producción?

Un bucle de prompts en memoria no alcanza en producción porque pierde todo el estado cuando el proceso se reinicia, y el agente queda sin forma de saber si una acción ya se ejecutó antes del corte de red.

Subís el agente, funciona perfecto en la demo de cinco minutos, el modelo llama a una herramienta, el resultado se agrega al array de mensajes, todo bien, hasta que el contenedor se recicla a mitad de un pago, el array desaparece con la memoria RAM y el próximo worker arranca sin ninguna pista de qué pasó antes. Esto se conecta con lo que analizamos en la evolución de los agentes autónomos de Meta.

El problema tiene nombre técnico según el artículo completo de DusynBlog: contaminación de contexto del prompt (payloads de herramientas y JSON verbosos que consumen el presupuesto de atención del modelo) y alucinaciones de razonamiento sobre replay, donde el modelo asume que un paso ya se completó porque figuraba mencionado en un mensaje viejo.

El caso típico es la dormancia. Un agente de aprobación de facturas puede tardar cuatro segundos en calcular totales y esperar setenta y dos horas a que un gerente apruebe las líneas. Un coordinador de onboarding de RRHH se queda parado cinco días hábiles esperando que alguien firme documentos impositivos. Mantener un proceso activo o un socket bloqueado durante esa espera es plata tirada, y encima garantiza pérdida de datos cuando el contenedor se recicla.

¿Qué tres fallos arquitectónicos identifica el análisis de DusynBlog sobre la máquina de estados IA?

DusynBlog identifica tres modos de falla crónicos en las configuraciones estándar de agentes: saturación de recursos sin límite, presión en cascada hacia servicios downstream e inconsistencia de estado durante particiones de red.

  • Saturación de recursos sin límite: colas y buffers sin techo que consumen heap desproporcionado, provocando pausas de garbage collection o kills por Out-Of-Memory del kernel.
  • Presión en cascada hacia downstream: dependencias bloqueantes sin backpressure, donde un pico transitorio de latencia escala hasta tirar abajo el cluster entero.
  • Inconsistencia de estado bajo partición: mutaciones de estado divergentes durante fallas de red o failover de nodos, que después exigen reconciliaciones de consenso caras.

La fuente compara esto contra lo que llama su propuesta “optimizada” en una tabla. Vale aclarar: son cifras y calificativos del propio blog de Dusyn, no un benchmark independiente.

Vector del sistemaConfiguración estándarPropuesta de Dusyn
Asignación de memoriaHeap dinámicoRing buffers pre-asignados
Mutación de estadoLock síncrono 2PCQuorum log event-driven
BackpressureCola infinita en memoriaDropping reactivo con backoff exponencial
Telemetría de ingresoPolling periódicoTracing eBPF a nivel kernel

¿Qué límites y trade-offs tiene reemplazar el bucle por una máquina de estados?

Reemplazar el bucle por una máquina de estados cambia RAM fija por latencia estable, y agrega complejidad operativa a cambio de mayor tolerancia a particiones de red.

Los ring buffers pre-asignados eliminan pausas de garbage collection, pero exigen fijar de antemano cuánta memoria vas a reservar. Si calculás mal ese límite, el sistema empieza a rechazar tareas en vez de degradarse con gracia. El quorum log event-driven da más throughput y tolerancia a particiones que un lock síncrono 2PC, pero un log de eventos distribuido no se debuggea igual que una transacción clásica: necesitás instrumentar percentiles p99 y p99.9, no promedios, porque el promedio esconde justo los casos que te van a explotar en producción. Tema relacionado: repartir modelos grandes entre varias máquinas.

¿Alguien corrió estos números en un entorno de producción real con tráfico verificable por terceros? No, según lo que muestran las dos fuentes disponibles. Todo el material de rendimiento (la tabla comparativa, los porcentajes de reducción de costo) sale del propio blog de Dusyn, sin auditoría externa ni paper revisado por pares. Tomalo como propuesta de arquitectura razonada, no como benchmark validado.

¿Cómo evitar acciones duplicadas en agentes de IA en producción?

Para evitar acciones duplicadas en agentes de IA hay que separar la decisión del modelo de la ejecución real, usando una transacción atómica que registre la intención de la herramienta antes de llamarla, con una clave de idempotencia determinística.

El patrón que muestra DusynBlog funciona en TypeScript con PostgreSQL. Cuando el modelo emite un tool call, el motor hace un BEGIN, actualiza la tabla agent_workflows con el nuevo estado, inserta la fila en agent_tool_outbox con status PENDING y hace COMMIT. La clave de idempotencia se calcula con SHA-256 sobre la tupla workflow_id, step_index, tool_name y el JSON ordenado del payload. La cláusula ON CONFLICT (idempotency_key) DO NOTHING hace que un reintento con la misma clave no inserte una fila nueva.

El punto clave: nunca generés un UUID random en el momento del retry. Si generás una clave nueva cada vez, el sistema downstream (Stripe, Twilio, o el gateway bancario interno del ejemplo) ve una operación “nueva” y la procesa de nuevo, exactamente el bug que causó el pago duplicado de USD 42.000. La clave tiene que salir siempre del mismo hash, para la misma operación, sin importar cuántas veces se reintente.

Los tenets de producción que propone la fuente para senior engineers:

  • Fijar techos estáticos de recursos: nunca dejar que colas o pools de conexión crezcan sin límite; setear topes en el arranque.
  • Medir p99 y p99.9, no promedio: la latencia promedio esconde los outliers patológicos que rompen el SLO.
  • Automatizar inyección de fallos: probar particiones de red, timeouts de socket y caída de nodos en staging antes de que pasen solos en producción.
  • Separar ingreso de persistencia: desacoplar el camino rápido de consulta del camino lento de escritura en disco.
  • Cero mocks en verificación: validar contratos de límites contra contenedores de integración reales, no solo con mocks de unit test.

Qué significa esto para empresas y equipos en Latinoamérica

Si en tu equipo están armando un agente que dispare pagos, tickets de soporte o provisioning de infraestructura, el caso de los USD 42.000 aplica igual en pesos, reales o dólares: un reintento sin idempotencia rompe cualquier moneda. Fintechs y logísticas que integran agentes con pasarelas de pago o sistemas de facturación electrónica en Argentina, Chile o México deberían auditar si sus tools críticos tienen alguna capa de outbox antes de dejarlos tocar dinero real.

Si vas a montar la base de datos Postgres que soporta este patrón (la tabla agent_workflows, el outbox, los workers que la consultan), necesitás un VPS o servicio cloud con latencia estable hacia tus integraciones bancarias locales. Para infraestructura y dominios en la región, donweb.com es una opción a evaluar si buscás soporte en español y datacenter cercano.

Qué está confirmado y qué no sobre este patrón de arquitectura

Está confirmado, porque figura tal cual en ambas fuentes, el patrón de código (outbox transaccional, hash SHA-256 para idempotencia, header Idempotency-Key compatible con Stripe y Twilio) y los seis estados del ciclo de vida propuesto (INITIALIZED, REASONING, OUTBOX_PENDING, SUSPENDED_HUMAN_GATE, TOOL_DISPATCHED, STATE_HYDRATED). Relacionado: los límites entre estado y conciencia artificial.

No está confirmado, porque no hay fuente independiente que lo respalde, el caso puntual de los USD 42.000 (empresa, fecha exacta, jurisdicción), ni ninguna de las cifras de rendimiento de la tabla comparativa (reducción de costo del 98% en dormancy, throughput en requests por segundo). Son afirmaciones del propio blog de Dusyn, sin benchmark reproducible ni auditoría de terceros publicada.

Errores comunes al implementar máquinas de estados en agentes

  • Generar la clave de idempotencia en el momento del retry: si usás Date.now() o un UUID random cada vez que reintentás, la clave cambia y el downstream procesa la acción de nuevo. Derivala siempre del hash de los inputs originales.
  • Meter el payload crudo de la herramienta en el prompt: si una query devuelve 500 filas, no las pegues todas en el contexto del modelo. Guardá el payload en storage de objetos (S3, R2) y pasale al modelo solo una referencia y un resumen de cinco líneas.
  • Ejecutar el llamado externo dentro de la misma transacción síncrona: si llamás a la API bancaria antes de confirmar el commit en base de datos, un fallo de escritura deja un side effect sin rastro. Primero el commit atómico del estado más el outbox, después el dispatch async.
  • Confiar en el promedio de latencia para decidir si el sistema está sano: un p50 perfecto puede convivir con un p99.9 desastroso. Medí percentiles altos, no el promedio.

Preguntas Frecuentes

¿Qué es una máquina de estados en agentes de IA?

Es un esquema explícito y persistente que registra en qué paso exacto del flujo se encuentra un agente, guardado en una base de datos en vez de en un array de chat en memoria. Si el proceso muere, un worker nuevo puede recuperar el estado desde disco y seguir sin adivinar qué pasó antes.

¿Por qué un agente de IA pagó dos veces la misma factura?

Porque estaba construido como un bucle de prompts que guardaba todo en memoria. Cuando un timeout de red cortó la operación y el proceso se reinició, el agente no tenía forma de confirmar si el pago ya se había ejecutado, así que volvió a intentarlo.

¿Cómo evitar que un agente de IA repita una acción tras un error de red?

Usando una clave de idempotencia derivada de un hash SHA-256 sobre los datos de la operación (workflow ID, número de paso, nombre de la herramienta y payload), enviada en el header Idempotency-Key hacia el servicio downstream. Si el mismo hash llega dos veces, el servicio devuelve la respuesta cacheada en vez de ejecutar la acción de nuevo.

¿Qué es la idempotencia en agentes de IA?

Es la propiedad que garantiza que ejecutar la misma operación varias veces produce el mismo resultado que ejecutarla una sola vez. En agentes de IA se implementa con claves determinísticas y una tabla outbox con restricción ON CONFLICT DO NOTHING que bloquea inserciones duplicadas a nivel base de datos.

¿Qué diferencia hay entre un bucle de prompts y una máquina de estados?

El bucle de prompts guarda todo en un array de mensajes en memoria que desaparece si el proceso se reinicia. La máquina de estados persiste cada transición en base de datos, con un patrón outbox transaccional que separa la decisión del modelo de la ejecución real de la herramienta.

Conclusión

El caso de los USD 42.000 (verificado solo por la propia fuente, vale repetirlo) sirve como excusa para algo que cualquiera que haya puesto un agente en producción ya sospechaba: un array de chat en memoria no es una base de datos, y tratarlo como tal termina costando plata real. La solución técnica que documenta DusynBlog (estado persistente, outbox transaccional, claves de idempotencia por hash) no es nueva ni exclusiva de agentes de IA, es el mismo patrón que ya usan Stripe y Twilio para pagos y mensajería. Lo que cambia es que ahora hay que aplicarlo también al lado del modelo, no solo al lado del backend clásico. Si tu equipo está por mandar un agente a tocar dinero o infraestructura real, la pregunta que hay que hacerse antes de lanzar no es qué tan bien razona el modelo, sino qué pasa el día que el socket se corta a las 2:17 AM.

Fuentes

Desplazarse hacia arriba