- entaina
- Posts
- llmemory: memoria persistente para agentes LLM en Ruby
llmemory: memoria persistente para agentes LLM en Ruby

Los modelos de lenguaje tienen un problema de fábrica: amnesia. Cada llamada a la API empieza de cero. Si quieres que tu agente recuerde que el usuario es vegano, que trabaja en Acme o que la semana pasada resolvió un problema parecido, tienes que construir esa memoria tú mismo. Eso es exactamente lo que hace llmemory, una gema Ruby que da a tus agentes una memoria completa: a corto plazo, a largo plazo y —lo más interesante— cognitiva.
Enlace a github: https://github.com/entaina/llmemory
La idea en 30 segundos
memory = Llmemory::Memory.new(user_id: "user_123", session_id: "conv_456")
memory.add_message(role: :user, content: "Soy vegano y trabajo en Acme")
memory.add_message(role: :assistant, content: "Entendido, lo recordaré")
# Consolida la conversación en memoria a largo plazo (extrae hechos con el LLM)
memory.consolidate!
# En la siguiente sesión, días después:
context = memory.retrieve("¿Qué preferencias alimentarias tiene el usuario?")
# => contexto listo para inyectar en tu prompt Una única API (Llmemory::Memory) orquesta todo: el historial de conversación se guarda como checkpoints (memoria a corto plazo), un extractor basado en LLM destila hechos hacia la memoria a largo plazo, y la recuperación combina ambas fuentes en un contexto formateado y acotado por tokens.
Dos formas de recordar: hechos o grafo de conocimiento
La memoria a largo plazo tiene dos sabores:
File-based (por defecto): hechos planos organizados en categorías y recursos. Simple y suficiente para la mayoría de chatbots.
Graph-based: un grafo de conocimiento con entidades y relaciones sujeto–predicado–objeto (
User —works_at→ Acme), combinado con embeddings vectoriales. La recuperación es híbrida: búsqueda semántica + recorrido del grafo desde los nodos encontrados. Incluye resolución de conflictos: si el usuario cambia de empresa, el predicado exclusivoworks_atarchiva el valor anterior en vez de acumular contradicciones.
Memoria cognitiva: el patrón CoALA
Aquí es donde llmemory va más allá del típico "RAG sobre conversaciones". Implementa la arquitectura de memoria del paper CoALA (Cognitive Architectures for Language Agents):
Memoria de trabajo (
WorkingMemory): un espacio simbólico estructurado (objetivos, tarea actual, slots arbitrarios) que persiste entre llamadas al LLM, separado del buffer de mensajes.Memoria episódica: trayectorias de experiencia completas (observación → acción → resultado), al estilo de los agentes que aprenden de lo que les pasó.
Memoria procedural: una biblioteca de skills (prompts, plantillas, código) inspirada en Voyager, con versionado automático y tasa de éxito/fracaso que alimenta el ranking de recuperación.
Reflexión: un
Reflectordestila episodios recientes en insights semánticos (patrón Reflexion / Generative Agents), con trazabilidad hacia los episodios de origen.Skill mining: extrae automáticamente procedimientos reutilizables de los episodios y los registra como skills.
Un solo método, memory.cognitive_maintain!, cierra el ciclo completo: consolida, reflexiona, mina skills y expira lo caducado.
Recuperación que entiende el tiempo (y aprende)
Recuperar memoria no es solo buscar: llmemory aplica decaimiento temporal (media vida configurable: lo de hace tres meses pesa menos que lo de ayer), importancia, búsqueda híbrida BM25 + vectores con re-ranking MMR opcional, y un bucle de feedback adaptativo — marca una memoria recuperada como útil o dañina y los siguientes rankings se ajustan. También hay recuperación iterativa multi-hop: el LLM propone consultas de seguimiento hasta cubrir la pregunta.
Preparado para producción
Backends conectables:
:memory, Redis, PostgreSQL o ActiveRecord (con generador de migraciones para Rails y pgvector para embeddings).Cifrado en reposo AES-256-GCM opcional, con clave global o por instancia — aislar tenants o agentes criptográficamente es una línea de código.
Contabilidad de tokens real: captura los contadores de las respuestas de OpenAI y Anthropic (chat y embeddings) y los acumula por usuario.
memory.llm_usagete dice cuánto te está costando la memoria de cada usuario.Gestión de contexto: flush de memoria antes de compactar (no se pierde conocimiento al resumir), poda de resultados de herramientas, seguimiento de la ventana de contexto y auto-consolidación al superar umbrales.
Olvido auditado:
forgetelimina memorias y deja constancia en unForgetLog— porque "borra lo que sabes de mí" también hay que poder demostrarlo.Trazabilidad (provenance): cada hecho, nodo o insight sabe de dónde salió, con qué método y con qué confianza.
Inspección e integración
CLI:
llmemory stats USER_IDpara ver qué recuerda el sistema (y cuántos tokens ha gastado).Dashboard Rails opcional para explorar la memoria desde el navegador.
Servidor MCP (Model Context Protocol) con transporte stdio y HTTP/HTTPS con autenticación: cualquier agente compatible con MCP — Claude Code incluido — puede leer y escribir memoria como herramientas nativas.
En resumen
llmemory convierte "mi bot no se acuerda de nada" en un problema resuelto con una gema: add_message, consolidate!, retrieve — y por debajo, una arquitectura cognitiva completa con grafo de conocimiento, memoria episódica y procedural, cifrado, y control de costes. Si construyes agentes LLM en Ruby, es la pieza de memoria que no tienes que volver a escribir.
gem "llmemory"