Lecciones de LangChain: diseñar un Runtime fiable para agentes de IA en producción

Tema: Ingeniería de agentes

Publicado:

Última actualización:


Introducción

Las demos de agentes son fáciles de encontrar emocionantes. Un modelo, unas cuantas herramientas, un prompt, lo envuelves en un bucle y de repente tienes algo que busca, escribe archivos y llama APIs.

Pero entre una demo y un sistema en producción hay un foso muy ancho. Yo lo llamo la brecha del Runtime — y lo que la cruza no es un modelo más inteligente. Es un runtime capaz de sostener cargas complejas, inestables, interrumpibles y recuperables en un entorno real.

Cuando despliegas de verdad en un contexto de negocio, un Agent puede ejecutarse durante minutos o decenas de minutos. Llama a varios sistemas externos, puede necesitar aprobación del usuario, puede toparse con fallos de red, timeouts de herramientas, derivas en la salida del modelo, permisos insuficientes, interrupciones del usuario a mitad de camino, reinicios del proceso y actualizaciones de versión. Peor aún, lleva estado: en qué punto está la tarea, qué se consultó ya, qué archivos intermedios se escribieron, qué conclusiones siguen sin confirmar, si este usuario puede acceder a un dataset concreto.

A esas alturas, optimizar el prompt no resuelve el problema de fondo. Lo que un Agent necesita es un runtime que sostenga el proceso de ejecución — complejo, inestable, interrumpible y recuperable.

Lo que LangChain ha escrito últimamente sobre production deep agents y su Runtime merece la pena para cualquiera que esté construyendo productos basados en Agents. Es un buen recordatorio: el foso defensivo de un Agent de nivel empresarial no es un agent loop más bonito. Es si puedes convertir estado, permisos, recuperación, observabilidad y colaboración humana en una base estable.



1. Los fallos de un Agent empresarial no ocurren solo cuando el modelo se equivoca

Cuando la gente piensa en la fiabilidad de los Agents, lo primero que suele venir a la mente son las alucinaciones. Importan, pero en un sistema de negocio la superficie de fallo es mucho más amplia.

El proceso puede caerse en el paso 8 de una tarea larga. Reejecutar gasta dinero y puede repetir llamadas a APIs externas, dejando datos sucios.

Una herramienta puede fallar. Un timeout de API, una página que no carga, una consulta a la base de datos que lanza una excepción — sin reintentos, fallbacks y persistencia de estado, toda la tarea se vuelve una apuesta de un solo tiro.

Puede perder el contexto mientras espera aprobación humana. El usuario vuelve media hora después a pulsar "Confirmar" y el sistema no recuerda qué paso estaban confirmando.

Puede perder el control en la capa de interacción. El Agent sigue ejecutándose y el usuario escribe "espera, esa dirección no es la correcta, cambia al plan B". ¿El sistema debería encolar, interrumpir, reiniciar o rechazar? Sin una política clara, la experiencia se desmorona.

Así que la fiabilidad para un Agent en producción son al menos seis cosas: ejecución fiable, estado fiable, interacción fiable, permisos fiables, observabilidad y fiabilidad operativa. El valor de un Runtime es productizar y enmarcar estos problemas — en lugar de dejar que cada equipo los reinvente desde cero.



2. Separa Harness y Runtime

En mi visión actual, una distinción clave es esta: Harness y Runtime no son lo mismo.

El Harness es la cáscara de comportamiento del Agent. Decide cómo se planifica la tarea, cómo se escribe el prompt, qué herramientas se pueden llamar, si se generan subtareas, si hay sistema de archivos, si se usan sub-Agents, cómo se comprime el contexto. Esta capa afecta directamente a lo inteligente que parece el Agent.

El Runtime es la capa de abajo. Decide cómo se ejecutan los Agents, cómo se persisten, cómo se recuperan, cómo se interrumpen, cómo se observan, cómo se planifican, cómo se aíslan entre usuarios y cómo se gestionan las peticiones concurrentes. Esta capa afecta directamente a si el Agent puede sostener un sistema de negocio.

