Memoria persistente entre sesiones de agentes IA
Los LLMs son stateless por diseño: cada conversación empieza desde cero. Aquí tienes una guía práctica para elegir la estrategia de memoria correcta — desde CLAUDE.md hasta mem0, Zep, Graphiti y Engram.
El problema
Los LLMs son stateless por diseño. Cada nueva conversación empieza desde cero. En un sistema agéntico esto se convierte en un freno real: el agente no recuerda qué tickets ha trabajado antes, qué decisiones técnicas tomó el equipo la semana pasada ni qué errores cometió en el último sprint.
La pregunta de fondo: ¿cómo hacer que un agente "recuerde" entre sesiones sin meter todo el histórico en el context window?
Taxonomía de memoria en agentes
Antes de elegir herramienta hay que saber qué tipo de memoria necesita el sistema. La mayoría de proyectos solo necesitan semantic + procedural — que es exactamente lo que resuelven CLAUDE.md y las reglas de Claude Code sin ninguna librería adicional.
| Tipo | Qué almacena |
|---|---|
| Working memory | Contexto de la conversación actual |
| Episodic memory | Registro de lo que pasó en sesiones anteriores |
| Semantic memory | Conocimiento factual del dominio o del proyecto |
| Procedural memory | Cómo hacer las cosas — reglas y flujos |
Memoria en ficheros — el punto de partida
Herramienta: CLAUDE.md + .claude/rules/ + .claude/agents/
El modelo lee los ficheros al inicio de cada sesión. La "memoria" es el propio repositorio versionado: reproducible, auditable, editable por todo el equipo y sin coste adicional.
→ Suficiente para el 80% de los casos. Es el punto de partida obligatorio antes de añadir cualquier capa adicional.
Memoria en base de datos vectorial
Las conversaciones o fragmentos de contexto se convierten en embeddings y se almacenan. Antes de cada nueva sesión se hace una búsqueda semántica para recuperar los fragmentos más relevantes — el patrón conocido como RAG (Retrieval-Augmented Generation).
Cuándo usarlo: cuando la base de conocimiento supera las ~50 páginas de documentación y no cabe toda en el context window. Añade latencia y requiere infraestructura adicional.
Librerías de memoria para agentes
Capa de memoria para aplicaciones LLM. Extrae automáticamente "recuerdos" de las conversaciones, los almacena y los recupera en la siguiente sesión inyectándolos en el contexto.
- Extracción automática de recuerdos
- Soporta múltiples usuarios y agentes
- Tier gratuito cloud + opción self-hosted
Memory store con temporal awareness: sabe qué recuerdos son más recientes y los prioriza. Extrae entidades, hechos y decisiones de forma estructurada. Integración directa con LangChain y LlamaIndex.
Ideal para: asistentes de soporte o ventas donde el historial por usuario es crítico.
Knowledge graph temporal: almacena la memoria como un grafo de entidades y relaciones con timestamps. Permite consultas como "¿qué decisiones técnicas tomamos en marzo sobre autenticación?" — algo que un vector store no puede responder bien.
Librería Python para gestión de memoria con TTL (time-to-live), distintos backends (in-memory, Redis, SQLite) y API similar a mem0. Menor tracción de comunidad que mem0 o Zep. Útil para prototipos y exploración del concepto.
Comparativa rápida
| Herramienta | Auto | Madurez |
|---|---|---|
| CLAUDE.md + reglas | — | Alta |
| mem0 | Media-alta | |
| Zep | Alta | |
| Graphiti | Experimental | |
| Engram | — | Baja-media |
Implementación mínima con mem0
Capa de memoria lista para un sprint agent en TypeScript. Añade dos funciones: una para guardar decisiones y otra para recuperar contexto relevante antes de ejecutar cada ticket.
// memory-layer.ts — capa de memoria para un sprint agent
import { MemoryClient } from 'mem0ai';
const mem = new MemoryClient({ apiKey: process.env.MEM0_API_KEY });
export async function rememberDecision(agentId: string, decision: string) {
await mem.add(
[{ role: 'assistant', content: decision }],
{ user_id: agentId }
);
}
export async function recallContext(agentId: string, query: string) {
const memories = await mem.search(query, { user_id: agentId, limit: 5 });
return memories.map(m => m.memory).join('\n');
}
// Uso en el agente:
// const ctx = await recallContext('backend-agent', 'decisiones de autenticación');
// → inyectar ctx en el system prompt antes de ejecutar el ticketRecomendación por caso de uso
Siempre primero: ficheros
CLAUDE.md + .claude/rules/ bien estructurado. Cero coste, control total, cubre el 80% de los casos.
Extracción automática entre sprints: mem0
Cuando el equipo necesita que el agente recuerde decisiones técnicas sin que nadie las escriba manualmente.
Historial por usuario en producción: Zep
Cuando hay un asistente de soporte o ventas que gestiona relaciones con múltiples usuarios a lo largo del tiempo.
Anti-patrón más común
Añadir una capa de memoria compleja cuando el problema real es que el CLAUDE.md está mal estructurado o es demasiado genérico.
¿Memorias vectoriales para tu vibe coding o tu orquestador?
La respuesta corta: probablemente no.
Añadir una capa de memoria compleja cuando el problema real es que el CLAUDE.md está mal estructurado es un antipatrón claro. Es sobre-ingeniería innecesaria.
El contexto que un agente necesita para trabajar bien tiene dos fuentes naturales: la base de código y el CLAUDE.md. Cuando ambos están bien estructurados — convenciones claras, arquitectura documentada, reglas explícitas — el agente tiene todo lo que necesita para ejecutar un ticket correctamente sin haber visto nunca esa conversación antes.
Una memoria vectorial adicional no mejora eso. Lo que hace es añadir un elemento más que mantener, sincronizar y depurar cuando algo falla. En la mayoría de los flujos de vibe coding o de un orquestador de sprints, la ventana de contexto debería estar ocupada por cosas que importan ahora: el ticket, el esquema de la base de datos, las reglas del equipo, los tests existentes. No por fragmentos recuperados de conversaciones pasadas que el agente probablemente no necesita.
El síntoma más común de este antipatrón es este: el agente sigue cometiendo los mismos errores a pesar de tener una capa de memoria activa. La causa casi siempre es que el CLAUDE.md no tiene esa regla escrita. La solución no es mejorar la memoria — es escribir la regla.
Sobre-ingeniería
- → Añadir mem0 porque el agente "no recuerda" las convenciones
- → Montar un vector store para guardar reglas que caben en 20 líneas de CLAUDE.md
- → Sincronizar memoria entre agentes cuando un AGENTS.md compartido haría lo mismo
Cuándo sí tiene sentido
- → El agente gestiona relaciones con múltiples usuarios a lo largo del tiempo
- → Necesitas recordar decisiones entre sprints que no caben en ningún fichero
- → El sistema tiene más de un agente y necesitan compartir contexto acumulado
Regla práctica: si puedes resolver el problema escribiendo una línea más en tu CLAUDE.md, escríbela. La memoria vectorial es para cuando eso ya no es suficiente.
Referencias
¿Construyendo un sistema agéntico?
En Kuuli Technologies diseñamos e implementamos arquitecturas de agentes para equipos de desarrollo. Contáctanos si quieres ayuda para elegir la capa de memoria correcta para tu caso de uso.