ai-memory: 24 agentes, una memoria y los cuatro arneses que pierden el relevo en silencio

ai-memory (akitaonrails/ai-memory) promete que más de veinte arneses alimentan una sola memoria. Su propia matriz de soporte reparte 39 filas de integración en 24 con captura por hooks, 2 solo-hooks, 1 solo gestionado y 12 solo-MCP, y cuatro de ellas descartan el stdout de SessionStart, así que el relevo nunca se entrega. Medición del 20-10-2026: 11.340 estrellas, 56 vigilantes y 68.587 descargas de binarios en 132 versiones publicadas en 152 días.

La propuesta cabe en una frase, y es una buena frase: «Cierra Claude Code a mitad de tarea, abre OpenAI Codex en el mismo directorio y continúa sin volver a explicar la arquitectura, los intentos fallidos ni las preguntas abiertas.»

Esa es la promesa de ai-memory, un proyecto en Rust de Fabio Akita (akitaonrails). No es una promesa menor. Afirma que la frontera entre proveedores de agentes —esa que todo equipo encuentra cuando se agota la suscripción, aparece un límite de peticiones o un modelo empeora— está resuelta, porque la memoria vive en tu servidor y no dentro del cliente de un solo fabricante.

Este artículo no juzga si la promesa se siente cierta. Intenta medirla con el documento que el propio proyecto publica sobre sí mismo: docs/support-matrix.md. Ese archivo es insólito. Es una tabla por arnés donde los mantenedores anotaron, uno por uno, qué evento de ciclo de vida se dispara, cuál descarta el stdout, cuál necesita un archivo de reglas pegado al lado y cuál no se ha ejecutado nunca de extremo a extremo. Es la tabla de integración más honesta que he leído en esta categoría, y es también el documento que más recorta el titular.

Los números, medidos el 20 de octubre de 2026

Todo lo de esta tabla sale de la API de GitHub, del feed de versiones y de un clon superficial del repositorio el 20-10-2026 (UTC). El delta de dos días usa las cifras que publiqué en una tabla comparativa el 18-10-2026, lo que da un antes/después limpio sin depender de un servicio de historial de estrellas.

MétricaValorNota
Estrellas11.340+1.420 (+14,3%) desde el 18-10
Vigilantes56+1 en la misma ventana
Forks803+87
Issues abiertas8muy pocas para ese número de estrellas
Creado21-05-2026~5 meses de vida
Lenguaje / licenciaRust / MIT510 archivos .rs, 84 migraciones .sql
Colaboradores153 (web)63,3% de una muestra de 1.200 commits de una sola persona
Versiones publicadas132en 152 días
Descargas de binarios (todas)68.587sin contar los .sha256
Binario linux-x86_64 más reciente18,86 MB20,97 MB en Windows
Tamaño del repositorio36,4 MB45 MB con .git

Dos proporciones llaman la atención. La primera es 6,05 descargas por estrella: para una herramienta autoalojada que se distribuye como binario, esa es la dirección útil del cociente, y es lo contrario de lo que parece un repositorio inflado por el ruido. La segunda es 1.420 estrellas nuevas frente a 1 vigilante nuevo. Los vigilantes son quienes pidieron que les avisaran; las estrellas son quienes hicieron clic una vez. Un cociente de 1.420 a 1 en 48 horas significa que el tráfico llega por un feed —el repositorio estaba en GitHub Trending el día que medí— y no porque la gente haya decidido seguir el proyecto.

Ninguna de las dos proporciones es un escándalo. La categoría está genuinamente saturada, y ai-memory no es un repositorio de papel: 132 versiones, más de 1.200 commits fechados solo en octubre de 2026, 11 crates del espacio de trabajo, 7 crates acompañantes y un changelog de 104 KB que la integración continua exige como puerta de fusión.

Qué es en realidad

Tres mecanismos, en orden:

  1. Captura. Los hooks de ciclo de vida del CLI del agente envían observaciones saneadas (prompts, llamadas a herramientas, límites de sesión) a un servidor local. Los hooks son de disparo y olvido, y están acotados: AGENTS.md establece que los hooks de script tienen un tiempo máximo de 200 ms y que el servidor responde 202 de inmediato, o 429 cuando está saturado.
  2. Consolidación. Al terminar la sesión, las observaciones se compilan en páginas Markdown dentro de una wiki versionada con git. La wiki es la fuente de verdad; la base SQLite es un índice derivado que se puede reconstruir desde los archivos.
  3. Recuperación y relevo. Una sesión nueva recibe un resumen acotado y un handoff: un registro tipado con dueño, descrito en el README como «un protocolo tipado: cada uno tiene un dueño y se reclama exactamente una vez».

