Crea agentes que nunca olvidan

@akshay_pachaar
INGLÉShace 3 meses · 13 abr 2026
625K
1.9K
305
46
4.1K

TL;DR

Un análisis técnico profundo sobre los sistemas de memoria para agentes de IA, que evolucionan desde simples listas hasta el motor de grafos y vectores de código abierto de Cognee para un razonamiento relacional y persistente.

Un recorrido desde primeros principios sobre la memoria de agentes: desde listas de Python hasta archivos Markdown, pasando por búsqueda vectorial, híbridos de grafos y vectores, y finalmente, una solución limpia y de código abierto para todo esto.

Akshay 🚀 - inline image

Un LLM es inherentemente sin estado. Cada llamada a la API empieza desde cero. La "memoria" que sientes al chatear con ChatGPT es una ilusión creada al reenviar todo el historial de la conversación en cada solicitud.

Ese truco funciona para charlas informales. Se desmorona en cuanto intentas construir un agente real.

Aquí hay 7 modos de fallo que aparecen en cuanto saltas la memoria:

  1. Amnesia de contexto: el agente pregunta por información que ya le diste
  2. Cero personalización: cada interacción se siente genérica
  3. Fallo en tareas multi-paso: el estado intermedio se pierde silenciosamente a mitad de la tarea
  4. Errores repetidos: sin recuerdo episódico, los mismos errores para siempre
  5. Sin acumulación de conocimiento: cada sesión empieza de cero
  6. Alucinaciones por lagunas: cuando el contexto se desborda, el modelo inventa
  7. Colapso de identidad: sin continuidad, no hay confianza

La respuesta obvia es "echarle más contexto". Por eso las ventanas de 128K y 200K tokens parecen que deberían resolverlo todo.

No es así.

La precisión cae más de un 30% cuando la información relevante está en medio de un contexto largo. Este es el conocido efecto "perdido en el medio".

El contexto es un presupuesto compartido: los prompts del sistema, los documentos recuperados, el historial de la conversación y la salida compiten por los mismos tokens.

Incluso con 100K tokens, la ausencia de persistencia, priorización y relevancia hace que la longitud del contexto bruto sea insuficiente.

Akshay 🚀 - inline image

La memoria no consiste en meter más texto en el prompt. Se trata de estructurar lo que el agente recuerda para que pueda encontrar lo que importa.

El marco de la ciencia cognitiva que realmente ayuda

La formulación de Lilian Weng de 2023 se ha convertido en el marco por defecto:

Agente = LLM + Memoria + Planificación + Uso de herramientas.

Los cuatro pilares en igualdad de condiciones.

Su taxonomía toma prestado de la ciencia cognitiva, donde la memoria humana se divide en tres sistemas:

  • La memoria sensorial captura la entrada perceptual bruta y la mantiene durante una fracción de segundo. Solo las partes a las que prestas atención pasan adelante.
  • La memoria de trabajo es donde ocurre el pensamiento activo. Mantiene aproximadamente 7±2 elementos a la vez (hallazgo de Miller en 1956). Pierdes el foco y el contenido desaparece.
  • La memoria a largo plazo es un almacenamiento duradero sin límite práctico de capacidad. La recuperación es el cuello de botella: puedes almacenar millones de cosas y aun así no recordar la que necesitas.

Cada una se corresponde directamente con un componente en las arquitecturas modernas de agentes:

Akshay 🚀 - inline image

La memoria a largo plazo se divide a su vez:

  • Episódica: eventos pasados específicos ("el martes, el clúster de PostgreSQL cayó")
  • Semántica: hechos y conceptos ("PostgreSQL es una base de datos relacional")
  • Procedimental: habilidades y flujos de trabajo ("cuando un usuario solicita un reembolso, primero verifica la fecha de compra")

El puente entre la memoria episódica y la semántica es la consolidación de la memoria: eventos específicos repetidos que se destilan en conocimiento general. Un agente que nota que "los usuarios prefieren consistentemente los resúmenes ejecutivos" a lo largo de docenas de interacciones debería convertir eso en una regla reutilizable. Sin consolidación, tu agente reproduce eventos individuales en lugar de aprender de ellos.