En muchos Agents de código abierto, todo termina metido en el harness: reglas en el prompt, try-catch dentro de las llamadas a herramientas, estado improvisado en la base de datos, un spinner de loading en el frontend. Funciona a corto plazo. A largo plazo se convierte en una maraña que nadie quiere mantener.

El enfoque del Runtime de LangChain consiste en sacar las capacidades transversales del contexto del agent loop.



3. Durable Execution: la primera base de la fiabilidad

Si solo pudiera aprender un diseño del Runtime de LangChain, empezaría por durable execution.

Una request web normal tiene vida corta: entra la petición, se procesa, se responde, fin. Los Agents son distintos. Un Agent de negocio puede ejecutar muchos pasos: entender la tarea, descomponerla, recuperar material, llamar herramientas, escribir archivos intermedios, esperar aprobación, continuar, generar un informe. El proceso atraviesa por naturaleza varias llamadas al modelo, varias llamadas a herramientas y varias interacciones del usuario.

Cuando las tareas se alargan, el sistema tiene que responder a una pregunta: ¿qué pasa si se cae en medio?

La respuesta de LangChain/LangGraph es el checkpointing. Los estados clave durante la ejecución se persisten de forma continua. Al recuperar, no se empieza de cero — se reanuda desde el último estado razonable. Para un sistema de negocio, esto no es solo ahorro de coste. Es cómo evitas duplicar efectos secundarios.

¿Cómo funciona en concreto? LangGraph modela la ejecución del Agent como un grafo de estados. Cada nodo es un paso — una llamada al modelo, una llamada a una herramienta, un condicional. El estado fluye entre nodos y, tras cada paso, el snapshot actual de todo el grafo se serializa al checkpointer. Hay varias decisiones de diseño que merece la pena desempaquetar.

Primero, la unidad mínima de checkpoint es la frontera de nodo, no la de llamada de función. Si una llamada al modelo en streaming muere a mitad de la salida, la recuperación reejecuta toda la llamada.

Segundo, el estado es estructurado, no un pickle opaco. LangGraph obliga a dividir el estado en canales con nombre (messages, plan, scratchpad), cada uno emparejado con un reducer (append para messages, overwrite para plan). Eso hace que los checkpoints sean diffs estructurados — trazables, reproducibles y viajables en el tiempo a cualquier paso.

Tercero, los checkpoints forman un árbol, no una línea. Cada checkpoint lleva una referencia a su padre. Puedes ramificar desde cualquier nodo histórico y reejecutar — ajustar la pregunta del usuario, saltar una aprobación, probar otra herramienta — todo eso hace crecer nuevas ramas del mismo árbol.

Cuarto, interrupt y checkpoint comparten el mismo mecanismo. Una interrupción antes o después de un nodo es, en esencia, un checkpoint escrito en ese punto seguido de una pausa. Aprobación humana, edición del usuario, despertar por señal externa — todos reutilizan la misma capa de persistencia. Por eso HITL puede ser una capacidad de Runtime y no lógica de UI.

Quinto, el backend es enchufable. En dev, memoria o SQLite; en producción, Postgres o Redis. El nivel de fiabilidad de tu Agent puede escalar con el negocio — no necesitas infraestructura pesada el primer día.

Imagina un Agent generando un informe de investigación para un cliente empresarial. Ha terminado la recopilación de material, el resumen de competidores y el primer borrador, y está esperando que el usuario confirme si extrae datos del CRM interno. Si el servicio se reinicia en ese instante, lo ideal no es hacer que el Agent vuelva a buscar todo desde cero, ni que el usuario describa de nuevo sus requisitos. Es reanudar en "esperando confirmación".

Ese es el sentido de durable execution: convertir la ejecución del Agent de una llamada a función única en una tarea con ciclo de vida real, que se puede guardar, recuperar y continuar.

Aún quedan preguntas concretas que conviene responder: ¿qué cuenta exactamente como frontera recuperable en cada paso del Agent? ¿Las escrituras hacia el sistema de negocio se pueden repetir sin riesgo?