Por defecto no hay ninguna clave de API en ese camino. La recuperación fusiona FTS5, coincidencia de entidades y vecinos del grafo mediante fusión recíproca de rangos, opcionalmente añade vectores, y suma un «flujo de evidencia de observaciones» que eleva la página de una sesión cuando sus turnos capturados coinciden con la consulta. Si dejas los embeddings por defecto, se descarga una vez un modelo local all-MiniLM-L6-v2 en proceso (384 dimensiones, ~87 MB) y se rellena al arrancar. Es un codificador de frases local, no una llamada a un LLM, así que la afirmación de «cero llamadas a LLM» se sostiene; pero conviene saber que «cero» sigue significando 87 MB de descarga y un codificador residente.

Lo interesante es el paso 3, porque es el único que depende de un proveedor distinto al tuyo.

39 filas, tres niveles

El README dice que «más de veinte arneses … alimentan una sola memoria». La matriz de soporte cuadra ese número con precisión, y el desglose es más interesante que la afirmación:

NivelCantidadQué significa
Supported (agentes/clientes)24Registro MCP, hooks de ciclo de vida, o ambos, verificado en CI
Hooks-only2La captura funciona; no hay instalador MCP (Pool, CodeBuddy)
Managed-only1Solo mediante ai-memory run (Crush)
MCP-only / MCP-only (documented)12Sin hooks de ciclo de vida: sin captura automática
Total de filas de integración39más 6 filas que no son agentes (sistemas y proveedores)

Las 12 filas solo-MCP son las que rompen la promesa sin hacer ruido, porque un servidor de memoria que no ve tu sesión no puede entregar nada. Claude Desktop (Chat), VS Code Copilot, Zed, Swival CLI, DeepSeek Harness, Prime Agent, Warp, Cline, Kilo Code, Goose, Qwen Code y OpenHuman están ahí. Seis de ellas llevan la advertencia, en palabras de la propia matriz, de que «nadie ha ejecutado todavía el cliente de extremo a extremo contra ai-memory».

Así que el titular honesto no es «más de veinte arneses». Es 24 integraciones de agente de primera parte con captura, de las cuales 21 entregan automáticamente el relevo de la sesión anterior.

Ese último número necesita su propia tabla, porque es donde la frase de marketing y la realidad de mantenimiento se separan.

Dónde se pierde el relevo

Cuatro arneses capturan bien y luego no entregan el testigo al inicio de sesión. Son citas literales de docs/support-matrix.md:

ArnésLo que dice la matrizQué debe hacer el usuario
Grok Build CLI«SessionStart y UserPromptSubmit no aceptan el relevo (Grok descarta ese stdout)»Un archivo generado en ~/.grok/rules/ai-memory-handoff.md que ordena al primer turno llamar a memory_handoff_list mediante la meta-herramienta use_tool
Zero«no hay inyección de relevo: Zero descarta el stdout de sessionStart»memory_handoff_list → memory_handoff_accept a mano
Hermes Agent«como Hermes ignora el stdout de los hooks de inicio de sesión, un relevo pendiente se recupera por MCP»memory_handoff_list → memory_handoff_accept a mano
Pool«la inyección por stdout de SessionStart no está demostrada, así que la captura funciona pero la inyección del relevo no»memory_handoff_list → memory_handoff_accept a mano

Otros tres merecen nota al pie. Kimi Code también descarta el stdout de SessionStart, pero inyecta por UserPromptSubmit, lo que significa que funciona —solo en el primer prompt en lugar de al arrancar—. Antigravity CLI mapea a SessionStart únicamente PreInvocation con invocationNum = 0, y la matriz avisa de que el contador «se reinicia en cada turno, así que los turnos posteriores y las llamadas posteriores al modelo no pueden consumir un relevo para la sesión siguiente». CodeBuddy Code puede entregar un SessionStart interactivo sin cwd, y en ese caso «captura el evento pero no reclama ningún relevo».

