Módulo 8: Memoria y Persistencia
Introducción: Por Qué los Agentes Necesitan Memoria
Descripción
Tu AI Research Assistant es robusto. Tiene retry con backoff exponencial, búsqueda paralela en múltiples fuentes, merge con deduplicación, y graceful degradation cuando una fuente falla. Lo construiste en el Módulo 7 y funciona en el mundo real.
Pero es amnésico. Cada ejecución empieza de cero.
Cierra el terminal, ábrelo de nuevo, y tu agente no tiene idea de que hace 5 minutos estaba a mitad de una investigación sobre RAG. El usuario vuelve mañana y pregunta "¿puedes profundizar en lo que encontraste ayer?" — el agente no sabe de qué le hablas. Una investigación que llevaba 5 minutos procesando 3 de 5 fuentes se interrumpe por un crash del sistema — todo ese trabajo se pierde.
Esto no es un edge case. Es lo que le pasa a cualquier sistema stateless en producción. Y es exactamente lo que diferencia un demo de un producto que puedes poner frente a usuarios reales.
Por qué importa: Sin memoria y persistencia, los Módulos 9-12 no son posibles. Human-in-the-loop (M9) requiere que el agente guarde su estado para pausarse y esperar aprobación. Multi-agent (M10) requiere que agentes compartan contexto. Producción (M12) requiere que nada se pierda. Este módulo es la base técnica de todo lo que viene.
¿Dónde estamos en la guía?
Este es el Módulo 8 de la guía LangChain & LangGraph: From Chains to Agents. Es el primer módulo del Bloque 3 (LangGraph Avanzado).
Bloque 1: LangChain Core (Módulos 1-4) ✅ Completado
Bloque 2: LangGraph Fundamentals (Módulos 5-7) ✅ Completado
Bloque 3: LangGraph Avanzado (Módulos 8-10) ← ESTÁS AQUÍ (Módulo 8)
Bloque 4: Producción (Módulos 11-12)
Tu progreso:
Bloque 1 — LangChain Core ✅ Completado
│
│ Módulo 1: Modelos y Proveedores ✅
│ Módulo 2: Tools y Tool Calling ✅
│ Módulo 3: Agents (create_agent) ✅
│ Módulo 4: Middleware y Customización ✅
│
▼
Bloque 2 — LangGraph Fundamentals ✅ Completado
│
│ Módulo 5: Introducción a LangGraph ✅
│ Módulo 6: Functional API ✅
│ Módulo 7: Flujos Avanzados ✅
│
▼
Bloque 3 — LangGraph Avanzado
│
│ Módulo 8: Memoria y Persistencia ← ESTÁS AQUÍ
│ Módulo 9: Human-in-the-Loop 🔒 Siguiente
│ Módulo 10: Multi-Agent Systems 🔒
│
▼
Bloque 4 — Producción 🔒
│
│ Módulo 11: Deep Agents 🔒
│ Módulo 12: LangSmith y Producción 🔒
El Bloque 2 te dio las herramientas de construcción: StateGraph, Functional API, retry, branching, error handling. El Bloque 3 las convierte en capacidades enterprise: persistencia (este módulo), supervisión humana (M9), y colaboración multi-agente (M10).
El puente desde el Módulo 7
Lo que ya tienes
Tu Research Agent v2 es un sistema robusto:
- ✅ Retry con backoff exponencial cuando las APIs fallan
- ✅ Búsqueda paralela en 3 fuentes simultáneamente
- ✅ Merge con deduplicación de resultados
- ✅ Graceful degradation: si una fuente falla, el reporte se genera con las que respondieron
- ✅ Logging estructurado para trazabilidad
Lo que le falta
Ejecuta esta secuencia mental:
Escenario 1 — Crash a mitad del proceso:
Tu agente lleva 5 minutos investigando "state of AI in healthcare 2025"
Procesó 3 de 5 fuentes exitosamente
La máquina se reinicia (actualización de OS, crash, cierre accidental)
Sin persistencia: empiezas de cero. 5 minutos + costos de API perdidos.
Con persistencia: resumes desde la fuente 4. 30 segundos.
Escenario 2 — El usuario vuelve mañana:
Hoy: "Investiga las tendencias de RAG en 2025"
Mañana: "¿Puedes profundizar en lo que encontraste ayer sobre hybrid search?"
Sin memoria: "No tengo información sobre investigaciones previas."
Con memoria: "Ayer encontré 3 papers sobre hybrid search. Profundizo en ellos."
Escenario 3 — Múltiples usuarios:
Usuario A investiga IA en salud. Usuario B investiga IA en finanzas.
Ambos usan el mismo agente desplegado.
Sin aislamiento: las conversaciones se mezclan.
Con thread_id: cada usuario tiene su propio contexto aislado.
Estos tres problemas — crash recovery, memoria entre sesiones, y multi-usuario — son exactamente lo que resuelve este módulo.
Los dos tipos de memoria (no los confundas)
Esta distinción es fundamental. Confundir short-term y long-term memory es el error más común al trabajar con agentes stateful. Son conceptos completamente diferentes con implementaciones diferentes.
Short-term memory: la conversación actual
Short-term memory es el historial de mensajes dentro de la sesión actual. Es lo que permite que el agente mantenga contexto entre turnos de conversación:
Turno 1 — Usuario: "¿Qué es RAG?"
Turno 1 — Agente: "RAG es Retrieval-Augmented Generation, un patrón que..."
Turno 2 — Usuario: "¿Me das un ejemplo?"
↑ Sin short-term memory, el agente no sabe a qué se refiere "un ejemplo"
↑ Con short-term memory, sabe que "un ejemplo" se refiere a RAG
Características:
- ✅ Existe dentro de una sesión (una conversación)
- ✅ Incluye: mensajes del usuario, respuestas del agente, tool calls, resultados de tools
- ✅ Se gestiona con
MessagesStateythread_id - ✅ Tiene un límite práctico: el context window del modelo (128K tokens en GPT-4.1)
- ❌ Se pierde cuando la sesión termina (a menos que uses checkpointing)
Long-term memory: lo que persiste entre sesiones
Long-term memory es información que sobrevive entre conversaciones diferentes. No son mensajes — son datos estructurados que el agente acumula y consulta:
Sesión 1 (lunes):
Usuario investiga "AI in healthcare"
Agente guarda: preferencia por fuentes académicas, interés en diagnóstico médico
Sesión 2 (miércoles):
Usuario: "Investiga algo nuevo"
Agente consulta long-term memory:
→ "Este usuario prefiere fuentes académicas"
→ "Sus temas previos incluyen IA en salud, especialmente diagnóstico"
→ Adapta la búsqueda automáticamente
Características:
- ✅ Persiste entre sesiones diferentes (días, semanas)
- ✅ Incluye: preferencias del usuario, conocimiento acumulado, perfiles de intereses
- ✅ Se gestiona con
InMemoryStoreo bases de datos externas - ✅ No está limitada por el context window — se almacena fuera del modelo
- ❌ Requiere diseño explícito: qué guardar, cuándo consultarlo, cómo actualizarlo
Episodic memory: interacciones pasadas específicas
Episodic memory es un subconjunto de long-term memory que se refiere a interacciones específicas que el agente puede referenciar:
Usuario: "¿Recuerdas lo que encontraste la última vez sobre RAG?"
Agente consulta episodic memory:
→ Sesión del 3 de marzo: investigó RAG, encontró 5 papers, conclusión principal fue...
→ "Sí, la última vez encontré que hybrid search supera a dense retrieval en un 15%..."
No es un sistema separado — es cómo usas la long-term memory para recordar eventos pasados.
Tabla comparativa
| Aspecto | Short-term | Long-term | Episodic |
|---|---|---|---|
| Alcance | Una sesión | Todas las sesiones | Sesiones específicas |
| Contenido | Mensajes, tool calls | Preferencias, perfiles | Eventos pasados |
| Límite | Context window | Almacenamiento externo | Almacenamiento externo |
| Implementación | MessagesState | InMemoryStore / DB | Subset de long-term |
| Se pierde si... | La sesión termina | Se borra el store | Se borra el store |
| Ejemplo | "Acabas de preguntar sobre RAG" | "Prefieres fuentes académicas" | "El lunes investigaste healthcare" |
Stateless vs stateful: por qué importa
Agente stateless (lo que tienes ahora)
result = agent.invoke({"query": "¿Qué es RAG?"})
# El agente responde, y olvida todo inmediatamente.
result = agent.invoke({"query": "Dame más detalles"})
# "¿Más detalles sobre qué? No tengo contexto previo."
Cada invoke() es una isla. No hay conexión entre llamadas. Es como hablar con alguien que tiene amnesia anterógrada: cada interacción empieza desde cero.
Agente stateful (lo que construirás)
config = {"configurable": {"thread_id": "user_123"}}
result = agent.invoke({"query": "¿Qué es RAG?"}, config)
# El agente responde Y guarda la conversación en el thread "user_123"
result = agent.invoke({"query": "Dame más detalles"}, config)
# El agente lee el historial del thread "user_123"
# Sabe que "más detalles" se refiere a RAG
# Responde con contexto
El thread_id es la clave. Cada thread es una conversación independiente con su propio historial. Mismo agente, diferentes threads, diferentes contextos. Así funciona el multi-usuario.
El stack de persistencia
LangGraph tiene un diseño deliberado para persistencia: empiezas simple para desarrollo, y migras a producción cambiando una línea.
MemorySaver: desarrollo y testing
from langgraph.checkpoint.memory import MemorySaver
checkpointer = MemorySaver()
graph = builder.compile(checkpointer=checkpointer)
- ✅ Zero config: no necesitas base de datos, no necesitas Docker
- ✅ Perfecto para desarrollo: pruebas rápidas, iteración, debugging
- ❌ In-memory: si el proceso se reinicia, se pierde todo
- ❌ Single-process: no funciona con múltiples workers
Usa MemorySaver para: prototipar, testear, desarrollo local, tutoriales.
PostgresSaver: producción
from langgraph.checkpoint.postgres import PostgresSaver
checkpointer = PostgresSaver.from_conn_string("postgresql://user:pass@host:5432/db")
graph = builder.compile(checkpointer=checkpointer)
- ✅ Durable: sobrevive a reinicios del proceso, crashes, deployments
- ✅ Multi-process: múltiples workers pueden leer y escribir
- ✅ Escalable: PostgreSQL es battle-tested para producción
- ❌ Requiere una instancia de PostgreSQL
Usa PostgresSaver para: producción, staging, cualquier entorno donde la durabilidad importa.
La migración es trivial
Mira el cambio:
# Desarrollo
checkpointer = MemorySaver()
# Producción (la ÚNICA línea que cambia)
checkpointer = PostgresSaver.from_conn_string(os.getenv("DATABASE_URL"))
# El resto del código es IDÉNTICO
graph = builder.compile(checkpointer=checkpointer)
Una línea. El resto de tu código — nodos, edges, estado, lógica — no cambia absolutamente nada. Esa es la abstracción bien diseñada: el checkpointer es un backend intercambiable.
Mapa del módulo
| # | Cápsula | Qué aprenderás | Tipo |
|---|---|---|---|
| 01 | Introducción (esta) | Por qué los agentes necesitan memoria, tipos de memoria, stack de persistencia | Intro |
| 02 | Short-term memory: conversation history | MessagesState, thread_id, message trimming, summarization | Técnica |
| 03 | Checkpointing: MemorySaver | Checkpoint automático, inspeccionar estados, thread management | Técnica |
| 04 | Durable execution y crash recovery | Simular crashes, resume desde checkpoint, idempotencia | Técnica |
| 05 | Time-travel debugging | Navegar historial de estados, replay, debugging de decisiones | Técnica |
| 06 | Long-term memory con Store | InMemoryStore, namespaces, guardar y consultar datos entre sesiones | Técnica |
| 07 | PostgresSaver: persistencia en producción | Setup PostgreSQL, migración desde MemorySaver, multi-worker | Técnica |
| 08 | Proyecto: Research Agent con memoria | Research Agent v3: checkpointing + long-term memory + multi-usuario | Proyecto |
Flujo de aprendizaje
Empiezas con short-term memory (cápsula 02) — el concepto más inmediato: cómo mantener contexto entre turnos de conversación. Luego aprendes checkpointing (cápsula 03) — el mecanismo que guarda el estado del agente en cada paso. Con checkpointing, implementas crash recovery (cápsula 04) — el agente sobrevive a interrupciones y resume donde quedó. Después, usas los checkpoints para time-travel debugging (cápsula 05) — navegas el historial de estados y entiendes por qué el agente tomó cada decisión. Agregas long-term memory (cápsula 06) — información que persiste entre sesiones. Migras a PostgresSaver (cápsula 07) — persistencia real para producción. Finalmente, integras todo en el Research Agent v3 (cápsula 08).
La progresión es: conversación → checkpoints → durabilidad → debugging → memoria persistente → producción → proyecto.
Conexión con el proyecto
Research Agent v3: el agente que recuerda
Tu Research Agent evoluciona significativamente en este módulo:
v1 (Módulo 6): Funcional pero frágil
↓
v2 (Módulo 7): Robusto (retry, branching, error handling)
↓
v3 (Este módulo): Persistente (checkpointing, memoria, multi-usuario)
│
│ + Checkpointing: investigaciones se guardan paso a paso
│ + Crash recovery: si se interrumpe, resume donde quedó
│ + Long-term memory: recuerda preferencias entre sesiones
│ + Thread management: multi-usuario con contexto aislado
│
▼
v4 (Módulo 9): + Aprobaciones humanas antes de acciones costosas
La prueba de éxito es concreta: cierra el terminal, abre uno nuevo, ejecuta tu agente con el mismo thread_id — y recuerda la investigación anterior. Ese momento, cuando ves que el agente "sabe" lo que investigaste hace una hora, es cuando este módulo hace clic.
Conexión con el Módulo 9: Human-in-the-Loop
La persistencia es prerequisito técnico para human-in-the-loop. La razón es directa:
Sin persistencia:
Agente: "Voy a ejecutar una búsqueda costosa en 5 APIs"
Sistema: interrupt() — pausar para aprobación humana
??? El agente perdió su estado. No sabe dónde estaba.
Con persistencia:
Agente: "Voy a ejecutar una búsqueda costosa en 5 APIs"
Sistema: interrupt() — pausar para aprobación humana
Estado guardado en checkpoint con thread_id
... 10 minutos después ...
Humano: "Aprobado"
Sistema: resume desde checkpoint — el agente continúa exactamente donde pausó
Sin checkpointing, interrupt() no tiene sentido — el agente no puede pausarse y resumir si no tiene estado persistente. Por eso este módulo viene antes del M9.
Qué NO cubre este módulo
- ❌ Vector stores y RAG — Guardar embeddings para búsqueda semántica es un tema diferente. Este módulo trata sobre el estado del agente (conversaciones, checkpoints, preferencias), no sobre knowledge bases externas.
- ❌ Bases de datos de conocimiento — No construimos un sistema de retrieval. La long-term memory aquí son preferencias y perfiles, no documentos indexados.
- ❌ Redis como backend — Mencionamos que existe como opción, pero nos enfocamos en MemorySaver (dev) y PostgresSaver (prod). Redis es útil para caching y sesiones efímeras.
- ❌ Human-in-the-loop — Mencionamos que la persistencia lo habilita, pero la implementación de interrupts y approvals es del Módulo 9.
- ❌ Multi-agent memory sharing — Cómo comparten memoria múltiples agentes se cubre en el Módulo 10.
Setup técnico
Prerequisitos
- ✅ Módulo 7 completado — tienes un Research Agent v2 con retry, branching, y error handling
- ✅ Python 3.11+ instalado
- ✅ Al menos una API key de un proveedor (OpenAI recomendado)
Instalación
Si completaste el Módulo 7, ya tienes las dependencias principales. Agrega el paquete de checkpointing para PostgreSQL (lo usarás en la cápsula 07):
pip install langgraph langchain-openai python-dotenv langgraph-checkpoint-postgres
Verifica que la importación funciona:
from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import MessagesState
print("MemorySaver disponible")
print("MessagesState disponible")
# Output esperado:
# MemorySaver disponible
# MessagesState disponible
Variables de entorno
Tu .env del Módulo 7 sigue funcionando:
# .env
OPENAI_API_KEY=sk-...
# Para la cápsula 07 (PostgresSaver), agregarás:
# DATABASE_URL=postgresql://user:password@localhost:5432/langgraph_db
Verificación rápida: agente con memoria
Ejecuta este script para verificar que el checkpointing funciona:
from langgraph.graph import StateGraph, MessagesState, START, END
from langgraph.checkpoint.memory import MemorySaver
def echo(state: MessagesState) -> dict:
last_message = state["messages"][-1].content
return {"messages": [{"role": "assistant", "content": f"Echo: {last_message}"}]}
builder = StateGraph(MessagesState)
builder.add_node("echo", echo)
builder.add_edge(START, "echo")
builder.add_edge("echo", END)
checkpointer = MemorySaver()
graph = builder.compile(checkpointer=checkpointer)
config = {"configurable": {"thread_id": "test_001"}}
result1 = graph.invoke({"messages": [{"role": "user", "content": "Hola"}]}, config)
print(f"Turno 1: {result1['messages'][-1].content}")
result2 = graph.invoke({"messages": [{"role": "user", "content": "¿Recuerdas qué dije?"}]}, config)
print(f"Turno 2: {result2['messages'][-1].content}")
print(f"Mensajes en historial: {len(result2['messages'])}")
# Output esperado:
# Turno 1: Echo: Hola
# Turno 2: Echo: ¿Recuerdas qué dije?
# Mensajes en historial: 4
Si ves 4 mensajes en el historial (2 del usuario + 2 del agente), el checkpointing está funcionando. El agente acumula mensajes entre invocaciones gracias al thread_id.
Evidencia de éxito
Al terminar este módulo, sabrás que tuviste éxito si:
- ✅ Tu agente mantiene conversación con contexto: puedes referirte a mensajes anteriores y el agente entiende
- ✅ Puedes cerrar el terminal, abrir uno nuevo, y el agente recuerda la conversación anterior (con PostgresSaver)
- ✅ Simulas un crash a mitad de una investigación y el agente resume exactamente donde quedó
- ✅ Puedes navegar el historial de estados del agente y ver qué estado tenía en cada paso (time-travel)
- ✅ El agente recuerda preferencias del usuario entre sesiones diferentes (long-term memory)
- ✅ Dos usuarios diferentes usan el mismo agente con contextos completamente aislados (thread_id)
Test de autoevaluación
Si puedes responder estas preguntas, vas por buen camino:
- ¿Cuál es la diferencia entre short-term y long-term memory en un agente?
- ¿Por qué MemorySaver no es adecuado para producción?
- ¿Qué pasa si no implementas message trimming en una conversación larga?
- ¿Cómo permite el checkpointing que un agente se pause y resuma?
- ¿Qué es un
thread_idy por qué es necesario para multi-usuario?
Resumen
- Tu Research Agent v2 es robusto, pero amnésico: cada ejecución empieza de cero. Sin persistencia, los crashes destruyen trabajo, los usuarios no tienen continuidad, y no hay aislamiento multi-usuario
- Short-term memory es el historial de la conversación actual — mensajes, tool calls, resultados. Se gestiona con
MessagesStateythread_id - Long-term memory es información que persiste entre sesiones — preferencias, perfiles, conocimiento acumulado. Se gestiona con
InMemoryStoreo bases de datos - Episodic memory es un subset de long-term: interacciones pasadas específicas que el agente puede referenciar
- MemorySaver = desarrollo y testing (in-memory, zero config). PostgresSaver = producción (durable, multi-process). La migración es una línea de código
- La persistencia es prerequisito para human-in-the-loop (M9): el agente necesita estado guardado para pausarse y resumir
- Este módulo transforma el Research Agent de un prototipo que "funciona" a un sistema que recuerda — la diferencia entre un demo y un producto
Recursos adicionales
- LangGraph — Persistence — Documentación oficial sobre el sistema de persistencia de LangGraph: checkpointers, threads, estado
- LangGraph — Memory — Conceptos de short-term y long-term memory en LangGraph
- How to add memory to chatbots — Guía práctica para agregar historial de conversación
- How to add cross-thread memory — Implementar long-term memory que persiste entre threads
- LangGraph Checkpoint PostgreSQL — Setup de PostgresSaver para producción
- Designing AI Agents with Memory — LangChain Blog — Artículo sobre patrones de memoria para agentes
Módulo 8 — LangChain & LangGraph: From Chains to Agents
Siguiente cápsula: Short-term Memory: Conversation History — aprenderás cómo MessagesState gestiona el historial de conversación, cómo thread_id aísla contextos por usuario, y por qué message trimming es obligatorio para producción.