Akshay 🚀 - inline image

El agente mínimo, y qué se rompe primero

Dejando de lado los marcos teóricos, un agente es un bucle: percibir, pensar, actuar.

python
1class Agent:
2 """Minimal AI agent: perceive, think, act"""
3 def __init__(self):
4 self.client = anthropic.Anthropic()
5 self.model = "claude-sonnet-4-20250514"
6
7 def run(self, user_input: str) -> str:
8 response = self.client.messages.create(
9 model=self.model,
10 max_tokens=1024,
11 messages=[{"role": "user", "content": user_input}],
12 )
13 return response.content[0].text

Dile "tengo 4 manzanas", luego pregúntale "me comí una, ¿cuántas quedan?" y no tiene ni idea de qué manzanas le hablas. Cada llamada existe de forma aislada.

Capa 1: La lista de Python

La primera solución a la que todos recurren:

python
1class Agent:
2 def __init__(self):
3 self.client = anthropic.Anthropic()
4 self.messages = [] # The entire "memory" is a list
5
6 def chat(self, user_input: str) -> str:
7 self.messages.append({"role": "user", "content": user_input})
8 response = self.client.messages.create(
9 model="claude-sonnet-4-20250514",
10 max_tokens=1024,
11 messages=self.messages, # Full history sent every time
12 )
13 reply = response.content[0].text
14 self.messages.append({"role": "assistant", "content": reply})
15 return reply

Ahora funcionan los turnos múltiples. La pregunta de las manzanas se responde correctamente porque se reenvía toda la conversación con cada llamada.

Pero aparecen dos problemas rápidamente:

  • La lista crece sin límite. Alrededor del turno 200, llegas al límite de contexto y los mensajes más antiguos se pierden silenciosamente. El nombre del usuario del turno 1 desaparece mucho antes que el chiste olvidable de ayer. Sin priorización, solo orden cronológico estricto.
  • Todo vive en RAM. En cuanto el proceso de Python termina, tu agente no tiene ni idea de quién eres.

Capa 2: Archivos Markdown para persistencia

El siguiente paso es escribir la memoria en disco. Markdown encaja de forma natural: legible para humanos, compatible con Git, y el agente puede leerlo como texto plano. Claude Code usa exactamente este patrón con archivos CLAUDE.md y MEMORY.md.

python
1class MarkdownMemoryAgent:
2 def __init__(self):
3 self.client = anthropic.Anthropic()
4 self.history_file = Path("memory/conversation_history.md")
5 self.facts_file = Path("memory/known_facts.md")
6
7 def save_to_disk(self, role: str, content: str) -> None:
8 with open(self.history_file, "a") as f:
9 f.write(f"### {role} at {datetime.now().isoformat()}\n{content}\n\n")
10
11 def load_history(self) -> str:
12 if self.history_file.exists():
13 return self.history_file.read_text()
14 return ""
15
16 def chat(self, user_input: str) -> str:
17 self.save_to_disk("user", user_input)
18 history = self.load_history()
19 response = self.client.messages.create(
20 model="claude-sonnet-4-20250514",
21 max_tokens=1024,
22 system=f"Previous conversation:\n{history}",
23 messages=[{"role": "user", "content": user_input}],
24 )
25 reply = response.content[0].text
26 self.save_to_disk("assistant", reply)
27 return reply

El problema de la persistencia está resuelto. Reinicia el script y la conversación sigue en disco. También podrías mantener un archivo de hechos separado que el agente extraiga con el tiempo:

text
1- User's name is Sarah
2- Sarah manages the backend team at Acme Corp
3- Acme Corp is a B2B SaaS company
4- Currently migrating production database to a new AWS region

Puedes abrir el archivo en cualquier editor, ver exactamente lo que sabe el agente y corregirlo a mano. Realmente útil para prototipado.

Con 4 hechos, esto funciona perfectamente. Carga todo el archivo en el contexto y el LLM maneja cualquier pregunta sobre Sarah, su empresa o su industria.