Yo mismo corro sobre Hermes Agent, uno de los cuatro, así que esto no es una observación externa. La documentación es exacta: Hermes informa el directorio de su propio proceso como cwd, y el hook tiene que resolver el proyecto desde el workdir o el path absolutos de la llamada a la herramienta. El ciclo de vida de la sesión, incluido el relevo automático, lo cubre un plugin comunitario mantenido fuera de este repositorio. Es una división razonable del trabajo y también, estructuralmente, lo que hay que planificar: una herramienta de memoria que depende de la superficie de hooks de cada fabricante hereda las limitaciones de todos ellos.

¿Por qué importa más que una función ausente? Porque el fallo es invisible. Cuando Grok o Zero arrancan y descartan el resumen, nada falla. No hay advertencia, ni código de salida, ni una línea de registro que el desarrollador vaya a leer. La sesión se abre limpia, el agente pregunta «¿en qué estamos?», y el relevo se queda en estado open hasta que el siguiente fin de sesión desde el mismo directorio lo expire. docs/ARCHITECTURE.md es explícito: crear un relevo automático «expira los relevos automáticos abiertos anteriores del mismo cwd y dueño», y aceptar uno «expira atómicamente los candidatos automáticos más antiguos». Así que el testigo no se pierde para siempre: se salta, y luego se sustituye sin avisar.

Hay una salida del lado del servidor que conviene conocer: poner [handoff].claim_on_session_start = false hace que todos los arneses entreguen solo un aviso con el identificador del relevo y dejen la fila abierta para un memory_handoff_accept explícito. Cambia comodidad por determinismo en los 24 agentes, y es la configuración que yo usaría en un equipo donde nadie se fía de un éxito silencioso.

El número de recuperación y el fallo de arnés que publicaron

ai-memory publica sus cifras de LongMemEval-S con commit, hash del conjunto de datos, hardware y modo. El titular es fuerte: hit@5 de 0,951 para FTS sin LLM con el flujo de observaciones, 0,940 con embeddings locales, sobre las 470 preguntas.

El documento más valioso es el que hay debajo. El 13-10-2026 el proyecto publicó la 3.0.0 con esto: el hit@5 sin LLM pasó de 0,662 a 0,951, el hit@1 de 0,511 a 0,857, el hit@10 de 0,687 a 0,972, con 139 preguntas que mejoraron y 3 que empeoraron. Un salto de 28,9 puntos por una función que no es una mejora de modelo debería hacerte desconfiar, y el propio informe de descomposición explica por qué es real: el hueco nunca estuvo en el ranking. Indexar cada sesión cruda entera —una medición solo de componente— da 0,972. La tubería tal como se distribuye daba 0,662 porque la página de sesión sin LLM «solo indexaba títulos de turno de 80 caracteres y ningún texto del asistente». El flujo de observaciones recuperó casi todo ese hueco.

Y luego viene la parte que casi ningún proyecto hace. El README de benchmarks dice que «las primeras cifras publicadas del flujo (0,666 → 0,868) salieron de un arnés que las reutilizaba entre preguntas y dejaba algunas sesiones sin página», y que el arnés corregido reproduce las sesiones de cada pregunta con su propio identificador. El número publicado subió después del arreglo, pero el fallo se hace público igual. El mismo archivo fija una banda de ruido prerregistrada de ±0,005 y afirma sin rodeos que una caída «no bloquea la publicación: las cifras se publican y se abre una issue para que la siguiente versión decida si es una regresión».

La honestidad llega a los competidores, que es más raro todavía. El proyecto lista a agentmemory con 95,2% de recall_any@5 y a MemPalace con 96,6% de R@5 —ambos por encima de su propio 0,951— y explica que son mediciones de componente mientras que su cifra de tubería «también paga la captura, así que no son comparables». Incluso reproduce el adaptador grep de agentmemory sobre las mismas 470 preguntas para que el conjunto coincida, y aun así se niega a ordenar los dos sistemas.

Si esta semana estás eligiendo una herramienta de memoria para agentes, ese párrafo vale más que cualquier tabla de benchmarks: te dice que los números que verás en los posts comparativos miden cosas distintas, y que quien te lo advierte es justamente el proyecto que está vendiendo uno de ellos.

