Postmortems agénticos — cuando la fábrica de agentes deja pasar un incidente

El 16 de octubre de 2026 la reserva en línea de un cliente estuvo rota unas 18 horas. Cada vez que alguien elegía fecha, la app respondía error. No lo detectó un monitor. Lo detectó el dueño.
El cambio que la rompió lo hizo nuestra Software Factory: un equipo de agentes de código que planea, construye, revisa y mezcla. Una persona aprobó el plan y, al final, pulsó «Mezclar» sobre una tarjeta verde. Todo el proceso funcionó como estaba diseñado. Por eso vale la pena contarlo.
Qué pasó, en orden
- Dependabot abrió un PR que subía React Router de la 7 a la 8 en una app de reservas de un cliente.
- El agente que planea escribió un plan con este criterio de aceptación: «la reserva pública se completa de punta a punta en la preview del PR». La persona lo aprobó.
- El agente constructor aplicó la guía de migración hasta que compilaron el typecheck y el build.
- La preview nunca arrancó. Faltaban variables de entorno y la caja de trabajo no tenía MongoDB, la base que usa la app.
- El agente revisor probó la reserva en la caja, contra
http://localhost, y salió bien. Aprobó. En la descripción del PR quedó escrito: «probado en la caja, NO en la preview». - El smoke revisó 33 rutas, todas por GET, y reportó cero diferencias.
- Mezcla, deploy automático y, a partir de ahí, todo POST de la app respondía 400.
La causa técnica: un chequeo anti-CSRF que ahora compara el protocolo
React Router 8 cambió su protección contra CSRF. Antes comparaba sólo el host del Origin contra el de la petición. Ahora compara el origen completo, con protocolo.
En producción la app vive detrás del proxy TLS del hosting. El navegador manda Origin: https://…, pero al servidor la petición le llega como http://… porque el servidor no confiaba en las cabeceras del proxy. Los orígenes no coinciden y cada acción se aborta con 400.
En localhost no hay proxy: el protocolo coincide y el bug no aparece. La evidencia del revisor era cierta. Sólo que no medía el escenario que importaba.
Sin culpables, aunque los «culpables» sean agentes
La cultura de postmortem que escribió Google para SRE pide que un postmortem se concentre en las causas que contribuyeron al incidente «sin acusar a ningún individuo ni equipo», y que asuma que todos actuaron con buena intención con la información que tenían. La guía de PagerDuty lo dice más corto: el postmortem se queda en cómo pasó el error, no en quién lo cometió. Y John Allspaw, desde Etsy, defendió que esa cultura no exime a nadie: equilibra seguridad y responsabilidad.
Con agentes, la tentación es la contraria. «El modelo alucinó», «el revisor fue flojo» y se cambia el prompt. Eso es culpar a una manzana podrida con otro nombre. Un modelo no aprende de un regaño, y otro modelo mañana haría lo mismo con las mismas condiciones.
Así que hicimos las preguntas de sistema:
- ¿Qué creía el revisor que estaba pasando? Que «probado en la caja» bastaba. Su propia regla decía «si el PR tiene preview, prueba ahí». Sin preview, nada lo frenaba.
- ¿Qué permitió que la tarjeta se pusiera verde? Que la preview podía quedar en «faltan variables» en silencio. Y el criterio de aceptación era una frase en el plan, no un check que el sistema pudiera evaluar.
- ¿Por qué la persona mezcló? Porque tenía una tarjeta verde y ninguna señal de que faltaba la prueba principal. El riesgo sí estaba anotado en el plan, pero nadie lo cobró.
- ¿Por qué tardamos 18 horas? Porque nada probaba producción después del deploy, y lo único que se rompió fueron acciones POST.
Las cuatro respuestas apuntan a puertas que no existían.
El agente dijo que verificó y no verificó
Este es el patrón que más daña la confianza. La guía de buenas prácticas de Claude Code pide que el agente muestre evidencia en vez de afirmar que funcionó: la salida de las pruebas, el comando que corrió y lo que devolvió. Recomienda además que quien califica el trabajo no sea quien lo hizo. OpenAI entrenó a Codex para respaldar su trabajo con citas de logs de terminal y archivos. Devin graba en video su prueba de punta a punta.
Nuestro revisor sí mostró evidencia. El problema fue que la evidencia venía del entorno equivocado y el sistema la aceptó como sustituto del criterio aprobado. La evidencia sólo vale si sale del entorno que el criterio nombra.
El costo de esto va más allá de las 18 horas. En el estudio de Dietvorst, Simmons y Massey (2015) sobre algorithm aversion, la gente deja de confiar en un algoritmo después de verlo equivocarse, aunque sea mejor que un humano. Lo castiga más rápido que a una persona con el mismo error. En julio de 2025, un agente de Replit borró una base de producción durante un congelamiento de código. Replit contuvo el daño con barandales concretos: separar automáticamente las bases de desarrollo y producción, y un modo que sólo planea. Un agente que dice «ya lo probé» y no lo probó cae justo en ese hueco.
Del postmortem a los barandales
Cada hallazgo se volvió una regla que el sistema cumple solo, sin depender de que el agente se acuerde:
En el repo del cliente sumamos lo que recomienda la industria para este tipo de falla. Los majors ya no entran por Dependabot como un PR más. El deploy es blue-green. Un smoke de la reserva corre después de cada deploy, con rollback si falla, y cada 10 minutos abre un issue si algo se rompe. GitHub permite algo parecido con sus reglas: exigir que un deployment a un entorno salga bien antes de dejar mezclar.
La prueba: reabrir el mismo error
Un barandal que no se prueba es una frase más. Así que reabrimos el mismo bump a React Router 8 sin arreglar el chequeo CSRF y lo mandamos a la fábrica como un pedido nuevo.
Esta vez la preview arrancó, el smoke mandó el POST con Origin https, recibió 400 y el revisor no pudo aprobar. El pedido se escaló con el error citado.
Después mandamos el bump real con el arreglo: un servidor propio que confía en el proxy (trust proxy). En la preview, un POST con el Origin propio dio 200 y uno con un origen ajeno siguió dando 400. La protección quedó intacta y la reserva funcionó.
En resumen
Un postmortem de una fábrica de agentes se hace igual que uno de personas: sin culpables, preguntando qué condiciones permitieron el error. La diferencia está en qué se repara. Con personas, parte del arreglo es aprendizaje. Con agentes, el aprendizaje que no se convierte en código se pierde en la siguiente sesión. Por eso cada hallazgo de este incidente terminó como una puerta que el sistema cierra solo: preview obligatoria cuando el plan la pide, smoke con POST antes y después del deploy, y un diagnóstico que detecta un criterio aprobado sin evidencia. Y la prueba de que funciona es haber repetido el error y verlo frenado.