[!NOTE] Traducción automática Este artículo se tradujo automáticamente a partir de la versión original en inglés.
AI Arquitectura de memoria de agentes en 2026: Checkpoints, almacenes vectoriales y memoria basada en archivos
Parte 2 de la serie de ingeniería de la pila Agentic
Un reasoning loop solo puede persistir durante una única solicitud, a menos que su estado se almacene fuera del worker. Sin memoria de agente, el agente no puede reanudar un plan pausado, recuperarse tras una caída o recuperar una preferencia de una sesión anterior. Parte 1 Se abordó el flujo de control. Este artículo indica qué estado necesita cada turno posterior y dónde debe residir dicho estado.
Explicaré en detalle la arquitectura de memoria del Agente Analista de Mercado, Se mostrará cómo los almacenes de vectores checkpoints calientes y fríos, junto con la memoria de documentos basada en archivos, colaboran entre sí para permitir la ejecución de agentes de larga duración. A continuación, se analizará en qué casos resultan adecuados PostgreSQL, Redis, Qdrant, los almacenes clave-valor y los archivos de Markdown simples.
TL;DR: Separa la memoria según el patrón de acceso. La memoria caliente representa el estado a nivel de hilo checkpoint necesario para realizar pausas y reanudaciones. La memoria fría almacena datos entre sesiones en un sistema de almacenamiento de tipo clave-valor o vectorial. La memoria documental conserva el conocimiento del proyecto en archivos que se pueden inspeccionar. Comienza por identificar el fallo que debes solucionar y, a continuación, elige el tipo de almacenamiento adecuado. No introduzcas datos precisos en un sistema de recuperación basado en patrones difusos, ni trates a un checkpoint como un registro de auditoría.
¿Qué es la memoria del agente AI?
AI memoria del agente es la capa de estado que permite a un agente conservar el progreso de las tareas, recuperar conocimientos previos y actualizar sus datos a lo largo de diferentes ejecuciones. En entornos de producción, no se trata de una única base de datos vectorial, sino de una combinación de almacenamientos checkpoints activos, almacenamientos semánticos o estructurados pasivos, además de una memoria de documentos legible por humanos.
| Necesito | Mejor valor predeterminado | ¿Por qué? |
|---|---|---|
| Pausar y reanudar una ejecución | PostgreSQL checkpoint de almacenamiento | Datos de la aplicación duraderos, consultables y fáciles de operar |
| Estado transitorio de baja latencia | Almacén Redis checkpoint | Recuperación rápida y estado de corta duración, con compromisos en cuanto a la persistencia |
| Recuperación semántica entre sesiones | Qdrant o pgvector | Recupera los recuerdos por su significado, y no solo mediante claves exactas. |
| Hechos estructurados del usuario | PostgreSQL o almacén clave-valor | Las actualizaciones determinísticas superan a la recuperación difusa en el caso de preferencias e identificadores. |
| Convenciones del proyecto y procedimientos establecidos | Archivos en formato Markdown o JSON | Legible para humanos, apto para realizar diferencias y fácil de actualizar por parte de los agentes |
| Memoria de relaciones entre múltiples entidades | Gráfico de conocimiento |
No comience hablando de la memoria, ya que suena a algo relacionado con la inteligencia artificial. En su lugar, aborde el fallo visible para el usuario: la pérdida del progreso, el olvido de una preferencia, la repetición de tareas de investigación o la imposibilidad de reutilizar una convención establecida en un proyecto.
Los fallos que requieren memoria
Un agente sin estado puede responder a una pregunta aislada, pero olvida la solicitud en cuanto finaliza la llamada. Dicho diseño falla cuando el producto requiere alguno de los siguientes comportamientos:
- Pausa y reanudación: un usuario inicia una tarea de investigación, cierra su portátil y vuelve al día siguiente. Sin un estado con puntos de control, el agente debe reiniciarse desde cero.
- Coherencia en múltiples turnos: durante una conversación prolongada, el agente debe recordar qué herramientas ha utilizado, qué datos ha recopilado y qué pasos del plan ha completado.
- Personalización: un usuario que regresa espera que el agente conozca su tolerancia al riesgo, el nivel de profundidad analítica preferido y sus interacciones anteriores.
- Human-in-the-loop (HITL): el agente elabora un informe y espera la aprobación. El estado de “espera” debe mantenerse intacto incluso tras los reinicios del proceso.
En el Agente Analista de Mercado desde Parte 1, La solicitud “Analizar NVDA” genera un plan, cinco tool calls, los datos recopilados y un borrador de informe. Cuando el usuario responde “parece bien, pero añada un análisis de la competencia”, un almacén de checkpoint permite al agente cargar el estado del nodo anterior y agregar la fase correspondiente al análisis de la competencia. Sin un estado guardado en puntos de control, no puede determinar a qué se refiere la expresión “parece bien” y debe comenzar todo de nuevo.
La memoria a largo plazo maneja un caso diferente. Si el usuario vuelve una semana después y pregunta: “Actualiza mi análisis de NVDA”, el agente podría necesitar recordar su preferencia por evaluaciones de riesgo conservadoras y su interés en acciones de semiconductores. Un almacén de memoria basado en vectores puede recuperar esos datos entre sesiones sin tener que solicitarlos nuevamente.
LangGraph divide los datos según su ámbito de aplicación. Cada ejecución del grafo tiene lugar dentro de un hilo, es decir, para una conversación o tarea concreta. El estado persistente dentro de dicho hilo se denomina memoria a corto plazo. El estado compartido entre hilos, por su parte, constituye la memoria a largo plazo. El contexto actual del modelo y las variables en proceso forman la capa de memoria de trabajo que se sitúa por encima de ambas almacenaciones.
Una taxonomía de la memoria de agente AI
Antes de pasar a la implementación, resulta útil clasificar qué es lo que los agentes deben recordar. CoALA framework (Sumers, Yao et al., 2023) constituye la taxonomía estándar y se basa en la ciencia cognitiva. Yo introduje el concepto de alcance de la memoria en mi trabajo. context engineering publicación; Aquí lo desgloso en seis categorías:
| Tipo de memoria | Alcance | Vida útil | Ejemplo | Patrón de almacenamiento |
|---|---|---|---|---|
| En funcionamiento | Paso actual | Milisegundos | Tool call argumentos, respuesta actual LLM | |
| A corto plazo | Hilo actual | Minutos–horas | Historial de conversación, avance del plan, datos recopilados | Checkpoint almacenar |
| Episódico | Entre hilos | Días–meses | La semana pasada, el usuario preguntó por los resultados financieros de NVDA. | Almacén de vectores / Almacén KV |
| Semántico | Entre hilos | Meses: permanente | ”El usuario prefiere inversiones conservadoras” | Almacén de vectores / Almacén KV |
| Documento | Entre hilos | Días – permanente | Notas del proyecto, resúmenes de investigación, patrones aprendidos | Almacén de archivos (Markdown/JSON) |
| Procedimental | A nivel de sistema | Permanente | Al analizar acciones, siempre hay que revisar los documentos presentados ante la SEC. | Configuración / system prompt |
Memoria de trabajo es aquello con lo que el LLM está razonando activamente en este momento: las variables de Python de la función actual, el contenido de la ventana de contexto y los argumentos de tool call durante su ejecución. Se trata de la capa más rápida, pero también la más efímera, ya que nada permanece más allá del paso actual. La memoria de trabajo está limitada por la ventana de contexto del modelo, lo que la convierte en el cuello de botella real. Todo lo que el agente “sabe” en el momento de tomar una decisión debe caber aquí, independientemente de si proviene del almacenamiento de checkpoint, de una consulta vectorial o de la lectura de un archivo. Las demás capas existen para suministrar la información adecuada a la memoria de trabajo en el momento oportuno.
Memoria a corto plazo es la información que LangGraph escribe después de cada nodo mediante el checkpoint. Las memorias episódicas y semánticas persisten a lo largo de los hilos de ejecución. La memoria de documentos almacena notas del proyecto, resúmenes de investigación y convenciones aprendidas en archivos que tanto las personas como los agentes pueden consultar. Por su parte, la memoria procedural se encuentra en las instrucciones del sistema y las definiciones de herramientas, por lo que no varía para cada usuario.
Para su implementación, estas categorías se reducen a tres niveles. La memoria caliente almacena la sesión actual. La memoria fría permite recuperar información entre sesiones distintas. La memoria de documentos mantiene el conocimiento acumulado del proyecto en un estado legible y directamente editable.
La clase CoALA clasifica la memoria de trabajo, la memoria episódica, la memoria semántica y la memoria procedimental. La memoria en la era de los agentes AI: una revisión Destaca los almacenes vectoriales y los grafos de conocimiento, mientras que LangGraph documenta checkpoints y su interfaz Store. El conocimiento de los proyectos almacenado en archivos queda fuera de esas taxonomías, aunque herramientas como Claude Code, Cursor, Windsurf y Devin cargan archivos de proyecto persistentes.
El mismo patrón de almacenamiento se observa en otros dominios. Voyager almacena habilidades reutilizables para juegos como bibliotecas de código, los equipos de ECR3 trabajaron en documentos procedurales prompt, y la Memoria de Flujo de Trabajo de Agente permite generar flujos de trabajo web reutilizables a partir de episodios exitosos. Los archivos hacen que dicho conocimiento sea inspeccionable y versionable, sin necesidad de un servicio embedding separado.
La memoria gestionada por un agente también difiere de una RAG pipeline fija en cuanto a quién realiza la escritura. El agente o su harness decide qué datos almacenar, actualizar o eliminar, y posteriormente elige el momento adecuado para recuperarlos.
El Artículo sobre Agentes Generativos (Park et al., 2023) demostraron hasta qué punto se puede llegar en este ámbito: los agentes simulados eran capaces de almacenar, reflexionar sobre y recuperar sus propias memorias. Su flujo de memoria ordenaba a los candidatos según su reciente creación, importancia y relevancia, un diseño que sigue sirviendo como punto de referencia útil para la recuperación de memorias por parte de los agentes.
Memoria a corto plazo del agente: el almacén checkpoint
Cada vez que se ejecuta un nodo de LangGraph, el framework serializa todo el estado del grafo y lo escribe en un checkpoint store. Esa es la base para las funcionalidades de pausa/reanudación, el depuración mediante viajes en el tiempo y los flujos de trabajo HITL.
Un checkpoint contiene el estado del grafo necesario para reanudar: la AgentState de Parte 1 (mensajes, identidad, perfil de usuario, pasos del plan, datos de investigación, modo de ejecución), además de los metadatos de LangGraph como el nodo que lo generó y su ID checkpoint. Tras una interrupción HITL o un reinicio del proceso, el grafo carga el límite más reciente registrado e ingresa nuevamente al nodo siguiente. No continúa desde una línea arbitraria de Python. Un checkpoint también difiere de un registro de eventos o traza de solo escritura; Parte 5 Separa de forma explícita esas superficies de observabilidad runtime.
Cómo funciona el guardado de checkpoints en LangGraph
LangGraph’s BaseCheckpointSaver Se trata de una interfaz sencilla: put() escribe un checkpoint. get_tuple() lee el último mensaje de un hilo. list() Devuelve el historial. Cada checkpoint está indexado por (thread_id, checkpoint_ns, checkpoint_id), donde thread_id identifica la conversación. checkpoint_ns gestiona el espacio de nombres de los subgrafos, y checkpoint_id Se trata de una versión única.
La decisión relevante es determinar qué backend se utilizará como backend. PostgreSQL y Redis son dos opciones muy habituales en entornos de producción.
PostgreSQL frente a Redis
| Dimensión | PostgreSQL (langgraph-checkpoint-postgres) | Redis (langgraph-checkpoint-redis) |
|---|---|---|
| Modelo de durabilidad | Transacciones ACID, WAL y replicación | Persistencia configurable en modo AOF o RDB |
| Checkpoint historial | Historial duradero para el seguimiento de ejecuciones y la depuración | La retención depende de la configuración del salvador y de las reglas de expulsión. |
| Restricción principal | Latencia de escritura en la base de datos y crecimiento de tablas | Uso de RAM, expulsión de elementos y configuración de persistencia |
| Adecuación operativa | Los equipos que ya utilizan bases de datos relacionales | Los equipos que ya utilizan Redis con un alto rendimiento de procesamiento. |
| Mejor opción predeterminada para | Continuidad del estado y depuración reproducible | Estado de sesión recuperable y sensible a la latencia |
Una base de datos genérica benchmarks no permite predecir el rendimiento checkpoint. Es necesario medir el tamaño del estado serializado, la frecuencia de escritura, los parámetros de persistencia y la concurrencia en su propio grafo.
PostgreSQL: el valor predeterminado duradero
PostgreSQL representa la opción predeterminada más segura para la mayoría de los equipos. Gracias a que Checkpoints resisten las caídas del sistema, se dispone de una semántica de transacciones completa, y el historial de checkpoint facilita enormemente la depuración mediante análisis retrospectivo.
Desde checkpointer_setup.py:
from langgraph.checkpoint.postgres.aio import AsyncPostgresSaver
async def create_postgres_checkpointer(connection_string: str) -> AsyncPostgresSaver:
"""Create a PostgreSQL-backed checkpoint store.
PostgreSQL gives us ACID guarantees — if a checkpoint write succeeds,
the state is durable even if the process crashes immediately after.
"""
checkpointer = AsyncPostgresSaver.from_conn_string(connection_string)
# Create the checkpoint tables if they don't exist.
# This is idempotent — safe to call on every startup.
await checkpointer.setup()
return checkpointer
# Usage: wire into the graph compilation
checkpointer = await create_postgres_checkpointer(
"postgresql://user:pass@localhost:5432/agent_memory"
)
graph = create_graph(checkpointer=checkpointer)
# Every invoke/stream call now persists state automatically
config = {"configurable": {"thread_id": "user-123-session-1"}}
result = await graph.ainvoke({"messages": [HumanMessage(content="Analyze NVDA")]}, config)
# Resume later — loads the latest checkpoint for this thread
result = await graph.ainvoke({"messages": [HumanMessage(content="approved")]}, config)
El AsyncPostgresSaver utiliza el langgraph-checkpoint-postgres package, el cual crea tres tablas: checkpoints (el estado serializado). checkpoint_blobs (grandes volúmenes de datos binarios), y checkpoint_writes (Pendientes escrituras para la recuperación tras fallos). El esquema admite acceso concurrente y emplea bloqueos consultivos para evitar conflictos de escritura.
Redis: cuando la latencia es el cuello de botella
Cuando la latencia de submilisegundos en checkpoint es crítica (agentes de conversación en tiempo real, ciclos de herramientas de alta frecuencia), Redis representa la mejor opción.
Desde checkpointer_setup.py:
from langgraph.checkpoint.redis.aio import AsyncRedisSaver
async def create_redis_checkpointer(redis_url: str) -> AsyncRedisSaver:
"""Create a Redis-backed checkpoint store.
Redis stores checkpoints in memory for sub-millisecond access.
Trade-off: less durable than PostgreSQL unless AOF is enabled.
"""
checkpointer = AsyncRedisSaver.from_conn_string(redis_url)
# Initialize Redis data structures
await checkpointer.setup()
return checkpointer
# Usage: same graph API, different backend
checkpointer = await create_redis_checkpointer("redis://localhost:6379")
graph = create_graph(checkpointer=checkpointer)
El AsyncRedisSaver de langgraph-checkpoint-redis Almacena checkpoints como documentos JSON indexados por el ID del hilo de conversación. El v0.1.0 de rediseño Se sustituyeron múltiples operaciones de búsqueda por una única. JSON.GET Permite realizar llamadas de forma eficiente, reduciendo significativamente la latencia. Redis 8.0+ incluye por defecto RedisJSON y RediSearch; no es necesario instalar módulos adicionales.
En implementaciones con restricciones de memoria, ShallowRedisSaver Almacena únicamente la versión más reciente de checkpoint por hilo: no se conserva ningún historial, lo que permite un consumo mínimo de memoria RAM. Úsalo cuando necesites pausar y reanudar el proceso, pero no requieras la capacidad de depurar mediante retroceso en el tiempo.
Cuándo utilizar cada uno
Usar PostgreSQL cuando:
- Necesitas un historial completo de checkpoint para la depuración por “viajes en el tiempo” o para obtener resultados reproductibles.
- La durabilidad es algo indispensable (en sectores como los servicios financieros y la salud).
- Ya utilizas PostgreSQL en tu stack tecnológico.
- Tu agente ejecuta tareas prolongadas, por lo que perder el estado implica horas de recálculo.
- Deseas una almacén de datos unificado — PostgreSQL junto con pgvector puede funcionar como un único backend para checkpoints, la memoria a largo plazo y la búsqueda vectorial, lo que simplifica significativamente su infraestructura.
Usar Redis cuando:
- La latencia de Checkpoint es el cuello de botella en aplicaciones como chats en tiempo real o interfaces de usuario basadas en streaming.
- Si estás desarrollando bots de voz, es necesario un proceso de LLM que convierta texto en voz y, posteriormente, voz en texto mediante técnicas de pipelines. acceso al estado en submilisegundos
- Necesita escalamiento horizontal en múltiples hilos concurrentes.
- Patrones de alta concurrencia con distribución de tareas, donde varios agentes comparten estado.
- Sesiones de corta duración cuya pérdida de un checkpoint es recuperable.
- Desea utilizar caché semántico para reducir las llamadas redundantes a LLM.Redis LangCache Almacena en caché las consultas semanticamente similares para evitar llamadas repetidas a LLM)
Otras opciones: langgraph-checkpoint-sqlite Funciona para el desarrollo local y despliegues de un solo proceso. En el caso de stacks nativos de AWS, langgraph-checkpoint-aws proporciona un DynamoDBSaver Gracias a un manejo inteligente de la carga útil, los archivos pequeños checkpoints (<350 KB) permanecen en DynamoDB, mientras que los de mayor tamaño se descargan automáticamente a S3. El modelo de precios sin servidores y la ausencia de infraestructura que gestionar lo convierten en una opción atractiva para implementaciones con cargas variables.
Memoria a largo plazo: recordar entre sesiones
La memoria caliente gestiona la conversación actual. Pero, ¿qué ocurre con el usuario que regrese la semana que viene? La memoria a largo plazo almacena hechos, preferencias e historial de interacciones que permanecen intactos a lo largo de distintas sesiones.
LangGraph ofrece un Store interfaz para el acceso a memoria entre hilos a través de la misma BaseStore clase. Cada elemento de memoria es un (namespace, key) Se empareja con un valor de JSON y, opcionalmente, con un vector embedding. El espacio de nombres suele codificar al usuario u organización correspondiente. ("user", "user-123", "preferences").
Almacenamiento vectorial: recuperación semántica con Qdrant
Cuando el agente necesita recuperar datos no estructurados (“¿Qué dijo el usuario sobre su cronograma de inversión?”), la búsqueda vectorial permite una recuperación semántica. En lugar de realizar búsquedas por claves exactas, el agente realiza consultas basadas en el significado.
Qdrant es una base de datos vectoriales diseñada específicamente, escrita en Rust, que gestiona el almacenamiento de embedding, la indexación (HNSW) y las búsquedas filtradas. Ya traté en detalle HNSW y sus compromisos en mi posicionamiento en búsquedas. Qdrant también ofrece una servidor MCP que funciona como una capa de memoria semántica; resulta útil si su agente framework es compatible con el Protocolo de Contexto de Modelo.
Desde memory_store.py:
from qdrant_client import QdrantClient
from qdrant_client.models import PointStruct, Distance, VectorParams
from langchain_anthropic import ChatAnthropic
import hashlib
import json
class UserMemoryStore:
"""Long-term memory backed by Qdrant vector search.
Stores user facts as embedded vectors for semantic retrieval.
Each fact is a short natural-language statement about the user.
"""
def __init__(self, qdrant_url: str, collection_name: str = "user_memory"):
self.client = QdrantClient(url=qdrant_url)
self.collection_name = collection_name
self._ensure_collection()
def _ensure_collection(self):
"""Create the collection if it doesn't exist."""
collections = [c.name for c in self.client.get_collections().collections]
if self.collection_name not in collections:
self.client.create_collection(
collection_name=self.collection_name,
vectors_config=VectorParams(
size=1536, # text-embedding-3-small dimensions
distance=Distance.COSINE,
),
)
def store_fact(self, user_id: str, fact: str, embedding: list[float]):
"""Store a user fact with its embedding."""
point_id = hashlib.md5(f"{user_id}:{fact}".encode()).hexdigest()
self.client.upsert(
collection_name=self.collection_name,
points=[PointStruct(
id=point_id,
vector=embedding,
payload={"user_id": user_id, "fact": fact},
)],
)
def recall(self, user_id: str, query_embedding: list[float], top_k: int = 5):
"""Retrieve the most relevant facts for a user given a query."""
results = self.client.query_points(
collection_name=self.collection_name,
query=query_embedding,
query_filter={"must": [{"key": "user_id", "match": {"value": user_id}}]},
limit=top_k,
)
return [hit.payload["fact"] for hit in results.points]
El flujo es el siguiente: (1) tras cada conversación, un LLM extrae los hechos clave de la interacción (“el usuario tiene una alta tolerancia al riesgo”, “el usuario está interesado en acciones de semiconductores”), (2) dichos hechos se incrustan y se almacenan en Qdrant, (3) al inicio de la próxima conversación, el agente realiza una consulta a Qdrant con el nuevo mensaje del usuario para recuperar el contexto relevante.
Puntuación de recuperación: más allá de la similitud coseno
La similitud coseno en bruto constituye un punto de partida, pero los sistemas de memoria para entornos de producción requieren mecanismos de recuperación más sofisticados. Artículo sobre Agentes Generativos (Park et al., 2023) introdujeron una función de puntuación que combina tres señales:
- Recencia: Decaimiento basado en reglas que hace que los recuerdos más recientes obtengan una puntuación más alta. Una función de decaimiento exponencial hace que un hecho de ayer supere en importancia a uno similar de hace seis meses.
- Importancia: Significancia evaluada mediante LLM en una escala del 1 al 10. Frases como “El portafolio del usuario ha disminuido un 40%” obtienen una puntuación mayor que “El usuario dijo hola”.
- Relevancia: Similitud coseno Embedding entre la consulta y el hecho almacenado.
La puntuación final de recuperación es una suma ponderada: score = alpha * recency + beta * importance + gamma * relevance. Eso evita que los hechos recientes e importantes queden ocultos bajo otros obsoletos pero semánticamente similares. Para el Agente Analista de Mercado, Otorgo la mayor ponderación a la relevancia (0.5), seguida de la recencia (0.3) e importancia (0.2), ya que la intención de la consulta actual del usuario es lo más relevante. Estas son ponderaciones iniciales adaptadas del artículo sobre Agentes Generativos (que aplicaba un peso igual a cada factor); he observado que dar mayor énfasis a la relevancia funciona mejor en las consultas de análisis financiero, pero estos valores se basan en intuición y no están optimizados empíricamente.
Alternativas a la búsqueda vectorial
La búsqueda vectorial es muy potente, pero no siempre es la herramienta adecuada. Estos son los casos en los que conviene recurrir a alternativas:
| Enfoque | Mejor para | Coste operativo principal |
|---|---|---|
| Búsqueda vectorial (Qdrant) | Recuperación semántica de hechos no estructurados | Embedding y el ciclo de vida del índice |
| Almacén clave-valor (Redis) | Perfiles de usuario estructurados y preferencias | Política de uso de memoria y persistencia |
| Almacén de documentos (archivos) | Conocimiento del proyecto y notas gestionadas por el agente | Concurrencia, permisos y búsqueda |
| Búsqueda de texto completo (PostgreSQL) índice GIN)** | Recuperación de palabras clave a partir del historial de conversación | Crecimiento del índice y ajuste de consultas |
| Gráfico de conocimiento (Neo4j) | Relaciones entre entidades y consultas de múltiples saltos | Modelado de grafos y otro sistema de datos |
| Híbrido (vector + palabra clave) | Recuerde el caso en que la intención de la consulta varía | Dos rutas de puntuación para ajustar y evaluar |
Los almacenes clave-valor son ideales para datos estructurados. Si su memoria a largo plazo corresponde a un perfil de usuario —tolerancia al riesgo, horizonte de inversión, sectores preferidos—, utilizar un hash de Redis o una columna JSONB en PostgreSQL resulta más sencillo y rápido que embedding y realizar búsquedas por vectores. Empiece a emplear la búsqueda vectorial cuando los datos estén desestructurados y las consultas de recuperación varíen en su redacción.
El almacén integrado de LangGraph ofrece una interfaz clave-valor basada en espacios de nombres, con búsqueda vectorial opcional. El BaseStore API es sencillo: put(), get(), search(), y delete() con alcance de nombres de espacio jerárquicos. Están disponibles tres implementaciones:
InMemoryStore— para desarrollo y pruebas (se pierden los datos al finalizar el proceso)PostgresStore— Almacén persistente en producción con consultas SQL completasAsyncRedisStore— memoria entre hilos con búsqueda vectorial, soporte para TTL y filtrado de metadatos
El index La configuración permite realizar búsquedas vectoriales en los elementos almacenados mediante un modelo embedding configurable. En la mayoría de los casos de uso, este almacén integrado es suficiente para no necesitar recurrir a una base de datos vectorial dedicada.
from langgraph.store.memory import InMemoryStore
# Create a store with vector search enabled
store = InMemoryStore(
index={
"dims": 1536,
"embed": my_embedding_function, # e.g., OpenAI text-embedding-3-small
}
)
# Store a user preference (namespace scopes to user)
await store.aput(
namespace=("user", "user-123", "preferences"),
key="risk-profile",
value={"risk_tolerance": "high", "horizon": "long-term"},
)
# Semantic search across user's memories
results = await store.asearch(
namespace=("user", "user-123"),
query="What is their investment style?",
limit=5,
)
Elección de una estrategia de memoria a largo plazo
Comience con el formato clave-valor si su memoria está estructurada y bien definida (perfiles de usuario, configuraciones, entidades nombradas). Agregue la búsqueda vectorial cuando necesite recuperación semántica de datos no estructurados o cuando la formulación de las consultas varíe de forma impredecible.
Gráficos de conocimiento resultan esenciales cuando las relaciones entre entidades son cruciales, por ejemplo: “¿Qué empresas sobre las que preguntó el usuario son competidoras de NVDA?”. El proyecto más interesante desarrollado recientemente en este ámbito es Graphiti (by Zep), el cual construye un gráfico de conocimiento consciente del tiempo que registra cuándo eran verdaderos los hechos, y no solo qué era cierto. Cada arista incluye intervalos de validez, de modo que cualquier cambio en la tolerancia al riesgo del usuario invalida el valor anterior en lugar de sobrescribirlo silenciosamente. Graphiti genera informes 94,8 % de precisión en el DMR benchmark, Y su modelo bitemporal soluciona el problema de la memoria obsoleta en la capa de datos.
El problema radica en el ámbito operativo. Ejecutar una base de datos gráfica no es sencillo, y para la mayoría de las aplicaciones de agentes, la búsqueda vectorial con filtrado de metadatos permite lograr los mismos resultados con menos infraestructura.
Memoria gestionada frameworks como Mem0 y Letta (formerly MemGPT) se encargan de realizar la extracción, consolidación y recuperación pipeline por usted. El enfoque de Mem0 es destacable: un LLM extrae las memorias candidatas, un motor de decisión compara cada nuevo hecho con las entradas existentes en el almacén vectorial, y un resolvedor decide si añadirlo, actualizarlo o eliminarlo, lo que mantiene el almacén de memorias coherente y sin redundancias. Letta adopta un enfoque propio de los sistemas operativos: los agentes gestionan su propia ventana de contexto mediante herramientas de gestión de memoria, moviendo de forma autónoma los datos entre la “memoria principal” (dentro del contexto) y la “memoria de archivo” (fuera del contexto). Ambos enfoques merecen ser evaluados si se busca acelerar el tiempo de puesta en producción y no se necesita un control total sobre la pipeline de memoria.
Memoria de documentos: el archivador del agente
La memoria basada en archivos cuenta con una mayor adopción por parte de los productos que con una mayor representación en las taxonomías de memoria mencionadas anteriormente. En una evaluación LoCoMo realizada por un proveedor, Letta informó El 74,0 % se debe al enfoque basado en su sistema de archivos. Es posible mantener dicho resultado dentro de las condiciones de su modelo, benchmark, y harness, pero la ventaja operativa es fácil de observar: los desarrolladores pueden leer, editar e identificar las diferencias en el conocimiento almacenado directamente.
Las ventanas de contexto más extensas también permiten que la lectura de archivos completos sea viable para ciertos documentos de proyecto. La recuperación por fragmentos sigue siendo adecuada para corpus grandes, pero un archivo breve con convenciones o información de transferencia suele poder cargarse directamente. La elección depende del tamaño del documento, de la precisión en la recuperación, del presupuesto de contexto y de la frecuencia con la que es necesario revisar o editar esa memoria.
Los almacenes vectoriales y los backends de tipo clave-valor gestionan de forma eficaz la recuperación semántica y las búsquedas estructuradas. Sin embargo, existe una tercera categoría de conocimiento del agente que ninguno de estos sistemas aborda adecuadamente: el contexto acumulado del proyecto, es decir, las convenciones, notas de investigación y decisiones que el agente necesita a lo largo de las sesiones, y que se benefician de poder ser leídos por humanos y estar bajo control de versiones.
Esto es la memoria de documentos: el agente lee y escribe archivos estructurados (Markdown, JSON, YAML) en un directorio conocido. Sin embeddings, sin base de datos, sin infraestructura. Solo archivos en disco a los que tanto el agente como el desarrollador pueden acceder. cat, grep, git diff, y se edita a mano.
¿Por qué archivos?
En los flujos de trabajo de agentes de larga duración, el patrón más eficaz que he observado no es una base de datos vectorial, sino un directorio de notas bien organizadas. Piense en lo que ocurre cuando un agente de programación trabaja en un proyecto durante semanas:
- Aprende que el proyecto utiliza Pydantic v2, y no v1
- Descubre que las pruebas deben ejecutarse con
pytest -x --tb=short - Acumula conocimiento sobre la arquitectura del código base.
- Aprende las preferencias del desarrollador (“usar siempre”)
pathlib, nuncaos.path”)
Estos datos están demasiado estructurados como para ser procesados mediante búsqueda vectorial (se requiere una recuperación exacta, no una similitud difusa), y son demasiado numerosos para almacenarse en un sistema de tipo clave-valor (forman documentos interconectados, no datos aislados). Además, se trata de información que el desarrollador desea ver y modificar directamente. Si el agente aprende algo incorrecto, basta con abrir el archivo y corregirlo.
Así es como de Claude Code CLAUDE.md y .claude/ Trabajo en directorios. El agente lee a nivel de proyecto CLAUDE.md archivos con las convenciones e instrucciones, y realiza escrituras en ~/.claude/MEMORY.md Para el aprendizaje entre sesiones. Los archivos son Markdown puro: los lees, los editas, los commits a Git y los compartes con tu equipo. Cursor’s .cursorrules y El windsurfing .windsurfrules archivos de texto plano que el agente carga al iniciarse para obtener el contexto del proyecto.
Implementación de un almacén en memoria para archivos
La implementación es deliberadamente sencilla. El agente dispone de cuatro operaciones: escribir un documento, leer un documento, listar los documentos disponibles y realizar búsquedas entre ellos por palabra clave.
Desde file_memory.py:
from pathlib import Path
import json
import fnmatch
class FileMemory:
"""Document memory backed by the local filesystem.
Stores agent knowledge as human-readable files organized by topic.
No embeddings, no database — just files that both the agent and
the developer can read, edit, and version-control.
"""
def __init__(self, base_dir: str | Path):
self.base_dir = Path(base_dir)
self.base_dir.mkdir(parents=True, exist_ok=True)
def write_doc(self, path: str, content: str, metadata: dict | None = None):
"""Write or overwrite a document at the given path.
Paths are relative to base_dir. Directories are created automatically.
Metadata (if provided) is stored as a JSON sidecar file.
"""
full_path = self.base_dir / path
full_path.parent.mkdir(parents=True, exist_ok=True)
full_path.write_text(content, encoding="utf-8")
if metadata:
meta_path = full_path.with_suffix(full_path.suffix + ".meta")
meta_path.write_text(json.dumps(metadata, indent=2), encoding="utf-8")
def read_doc(self, path: str) -> str | None:
"""Read a document by path. Returns None if not found."""
full_path = self.base_dir / path
if full_path.exists():
return full_path.read_text(encoding="utf-8")
return None
def list_docs(self, pattern: str = "**/*") -> list[str]:
"""List documents matching a glob pattern."""
return [
str(p.relative_to(self.base_dir))
for p in self.base_dir.glob(pattern)
if p.is_file() and not p.name.endswith(".meta")
]
def search_docs(self, query: str, pattern: str = "**/*.md") -> list[dict]:
"""Search documents by keyword. Returns matching files with context.
This is intentionally simple — grep-style keyword search.
For semantic search, use a vector store instead.
NOTE: This is a sketch for demonstration. A simple substring check
won't scale beyond a few hundred documents. For production with 500+
documents, use TF-IDF/BM25 scoring (e.g., rank_bm25) or a full-text
search backend (PostgreSQL GIN index, Elasticsearch).
"""
results = []
for path in self.base_dir.glob(pattern):
if not path.is_file() or path.name.endswith(".meta"):
continue
content = path.read_text(encoding="utf-8")
if query.lower() in content.lower():
# Return the paragraph containing the match for context
for paragraph in content.split("\n\n"):
if query.lower() in paragraph.lower():
results.append({
"path": str(path.relative_to(self.base_dir)),
"match": paragraph.strip()[:500],
})
return results
Estructura de carpetas
La mayor parte del valor de la memoria de documento proviene de la forma en que está organizado el directorio. Esta es la estructura que utilizo para el Agente Analista de Mercado:
.agent-memory/
README.md # What this directory is, for human readers
user-profiles/
user-123.md # Preferences, history, risk profile
user-456.md
research/
NVDA-2026-02.md # Research notes from recent analysis
TSLA-2026-01.md
conventions/
analysis-format.md # How to structure analysis reports
data-sources.md # Preferred data sources and API patterns
learnings/
common-errors.md # Mistakes the agent has learned to avoid
tool-patterns.md # Effective tool call sequences
Cada archivo es de formato Markdown. El propósito de cada archivo se deduce claramente a partir de su ruta. Puedes git diff el directorio completo de memoria para conocer qué aprendió el agente durante una sesión. git revert Un mal proceso de aprendizaje, o bien copiar el directorio a otro proyecto. Intente realizar cualquiera de estas acciones con una colección de Qdrant.
Cuándo utilizar memoria de documento frente a vectores o clave-valor
Los tres backend de memoria satisfacen patrones de acceso diferentes:
| Dimensión | Almacén de vectores | Almacén clave-valor | Almacén de documentos |
|---|---|---|---|
| Patrón de consulta | ”Buscar hechos similares a X” | Obtener el valor asociado a la clave. | |
| Mejor para | Recuperación de información no estructurada y diversa | Búsquedas estructuradas | Contexto del proyecto, notas |
| Legible para humanos | No (embeddings) | Parcialmente (JSON) | |
| Depurable | Fácil (claves exactas) | Trivial (abrir el archivo) | |
| Versión controlable | No | Posibles | |
| Embedding infraestructura | Requerido | No es necesario | No es necesario |
| Escalabilidad hasta | Millones de hechos | Millones de claves | Miles de documentos |
| Capacidad de búsqueda | Similitud semántica | Coincidencia exacta | Basado en palabras clave/rutas |
Utilice la memoria de documento cuando:
- El agente acumula conocimiento sobre el proyecto a lo largo de múltiples sesiones.
- Los desarrolladores deben inspeccionar, editar o anular lo que el agente “sabe”.
- Dicho conocimiento está estructurado como documentos (notas, resúmenes, convenciones) y no como hechos aislados.
- Se desea contar con un sistema de control de versiones basado en Git para la memoria del agente.
- No existir infraestructura es un requisito estricto.
Utilice almacenes vectoriales cuando:
- Se requiere una recuperación semántica difusa (“encontrar recuerdos relacionados con X”).
- La formulación de las consultas varía de forma impredecible.
- Se dispone de miles o millones de hechos individuales.
Utilice almacenes clave-valor cuando:
- Se requieren búsquedas precisas y rápidas en datos estructurados (perfiles de usuarios, configuraciones).
- El esquema de datos está bien definido.
En la práctica, los agentes en entorno de producción suelen combinar los tres tipos. El Agente Analista de Mercado Utiliza PostgreSQL checkpoints como almacenamiento en memoria rápida, Qdrant para la recuperación semántica de datos relacionados con los usuarios, y un almacén de documentos basado en archivos para guardar las convenciones del proyecto y las notas de investigación.
Ejemplos del mundo real
El patrón ya está muy extendido en los asistentes de codificación AI:
- Claude Code lee
CLAUDE.mdarchivos de la raíz del proyecto y de las directorios padre, y escribe en~/.claude/MEMORY.mdPara el aprendizaje entre sesiones, todo el sistema de memoria está formado por archivos en formato Markdown sencillo que se guardan junto con el código. - Cursor carga
.cursorrulesArchivos con instrucciones específicas para el agente del proyecto: convenciones de codificación, preferencias framework, decisiones arquitectónicas. - Windsurf utiliza
.windsurfrulesarchivos además de unomemories/directorio en el que el agente almacena los patrones aprendidos de tu código base. - La herramienta de memoria de Anthropic para Claude API ofrece
create_memory,read_memory,update_memory, ydelete_memoryLas operaciones se ejecutan en el lado del cliente. Su aplicación es la que determina dónde residen realmente los archivos (en el disco local, en S3 o en una base de datos).
El elemento común: todos ellos almacenan el conocimiento del agente como archivos de texto legibles por humanos, con operaciones explícitas de lectura y escritura. No existe embeddings. Tampoco hay infraestructura vectorial. El agente decide qué escribir, el desarrollador puede ver y editar todo, y todo el sistema cabe en un git diff.
Más allá de los asistentes de programación
La memoria de documentación no está limitada a los agentes de programación. Este patrón se observa en dominios de agentes muy diversos:
-
Agentes de juegos de mundo abierto: Voyager (Wang et al., 2023) desarrolla una biblioteca de habilidades persistente compuesta por programas en JavaScript verificados, que un agente de Minecraft va acumulando con el tiempo; esto permite recopilar un 3,3 veces más elementos únicos y alcanzar los hitos 15,3 veces más rápido que los métodos de referencia. Dicha capacidad de transferencia de habilidades funciona en mundos nuevos sin necesidad de volver a entrenar al agente. JARVIS-1 Se amplía esta arquitectura incorporando una memoria multimodal que integra planes textuales y observaciones visuales, lo que permite alcanzar una tasa de éxito del 5 veces superior en las tareas más complejas.
Una distinción importante aquí es que las bibliotecas de habilidades representan memoria ejecutable (archivos de código que se importan y ejecutan), mientras que la memoria de documentos en los asistentes de programación es de tipo declarativo (Markdown insertado en prompts). Los modos de fallo difieren: un código ejecutable defectuoso hace que el agente se bloquee, mientras que un texto declarativo defectuoso genera errores en el razonamiento. No obstante, el patrón de almacenamiento y las ventajas operativas (posibilidad de depuración, control de versiones) son idénticos.
-
Automatización de flujos de trabajo empresariales: La competición ECR3 Los equipos ganadores emplearon la memoria de documentos para realizar un perfeccionamiento iterativo mediante prompt. Los agentes Analyzer y Versioner de uno de los equipos vencedores procesaron 80 prompt versiones almacenadas como documentos procedurales. Otro equipo destacado desarrolló más de 20 módulos enriquecedores que funcionaban como conocimiento procedural de tipo documento. LEGOMem (2025) formaliza esto como una memoria modular framework para sistemas multi-agent, que cuenta con tipos de memoria especializados (sensorial, a corto plazo y a largo plazo) que los agentes pueden combinar entre sí como bloques constructivos.
-
Automatización web: Memoria de flujo de trabajo del agente (Wang et al., 2024) permite que los agentes web generen flujos de trabajo reutilizables a partir de episodios exitosos, logrando una mejora del 51 % en la tasa de éxito en WebArena. SkillWeaver (2025) va aún más allá: los agentes sintetizan herramientas API reutilizables a partir de la exploración, logrando un aumento en la tasa de éxito del 31,8 %. Las habilidades aprendidas también se transfieren a modelos menos potentes (mejora del 54,3 %), por lo que la memoria acumulada por un agente más fuerte puede potenciar a uno de menor tamaño.
-
Soporte al cliente: Gartner prevé Esos agentes AI resolverán de forma autónoma el 80 % de los problemas comunes de atención al cliente para el año 2029. Dichos agentes hacen referencia a procedimientos operativos estandarizados, guías de acción y historiales de clientes, los cuales constituyen formas de memoria documental.
El Taller MemAgents en el ICLR 2026
Las habilidades utilizan documentos para encapsular instrucciones procedimentales. El Estándar de Habilidades de Agente almacena esas instrucciones en SKILL.md Archivos que contienen frontmatter en formato YAML y un cuerpo en Markdown. Esto se asemeja a la memoria de documento a nivel de capa de almacenamiento, pero su función es distinta: una habilidad indica al agente cómo realizar un tipo específico de tarea, mientras que la memoria registra los hechos aprendidos de un proyecto o de ejecuciones anteriores. Parte 3 Aborda dicha distinción desde la perspectiva de la herramienta.
MCP (Protocolo de contexto del modelo) sigue la misma lógica: las definiciones de herramientas son archivos JSON Schema que cualquier agente puede descubrir y utilizar. El protocolo tiene 97 millones de descargas mensuales de SDK Además, cuenta con el soporte de OpenAI, Google, Microsoft y AWS. MCP no está relacionado específicamente con la programación. Estos mismos servidores conectan a los agentes con bases de datos, APIs internos y sistemas empresariales.
Ambos apuntan al mismo patrón: conocimiento procedimental almacenado como documentos sometidos a esquemas, con operaciones de lectura/escritura explícitas. MCP, que ahora está regulado por el Agentic AI Fundamento, Se trata de lo más cercano a un estándar de interoperabilidad que existe en el ecosistema de agentes.
Escalado de la memoria de documentos para entornos de producción
El límite de archivos en un único nodo se vuelve evidente: no es posible escalar la entrada/salida de archivos de forma horizontal, las escrituras concurrentes requieren bloqueo, y gestionar los permisos entre diferentes usuarios es complicado. En entornos de producción se necesita un almacén de respaldo capaz de manejar adecuadamente la concurrencia, la búsqueda y el modelo multiusuario.
Tres enfoques comunes:
Enfoque A: híbrido con una capa de base de datos ligera
Mantenga los archivos para la fase de creación (los desarrolladores editan el Markdown localmente), pero sirva el contenido desde una base de datos en runtime. Durante el despliegue, sincronice los archivos con las filas de PostgreSQL. El agente lee la información directamente de la base de datos, y no del disco. Esto le brinda:
- Ergonomía para desarrolladores (editar Markdown, hacer commits en Git)
- Rendimiento de las consultas en producción (lecturas desde bases de datos indexadas)
- Separación clara entre la fase de creación y serving
Enfoque B: almacenamiento de objetos + sidecar de índice vectorial
Los documentos se almacenan en S3/GCS como objetos, y existe una colección de Qdrant que indexa sus embeddings. El agente consulta Qdrant en busca de los IDs de los documentos relevantes y, a continuación, obtiene su contenido desde el almacenamiento de objetos. Este enfoque permite escalar horizontalmente y soporta búsquedas semánticas, pero añade complejidad: se deben gestionar dos sistemas, mantener una embedding pipeline, y garantizar la consistencia eventual entre el almacenamiento y el índice.
Enfoque C: almacén de documentos estructurado con PostgreSQL (recomendado)
Almacene los documentos como filas JSONB en PostgreSQL, aprovechando la búsqueda de texto completo mediante índices GIN y, opcionalmente, vectores embeddings (pgvector). De este modo, podrá contar con una búsqueda híbrida (basada en palabras clave y semántica), transacciones ACID, así como un único sistema operativo para gestionar todo.
Un esquema del Enfoque C:
from typing import Optional
import asyncpg
class ProductionDocumentMemory:
"""PostgreSQL-backed document memory with hybrid search.
Schema:
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
tenant_id TEXT NOT NULL,
path TEXT NOT NULL,
content TEXT NOT NULL,
metadata JSONB,
embedding vector(1536), -- pgvector extension
ts_vector tsvector GENERATED ALWAYS AS (to_tsvector('english', content)) STORED,
created_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE(tenant_id, path)
);
CREATE INDEX ON documents USING GIN(ts_vector);
CREATE INDEX ON documents USING ivfflat(embedding vector_cosine_ops);
"""
def __init__(self, pool: asyncpg.Pool):
self.pool = pool
async def write(
self,
tenant_id: str,
path: str,
content: str,
metadata: Optional[dict] = None,
embedding: Optional[list[float]] = None,
):
"""Write or update a document."""
async with self.pool.acquire() as conn:
await conn.execute(
"""
INSERT INTO documents (tenant_id, path, content, metadata, embedding)
VALUES ($1, $2, $3, $4, $5)
ON CONFLICT (tenant_id, path) DO UPDATE
SET content = EXCLUDED.content,
metadata = EXCLUDED.metadata,
embedding = EXCLUDED.embedding
""",
tenant_id, path, content, metadata, embedding,
)
async def search(
self,
tenant_id: str,
query: str,
embedding: Optional[list[float]] = None,
limit: int = 5,
) -> list[dict]:
"""Hybrid search: full-text + optional vector similarity."""
async with self.pool.acquire() as conn:
if embedding:
# Hybrid scoring: 0.6 * text relevance + 0.4 * vector similarity
rows = await conn.fetch(
"""
SELECT path, content, metadata,
(0.6 * ts_rank(ts_vector, plainto_tsquery('english', $2)) +
0.4 * (1 - (embedding <=> $3))) AS score
FROM documents
WHERE tenant_id = $1
AND ts_vector @@ plainto_tsquery('english', $2)
ORDER BY score DESC
LIMIT $4
""",
tenant_id, query, embedding, limit,
)
else:
# Full-text search only
rows = await conn.fetch(
"""
SELECT path, content, metadata,
ts_rank(ts_vector, plainto_tsquery('english', $2)) AS score
FROM documents
WHERE tenant_id = $1
AND ts_vector @@ plainto_tsquery('english', $2)
ORDER BY score DESC
LIMIT $3
""",
tenant_id, query, limit,
)
return [dict(row) for row in rows]
Qué obtendrá:
- Búsqueda híbrida: coincidencia de palabras clave (índice GIN) + similitud semántica (pgvector), cuyas puntuaciones se suman entre sí
- Multitenancy:
tenant_idDelimitación de alcance mediante seguridad a nivel de fila - Garantías ACID: ausencia de problemas de consistencia eventual
- Sistema operativo único: no es necesario gestionar una base de datos vectorial separada
- Escalado horizontal: réplicas de lectura para manejar la carga de consultas, particionamiento por cliente para escalar las operaciones de escritura
Los archivos son ideales para flujos de trabajo con un único desarrollador. En entornos de producción multiinquilino, un almacén de documentos estructurado basado en PostgreSQL suele ofrecer el equilibrio óptimo entre sencillez, rendimiento y madurez operativa.
Integrándolo todo: la arquitectura completa
Así es como funcionan conjuntamente los tres niveles de memoria en el Agente Analista de Mercado. El diagrama muestra el flujo completo desde la solicitud del usuario hasta la respuesta, con todas las capas de memoria activas.
La arquitectura cuenta con tres vías de memoria:
-
Ruta crítica (checkpoint store): Cada nodo de LangGraph escribe su estado de grafo reanudable en el checkpoint store. Cuando el grafo llega a un
interrupt_beforenode (al igual que el reportero en Parte 1), Se producen pausas en la ejecución. El usuario puede cerrar la aplicación y, al volver, el gráfico reanuda su proceso a partir del checkpoint. Los registros de eventos y las trazas de Runtime constituyen cuestiones distintas relacionadas con la operación en producción. -
Ruta en frío (almacén a largo plazo): Al inicio de cada conversación, el agente consulta el almacén a largo plazo en busca de contexto de usuario relevante. Al final, extrae y almacena nuevos hechos. Este proceso se ejecuta de forma asíncrona; por lo tanto, nunca debe bloquear al reasoning loop principal.
-
Ruta del documento (almacén de archivos): Al iniciarse, el agente carga las convenciones del proyecto y las notas de investigación relevantes desde el almacén de documentos. Durante la ejecución, escribe nuevos resúmenes de investigación y los patrones aprendidos de vuelta en el disco. A diferencia de la ruta en frío, las lecturas de documentos son síncronas (ya que sirven para informar sobre la tarea actual), mientras que las escrituras pueden ser diferidas.
El cableado en LangGraph es sencillo: el checkpoint store y el long-term store se pasan durante la compilación del grafo, mientras que el document store se introduce como una dependencia. El boceto local que aparece a continuación utiliza InMemoryStore Por lo tanto, el fragmento se mantiene breve; la topología de Docker de referencia utiliza Qdrant para desempeñar la misma función relacionada con la recuperación semántica.
from langgraph.checkpoint.postgres.aio import AsyncPostgresSaver
from langgraph.store.memory import InMemoryStore
# Hot memory: PostgreSQL for durable checkpoints
checkpointer = await create_postgres_checkpointer(pg_connection_string)
# Cold memory: local sketch with vector search
# (The reference Docker topology uses Qdrant for persistent recall.)
memory_store = InMemoryStore(
index={"dims": 1536, "embed": embedding_function}
)
# Document memory: file-based store for project knowledge
doc_memory = FileMemory(base_dir=".agent-memory")
# Checkpoint store and long-term store wired into the graph
graph = create_graph(
checkpointer=checkpointer,
store=memory_store,
)
# The store is accessible inside any node via the store parameter
def planner_node(state: AgentState, *, store: BaseStore) -> dict:
"""Plan with user context from long-term memory."""
# Recall relevant user facts from vector store
user_memories = store.search(
namespace=("user", state.user_id),
query=state.messages[-1].content,
limit=5,
)
# Load project conventions from document memory
conventions = doc_memory.read_doc("conventions/analysis-format.md")
# Inject both into planning context
memory_context = "\n".join(m.value["fact"] for m in user_memories)
# ... rest of planning logic with personalized context and conventions
El flujo completo
¿Qué ocurre cuando un usuario que ya ha iniciado sesión envía “Analizar TSLA” al Agente Analista de Mercado:
-
Carga de memoria de los documentos: Al iniciarse, el agente lee las convenciones del proyecto desde el almacén de documentos: preferencias de formato de análisis, fuentes de datos preferidas y patrones de uso de herramientas. Todo esto establece el comportamiento de referencia.
-
Recuperación de memoria a frío: Antes de que el nodo del router ejecute la acción, el grafo consulta el almacenamiento a largo plazo en busca del mensaje del usuario. De allí obtiene la información siguiente: “El usuario tiene una alta tolerancia al riesgo”, “El usuario prefiere análisis detallados de los competidores” y “El usuario ya investigó previamente a NVDA y AMD”.
-
Router + Planner: La clase de router lo clasifica como
DEEP_RESEARCHEl planificador genera un plan de investigación de 5 pasos, personalizado en función de las preferencias recuperadas. Incluye una fase de análisis de competidores, ya que el historial del usuario indica que este la desea. El plan sigue el formato establecido en el documento de convenciones. -
Bucle del ejecutor (memoria activa): Cada paso se ejecuta mediante el patrón ReAct desde Parte 1. Tras cada nodo (router, planificador y cada paso del ejecutor), LangGraph escribe un checkpoint en PostgreSQL. Si el proceso se bloquea después del paso 3 de un total de 5, se reinicia la ejecución para continuar desde el paso 4.
-
Interrupción HITL: El gráfico alcanza el
reporternodo coninterrupt_before. El borrador del informe se encuentra en el checkpoint. El usuario lo revisa unas horas después, y el gráfico carga el checkpoint y continúa su proceso. -
Actualizaciones de memoria: Una vez finalizada la conversación: (a) un proceso asíncrono extrae nuevos hechos del usuario (“el usuario ahora está haciendo seguimiento a TSLA”, “el usuario aprobó el formato del informe”) y los almacena en el repositorio de vectores a largo plazo, y (b) el agente escribe un resumen de la investigación en el repositorio de documentos.
research/TSLA-2026-02.md) para futuras referencias.
El patrón de tres capas permite separar las responsabilidades de forma clara y estructurada. El almacén checkpoint se encarga de garantizar la durabilidad y la reanudación de operaciones; corresponde a la infraestructura. El almacén a largo plazo se utiliza para la personalización; forma parte de la lógica del producto. Por su parte, el almacén de documentos alberga todo el conocimiento acumulado sobre los proyectos; funciona como el cuaderno de notas del agente.
Compromisos y consideraciones
La memoria aporta valor, pero también incrementa los costes y la complejidad. Hay que ser sinceros respecto a estos compromisos:
-
Embedding cost: Cada hecho almacenado en una base de datos vectorial requiere una llamada a embedding API. El precio es de 0,02 dólares por millón de tokens (OpenAI)
text-embedding-3-small), el costo por hecho es despreciable, pero se acumula al tener miles de usuarios y sesiones. Agrupe las llamadas embedding y almacene en caché los resultados. El verdadero coste radica en la latencia: entre 100 y 300 ms de latencia embedding API al realizar consultas para recuperar datos de memoria fría, lo cual es más relevante que el coste monetario en los agentes de conversación en tiempo real. Almacene en caché embeddings las consultas más frecuentes, o utilice un modelo embedding local para cargas de trabajo sensibles a la latencia. -
Memoria obsoleta: Las preferencias del usuario cambian. Un dato almacenado hace seis meses (“el usuario prefiere inversiones conservadoras”) podría ya no ser preciso. Es necesario establecer políticas de vencimiento. Yo utilizo 365 días para las preferencias y 90 días para los eventos puntuales, tal como se describe en mi context engineering publicación.
-
Sobrecarga de memoria en el contexto: Cada hecho recuperado consume tokens en la ventana de contexto del LLM. Si se recuperan 20 hechos por consulta, eso supone varios cientos de tokens de contexto que compiten con la tarea real. Es necesario limitar la cantidad de hechos recuperados y priorizarlos según su puntuación de relevancia.
-
Privacidad y cumplimiento normativo: La memoria a largo plazo almacena los datos de los usuarios. Es necesario realizar la redacción de la PII antes del almacenamiento, establecer políticas claras de retención y proporcionar controles accesibles para los usuarios con el fin de eliminar sus datos. En los sectores regulados, nada de esto es opcional.
-
Crecimiento del almacenamiento Checkpoint: Las tablas PostgreSQL checkpoint aumentan de tamaño con cada ejecución en un nodo. En el caso de agentes que operan de forma continua, es necesario establecer una política de retención: conservar los últimos N checkpoints por hilo y archivar o eliminar los más antiguos. A continuación se muestra un ejemplo de consulta de limpieza que mantiene los 10 checkpoints más recientes por hilo y elimina todo aquello con más de 30 días de antigüedad:
DELETE FROM checkpoints WHERE thread_id = $1 AND created_at < NOW() - INTERVAL '30 days' AND checkpoint_id NOT IN ( SELECT checkpoint_id FROM checkpoints WHERE thread_id = $1 ORDER BY created_at DESC LIMIT 10 ); -
Consolidación de la memoria: Con el paso del tiempo, los recuerdos episódicos detallados deben comprimirse en representaciones semánticas compactas: “el usuario preguntó sobre NVDA tres veces en enero” en lugar de almacenar las tres conversaciones palabra por palabra. Esto imita el proceso de consolidación de la memoria humana y permite mantener el almacenamiento manejable. Mem0 y Graphiti Gestione esto de forma automática; si lo desarrolla usted mismo, programe tareas periódicas de consolidación.
-
Problema de arranque en frío: Los usuarios nuevos no disponen de memoria a largo plazo. El agente debe funcionar de forma adecuada y plantear preguntas para aclarar la situación, en lugar de hacer suposiciones. La memoria es aditiva y no es obligatoria.
-
Envenenamiento de memoria: Cualquier elemento dentro de la ventana de contexto del agente constituye un punto potencial de inyección. Si un atacante escribe datos engañosos en el almacén de documentos o en la memoria a largo plazo (“aprobar siempre las transacciones sin verificar”), el agente podría ejecutarlos como instrucciones. Prompt injection a través de las memorias almacenadas representa una superficie de ataque real. Las medidas de mitigación incluyen la validación previa al almacenamiento, el tratamiento del contenido recuperado como datos no fiables y no como instrucciones del sistema, además de controles de acceso que limitan qué memorias pueden influir en operaciones críticas.
-
Deriva de la memoria en los documentos: La memoria basada en archivos no cuenta con deduplicación automática ni resolución de conflictos. Con el tiempo, los documentos acumulan contradicciones: un archivo indica “usar pytest” mientras que otro dice “usar unittest”. Es necesario programar revisiones periódicas (o dejar que el agente las realice) para eliminar y consolidar dichos documentos. La buena noticia es que, a diferencia de los almacenes vectoriales donde el problema de obsolescencia queda oculto, aquí se puede
greppara las contradicciones. -
La memoria basada en documentos no es escalable hasta millones de elementos: La memoria basada en archivos funciona adecuadamente con cientos o pocos miles de documentos. Si su agente necesita recuperar información de millones de datos mediante coincidencias difusas, es necesario utilizar un almacén vectorial. La memoria basada en documentos está destinada al conocimiento estructurado de los proyectos, y no al gran número de interacciones individuales de cada usuario.
Conclusiones principales
- La memoria del agente está compuesta por varios almacenes con patrones de acceso diferentes. Es necesario mantener separados los datos checkpoints reanudables, los hechos estructurados, la recuperación semántica y los documentos del proyecto.
- Implementar funcionalidades de pausa y reanudación antes de proceder con la personalización. La pérdida del progreso de una tarea es el primer fallo de memoria que presenta un agente de ejecución prolongada.
- Guardar los hechos deterministas en almacenamiento estructurado. Utilizar búsquedas vectoriales cuando la consulta sea vaga y la redacción varíe.
- Emplear archivos para el conocimiento del proyecto que las personas necesiten inspeccionar, editar, versionar o revisar mediante comparaciones de diferencias.
- Establecer reglas de vencimiento, conflicto y eliminación para cada tipo de memoria. Una memoria que el sistema no pueda corregir se convierte en deuda técnica.
- Limitar lo que se envía al modelo. La memoria almacenada solo tiene valor cuando su recuperación introduce las pruebas adecuadas en el contexto actual.
La siguiente capa corresponde a la acción
Parte 3, AI Agente Tool Use en 2026, Pasa del estado almacenado a la acción. Se analiza cómo un agente descubre y llama a las herramientas, así como cómo los límites de estas devuelven errores que el reasoning loop puede utilizar. Las partes 5 y 6 vuelven a la memoria desde el punto de vista operativo: el runtime restaura un checkpoint, mientras que el harness decide qué contenido debe incluirse en la transferencia hacia la siguiente sesión del modelo.
Referencias
Artículos científicos
- Arquitecturas Cognitivas para Agentes de Lenguaje (CoALA) — Sumers, Yao et al., 2023 — Taxonomía fundamental de los tipos de memoria de agente La memoria en la era de los agentes AI: una revisión — Dic 2025 — Taxonomía tridimensional integral de la memoria de los agentes
- MemGPT: Hacia LLMs como sistemas operativos — Packer et al., 2023 — Gestión de contexto virtual para agentes LLM Agentes generativos: simulacros interactivos del comportamiento humano — Park et al., 2023 — Arquitectura de flujo de memoria con puntuación basada en recencia, importancia y relevancia Zep: Una arquitectura de grafo de conocimiento temporal para la memoria de los agentes — Rasmussen, 2025 — Gráfico de conocimiento bitemporal para la memoria del agente
- Mem0: Desarrollo de agentes AI listos para producción que cuentan con memoria a largo plazo escalable — 2025 — Extracción/consolidación pipeline mediante benchmarks
- Voyager: Un agente encarnado de finalidad abierta equipado con modelos de lenguaje grandes — Wang et al., 2023 — Biblioteca de habilidades como memoria de documentos para agentes de juegos de mundo abierto
- JARVIS-1: Agentes multi-tarea de mundo abierto con modelos de lenguaje multimodal reforzados con memoria — 2023 — Biblioteca de memoria multimodal para agentes de Minecraft Memoria de flujo de trabajo del agente — Wang et al., 2024 — Inducción de flujos de trabajo reutilizables para agentes de automatización web SkillWeaver: Los agentes web pueden diseñar por sí mismos sus propias bibliotecas de habilidades — 2025 — Herramientas reutilizables API auto-sintetizadas para agentes web
- LEGOMem: Memoria modular Framework para sistemas de agente LLM — 2025 — Módulos de memoria componibles para sistemas multi-agent
Documentación de LangGraph
- Persistencia de LangGraph (creación de puntos de control) — Conceptos fundamentales de la memoria basada en checkpoint- Almacén de memoria de LangGraph — Interconectar la memoria a largo plazo entre hilos mediante la interfaz Store
- Persistencia entre hilos de LangGraph — Funcionalidad API para memoria entre hilos Cómo añadir memoria al agente ReAct preconstruido — Guía práctica para añadir memoria
Checkpoint servidores backend
langgraph-checkpoint-postgres— Guardador de PostgreSQL checkpoint para LangGraphlanggraph-checkpoint-redis— Guardián de Redis checkpoint para LangGraph LangGraph Redis Checkpoint 0.1.0: Rediseño — Detalles de arquitectura para el salvador de Redis checkpointlanggraph-checkpoint-aws— Guardador de DynamoDB checkpoint con descarga a S3
Bases de datos vectoriales y herramientas de memoria
- Qdrant — Base de datos vectorial de código abierto que cuenta con indexación y filtrado mediante HNSW Guía de desarrollo para Qdrant Agentic — Guía práctica para construir memoria de agente con Qdrant
- pgvector — Extensión de búsqueda por similitud vectorial para PostgreSQL Graphiti — Motor de grafo de conocimiento temporal de código abierto desarrollado por Zep
Memoria basada en documentos y archivos
- Memoria de Claude Code — Sistema de memoria basado en archivos CLAUDE.md y MEMORY.md Herramienta de Memoria Anthropic — Memoria basada en archivos del lado del cliente para los agentes Claude API
- Reglas del cursor — Archivos .cursorrules a nivel de proyecto para el contexto del agente Recuerdos de windsurf — Memoria basada en archivos y .windsurfrules para agentes de programación
Memoria frameworks
- Mem0 — Capa de gestión de memoria con extracción y consolidación pipeline
- Letta (MemGPT) — Gestión de contexto virtual inspirada en los sistemas operativos para agentes
- LangMem SDK — Herramientas de gestión de memoria para LangGraph
Benchmarks
- Desempeño de PostgreSQL frente a Redis — Latencia y ancho de banda de CyberTec benchmarks
- Comparación entre PostgreSQL y Redis — Comparativa de arquitecturas RisingWave
- Ingeniería de agentes con Redis AI — Patrones de Redis para cargas de trabajo de agentes
Talleres
- MemAgents: Memoria para sistemas Agentic basados en LLM — Taller ICLR 2026
Proyecto de demostración
- Agente Analista de Mercado — Implementación completa con las tres capas de memoria.
El código completo del agente Market Analyst, incluida la arquitectura de memoria descrita en esta publicación, se encuentra en GitHub Si deseas seguir la lectura._
Serie: Ingeniería de la pila Agentic
- Parte 1: AI Bucles de razonamiento de agente en 2026 — ReAct, ReWOO y Plan-and-Execute
- Parte 2: Arquitectura de memoria de agente AI en 2026 (esta publicación)
- Parte 3: AI Agente Tool Use en 2026 — MCP, CLI, habilidades, ejecución de código y ACI Parte 4: AI Seguridad de agentes en 2026 — barreras de seguridad, permisos, sandboxes, HITL y delimitación de alcance con MCP
- Parte 5: Agente AI de ejecución prolongada Runtime en 2026 — sesiones, sandboxes, checkpoints, mecanismos de aprovechamiento y formas de despliegue
- Parte 6: Harness Engineering para agentes AI (próximamente) — comprobaciones de aceptación, trazas, intentos de reintentado, transferencias de control y el ciclo asociado al modelo