4. Estado por capas: estado a corto plazo, memoria a largo plazo y datos de negocio no deberían mezclarse

Las tareas complejas de los Agents producen estado. Pero el estado no debería ser una sopa única.

El estado a corto plazo es el contexto de la tarea actual: cuál es el plan, en qué paso está la ejecución, los resultados intermedios, qué llamadas a herramientas se completaron, qué queda pendiente de confirmar. Este estado encaja ligado a thread, run y checkpoint.

La memoria a largo plazo es contexto entre sesiones: preferencias de usuario, reglas de organización, flujos de trabajo habituales, restricciones recurrentes, conocimiento reutilizable. Debe vivir en un store de largo plazo, con namespaces por usuario, organización, aplicación, asistente, etc.

Los datos de negocio son otra capa: pedidos, problemas, lecciones, fichas de clientes, activos organizativos, modelos de permisos. Estos datos no deberían ser engullidos a la ligera por el Agent Runtime. Deberían seguir siendo propiedad del sistema de negocio, y el Agent acceder a ellos a través de herramientas controladas.

El diseño de LangChain es instructivo aquí: separa los checkpoints de thread del long-term store, y a la vez permite que los deep agents accedan a distintas capas de estado a través de algo parecido a un sistema de archivos virtual. Para el Agent que está arriba, leer y escribir archivos y memoria resulta natural; para el sistema de abajo, el estado sigue teniendo fronteras claras.

Esto importa mucho en sistemas reales. Muchos productos de Agent en su fase temprana amontonan historial de chat, resultados de herramientas, preferencias del usuario y datos de negocio en una única conversation memory. Es simple de implementar, pero más adelante todo estalla a la vez: permisos, coste, calidad de recuperación, limpieza de datos y auditoría regulatoria.

Un patrón más robusto: el estado a corto plazo sirve a la recuperación de tareas, la memoria a largo plazo sirve a la continuidad de experiencia, y los datos de negocio se quedan dentro del sistema de negocio — el Agent solo llega a ellos por herramientas con permisos controlados.



5. Human-in-the-loop no es decoración — es un mecanismo de fiabilidad

Los Agents de nivel producción son difíciles de automatizar por completo. Sobre todo cuando hay escrituras, llamadas a sistemas externos, decisiones importantes, recursos de pago o privacidad del usuario — la colaboración humana es una válvula de seguridad necesaria.

La clave no es lanzar un diálogo de confirmación. La pregunta real de ingeniería es: ¿cómo se pausa el Agent? ¿Qué estado se guarda mientras se pausa? ¿Puede el usuario volver mucho tiempo después y continuar? ¿Puede el usuario modificar el plan que produjo el Agent? Tras la edición, ¿desde dónde se reanuda? ¿Son auditables los registros de aprobación?

El Runtime de LangChain convierte interrupt/resume en una capacidad de runtime, en lugar de que la capa de aplicación decida sobre la marcha. Porque si HITL vive solo en la capa de interacción frontend, se convierte rápidamente en lógica de UI — y en cuanto las tareas atraviesan procesos, workers y tiempo, el frontend no la puede sostener.

Hay muchos escenarios en Agents de negocio que necesitan esto:

  • Un Agent financiero a punto de enviar un reembolso necesita confirmación humana.
  • Un Agent de educación que genera planes de clase en lote necesita que el profesor escoja el estilo de enseñanza.
  • Un Agent de atención al cliente que va a tramitar una devolución necesita aprobación del supervisor.
  • Un Agent de análisis de datos que quiere acceder a campos sensibles necesita una autorización temporal del usuario.

Estos no son experiencias de chat ordinarias — son flujos de negocio. Si el Runtime soporta de forma nativa pausar, reanudar, aprobar y persistir estado, la fiabilidad del Agent sube un escalón claro.



6. Permisos y multitenencia: un Agent no debería pasearse con la llave maestra

Uno de los mayores riesgos para un Agent de producción son los permisos.