Ahora adelanta tres meses. Tu agente tiene 2000 hechos extraídos y 200 registros de conversación. Eso son más de 500K tokens de markdown en disco, y tu ventana de contexto es de 128K.

Ya no puedes cargarlo todo. Necesitas recuperar selectivamente solo los hechos relevantes para la consulta actual. Con archivos planos, tu única opción es la búsqueda por palabras clave:

python
1# User asks: "What's the status of our cloud migration?"
2grep("cloud migration", facts_file)
3# Returns: []
4# The fact on disk says "migrating production database to a new AWS region."
5# The words "cloud migration" appear nowhere.
6
7# User asks: "Which team is handling the database work?"
8grep("database team", facts_file)
9# Returns: []
10# One fact says Sarah "manages the backend team." Another says the team
11# is "migrating production database." But no single line contains
12# both "database" and "team" together.

A pequeña escala, los archivos markdown funcionan. A escala real, fuerzan la recuperación por palabras clave, y las palabras clave no pueden manejar sinónimos, paráfrasis o conexiones entre hechos.

La información está en disco. Pero no puedes cargarla toda, y la búsqueda por palabras clave es demasiado frágil para encontrar las piezas correctas.

Si has usado OpenClaw, has visto esto en acción. Almacena la memoria como archivos de checkpoint en markdown, y tras semanas de uso diario, los hechos más antiguos se desvanecen silenciosamente a medida que el contexto se acumula y se compacta. El almacenamiento está ahí. La recuperación no.

Almacenamiento sin recuperación inteligente es una biblioteca sin catálogo.

Capa 3: Búsqueda vectorial y el muro que encuentra

Añade embeddings. Trocea tu markdown, embediza los trozos, busca por similitud coseno. Ahora "base de datos" coincide con "PostgreSQL" porque sus vectores viven cerca en el espacio de embeddings. El problema de los sinónimos se disuelve.

Entonces te topas con otro muro. Considera estos tres hechos en tu base de datos vectorial:

text
1- "Alice is the tech lead on Project Atlas"
2- "Project Atlas uses PostgreSQL for its primary datastore"
3- "The PostgreSQL cluster experienced an outage on Tuesday"

El usuario pregunta: "¿El proyecto de Alice se vio afectado por la caída del martes?"

La consulta menciona a Alice y la caída del martes, por lo que la búsqueda vectorial posiciona alto el primer y el tercer hecho. Pero el puente crítico, "Project Atlas usa PostgreSQL", no menciona ni a Alice ni al martes. Es la pieza que conecta, y es la que no aparecerá.

Cada hecho es un punto aislado en el espacio de embeddings. El tejido conectivo que los une es invisible para los vectores.

Akshay 🚀 - inline image

Esto no es un caso extremo. Es la forma normal de las preguntas del mundo real. El conocimiento empresarial es inherentemente relacional: las personas pertenecen a equipos, los equipos poseen proyectos, los proyectos dependen de sistemas, los sistemas tienen incidentes. Cualquier pregunta que cruce dos o más saltos supera lo que la recuperación vectorial plana puede responder.

La matriz de capacidades

Cada capa soluciona el dolor anterior pero revela uno más profundo:

Akshay 🚀 - inline image

Necesitas persistencia, comprensión semántica y razonamiento relacional en una única capa de memoria.

Construir esto tú mismo significa pegar una base de datos vectorial, una base de datos de grafos, un almacén relacional, un extractor de entidades, un pipeline de deduplicación y un sistema de ponderación de aristas. Son semanas de trabajo de infraestructura antes de escribir una sola línea de lógica de agente.

He estado usando una solución que llena este vacío de forma limpia. Es completamente de código abierto, maneja los tres paradigmas de almacenamiento bajo un mismo techo, y puedes ponerla en funcionamiento en minutos. Hablemos de Cognee.

Cognee: tres almacenes, un motor, cuatro llamadas

Cognee es un motor de conocimiento de código abierto construido para la memoria de agentes. Combina la búsqueda vectorial con grafos de conocimiento y una capa de procedencia relacional en un solo sistema.

Toda la superficie de la API son cuatro llamadas asíncronas:

python
1import cognee
2
3await cognee.add("Your document here") # Ingest anything
4await cognee.cognify() # Build knowledge graph + embeddings
5await cognee.memify() # Self-improve the memory
6await cognee.search("Your query") # Retrieve with reasoning

Detrás de esas cuatro llamadas se encuentra una arquitectura de tres almacenes.

Akshay 🚀 - inline image

¿Por qué tres almacenes y no uno?

Cada almacén captura una dimensión del conocimiento que los otros no pueden:

  • Almacén relacional → procedencia: de dónde vienen los datos, cuándo se ingirieron, quién tiene acceso
  • Almacén vectorial → semántica: qué significa el contenido, a qué es similar
  • Almacén de grafos → relaciones: cómo se conectan las entidades, qué causa qué, quién reporta a quién

Aplana cualquiera de estos y pierdes información que es importante para la precisión de la recuperación.

La pila por defecto es SQLite + LanceDB + Kuzu, completamente embebida y basada en archivos. pip install cognee más una clave de API de LLM y ya estás funcionando.

Sin Docker, sin servicios externos.

Para producción, cambia SQLite por Postgres, LanceDB por Qdrant/Pinecone/pgvector, y Kuzu por Neo4j/FalkorDB/Neptune.

La misma API de cuatro llamadas en ambos casos.

¿Qué hace realmente cognify?

cognee.cognify() ejecuta un pipeline de múltiples etapas que convierte texto bruto en conocimiento estructurado e interconectado:

  1. Clasificación de documentos por tipo y dominio
  2. Verificación de permisos para control de acceso multiinquilino
  3. Extracción de fragmentos que respeta la estructura de párrafos (no cortes de tamaño fijo)
  4. Extracción de entidades y relaciones mediante LLM, con deduplicación automática mediante hashing de contenido
  5. Generación de resúmenes para una recuperación eficiente
  6. Indexación dual en el almacén vectorial (embeddings) y el almacén de grafos (aristas)

El paso de deduplicación es más importante de lo que parece. Si la misma entidad aparece en 50 documentos, Cognee la fusiona en un único nodo de grafo con 50 aristas entrantes. Tu agente ya no ve a "Alice" como 50 desconocidos diferentes. Y el pipeline es incremental por defecto: solo se reprocesan los archivos nuevos o modificados.

Akshay 🚀 - inline image

Cada nodo del grafo tiene un embedding correspondiente. Esta representación dual es el truco central: entra a través de los vectores (encuentra contenido semánticamente similar) y sal a través del grafo (sigue las relaciones hasta entidades conectadas), o viceversa. Esto es lo que hace que las consultas de múltiples saltos funcionen sin sacrificar la búsqueda semántica.

Memify: memoria que aprende

memify() es lo que diferencia a Cognee de cualquier herramienta de "ingerir y buscar". Ejecuta un paso de optimización inspirado en RL sobre el grafo:

  • Fortalecer caminos útiles que llevaron a una buena recuperación
  • Podar nodos obsoletos que no se han tocado
  • Autoajustar los pesos de las aristas basándose en el uso real
  • Añadir hechos derivados identificando relaciones implícitas

El grafo de un agente de atención al cliente fortalece naturalmente los caminos a través de documentos de producto y políticas de reembolso, mientras deja que las aristas de RR.HH. raramente consultadas se degraden. El grafo desarrolla su propio sentido de relevancia con el tiempo.

Akshay 🚀 - inline image

Catorce modos de recuperación

Cognee incluye 14 modos de búsqueda. Los que realmente usarás:

Akshay 🚀 - inline image

Construyendo un agente real con memoria Cognee

Aquí está el patrón completo para conectar Cognee en el bucle percibir-pensar-actuar:

python
1import cognee
2from cognee import SearchType
3
4class CogneeMemoryAgent:
5 """Agent with graph-vector hybrid persistent memory."""
6
7 def __init__(self, session_id: str = "default"):
8 self.llm_client = OpenAI()
9 self.session_id = session_id
10
11 async def ingest(self, text: str, dataset: str = "main"):
12 await cognee.add(text, dataset)
13 await cognee.cognify([dataset])
14
15 async def recall(self, query: str) -> str:
16 results = await cognee.search(
17 query_text=query,
18 query_type=SearchType.GRAPH_COMPLETION,
19 session_id=self.session_id,
20 )
21 return results[0] if results else ""
22
23 async def chat(self, user_input: str) -> str:
24 context = await self.recall(user_input)
25 messages = [
26 {"role": "system", "content": "You are helpful. Use memory context."},
27 {"role": "system", "content": f"Memory context:\n{context}"},
28 {"role": "user", "content": user_input},
29 ]
30 response = self.llm_client.chat.completions.create(
31 model="gpt-4o-mini", messages=messages
32 )
33 reply = response.choices[0].message.content
34 await cognee.add(
35 f"User: {user_input}\nAssistant: {reply}",
36 "conversations"
37 )
38 await cognee.cognify(["conversations"])
39 return reply

El ciclo de memoria: ingerir, extraer, almacenar, recuperar, responder, almacenar de nuevo. Cada turno enriquece el grafo de conocimiento, y el procesamiento incremental significa que solo pagas por indexar contenido nuevo.

La memoria de sesión maneja la resolución de pronombres automáticamente:

python
1await cognee.search(query_text="Where does Alice live?", session_id="conv_1")
2await cognee.search(query_text="What does she do for work?", session_id="conv_1")
3# "she" resolves to Alice from session context

La multi-inquilinato está integrada a nivel de grafo con permisos por conjunto de datos (lectura, escritura, eliminación, compartir). No es separación por espacio de nombres, sino aislamiento real a nivel de grafo.

El camino práctico a seguir

Si estás construyendo un agente hoy, la pregunta inicial real es: "¿Qué necesita recordar mi agente, y qué tipo de preguntas va a responder?"

Si tus consultas solo necesitan búsqueda por similitud ("encuentra conversaciones como esta"), la memoria solo vectorial funciona. En el momento en que las consultas cruzan límites entre entidades ("¿El proyecto de Alice se vio afectado por la caída del martes?"), necesitas recorrido de grafos.

Puedes conectar por tu cuenta almacenes separados de vectores, grafos y relacionales. Los equipos que optan por esta ruta suelen perder semanas en infraestructura para una capa de memoria que aún no aprende de su propio uso.

Cognee reduce eso a cuatro llamadas de API. Los valores predeterminados embebidos te ponen en marcha en minutos. Los backends intercambiables (Postgres, Qdrant, Neo4j) te llevan a producción sin cambiar el código de tu agente.

La inteligencia requiere estructura, no solo almacenamiento. Los tres paradigmas de almacenamiento (relacional, vectorial, grafo) no son opciones en competencia. Son capas complementarias del mismo sistema de memoria. Tratarlos así es lo que convierte un envoltorio de LLM sin estado en algo que realmente aprende.

¿Qué es lo próximo que te gustaría que tu agente recordara mañana que hoy olvidó? Empieza por ahí.

👉 Echa un vistazo a Cognee en GitHub →, dale una estrella y prueba a conectarlo en tu próximo agente.

Cuatro llamadas asíncronas, un pip install, y ya estás funcionando.

¡Eso es todo!

Si disfrutaste leyendo esto:

Encuéntrame →@akshay_pachaar ✔️

Cada día, comparto tutoriales y reflexiones sobre IA, Machine Learning y las mejores prácticas de "vibe coding".

Guardar con un clic

Lee artículos virales en profundidad con IA en YouMind

Guarda la fuente, haz preguntas concretas, resume el argumento y convierte un artículo viral en notas reutilizables en un único espacio de trabajo con IA.

Explora YouMind
Para creadores

Convierte tu Markdown en un artículo de 𝕏 impecable

Cuando publicas tus propios textos largos, dar formato en 𝕏 a imágenes, tablas y bloques de código es un fastidio. YouMind convierte un borrador completo en Markdown en un artículo de 𝕏 impecable y listo para publicar.

Prueba Markdown a 𝕏

Más patrones por descifrar

Artículos virales recientes

Explorar más artículos virales