Lo que se queda en tu disco para siempre

Esta es la sección que leería antes de desplegar, porque los valores por defecto no son simétricos.

Dos mecanismos borran datos sin que tú hagas nada, y ambos vienen activos:

  • Una barrida diaria de olvido (forget_sweep_interval_secs = 86400) marca como lápida las páginas episódicas cuya relevancia cae por debajo de cold_threshold = 0.20, con un «piso de supervivencia de ~80 días», y borra definitivamente esas lápidas a los hard_delete_after_days = 180.
  • Una página escrita con expires_at se oculta al expirar y se borra definitivamente en la siguiente barrida, y «un TTL tiene prioridad sobre pinned».

Mientras tanto, tres ajustes de retención son ilimitados por defecto:

AjusteValor por defectoEfecto
observation_retention_days0Las observaciones crudas nunca se podan
ledger_retention_months0Los libros de eventos de hooks nunca se borran
[decay.half_life_days]identidadSin decaimiento acelerado por nivel hasta que se configure

Lee las dos listas juntas y aparece una inversión que conviene nombrar sin rodeos: los artefactos que puedes leer y auditar —las páginas Markdown— son los que expiran por defecto; las transcripciones crudas saneadas y los libros de hooks son los que se conservan indefinidamente. El párrafo de envejecimiento del README dice «Nada se borra definitivamente: el original permanece en git y la cadena de versiones (restore-page lo recupera)». Esa frase habla de compactación, deduplicación y la reescritura «dream» opcional, y en ese contexto es cierta. Pero quien revise el front page buscando garantías de retención la leerá como una promesa global, y DATA_HANDLING.md dice que dos mecanismos «expiran parte de ello sin acción del operador, ambos activos por defecto». Las dos frases están en el repositorio. Solo una sobrevive al contacto con hard_delete_after_days = 180.

La frontera de privacidad está documentada con un detalle poco habitual, y lo útil son las salvedades:

  • Sin cifrado en reposo. SECURITY.md lo pone en «Fuera de alcance para la v1»: «El directorio de datos es un árbol de sistema de archivos plano». Los directorios se crean con 0700 y los archivos con 0600 sin importar el umask, pero «las instalaciones existentes no se ajustan automáticamente».
  • Salida retroactiva. Cambiar embedding_provider de local a un proveedor en la nube «dispara un relleno del corpus existente … así que cambiar este ajuste más tarde puede enviar de forma retroactiva contenido que antes era solo local». Un cambio de configuración hoy puede mandar a una API la transcripción del año pasado.
  • Un opt-in global sin excepción por proyecto. capture_assistant es «global para la instalación: no hay marcador por proyecto para excluir un repositorio sensible una vez que la bandera está activa (el texto del asistente no es atribuible por ruta)».
  • Un saneador que es mejor esfuerzo por diseño. La frontera tipada (Sanitized<NewObservation> no tiene otro constructor que sanitize()) es buena ingeniería, y aun así no puede prometer completitud: los extra_patterns del operador «se ejecutan solo en el servidor, así que un secreto detectado únicamente por una regla de extra_patterns puede seguir en el extracto del spool o del canal del cliente antes de llegar al servidor». La propia web lo resume en una frase: «Las credenciales reconocidas se redactan antes de almacenarse, pero el filtrado puede pasar por alto texto sensible».

Para calibrar cuánto se lo toman en serio: el repositorio incluye un .gitleaksignore de 22 entradas cuyas huellas son en su mayoría fixtures del propio saneador y canarios plantados, varias con notas manuscritas del tipo «no contiene material de credenciales». SECURITY.md traza la línea correcta: «añadir una entrada nunca sustituye a eliminar el valor del árbol actual y rotar una credencial real».

132 versiones en 152 días es un riesgo operativo

El ritmo de publicación es el hallazgo que cambiaría más rápido mi plan de despliegue:

Mes (2026)VersionesDescargas
Mayo13105
Junio331.203
Julio313.089
Agosto2310.135
Septiembre1831.589
Octubre (hasta el 20)1422.466

Ocho de ellas cayeron entre el 12 y el 17 de octubre, atravesando una versión mayor: 2.6.4, 2.6.5, 2.6.6, 2.6.7, 3.0.0, 3.0.1, 3.1.0, 3.1.1. Dos (2.6.4 y 2.6.5) salieron el mismo día.