En una aplicación normal, el usuario pulsa un botón, llama a una API, el servidor comprueba permisos — la cadena es relativamente clara. Cuando entra un Agent, se complica: el modelo decide qué herramienta llamar, la herramienta puede acceder a sistemas externos, esos sistemas pueden requerir autorización del usuario, y el Agent puede escribir resultados intermedios en memoria a largo plazo.

El enfoque de LangChain consiste en partir identidad y permisos en capas: quién es el usuario final, a qué threads y recursos puede acceder ese usuario, a qué sistemas externos puede acceder el Agent en su nombre, y qué pueden hacer los miembros del equipo sobre la plataforma misma.

En este diseño, el Agent no es un super-administrador de backend. Es más bien un ejecutor delegado, autorizado a actuar solo dentro del alcance del usuario actual, la organización actual y la tarea actual.

Si estás diseñando un Runtime para tu propio Agent de producción, conviene pensar al menos en estas fronteras:

  • La identidad del usuario entra en el run context. Cada ejecución del Agent debe saber en nombre de quién está actuando.
  • El acceso a recursos debe aislarse por thread, archivo, proyecto y organización. No basta con un prompt que le pida al modelo no tocar los datos de otros.
  • La autorización de herramientas externas debe gestionarse aparte. GitHub, Slack, CRM, object storage, bases de datos — las claves de largo plazo no deberían entregarse directamente al entorno de ejecución del Agent.
  • La memoria a largo plazo necesita namespaces. De lo contrario, las preferencias que el Agent recuerda pueden convertirse en contaminación de datos en escenarios multi-tenant.
  • Las herramientas de alto riesgo necesitan aprobación o interceptación por política. Borrar, enviar, pagar, publicar, escribir en lote — no se puede confiar en el autocontrol del modelo.

Cuanto más humano parezca el Agent, más fácil resulta que un sistema asuma que hereda todos los permisos del humano. Desde la ingeniería, el Agent debería tener permisos acotados a la tarea, limitados en el tiempo y mínimos.



7. Middleware: meter las capacidades de protección en el ciclo de vida del runtime

Muchos equipos meten los guardrails en el prompt: "no filtres información privada", "no ejecutes operaciones peligrosas", "pregunta al usuario si dudas". Sirve, pero no basta.

Los modelos olvidan, los prompts se sobrescriben, las rutas de llamada a herramientas pueden esquivar las reglas, y el streaming y las tareas en background pueden comportarse de manera distinta. Un sistema de negocio necesita una línea de defensa más dura.

El diseño de middleware inserta puntos de control alrededor del ciclo de vida del Agent: antes de la llamada al modelo, durante la llamada al modelo, durante la llamada a una herramienta, y después de la llamada al modelo — todos pueden alojar política.

Eso significa que muchas capacidades de fiabilidad pueden bajar al Runtime:

  • Antes de una llamada al modelo: recortar contexto, inyectar información de permisos, comprobar presupuesto de tokens.
  • Durante una llamada al modelo: fallback de modelo, control de timeout, política de reintentos, contabilidad de coste.
  • Durante una llamada a una herramienta: chequeo de permisos, validación de parámetros, intercepción de acciones sensibles, aprobación humana.
  • Tras la salida del modelo: detección de PII, validación de formato, archivado de resultados, etiquetado de trace.

Esto es más estable que esparcir la lógica por cada herramienta y mucho más fácil de gobernar de manera uniforme.

Para un Agent de nivel empresarial, el middleware no es solo un filtro de seguridad — es el punto de entrada de la gobernabilidad del Runtime.



8. Streaming y double-texting: la fiabilidad de la interacción también pertenece al Runtime

Mucha gente trata el streaming como una optimización de UX. Para los Agents, el streaming también es un asunto de fiabilidad.

Si una tarea larga no tiene feedback en tiempo real, el usuario no sabe si el sistema sigue vivo ni en qué punto va. Sobre todo en investigación, programación, análisis de datos y generación de material didáctico, el usuario necesita ver el estado intermedio: recuperando, llamando a una herramienta, redactando, esperando confirmación.

