IA aplicada
Construyendo sistemas de IA que realmente llegan a producción
Qué cambia cuando un prototipo de IA se convierte en un sistema de producción: workers, infraestructura, confiabilidad, observabilidad y ejecución controlada.
· 15 min de lectura
Es fácil lograr que un prototipo de IA impresione. Un buen prompt, una llamada al modelo y una respuesta convincente pueden demostrar que vale la pena explorar una idea.
En producción, la pregunta cambia. Ya no se trata únicamente de si el modelo produce algo útil. Se trata de si el producto puede dar cuenta del trabajo cuando la ejecución se retrasa, se repite, se interrumpe o solo tiene éxito parcialmente. El problema pasa a ser también un problema de sistemas distribuidos, además de uno de IA.
Las lecciones de este artículo provienen de un backend de producto que combina generación y redacción con IA, procesamiento asíncrono e integraciones con sistemas de negocio externos. La implementación y sus pruebas de regresión aportan la evidencia; los diagramas y ejemplos que siguen generalizan deliberadamente el dominio. Describen mecanismos de arquitectura, no una auditoría de cada comportamiento desplegado.
El prototipo no es el producto
Un prototipo puede considerar que la respuesta del modelo marca el final de la operación. Un producto tiene que decidir qué significa esa respuesta dentro de un flujo de trabajo existente.
En el sistema que inspira este artículo, el contenido generado forma parte de procesos de aplicación con registros persistentes, estados de ejecución y sincronización externa. También hay cargas de trabajo sin IA: importar datos, enviar notificaciones y conciliar información con otros sistemas. Compiten por recursos y tienen sus propios modos de falla.
Esto cambia la definición de finalización. Una respuesta exitosa del proveedor no necesariamente significa que el resultado se haya guardado, que el flujo correspondiente haya avanzado o que un sistema externo haya aceptado una actualización. Son eventos distintos, con responsables distintos.
El producto necesita distinguir el trabajo aceptado del trabajo terminado, una interrupción recuperable de un fallo definitivo y una operación ya completada de una solicitud nueva. Sin esas distinciones, una respuesta impresionante del modelo puede coexistir con una experiencia de usuario que no funciona.
Ese es el primer cambio de arquitectura: la unidad de análisis pasa a ser la operación del producto, no la invocación del modelo.
El LLM se convierte en un componente más
El backend incluye redacción basada en LangGraph junto con otras integraciones de generación con IA. Eso demuestra IA aplicada, pero no demuestra que cada tarea sea un agente autónomo, ni que toda la aplicación deba vivir dentro de un grafo de agentes.
Los servicios de aplicación siguen coordinando la persistencia, validando entradas y decidiendo qué operación debe ejecutarse. Los workers ejecutan tareas encoladas. Las capas de integración gestionan las llamadas externas. Los registros de base de datos guardan el progreso y los resultados. Redis permite el encolamiento y la coordinación.
Estos límites importan porque los componentes fallan de formas distintas. Una llamada al modelo puede superar su tiempo de espera. Un worker puede desaparecer. Una transacción puede revertirse. Un servicio externo puede rechazar una actualización. Agruparlos en un único «flujo de IA» opaco oculta las decisiones necesarias para recuperarse.
- Usuario
- LLM
- Respuesta
- Producto / API
- Cola
- Worker
- IA + integraciones
- Resultado persistido
El diagrama está simplificado deliberadamente. No reproduce una topología interna de despliegue ni implica que todas las operaciones sigan la misma ruta. Su propósito es mostrar que la ejecución del modelo pertenece a un límite de aplicación más amplio.
La pregunta de ingeniería pasa a ser: ¿qué debe cumplirse antes de ejecutar el modelo, qué puede ocurrir durante su ejecución y qué debe quedar confirmado antes de que el producto informe que la operación terminó?
El trabajo asíncrono cambia el modelo de fallas
La implementación utiliza Celery con Redis para la entrega de tareas y sus resultados. Distribuye distintas clases de trabajo en colas diferentes, incluidas colas dedicadas a procesos más largos o más exigentes.
Esa separación tiene más consecuencias que agregar un decorador de tarea en segundo plano. Una operación de larga duración no debería necesariamente ocupar la misma ruta de ejecución que una solicitud breve o el mantenimiento periódico. Las colas separadas hacen explícitos los límites entre cargas de trabajo, aunque esa separación por sí sola no demuestra que los recursos estén aislados en todos los despliegues.
Desacoplar la ejecución del ciclo de vida HTTP también cambia el contrato. La solicitud puede iniciar el trabajo, pero el resultado eventual del worker necesita una identidad y un lugar donde persistir. La aplicación que ve el usuario no puede depender exclusivamente de que la solicitud original siga abierta.
El código representa esa distinción mediante registros de ejecución y estados persistentes. Algunas tareas reintentan con demoras y backoff. Cuando se agotan los reintentos, los wrappers de tareas pueden registrar un error para que el flujo general pueda resolverse, en lugar de permanecer indefinidamente en progreso. La lógica de recuperación también busca trabajo que se haya quedado detenido.
- Registrar la intención
- Encolar
- Ejecutar
- Persistir el resultado
Resultado + estado terminal
Fallo transitorio + espera
Error registrado + decisión de recuperación
Estos mecanismos responden preguntas distintas. Una cola indica dónde espera el trabajo. Una política de reintentos determina si debe ejecutarse otro intento. Un registro de ejecución indica qué sabe el producto en ese momento. El código de recuperación define qué hacer cuando esas perspectivas dejan de coincidir.
Es tentador reducir las cuatro a «el estado del job». Mantenerlas conceptualmente separadas facilita el diagnóstico e impide confundir el éxito en la capa de transporte con la finalización de la operación del producto.
La confiabilidad se convierte en una característica del producto
Una lección especialmente útil aparece en la configuración del broker y en una prueba de regresión específica: el momento del acknowledgment y los límites de ejecución deben ser coherentes.
Con acknowledgment tardío, la tarea se confirma después de ejecutarse, en lugar de antes. El manejo de la pérdida de workers puede permitir que el trabajo pendiente se entregue nuevamente. Pero un broker basado en Redis también tiene una ventana de visibilidad. Si esa ventana vence mientras una operación sigue ejecutándose, otro worker puede recibir el mismo mensaje.
El repositorio verifica explícitamente que el visibility timeout supere los límites de tiempo configurados para las tareas. La lección está en la relación entre esos parámetros, no en un valor concreto. Una configuración que parece un detalle de infraestructura puede determinar si el producto ejecuta trabajo simultáneo duplicado.
Por eso, el acknowledgment tardío no es una estrategia de confiabilidad completa. Cambia un riesgo —que el trabajo desaparezca tras una confirmación temprana— por otro: la ejecución repetida. La tarea y su límite de persistencia deben tolerar esa posibilidad.
La capa de integración con IA también distingue clases de fallas. Ante límites de tasa, puede respetar las indicaciones de reintento del proveedor; ante fallas de servidor o de red, puede aplicar backoff. Otros errores de cliente se consideran fallos, en vez de reintentarse indiscriminadamente. Un consumidor separado de un sistema externo trata los errores de autenticación de forma distinta a los límites de tasa y las fallas de servidor.
Estas decisiones expresan criterio de producto. Repetir una solicitud no corrige credenciales inválidas. Reintentar de inmediato durante una restricción de tasa puede aumentar la presión. Una falla transitoria de transporte puede justificar otro intento, pero solo dentro del presupuesto de tiempo de la operación.
Aquí existen reintentos en más de una capa: solicitudes al proveedor y tareas del worker. Por eso conviene examinar su interacción. Reintentar una tarea puede repetir intentos anteriores al proveedor; los límites de reintento no deberían interpretarse sin considerar el trabajo total que pueden generar. El código inspeccionado no permite afirmar que todas las rutas compartan un único presupuesto global de reintentos.
El estado es más que el contexto del modelo
El contexto del modelo describe la información usada para producir una respuesta. El estado de la aplicación describe qué puede hacer el sistema a continuación y qué ocurrió ya. No deben confundirse.
Un grafo de redacción puede transportar las entradas necesarias para generar texto. Ese estado no establece, por sí solo, si un flujo fue aprobado, si su resultado se guardó o si una actualización externa tuvo éxito.
El backend utiliza registros respaldados por SQL para el estado de la aplicación y de las ejecuciones. Redis cumple otras funciones, como transporte de tareas, resultados y coordinación. Un resultado del broker que expira no sustituye un registro durable del producto: su duración y propósito son diferentes.
La ruta de generación ofrece un ejemplo concreto. Consulta un registro de ejecución antes de realizar trabajo costoso, descarta estados terminales y utiliza una transición protegida al persistir el éxito. El resultado, la transición a completado y la actualización del flujo agregado se confirman juntos en la base de datos.
Esa transacción protege la relación entre «completado» y «existe un resultado». No incorpora la llamada remota de generación a la transacción de base de datos.
- Verificar el estado
- Llamada externa / IA
- Verificar el estado actual
Persistir el resultado + marcar la finalización + actualizar el estado agregado
La implementación libera los bloqueos de base de datos antes de las llamadas externas prolongadas y recupera la protección al persistir. Mantener un bloqueo de fila durante una latencia de red impredecible convertiría una dependencia externa en un problema de contención en la base de datos.
La contrapartida importa: otro intento aún puede consumir cómputo antes de descubrir que la finalización ya fue registrada. Proteger el resultado persistido es distinto de garantizar que el proveedor se invoque exactamente una vez.
Por eso describiría el mecanismo como persistencia protegida que contempla los reintentos, en lugar de afirmar que existe ejecución exactamente una vez de extremo a extremo. La distinción importa para el costo, los efectos externos y una explicación honesta de la confiabilidad.
Los efectos externos necesitan su propio límite
Una base de datos de aplicación y un sistema de negocio externo no comparten una transacción local. Guardar un cambio interno y llamar a una API externa crea un límite de falla parcial, incluso cuando ninguna de las operaciones involucra IA.
El backend incluye registros de outbox transaccional, despacho periódico y consumidores que registran trabajo pendiente, procesamiento, finalización, información de reintentos y errores. Las pruebas cubren casos como omitir eventos ya completados y registrar fallos permanentes.
Un outbox da una representación durable a la intención de entrega. En vez de depender únicamente de una solicitud para realizar de inmediato una actualización externa, un procesamiento posterior puede encontrar el trabajo que aún requiere atención. Es una responsabilidad de la aplicación, no una propiedad que pueda aportar el LLM.
El consumidor también necesita interpretar los resultados. Una actualización externa confirmada puede llevar el registro a completado. Un fallo reintentable debe preservar suficiente información para otro intento. Un rechazo permanente necesita un estado terminal y una razón útil.
Sin embargo, un outbox no elimina la incertidumbre en el límite remoto. Si una operación remota tiene éxito y la finalización local no se registra, un intento posterior puede repetir la llamada. Las comprobaciones locales de «ya completado» no pueden demostrar qué ocurrió remotamente antes de una caída.
El repositorio contiene varias defensas contra el trabajo repetido, incluidas deduplicación de webhooks y transiciones protegidas de ejecución. Resuelven límites específicos. No deben generalizarse como una promesa de que toda operación externa sea idempotente. La confiabilidad surge de identificar dónde aplica cada protección y dónde no.
La infraestructura pasa a formar parte de la ingeniería de IA
El código de infraestructura describe servicios en contenedores sobre AWS ECS/Fargate, recursos administrados de base de datos y Redis, roles de tareas, inyección de secretos y configuración de recursos por servicio. Los flujos de despliegue construyen imágenes de contenedores y actualizan las definiciones de tareas y los servicios de ECS. También existen flujos de pruebas y verificaciones de migraciones.
Nada de eso mejora directamente un prompt. Todo ello cambia si el producto puede operar el flujo que depende de ese prompt.
La memoria y la concurrencia de los workers afectan qué puede ejecutarse al mismo tiempo. Reemplazar un contenedor puede interrumpir una ejecución. Los límites de red afectan el acceso a la base de datos y a las integraciones externas. La configuración de secretos determina si un servicio puede autenticarse. Los cambios de esquema afectan si un worker en ejecución puede leer y escribir sus registros correctamente.
Estas son razones para tratar el despliegue y la recuperación como parte del diseño de la aplicación. Por ejemplo, configurar la reentrega de tareas solo ayuda si la lógica de persistencia admite otro intento. Una verificación de migraciones es valiosa porque el código de aplicación y el estado durable evolucionan juntos.
La presencia de Terraform y flujos de CI demuestra esos mecanismos en el código; no establece que todos los entornos tengan las mismas propiedades de disponibilidad, que todos los despliegues ocurran sin interrupciones o que cada condición de aprobación de una versión se haga cumplir. Necesitaría evidencia operativa y de ejecución antes de sostener esas afirmaciones.
Para un AI Product Engineer, el alcance útil va más allá del SDK del proveedor: comprender cómo se comporta una funcionalidad que depende del modelo durante una nueva versión, una interrupción y una ruta de recuperación.
La observabilidad debe responder preguntas operativas
El repositorio contiene logging estructurado, métricas de estilo Prometheus e infraestructura para dashboards operativos y agregación de logs. Las métricas incluyen volumen de procesamiento, duración, errores, marcas de tiempo del último éxito y tamaño del trabajo fallido acumulado. La capa de integración con IA también configura trazas de LangSmith, incluida su inicialización en los procesos de los workers.
Estas señales responden preguntas distintas. Una traza del modelo ayuda a inspeccionar una invocación. Un log del worker ayuda a explicar un intento. Una métrica de backlog permite detectar acumulación. La marca de tiempo del último éxito puede revelar un proceso que dejó silenciosamente de completar trabajo útil.
La operación del producto debe ser reconocible entre esas perspectivas. Los identificadores de ejecución y de eventos en logs estructurados ofrecen una buena base para investigar; los ejemplos públicos no necesitan revelar los formatos reales de los identificadores ni los nombres de eventos internos.
Aun así, instrumentar no equivale a tener observabilidad completa. Las trazas son configurables, y los archivos inspeccionados no demuestran evaluación integral de la calidad del modelo, correlación completa entre servicios ni un objetivo de confiabilidad medido.
La lección práctica es diseñar alrededor de preguntas: ¿qué operación falló, dónde se detuvo, puede reintentarse de forma segura y qué estado verá el usuario? Un dashboard que no conecta sus señales con esas preguntas puede mostrar actividad sin explicar el comportamiento del producto.
La ejecución controlada pertenece a la aplicación
Controlar no exige necesariamente un framework elaborado de seguridad para agentes. A menudo significa mantener la autoridad de las reglas normales de la aplicación cuando la IA entra en el flujo.
El backend tiene dependencias de autorización en rutas protegidas y transiciones explícitas de revisión. Algunas transiciones se bloquean cuando existen errores pendientes, y los cambios de estado incompatibles pueden producir una respuesta de conflicto. La integración de generación también utiliza salidas estructuradas del modelo y valida las entradas de la aplicación, en lugar de tratar texto arbitrario como instrucciones ejecutables.
Son controles distintos. La autorización decide quién puede solicitar una operación. Las comprobaciones de estado determinan si es válida en ese momento. La validación de esquema limita qué acepta la aplicación. Las transiciones de revisión determinan cuándo puede avanzar un proceso.
Una respuesta del modelo bien estructurada no concede permiso para ejecutar una acción. Del mismo modo, una instrucción en el prompt no reemplaza una comprobación a nivel de aplicación. El límite determinista sigue siendo importante, incluso cuando el modelo resulta útil dentro de él.
La implementación inspeccionada permite hablar de flujos controlados, no afirmar universalmente que toda salida de IA se revisa o que se impide cualquier acción insegura posible. Esa descripción más acotada es más precisa y más útil para tomar decisiones de ingeniería.
Lo que aprendí
El cambio principal consiste en pasar de evaluar una respuesta a dar cuenta de una operación. El modelo es un participante dentro de un producto cuya ejecución cruza límites de procesos, persistencia y servicios.
De los mecanismos anteriores se desprenden varias lecciones:
- La ejecución asíncrona introduce responsabilidades, no solo capacidad. El trabajo aceptado necesita identidad durable, estados significativos y una decisión de recuperación cuando deja de avanzar.
- Los reintentos y la idempotencia deben discutirse juntos. La reentrega puede preservar trabajo y, a la vez, crear intentos duplicados. Proteger un resultado almacenado no equivale a impedir todas las llamadas externas repetidas.
- La configuración de infraestructura determina comportamientos del producto. La visibilidad del broker, los límites de tiempo, la concurrencia y el ciclo de vida de los contenedores son asuntos de aplicación cuando determinan cómo termina el trabajo.
- La observabilidad necesita una operación que seguir. Las trazas del modelo, los logs y las métricas se complementan; ninguna señal por sí sola demuestra que el flujo del usuario esté funcionando correctamente.
- La IA no reemplaza los límites del producto. Permisos, validación, transiciones de estado y decisiones de revisión siguen determinando qué puede hacer el sistema.
Construir sistemas de IA para producción implica, por lo tanto, acompañar el problema del producto a lo largo de toda la ruta de ejecución. Mejorar la salida del modelo importa. También importa saber qué ocurre cuando desaparece el worker, una integración rechaza la solicitud o la base de datos todavía no ha registrado el resultado.
Ahí es donde la IA aplicada, la ingeniería backend, la infraestructura cloud y el pensamiento de producto se convierten en un mismo problema de ingeniería.