Todo este libro se deriva de cuatro ideas. No son opiniones sobre arquitectura. Son lo que queda después de las caídas.
1. Un modelo es una llamada de red poco fiable disfrazada.
Es un endpoint HTTP de terceros con latencia alta, salida variable, algún que otro 429 y una factura adjunta. Todo instinto que tengas sobre integrar una pasarela de pago poco fiable es correcto aquí. Ponle un timeout. Ponle un tope. Reintenta los fallos que vale la pena reintentar y ninguno más. Da por hecho que falla, y decide ahora qué ve el usuario cuando falle.
2. Los prompts son código.
Un prompt determina el comportamiento. Eso lo convierte en código, y el código va en el control de versiones, en la revisión y en un despliegue: no en una fila de base de datos que alguien edita un viernes, ni en un archivo de configuración del que nadie mira el diff. Cuando cambia un prompt, cambia el comportamiento, y deberías poder señalar el commit.
3. Pon tope a todo: tokens, tiempo de reloj, iteraciones, dinero.
Una funcionalidad de IA sin tope es una factura sin tope. Todo bucle necesita un número máximo de pasos. Todo job necesita un plazo más corto que su timeout. Todo inquilino necesita un techo. Toda respuesta necesita un límite de tokens que eliges tú en el servidor, no que insinúa el cliente ni que se hereda del valor por defecto de un paquete. No echarás de menos el tope que falta hasta el mes en que lo eches de menos.
4. El modelo es un llamante no confiable.
Se le puede convencer. Lo convencerán. Nada de lo que impones pidiéndole al modelo las cosas por las buenas está impuesto. La verificación, la propiedad, las cuotas y los permisos viven en tu base de datos y en tus middleware, detrás de las herramientas, nunca en las instrucciones.
Cómo lo aprendí
La primera versión de nuestro agente funcionó a la primera, y ese era el problema.
Era una caja de chat. Le contabas a qué se dedicaba tu negocio y te construía un sitio web. En la demo era realmente encantador. Hacía buenas preguntas, tomaba decisiones razonables y, un minuto después, había un sitio real en una dirección real. Se lo enseñamos a todo el mundo.
Lo primero que se rompió fue el tiempo. Un turno en el que el modelo usaba varias herramientas tardaba bastante más de un minuto, y todo corría dentro de la petición HTTP. Los usuarios miraban un spinner hasta que algo más arriba se rendía, y entonces no veían nada: ni un error, ni una respuesta parcial, ni un sitio, aunque ya habíamos pagado cada token. El trabajo estaba hecho. Solo que no teníamos dónde ponerlo.
Así que lo pasamos a la cola, y se rompió lo segundo. El job tenía un timeout, y un turno largo lo alcanzó. El job murió a mitad de turno sin haber escrito nada, mientras el widget consultaba con educación una clave de caché que nunca iba a aparecer. El usuario se quedaba delante de un chat que, sencillamente, había dejado de hablar.
Luego un turno volvió truncado. Habíamos puesto tope a los tokens de salida, con buen criterio, pero nunca miramos por qué se detenía el modelo. Una respuesta cortada caía por la misma rama que una terminada y se mostraba como respuesta. Se leía bien. Estaba mal.
Luego un usuario pulsó el botón dos veces.
A la herramienta que creaba un sitio se le había dicho, en su propia descripción, que hiciera esto una sola vez. Esa instrucción se respetó a la perfección, justo hasta que llegaron dos peticiones lo bastante juntas como para que «una vez» fuera ambiguo. Tuvimos dos aprovisionamientos para una sola persona. El arreglo no fue una instrucción mejor. El arreglo fue un índice único.
Y luego, meses después, le quitamos al modelo el paso irreversible por completo. Hoy la última herramienta del agente no construye nada. Le entrega a la persona un enlace de pago, y el sitio solo se construye cuando un humano registra una tarjeta. El modelo ya no puede gastar nuestro dinero, porque ninguna instrucción que pudiéramos escribir iba a ser nunca tan sólida como una puerta que no puede abrir.
Ninguno de estos era un problema del modelo. El modelo estaba bien. Cada fallo estaba en el código que lo rodeaba, y cada arreglo era algo que yo ya sabía hacer. Solo que nunca se me había ocurrido hacerlo aquí, porque esta parte iba disfrazada.
Por eso los capítulos de este libro son como son. No tratan de prompts. Tratan de colas, plazos, índices únicos, fronteras de confianza y logs estructurados, aplicados a un componente que resulta ser no determinista.