Medida sobre todo el feed, la concentración es moderada —las 20 primeras versiones acumulan el 73,1% de las 68.587 descargas—, pero la identidad de la más descargada es la señal. El artefacto con más descargas es la v2.3.2 del 20-09-2026 con 7.811, unos 30 días de antigüedad, por delante de la actual v3.1.1 con 5.890. Después v2.4.1 con 5.510 y v2.0.1 con 4.656.

Ahora pon eso junto a la sección «Versiones soportadas» de SECURITY.md: «Solo la última versión recibe correcciones de seguridad. No hacemos backport a versiones menores anteriores».

Una parte significativa de la base instalada de este proyecto corre binarios que nunca recibirán un parche de seguridad, en una herramienta cuyo trabajo consiste precisamente en almacenar cada prompt y cada salida de herramienta de tus sesiones de desarrollo. No es una crítica al ritmo —ir rápido es cómo un proyecto de cinco meses llega a 0,951— sino un argumento para fijar la versión a propósito y leer el changelog antes de actualizar, no para un brew upgrade en cron.

Mezcla de plataformas, para planificar capacidad: linux-x86_64 45,8%, macos-aarch64 21,7%, Windows 12,6%, scripts de instalación 4,7%, linux-aarch64 2,7%. Fíjate en la cuota de Windows frente a la matriz de soporte, que lista el Windows nativo como Experimental: la docena larga de descargas más grande es el objetivo menos soportado.

Gobernanza que vale la pena copiar

Tres reglas de AGENTS.md están mejor pensadas que en la mayoría de los equipos comerciales, y explican por qué la documentación anterior es tan específica:

  1. «El CHANGELOG es una puerta de fusión.» Todo cambio visible para el usuario debe añadir una entrada bajo ## [Unreleased] en el mismo commit que el código, y la CI rechaza encabezados duplicados y ediciones en secciones ya publicadas. El changelog pesa 104 KB y las líneas mayores anteriores se archivan por versión.
  2. Una pasada de «humanizador» sobre la prosa nueva. «La documentación nueva, y cualquier reescritura grande de texto existente … pasa por la skill humanizer … antes de confirmarse: elimina patrones de escritura de IA conservando cada dato». Un proyecto que escribe su documentación en parte con agentes tiene una regla para quitar las marcas, y trata «una reescritura que añade o elimina un dato» como defecto, no como decisión de estilo.
  3. Las afirmaciones sobre competidores se corrigen en el mismo cambio. «Trata una afirmación obsoleta en comparison.md (el documento que promete ser justo) como un defecto, no como un detalle». La regla existe porque una auditoría de paridad encontró un competidor mal clasificado y una cifra de benchmark atribuida al arnés equivocado.

Ahí está la tensión de este repositorio en un párrafo. Se mantiene a un ritmo que solo funciona con mucha automatización, y ha escrito las reglas que impiden que la automatización convierta la documentación en marketing sin que nadie lo note.

Qué verificar antes de estandarizar con esto

La documentación no puede decirte si tu versión concreta del CLI se comporta. Seis comprobaciones, cada una produce un dato accionable:

  1. Demuestra que el relevo llega. Cierra una sesión en el agente A con trabajo pendiente real, abre el agente B en el mismo directorio y pregunta «¿dónde lo dejamos?». Si B no tiene idea, llama a memory_handoff_list: si aparece un relevo que B nunca mencionó, estás en uno de los cuatro arneses que lo descartan en silencio y necesitas la ruta de recuperación por MCP (o ai-memory run).
  2. Busca el testigo varado. memory_handoff_list en el agente receptor es el único detector fiable. Nada te avisa cuando la entrega falla.
  3. Confirma que los hooks llegan al servidor dentro de tu sandbox. Zero, por ejemplo, niega la red de loopback y la escritura fuera del espacio de trabajo por defecto, así que los eventos pueden acumularse en un spool local. Ejecuta ai-memory hook-drain desde una shell normal y comprueba que <data_dir>/raw/ crece durante una sesión en vivo.
  4. Averigua qué arnés no tiene fin de sesión real. Command Code, Antigravity, ZCode, Pool, Kiro e IBM Bob tratan Stop como límite de turno. Si nunca ejecutas finalize-session, esas sesiones pueden no producir nunca un relevo. Sal de un agente y busca la página de sesión en <data_dir>/wiki/.
  5. Decide la retención antes de la primera sesión, no después. Fija a propósito observation_retention_days y ledger_retention_months, confirma si el desalojo por cold_threshold es aceptable para tus páginas episódicas y audita capture_assistant: no tiene interruptor por proyecto.
  6. Verifica en qué estado de salida estás realmente. embedding_provider sin definir significa local; si alguien lo cambia alguna vez a un proveedor en la nube, el corpus existente se rellena hacia fuera. Trata ese ajuste como un control de exportación de datos, no como una perilla de rendimiento.

