Una lista de verificación de preparación para producción para agentes de IA, etapa por etapa.
Una lista de verificación de cuatro etapas para llevar un agente de IA desde un prototipo local hasta la producción, con la razón detrás de cada ítem y un ejemplo concreto para cada verificación.
Fuentes: Shipping AI Agents: A Production Readiness Checklist
El proceso para pasar de un prototipo funcional a un agente de IA en producción sigue un camino predecible, y cada etapa cuenta con sus propias verificaciones y sus propios riesgos si se omiten. Esta explicación aborda cada etapa por separado.
Un prototipo tiene una única función: demostrar que una idea funciona; consiste en una sola máquina, con el estado almacenado en memoria y sin usuarios reales. La producción exige más: debe resistir reinicios, atender a varias personas al mismo tiempo, recuperarse cuando algún paso falla a mitad de camino, y dejar un registro que permita rastrear los problemas.
Poco de esta diferencia afecta a la IA en sí, ya que la llamada al modelo suele ser la parte más sencilla. El trabajo más complicado está relacionado con aspectos circundantes: dónde se almacena el estado, qué ocurre cuando un paso se ejecuta dos veces, y cómo un cambio llega a un usuario real sin causar daños. Utilice las listas a continuación para saber qué ya está cubierto y qué aún no antes de poner en producción un agente.
Etapa 1: desarrollo y prototipo local
El objetivo aquí es deliberadamente limitado: demostrar que la idea central funciona al menos de alguna manera. No lo conviertan aún en una solución lista para producción. Hacerlo demasiado pronto suele significar construir la infraestructura incorrecta para un diseño que aún no está definido.
Hagan que el flujo de trabajo básico funcione una vez, de la forma más sencilla posible. Realicen una sola ejecución limpia desde la entrada hasta la salida correcta, antes de que entren en juego las colas, las bases de datos o el despliegue.
Por qué: Las decisiones sobre la infraestructura tomadas temprano suelen ser erróneas porque la verdadera naturaleza del problema es desconocida: el tiempo de ejecución, el tamaño del estado y los modos de fallo siguen siendo suposiciones. Una versión de nivel producción construida primero normalmente tendrá que reconstruirse de todos modos.
Ejemplo: Un agente de triaje de tickets de soporte comienza su funcionamiento con un script breve: lee un ticket, solicita al modelo una categoría y muestra la respuesta. No hay servidor ni base de datos, y se ejecuta manualmente desde una terminal.
Haga que el comportamiento sea configurable en lugar de estar codificado de forma fija. Cuando el sistema debe actuar de manera diferente según las entradas, como segmentos de clientes, tipos de documentos, idiomas o tonos, gestione eso mediante configuraciones en lugar de crear otra rama de código.
Por qué: Las variaciones se acumulan rápidamente una vez que aparecen los usuarios (“¿Funciona con tickets en francés?”, “¿Pueden las cuentas empresariales tener un tono más estricto?”). Cada variación requiere un cambio en el código y un lanzamiento, lo que hace que nuevos casos se acumulen esperando atención de los ingenieros; en cambio, con configuraciones se trata de una edición rápida.
Ejemplo: En lugar de usar un if/else para cada nivel de cliente, las instrucciones del agente se construyen a partir de pequeños templates de texto, uno base y uno por nivel. Agregar un nivel implica añadir un archivo.
Anote qué problemas aún no resuelve el prototipo. Antes de pasar a la siguiente fase, enumere intencionadamente las deficiencias: reinicios en medio de una ejecución, varios usuarios al mismo tiempo, registro de fallos, ejecución en cualquier lugar excepto en su propia máquina.
Por qué: Una deficiencia que nadie registró se convierte más tarde en una sorpresa, generalmente descubierta durante un incidente y no en una conversación de planificación. Una deficiencia registrada se convierte en la lista de verificación para la siguiente etapa.
Ejemplo: Una tabla breve con filas como “la información del estado se almacena en un diccionario de Python, por lo que se necesita un almacenamiento duradero”, “solo se puede ejecutar una tarea a la vez, por lo que se deben soportar ejecuciones concurrentes” y “no hay registro de lo que ocurrió, por lo que se necesita un registro de auditoría”. Por el momento nada está definido; solo se han dado nombres a los elementos.
Etapa 2: entorno reducido y pruebas
Aquí el sistema se enfrenta por primera vez a la infraestructura real y a las formas en que puede fallar. Ahora funciona desde la computadora portátil, se reinicia y puede ser utilizado por varias personas al mismo tiempo.
Elige el entorno de ejecución adecuado para la carga de trabajo real. Examina cifras concretas antes de decidir dónde se instalará el agente: el tiempo máximo de ejecución permitido, el costo de estar inactivo y si un proceso interrumpido puede continuar desde donde lo dejó.
Por qué: Las cargas de trabajo de los agentes rara vez se asemejan a solicitudes web ordinarias. Una ejecución puede durar minutos y debe transportar una gran cantidad de contexto a lo largo de numerosos pasos. Un entorno de ejecución diseñado para solicitudes cortas generará un tiempo de espera en medio de la ejecución, mientras que uno diseñado para tráfico constante costaría demasiado para algo que se ejecuta unas pocas veces al día.
Ejemplo: Un agente de revisión de documentos legales examina las secciones de un documento una por una en una sola ejecución, de modo que mantenga todo el contexto; un documento largo puede tardar de 10 a 15 minutos. Esto descartó el uso de una función sin servidor con un límite estricto de tiempo. También descartó el uso de un conjunto de contenedores siempre activos, ya que el agente solo se ejecuta unas pocas veces al día y la capacidad ociosa quedaría sin utilizar. Las ejecuciones largas, intermitentes e infrecuentes indicaban la necesidad de un entorno de ejecución que solo facture por el tiempo de procesamiento activo y que no tenga tiempo de espera.
Transfiera el estado de la memoria a un almacenamiento duradero y compartido. Todo aquello que debe sobrevivir a un reinicio o ser visible para más de un servidor, como el estado de ejecución, el historial de conversaciones y los resultados en curso, debe encontrarse en un almacenamiento real y no en una variable dentro del proceso en ejecución. Elija un sistema como fuente de verdad.
Por qué: El estado almacenado únicamente en la memoria desaparece cuando se reinicia el proceso, y en entornos de producción esto ocurre con más frecuencia de la que la mayoría de las personas imagina, debido a despliegues, fallos y escalado. El estado distribuido en varios almacenamientos sin un propietario claro termina haciendo que dos sistemas discrepen sobre qué es cierto.
Ejemplo: Aquí, un agente de edición de documentos almacena el estado de ejecución, el historial de chat y las ediciones propuestas en almacenamiento de objetos, sin conservar nada durante el proceso de manejo de solicitudes. El almacenamiento de objetos es la única fuente de verdad, y una base de datos se utiliza para una tarea específica: un bloqueo de solicitud que impide que dos trabajadores procesen la misma ejecución. El estado general no se distribuye entre ambos, sin regla que determine cuál prevalece.
Supongamos que “esto se ejecutó dos veces” y “estos se ejecutaron simultáneamente”. La mayoría de los sistemas de mensajería reales pueden enviar un disparador más de una vez. Una simple verificación de estado (“iniciar si no se ha iniciado”) falla porque dos procesos pueden leer “no se ha iniciado” antes de que cualquiera de ellos registre “se ha iniciado”. Es necesario contar con un mecanismo que permita que solo uno de ellos tenga éxito.
Por qué: Sin ello, dos procesos podrían repetir el mismo trabajo costoso o escribir resultados contradictorios, y el error solo aparece cuando realmente hay solapamiento, algo que un entorno de desarrollo tranquilo rara vez produce.
Ejemplo: Un mecanismo de bloqueo para reclamar ejecuciones funcionaba en condiciones normales, pero no podía liberar una ejecución si el proceso que la tenía se detenía o colgaba. En producción, esto se manifestaba como un montón de ejecuciones congeladas en estado “en procesamiento” durante días, sin posibilidad de rescatarlas. La solución incluyó un plazo de validez para el bloqueo, un token que evita que un proceso recuperado sea confundido con el titular original, y una revisión periódica que recupera cualquier ejecución cuyo plazo haya expirado sin finalizar. Esto es mucho más completo que simplemente “reclamarlo una vez”.
Agregue seguimiento y registro antes de que un incidente los exija. Cuando participan más de un servicio, como una capa web, una cola, un proceso de trabajo y un entorno de ejecución de IA, una acción del usuario pasa por cada uno de ellos. Organice ahora una forma de seguir ese camino a través de los servicios, para no tener que armarlo pieza por pieza durante una interrupción.
Por qué: Reconstruir eventos a partir de registros separados que no están conectados es lento y propenso a errores, especialmente bajo presión. Un sistema que puede rastrearse desde el inicio convierte una investigación estresante en una búsqueda rápida.
Ejemplo: El entorno de ejecución de la IA de un sistema contaba desde el principio con un seguimiento detallado, pero el servicio accesible desde la web que estaba delante de él no lo tenía, por lo que un registro mostraba todo lo que hacía el agente y no la solicitud que lo activó, ya que nada compartido vinculaba los dos. La solución fue crear un ID de ejecución en el momento de la solicitud y transmitirlo a través de los registros de cada servicio, de modo que una sola búsqueda pudiera recopilar todo el recorrido de una ejecución específica, aun cuando los dos sistemas de seguimiento permanecieran separados.
Pruebe el cliente real lo antes posible. Cuando los usuarios acceden al sistema a través de un navegador, aplicación o dispositivo en particular, realice pruebas en ese objetivo cuanto antes, y no se conforme con un cliente API genérico o una aproximación.
Por qué: Los clientes reales presentan peculiaridades, como límites de longitud, cortes silenciosos y codificaciones inusuales, que una herramienta genérica no puede detectar. Estas problemáticas suelen manifestarse solo con usuarios reales, para entonces ya se han convertido en incidentes en producción y no son algo que se encuentre en entornos de pruebas.
Ejemplo: La función de apertura de documentos de una aplicación de escritorio superó todas las pruebas automatizadas, pero fallaba de forma intermitente para los usuarios de un sistema operativo específico. La aplicación truncaba silenciosamente los enlaces de descarga cuando superaban cierta longitud, y las credenciales de seguridad temporales utilizadas para firmar esos enlaces los hacían superar aún más ese límite. La solución fue firmar los enlaces con una identidad separada que genera una firma mucho más corta, en lugar de las credenciales temporales que utilizaba el resto del sistema.
Coordine la ruta de red de la puerta principal con la forma en que se conectan los clientes. Si los usuarios solo acceden al sistema a través de una red privada, como una VPN, un proxy de confianza cero o una red exclusiva para empleados, asegúrese de que la dirección que utilizan realmente conduzca a algo en esa misma ruta privada de principio a fin. Un dominio que parece interno pero que en realidad se resuelve hacia un balanceador de carga o CDN público puede funcionar para algunos usuarios y fallar de forma intermitente para otros.
Por qué: Este tipo de desajuste provoca fallos inconsistentes: algunos usuarios, en ocasiones, lo experimentan, por lo que parece ser una infraestructura poco fiable y no un ajuste defectuoso. Escapa a la detección porque puede transmitirse desde la máquina de un desarrollador, la cual suele seguir una ruta de red diferente a la de una computadora portátil del personal.
Ejemplo: Se pretendía acceder a una herramienta interna únicamente a través de la red de la empresa, mediante un proxy de confianza cero que enviaba el tráfico por diferentes conectores según lo que seleccionara cada ordenador portátil. El dominio de la herramienta parecía interno, pero apuntaba a una red pública de distribución de contenido. Algunos conectores podían llegar a esa dirección pública, mientras que otros solo podían acceder a las direcciones privadas; por eso los fallos aparecían y desaparecían según el conector que se estuviera utilizando. La solución fue alojar la puerta de entrada en un balanceador de carga dentro de la red privada, accesible por completo mediante la ruta que utilizan los usuarios reales, además de un camino separado y firmado para una aplicación de escritorio que no podía usar el proxy en absoluto.
Cree un cliente ficticio que pueda ejecutar todo el proceso cada vez que lo desee. Se trata de un script que realiza las mismas solicitudes y seguimientos que un usuario real, a través de la misma interfaz, de modo que se pueden repetir ejecuciones completas sin tener que esperar a un probador humano.
Por qué: Los flujos de los agentes rara vez consisten en una solicitud y una respuesta. Involucran varias interacciones, llamadas a herramientas y actualizaciones que se envían a lo largo del tiempo, lo cual es difícil de verificar completamente a mano. Las pruebas unitarias e de integración, por sí solas, tienden a probar partes por separado y no una sesión real completa. Con un cliente falso, la cuestión de si una conversación multifase se desarrolló correctamente se convierte en una verificación que se puede realizar en cualquier momento.
Ejemplo: Un conjunto de herramientas para pruebas de carga realiza las mismas llamadas a la API que haría un panel de control de cliente real para iniciar una ejecución, y luego verifica una tabla de estado para saber cuándo se ha completado, ya que la ejecución finaliza más tarde y la primera respuesta no indica nada sobre el resultado. La cantidad de ejecuciones simultáneas aumenta gradualmente, de unas pocas a docenas y luego a más de cien, con un límite estricto en el total de ejecuciones y gastos, ya que cada ejecución falsa equivale a una llamada real al modelo de facturación. Esto reveló que el verdadero cuello de botella bajo carga era el proveedor del modelo y no la infraestructura circundante, algo que las pruebas realizadas por separado no habrían mostrado.
Elija el momento en el que una persona revise la salida del agente antes de que esta tenga efecto. Ofrezca un lugar donde alguien pueda ver qué va a hacer el agente y decidir si lo aprueba, lo modifica o lo rechaza, en lugar de permitir que la salida surta efecto por sí sola desde el primer día.
Por qué: Los errores de los agentes se diferencian de los bugs comunes. Parecen plausibles pero están equivocados, y no se asemejan a un fallo evidente. La revisión humana detecta los errores que pasan por todas las pruebas automatizadas, y genera el historial necesario para decidir posteriormente dónde el agente puede actuar sin revisión de forma segura.
Ejemplo: Un agente de edición de documentos nunca escribe directamente en el documento final. Ofrece sugerencias que un revisor acepta, modifica o rechaza individualmente, por lo que nada de lo que genera cuenta hasta que una persona interviene.
Etapa 3: preproducción
Este es el último entorno antes de los usuarios reales. La pregunta pasa de “¿funciona la función?” a “¿se mantiene el comportamiento de todo el proceso cuando las condiciones no son ideales?”. Esto incluye despliegues repetidos, interrupciones parciales y desviaciones cuando se cambia el modelo o la instrucción subyacente.
Elabore una evaluación adecuada, ya que solo saber si es aprobado o rechazado no es suficiente. Decida qué significa “bueno” para la salida del agente, lo cual suele incluir varios aspectos (actuar con la entrada correcta, ser sustancialmente preciso, mantener coherencia de una ejecución a otra), y quién o qué verificará cada uno de ellos: una regla fija, un revisor humano o un modelo separado que actúe como juez.
Por qué: La salida del agente rara vez es simplemente correcta o incorrecta como lo es una afirmación en una prueba unitaria. Una señal de aprobación/rechazo simple oculta qué parte empeoró, y un método de puntuación que nadie ha examinado detenidamente, especialmente un juez automatizado, puede desviarse silenciosamente de lo que realmente importa para quienes utilizan esa salida.
Ejemplo: Un agente de resumen es evaluado en tres aspectos separados: la cobertura de los hechos clave, cualquier contenido inventado que no esté en la fuente, y cuánto varía su salida entre dos ejecuciones con el mismo input. Una persona revisa una muestra para verificar si se ha “inventado algo”, ya que cometer un error en este punto tiene el mayor costo.
Ejecuta nuevamente el agente con un conjunto fijo de ejemplos conocidos y correctos. Mantén una colección pequeña e inmutable de inputs con salidas aprobadas, y úsala en cada despliegue, especialmente después de cualquier cambio en el prompt o en el modelo.
Por qué: A diferencia del código regular, el comportamiento de un agente puede cambiar sutilmente tras un pequeño cambio en el prompt o una actualización del modelo, sin que ninguna prueba genere un error. Un conjunto de ejemplos fijo suele ser lo único que permite detectar que “funciona bien, pero los resultados han ido empeorando gradualmente”.
Ejemplo: Se verifica a un agente de edición de documentos en un conjunto de ejemplos fijos de tres maneras: si seleccionó las secciones correctas para editar (en comparación con una clave de respuestas revisada por humanos), si las ediciones propuestas eran correctas (evaluadas por un modelo de juez independiente), y cuánto varía su salida entre ejecuciones con el mismo input. Al seguir de cerca estos tres aspectos en distintas versiones, y no solo un indicador de éxito o fracaso, se descubrió que un cambio había mejorado una métrica mientras perjudicaba silenciosamente otra.
Deje que una verificación fallida detenga el lanzamiento. Un conjunto de pruebas cuyo fallo aún permite el despliegue no es más que un comentario. Conecte los resultados al proceso para que un fallo detenga el lanzamiento, de modo que omitirlo no sea la opción por defecto.
Por qué: Si se puede saltar una verificación sin inconvenientes, así se hará, generalmente bajo presión de plazos, momento en el que es más probable que los cambios defectuosos pasen desapercibidos.
Ejemplo: Se configura una tubería de procesos de tal manera que, si alguna prueba falla, el paso de despliegue nunca se ejecuta. No existe un botón de “desplegar de todos modos”, y para evitarlo es necesario realizar un cambio consciente en la configuración de la tubería de procesos, en lugar de simplemente hacer clic en una advertencia.
Intente interrumpir intencionadamente el camino rápido y confirme que el sistema funciona de manera adecuada en esas condiciones. Si los resultados normalmente se entregan a través de un camino rápido como un caché, una conexión en tiempo real o una cola, desactívelo deliberadamente y verifique que exista un método alternativo más lento que siga funcionando, en lugar de que la función deje de funcionar por completo.
Por qué: Los cachés, las conexiones en tiempo real y otros atajos similares son los componentes que con mayor probabilidad fallan en producción. Sin un método alternativo, una pequeña interrupción en un componente hace que toda la función deje de funcionar.
Ejemplo: Las actualizaciones suelen llegar en menos de un segundo a través de una conexión push. En una prueba con esa conexión desactivada, el sistema hace consultas cada pocos segundos, lo cual es un método más lento pero que aún así muestra los resultados al usuario.
Deje que las herramientas garanticen el orden cuando algo debe existir antes que otro. Si la parte A debe estar lista antes de que se pueda configurar la parte B, incluya esa secuencia dentro del proceso de despliegue y no en la memoria de alguna persona.
Por qué: Una regla como “desplegar X antes que Y” solo sigue vigente hasta que la persona que la conoce se ausenta o alguien automatiza el proceso sin saber de ella. Las secuencias importantes deben estar definidas en las herramientas.
Ejemplo: Un servicio de orquestación necesita el ID de un entorno de ejecución de IA creado por otra pila de despliegue, y si cada pila hiciera referencia a la otra se crearía un ciclo. Por eso, la pila del entorno de ejecución escribe su ID en un almacén de parámetros compartido al crearse, y la pila de orquestación lo lee allí. Se garantiza que el entorno de ejecución exista primero, y las pilas nunca se hacen referencia mutuamente.
Etapa 4: la puerta de producción
La lista de verificación final se realiza antes de que los usuarios reales dependan del sistema. Para entonces ya debería haberse confirmado la corrección del sistema. Lo que queda es asegurarse de que lo que se envía sea exactamente lo que se probó, y de que los fallos puedan resolverse y explicarse.
Envíe el artefacto exacto que se probó. Utilice la versión compilada que superó las pruebas previas a producción y cámbiele la etiqueta para que sea apta para producción, en lugar de compilar una copia nueva en el último paso.
Por qué: Una reconstrucción de último minuto, incluso a partir de la fuente “misma”, puede incluir una versión diferente de una dependencia, una marca de tiempo o detalles del entorno. Esa diferencia significa que en producción se ejecuta algo que en realidad nunca se probó.
Ejemplo: La aplicación empaquetada que superó todas las pruebas previas a producción simplemente se vuelve a etiquetar como versión de producción y se envía tal como está, siendo el mismo archivo y no una nueva construcción a partir del mismo código.
Decida de antemano a dónde irán los fallos repetidos y cuánto tiempo se conservarán. Establezca un límite estricto de intentos, elija dónde debe ir todo lo que falle más allá de ese límite y decida cuánto tiempo se mantendrá.
Por qué: Sin límite, un trabajo defectuoso puede intentarlo una y otra vez indefinidamente, consumiendo recursos en silencio o bloqueando una cola. Sin un destino, un trabajo fallido simplemente desaparece, y nadie puede actuar ante un fallo que no puede ver.
Ejemplo: Una tarea que falla tres veces se coloca automáticamente en un área de almacenamiento separada y no se vuelve a intentar indefinidamente. Se mantiene durante quince días, lo que da tiempo al ingeniero para detectarla e investigarla.
Planifique la huella de auditoría ahora mismo. Si las decisiones del sistema podrían necesitar explicación más adelante ante un usuario, un auditor o un colega, decida de antemano qué se registrará y cómo se encontrará.
Por qué: La frase “Añadiremos un registro adecuado más tarde” casi nunca se cumple cuando llegan los plazos reales, y para cuando se hace evidente la necesidad, ya no es posible reconstruir la historia faltante posteriormente.
Ejemplo: Cada decisión automatizada se guarda como un registro propio con marca de tiempo. Si alguien pregunta más adelante por qué se tomó una decisión en un caso específico, existe una respuesta escrita a la que recurrir en lugar de una suposición.
Describa cada incidente real, no solo la solución aplicada. Después de un fallo inesperado, registre la causa raíz y la solución para que el equipo pueda encontrarla más tarde; esto significa algo más que un ticket cerrado o un hilo de conversación.
Por qué: Una solución no documentada tendrá que ser resuelta de nuevo desde cero por otra persona, generalmente bajo mayor presión. Una breve nota suele ser la forma más económica de evitar repetir una investigación que dura varias horas.
Ejemplo: Un lote de ejecuciones estuvo durante días en estado de procesamiento parcial porque nada las recuperaba automáticamente. La causa, la solución y el razonamiento detrás de ello se registraron en un documento aparte del parche de código. Más tarde, un análisis posterior reabrió una conclusión anterior, según la cual el problema se debía a que el modelo inventaba datos, pero al examinarla con más detenimiento se descubrió que la verdadera causa era más sutil de lo que se pensaba inicialmente. Esa actualización también se documentó, por lo que la conclusión original, menos precisa, ya no era válida.
El patrón detrás de la lista de verificación
Casi nada de esto es específico de la IA. Estos son los hábitos que necesita todo sistema distribuido: un estado duradero, un manejo seguro de las repeticiones, visibilidad sobre lo que ocurrió y por qué, y un proceso de lanzamiento que distribuya lo que ya se ha probado.
El agente cambia el lugar donde se encuentra el riesgo. Las ejecuciones son más largas y contienen más contexto, por lo que el procesamiento debe adaptarse a ello. Una ejecución puede fallar o desviarse de maneras que una prueba ordinaria no detecta, por lo que las verificaciones de regresión en ejemplos conocidos como correctos son aún más importantes. Y tarde o temprano alguien preguntará “¿por qué hizo eso?”, y el registro de auditoría debe poder responder a esa pregunta.
Leer más
- Por qué la memoria de un agente de programación solo debe contener el delta y cómo almacenarlo — La memoria del agente debería registrar únicamente lo que el modelo no pudo adivinar. Cuatro pruebas para cada entrada, tres requisitos para el almacenamiento, y por qué el markdown en git es adecuado.
- Inyección de Prompt y la Tríada Letal: Seguridad para Agentes de IA — Por qué los agentes no pueden separar sus instrucciones de las de un atacante, cómo funcionaron los ataques EchoLeak y GitHub MCP, y qué defensas son efectivas.
- Desplegando Agentes de IA en Producción: Compromisos entre Nube, Autoalbergado o Híbrido — Compare los despliegues de agentes en nube, autoalbergados e híbridos en términos de exposición de datos, costos, dependencia, enrutamiento y capacidad de observación, con cuatro preguntas para tomar decisiones y errores que evitar.