Más complicado es la entrada del usuario a mitad de camino. El Agent sigue ejecutándose y el usuario envía una instrucción nueva — lo que LangChain llama un problema de double-texting. No es un detalle menor de UX. Es un problema de protocolo de interacción.

El sistema tiene que decidir: ¿la nueva entrada se encola o interrumpe la tarea actual? ¿Se fusiona con el contexto actual o se cancela y se reejecuta? ¿Se permite al usuario cambiar de objetivo a media tarea o debe esperar a que termine?

En sistemas de negocio, la respuesta correcta varía.

Un Agent de escritura puede dejar que el usuario ajuste el rumbo a mitad de tarea.

Un Agent de pagos no puede interrumpirse a la ligera y luego seguir con operaciones peligrosas.

Un Agent de planes de clase puede encajar bien con encolar la nueva entrada en una lista de tareas.

Un Agent de programación quizás necesite pausar el comando actual y esperar a que el usuario confirme un cambio de plan.

Por eso la experiencia de chat es, en realidad, parte del diseño del Runtime.



9. Observabilidad: no se depura un Agent de negocio solo con logs

Para aplicaciones tradicionales, logs, métricas y trazado distribuido suelen bastar. Para los Agents, los logs por sí solos a menudo no llegan.

Eso es porque muchos errores de Agent son errores de proceso: el paso 1 entendió mal la tarea, el paso 3 usó la herramienta equivocada, el paso 5 aceptó una recuperación de baja calidad, el paso 7 elevó un supuesto intermedio a conclusión. La respuesta final está mal, pero la causa real está enterrada en la ruta de ejecución.

LangChain/LangSmith insisten en trace, time travel y debug. Un Agent de nivel empresarial necesita más que una tasa de éxito de llamadas — necesita saber:

  • ¿Por qué nodos pasó esta tarea?
  • ¿Qué contexto vio realmente la llamada al modelo en cada paso?
  • ¿Qué herramientas se llamaron? ¿Con qué parámetros? ¿Devolviendo qué?
  • ¿Cómo cambió el estado intermedio?
  • ¿En qué paso se produjo una ramificación?
  • ¿Se dispararon middleware, aprobaciones, reintentos o fallbacks?
  • Si modificas el estado de un checkpoint concreto, ¿cambian los resultados aguas abajo?

Estas capacidades deciden si el Agent puede mejorarse de forma continua. Si no, el equipo solo está retocando prompts a ojo — y eso no es un bucle de ingeniería.

Más aún: la observabilidad también alimenta el eval. Las trazas no sirven solo para triage — se convierten en muestras de evaluación, tests de regresión, análisis de coste e insights de producto.



10. Un Agent Runtime tiene que escalar horizontalmente y controlar coste

En cuanto un Agent de negocio entra en producción y empieza a tener usuarios, aparecen las preocupaciones operativas.

Algunas tareas son cortas, otras son largas. Algunas solo leen datos; otras llaman a herramientas lentas. Algunos usuarios envían mensajes uno detrás de otro; algunas tareas se disparan por planificación. Las llamadas al modelo son caras; las llamadas a herramientas también pueden serlo. Cuando se acumulan tareas largas, el API server, los queue workers, Redis, Postgres y las herramientas externas se vuelven cuellos de botella.

Hay varias cosas en LangChain Agent Server de las que conviene aprender:

Separar API server de queue workers. El primero acepta peticiones; los segundos ejecutan tareas largas. Esto evita que las tareas largas tumben el servicio de entrada.

Estratificar estado efímero y estado durable. El estado transitorio puede vivir en algo como Redis; threads, runs, checkpoints y memoria van a almacenamiento durable.

La concurrencia es configurable. Distintos Agents tienen distintas formas de tarea — los workers I/O-heavy y CPU-heavy necesitan políticas de concurrencia distintas.

Evitar polling desde el frontend. Para tareas largas, join/stream gana a un polling tosco — tanto en UX como en coste de recursos del sistema.

Soportar cron. Muchos Agents de negocio no se disparan porque un usuario haga clic; necesitan ejecutar comprobaciones periódicas, resúmenes periódicos, sincronizaciones periódicas, generación periódica de contenido.