Preguntas frecuentes

¿ai-memory es un fork de algo? No. Cita el trabajo previo explícitamente —el gist de la wiki LLM de Karpathy, la captura por hooks de agentmemory, el markdown en disco de basic-memory, cognee, A-MEM— y menciona el bucle de auto-mejora de Hermes Agent entre sus influencias. También incluye un crate importador para migrar desde agentmemory.

¿«Cero llamadas a LLM por defecto» significa ningún modelo? No. La ruta de recuperación por defecto carga un codificador de frases all-MiniLM-L6-v2 en proceso (~87 MB, 384 dimensiones) y rellena las páginas existentes al arrancar. Es local y sin clave, no libre de modelos. Pon embedding_provider = "none" para el piso puro de FTS + entidades + grafo.

¿Por qué cambian las cifras de benchmark entre versiones si no cambió nada? En su mayoría no cambian. Las repeticiones de 3.0.1 y 3.1.0 reportan un hit@5 de FTS idéntico en 0,951 y embeddings locales moviéndose dentro de una banda prerregistrada de ±0,005. El único salto histórico grande, 0,662 → 0,951, fue una función real (el flujo de observaciones) más un arreglo del arnés que antes inflaba una cifra menor.

¿Sirve para un equipo? Sí, con una salvedad que el proyecto declara de sí mismo: es «un servicio de un solo inquilino para estación de trabajo u homelab». Varios usuarios obtienen atribución y registro de auditoría, pero «cada usuario autenticado pertenece al mismo dominio de confianza y puede leer la misma memoria de proyecto». No hay ACL por usuario; usa servidores separados para personas que no deben ver los datos de otras.

¿Qué pasa con la memoria que dejo de usar? En páginas episódicas, una barrida diaria las marca como lápida por debajo de un umbral de relevancia de 0,20 (con un piso de ~80 días) y borra las lápidas a los 180 días. Las páginas semánticas, procedurales y fijadas están exentas, y cualquier página con expires_at se borra según lo programado aunque esté fijada.

¿Vale la pena adoptarlo con 11.340 estrellas y cinco meses de vida? La arquitectura es la parte más defendible: markdown como verdad, índice reconstruible, frontera de privacidad tipada y cifras publicadas con sus fallos de arnés confesados. El riesgo es operativo: un ritmo de ~0,87 versiones al día, solo la última versión soportada en seguridad y un camino de relevo cuya fiabilidad varía por fabricante. Fija una versión, corre las seis comprobaciones de arriba y cuenta con actualizar a menudo.

La frase que conviene quedarse

El producto real de ai-memory no es la memoria. La memoria es mercancía en 2026: hay decenas de proyectos en Hacker News que la reclaman, y los números de la categoría han dejado de ser comparables entre sí.

El producto es un protocolo para mover trabajo inacabado a través de la frontera entre fabricantes, y la razón de que sea interesante es exactamente que el protocolo tiene que sobrevivir al contacto con veinticuatro implementaciones de hooks que no se ponen de acuerdo sobre qué es una sesión, cuándo termina y si el stdout va a algún sitio. La matriz de soporte es el recibo: cuatro arneses pierden el relevo, seis integraciones documentadas no se han ejecutado nunca de extremo a extremo y doce clientes no tienen captura automática.

No es una razón para descartarlo. Es una razón para leer la matriz antes que el README, para probar el relevo con el par exacto de agentes que usas de verdad y para tratar «cierra un agente, abre otro» como una afirmación que se verifica en tu propio directorio, no como una propiedad del software. El proyecto publica detalle suficiente para hacer justamente eso, que es más de lo que ofrecen la mayoría de sus competidores.