Contenido del curso
El Núcleo del Agente: Estado y LLMs
Lógica y Estructura de Nodos
Agentes ReAct
Grafos Avanzados y Colaboración
- 17

Enrutamiento de agentes con conditional edge en LangGraph
09:49 min - 18

Routing inteligente con LLM para derivar conversaciones automáticamente
22:14 min - 19

Paralelización de nodos en agentes con LangGraph
06:58 min - 20

Desarrollo de un agente de code review con análisis paralelo
15:47 min - 21

Patrón orchestrator para selección dinámica de nodos en paralelo
16:31 min - 22

Evaluator Optimizer: ciclos de autocrítica para agentes de IA
12:48 min
Puesta en Producción
Persistencia de memoria en LangGraph con Postgres
Resumen
Conectar tu agente de LangGraph a una base de datos Postgres es el paso que transforma una demo en una aplicación real con memoria. Aquí verás cómo integrar el checkpointer de Postgres con FastAPI para que tu agente recuerde conversaciones, mantenga el estado por thread y siga siendo debugueable desde LangGraph Studio.
¿Por qué construir el grafo de forma dinámica en LangGraph?
La clave está en no instanciar el agente con un checkpoint fijo dentro del archivo, sino envolverlo en una función que reciba la configuración por parámetro. Esto te da lo mejor de dos mundos: puedes seguir debugueando con LangGraph Studio y, al mismo tiempo, inyectar la conexión a Postgres desde FastAPI.
En la clase se crea una función llamada make_graph que recibe un config tipado como TypedDict. Dentro de ese config viaja el checkpoint, y si no llega ninguno, queda en None por defecto, lo que permite que LangGraph Studio use su propio checkpointer en memoria [02:15].
¿Qué es un checkpoint en LangGraph? Es la instancia que guarda el estado del grafo entre ejecuciones. Si usas
PostgresSaver, ese estado persiste en tablas dedicadas dentro de tu base de datos.
¿Cómo queda el método make_graph?
La función recibe el config, extrae el checkpoint y se lo pasa al constructor del agente al hacer return. Cuando llamas a support desde LangGraph Studio, en lugar de invocar al agente directo, invocas make_graph y Studio se encarga de inyectar su propio checkpoint para debuguear.
Esto significa que el mismo código sirve para producción y para desarrollo, sin duplicar lógica.
¿Cómo configurar el checkpointer de Postgres con FastAPI?
La integración se hace con el ciclo de vida (lifespan) de FastAPI, que permite ejecutar código antes de levantar la aplicación. Eso es ideal para abrir la conexión a Postgres una sola vez y reutilizarla [05:40].
El patrón usa tres piezas:
- Una variable global que arranca en
Noney guarda la instancia del checkpoint. - Una función asíncrona de lifespan que crea la conexión, instancia el
PostgresSavery ejecutasetup()para crear las tablas necesarias. - Una función getter que devuelve el checkpoint o lanza un error si no existe, expuesta como dependencia de FastAPI.
¿Dónde guardo la cadena de conexión?
En la demo la cadena queda hardcoded apuntando al contenedor Docker de Postgres, pero lo recomendable es leerla desde una variable de ambiente. Quemar el password en el código expone credenciales y rompe cualquier buena práctica de seguridad.
¿Qué hace el método setup() del PostgresSaver? Crea automáticamente las tablas que LangGraph necesita para guardar el estado del grafo, asociadas al
thread_idde cada conversación.
¿Cómo inyectar el checkpoint en los endpoints de FastAPI?
En el endpoint /chat declaras un parámetro tipo CheckpointerDep, que es la dependencia que resuelve la función getter. FastAPI se encarga de pasarte la instancia ya conectada cada vez que entra una petición [08:20].
Dentro del handler haces:
- Llamas a
make_graphenviándole el checkpoint en el config. - Recibes el agente ya construido con memoria persistente.
- Invocas el agente con el
stateinicial, que incluye los mensajes y campos comocustomer_name. - Asocias todo a un
thread_idúnico por conversación.
El thread_id es lo que separa una memoria de otra. Si cambias el ID, arrancas una conversación desde cero.
¿Y el endpoint de stream?
Mismo patrón: también necesita la dependencia del checkpoint y debe llamar a make_graph en lugar del agente directo. Si olvidas este detalle, FastAPI levanta pero el endpoint falla con internal server error, como pasó en la demo.
¿Por qué se ensucia el historial de la conversación?
Al probar el flujo aparece un detalle importante: cuando guardas el AIMessage completo en el estado, también guardas metadata, formato enriquecido y referencias a herramientas como file_search. Ese ruido viaja después al language model en las siguientes llamadas y corrompe el contexto.
El error típico que aparece es invalid value file_search, support image, que se dispara cuando el RAG de OpenAI recibe un payload contaminado.
¿Cómo limpiar el AIMessage antes de persistirlo?
Dentro del nodo de conversation parseas el mensaje y extraes solo el texto. Descartas metadata, anotaciones y estructuras anidadas, salvo que tu agente genere contenido enriquecido como imágenes. Después de este ajuste necesitas crear un thread nuevo, porque el historial viejo ya quedó sucio en la base de datos.
Una vez aplicado el fix, el historial queda limpio: aparece un HumanMessage con tu texto y un AIMessage con la respuesta plana, sin ruido. El agente de booking, que sí consume todo el historial, ahora puede recordar que te llamas Nicolás y agendar la cita con el doctor Pérez sin perder contexto.
¿Qué diferencia hay entre el agente de conversation y el de booking?
El de conversation solo toma el último mensaje y lo manda al RAG. No tiene memoria conversacional a menos que se la inyectes vía prompt o estado compartido. El de booking es un query rig agent que sí recibe el historial completo, y por eso es el más afectado cuando los mensajes vienen con metadata sucia.
Métodos útiles del agente que vale la pena conocer: get_graph, get_state, get_state_history y get_prompt. Te permiten inspeccionar el estado en cualquier punto sin tener que reconstruirlo desde la base de datos [12:30].
¿Ya estás guardando tus conversaciones en Postgres o sigues usando memoria en RAM? Cuéntame en los comentarios cómo manejas el thread_id en tu aplicación.