Un Agent Runtime fiable tiene que preocuparse a la vez de la semántica de la tarea y del coste de infraestructura.



11. Una lista de diseño de Runtime

Si no vas a copiar LangChain al pie de la letra, sino diseñar un runtime para tu propio Agent de negocio, aquí tienes una lista con la que descomponer la superficie de capacidades.

Uno: ciclo de vida de la tarea. ¿Tienes abstracciones básicas como thread, run y step? ¿Puede una ejecución de Agent ser rastreada, cancelada, pausada, reanudada o reintentada?

Dos: ejecución durable. ¿El estado clave de cada paso está checkpointed? ¿Dónde están las fronteras de recuperación? ¿Qué operaciones son reproducibles, cuáles tienen que ser idempotentes y cuáles solo pueden continuar tras confirmación humana?

Tres: estado por capas. ¿Están separados el estado a corto plazo, la memoria a largo plazo y los datos de negocio? ¿Hay namespaces? ¿Se soporta limpieza, migración y auditoría?

Cuatro: modelo de permisos. ¿En nombre de quién actúa el Agent? ¿A qué recursos puede acceder? ¿Qué herramientas puede llamar? ¿Cómo se gestionan las autorizaciones de sistemas externos? ¿Las operaciones de alto riesgo requieren aprobación?

Cinco: gobierno de herramientas. ¿Las herramientas tienen schema, permisos, timeout, reintentos, rate limit, auditoría? Cuando una herramienta falla, ¿reintentas, haces fallback, saltas o interrumpes?

Seis: human-in-the-loop. ¿Se puede interrumpir un run en pleno vuelo? ¿Se puede reanudar tras confirmación del usuario? ¿Son auditables el contenido de la aprobación, el aprobador y el momento?

Siete: protocolo de interacción. ¿Cómo está diseñado el streaming? ¿Cómo se maneja la entrada del usuario a mitad de camino? ¿Cuándo conviene encolar, rechazar, interrumpir o reiniciar?

Ocho: observabilidad y debugging. ¿Hay trazado estructurado? ¿Se pueden ver llamadas al modelo, llamadas a herramientas, cambios de estado y disparos de middleware? ¿Se pueden convertir los bad cases en evals?

Nueve: escalado operativo. ¿Están separados el servicio de entrada y los workers de ejecución? ¿Cómo está diseñada la cola? ¿Dónde están los cuellos de botella de almacenamiento? ¿Cómo aplicas rate limiting cuando se acumulan tareas largas? ¿Cómo se atribuye el coste?

Diez: fronteras de despliegue. ¿Qué te auto-hospedas y qué delegas en una plataforma gestionada? ¿Los datos pueden quedarse dentro de tu sistema? ¿No te estás amarrando demasiado a un runtime concreto?



12. Cierre

Los productos de Agent no solo persiguen ser más inteligentes. Cuando entran en un sistema de negocio, importa tanto o más ser más fiables: recuperables, aislables, aprobables, trazables, escalables y con coste controlable.

Por eso conviene mirar Agent Harness y Runtime por separado. El Harness fija el techo de lo que puede hacer un Agent. El Runtime fija el suelo bajo el cual no se puede lanzar con seguridad. Sin el primero, el Agent no es lo bastante inteligente; sin el segundo, el Agent no puede salir a producción.

Si vamos a construir nuestros propios Agents de nivel producción, el Runtime debería entrar en la arquitectura desde el día uno. Aunque la v1 no sea un sistema completo, primero hay que definir las fronteras: cómo se guarda el estado de la tarea, cómo se transmite la identidad del usuario, cómo se controlan los permisos de las herramientas, cómo recupera la aprobación humana, cómo se sedimentan las trazas como datos de evaluación.

El futuro de los Agents no es solo modelos más potentes — también es un Runtime más maduro. Quien consiga que la ejecución de un Agent complejo sea estable, controlable y auditable estará más cerca del despliegue real en negocio.

Eso es lo que más me parece digno de aprender del artículo de LangChain sobre Runtime.



Referencias