GENOME
Memoria completamente local para agentes de IA: cero llamadas a LLM en la ruta de escritura, funciona aislada de la red, con paridad de precisión con Mem0 en benchmarks publicados.
Documentación
GENOME
Memoria abierta para agentes de IA. La misma precisión de respuestas que Mem0, pero ~1.000× más barata de almacenar, funciona completamente sin conexión y mantiene un registro auditable.
Artículos: ¿Necesitan los agentes un LLM para recordar? (la evaluación central, 2026) y ¿Qué aporta cada función de memoria? (una auditoría medida de las cinco funciones opcionales, con aciertos y fallos, 2026). PDFs en papers/; tablas de resultados en benchmarks/AUDIT-RESULTS.md.
La mayoría de las herramientas de memoria para agentes (como Mem0) llaman a un LLM en cada mensaje para decidir qué recordar. Esa es la parte lenta y costosa, y la apuesta de GENOME es que no la necesitas. GENOME simplemente incrusta cada mensaje localmente: sin LLM, sin API, sin red en la ruta de escritura.
Evaluado honestamente con conjuntos de datos públicos (LoCoMo, LongMemEval), GENOME responde con la misma precisión que Mem0, mientras almacena recuerdos por una fracción mínima del coste y funciona completamente sin conexión.
Transparencia desde el principio: en precisión de respuestas, GENOME empata con Mem0; no afirmamos superarlo en ese aspecto (seis configuraciones independientes de evaluación confirman la paridad, ninguna significativa en ninguna dirección). La ventaja está en el coste, la velocidad, el funcionamiento sin conexión y un registro temporal/auditable que Mem0 no puede producir.
Véalo funcionar

Cada fotograma es salida real de examples/demo_timeline.py,
capturada por tools/render_demo_gif.py. Ejecútelo usted mismo,
sin necesidad de clave API:
python examples/demo_timeline.py
La parte interesante es el paso 3. La misma pregunta obtiene tres respuestas correctas diferentes según cuándo preguntes, porque el almacén conserva cuándo se hizo realidad cada hecho en lugar de sobrescribirlo:
| Pregunta | Respuesta |
|---|---|
| ¿Cuál era la ciudad de Priya en mayo de 2023? | Boston [mar 2023 - ene 2024] |
| ¿Cuál era la ciudad de Priya en marzo de 2024? | Seattle [ene 2024 - feb 2025] |
| ¿Cuál es la ciudad de Priya ahora? | Austin [feb 2025 - presente] |
El turno de "pensando en mudarme quizá a Denver, nada decidido" se almacena pero nunca se convierte en respuesta: es un plan, no un hecho duradero.
Cómo funciona
La ruta de escritura es deliberadamente simple y barata. Toda la inteligencia ocurre en el momento de la lectura, cuando hay una consulta que la enfoque.
flowchart LR
M["incoming message"] --> E["local embedder<br/>all-MiniLM-L6-v2"]
E --> S[("local store<br/>SQLite or Postgres")]
M -. "optional, opt-in" .-> B["belief extraction<br/>(the only LLM call)"]
B --> K[("bi-temporal<br/>fact log")]
Q["query"] --> R["exact cosine search<br/>over this tenant's rows"]
S --> R
R --> RR["optional cross-encoder<br/>rerank"]
RR --> A["context for the agent"]
Q --> PIT["as-of resolution<br/>facts_valid_at(entity, T)"]
K --> PIT
PIT --> A
style E fill:#0A84FF,color:#fff
style S fill:#1c2530,color:#fff
style K fill:#1c2530,color:#fff
style B fill:#3a3a3a,color:#fff
Escritura: incrustar localmente y almacenar. Unos 10 ms, cero llamadas a LLM, cero llamadas de red. La incrustación es determinista: el mismo texto siempre produce el mismo vector, sin paso de extracción muestreado que decida qué importa, así que lo que se almacena es una función de la entrada, y reproducir un diario reproduce ese almacén exactamente. (Los IDs y las marcas de tiempo se sellan por escritura, así que dos ingestas independientes de la misma conversación coinciden en contenido y vectores, no en IDs de registro).
Lectura: búsqueda exacta por coseno dentro del ámbito del inquilino (sin índice ANN que construir o actualizar), con un reranker local opcional de codificador cruzado.
Capa bi-temporal (optativa): registra cada hecho en su tiempo de dominio, el momento en que se hizo real en el mundo, no el momento en que se ingirió. Eso es lo que hace que las preguntas puntuales sean respondibles incluso cuando los hechos llegan desordenados.
Por qué el registro puede re-derivarse
flowchart TB
subgraph LLM["LLM-extraction memory"]
A1["message"] --> A2["LLM decides what matters<br/>(sampled, non-deterministic)"]
A2 --> A3[("store")]
A3 --> A4["replaying the same input<br/>can produce a different store"]
end
subgraph GEN["GENOME"]
B1["message"] --> B2["local embedding<br/>(deterministic)"]
B2 --> B3[("store")]
B3 --> B4["replaying the same input<br/>reproduces the same store"]
end
style A4 fill:#5c1f1f,color:#fff
style B4 fill:#1f4d33,color:#fff
Un registro que no puede re-derivarse es difícil de auditar. Esa propiedad, no la precisión, es el argumento real de este diseño.
¿No lo cree? Compruébelo usted mismo
Las afirmaciones de coste, velocidad y funcionamiento sin conexión no necesitan clave API: mídalas en su máquina en 60 segundos:
git clone https://github.com/NORTHTEKDevs/genome && cd genome
pip install -e . && python -m genome.verify
La primera ejecución descarga el modelo de incrustación local (~90 MB, una sola vez) antes de imprimir nada, así que espere 30-120 segundos de aparente silencio en una máquina fría. Cada ejecución posterior es instantánea.
Escribe recuerdos con su red de salida físicamente bloqueada e imprime un recibo de aprobado/fallo en vivo: 0 llamadas de red, 0 llamadas a LLM, escrituras de un solo dígito de ms, recuperación que funciona:
[PASS] Air-gapped write path: wrote 200 memories with every outbound socket blocked -> 0 network attempts, 0 LLM calls
[PASS] Write latency: 7.1 ms/message (Mem0's measured write path: ~2,055 ms + 1 LLM call/message)
[PASS] Retrieval works: top hit score 0.598
Ese recibo cubre solo la historia de coste/velocidad/sin conexión. La afirmación de paridad de precisión con Mem0
es una comprobación aparte, más amplia, que necesita una clave de LLM: reprodúzcala cara a cara con las mismas
preguntas con su propia clave mediante python benchmarks/head_to_head.py (una clave de OpenRouter basta;
consulte benchmarks/RESULTS.md para las ejecuciones n=90 / n=205, las pruebas
de significación pareadas y los nulos publicados). La suite de pruebas completa se ejecuta en CI público (insignia
arriba). El discurso no es "confíe en mí", es "ejecútelo".
Añada memoria persistente a su agente en una línea (MCP)
GENOME incluye un servidor MCP totalmente local: memoria entre sesiones para Claude Desktop, Claude Code o Cursor sin clave API y sin que los datos salgan de su máquina:
pip install "genome-memory[mcp]"
{ "mcpServers": { "genome": { "command": "genome-mcp" } } }
O instalación cero mediante uv: { "command": "uvx", "args": ["--from", "genome-memory[mcp]", "genome-mcp"] }
Herramientas que recibe el agente: remember, recall, forget, reset_memories.
Los recuerdos persisten localmente en ~/.genome/memories.db. Detalles completos de MCP ↓
GENOME vs Mem0 de un vistazo
| GENOME | Mem0 | |
|---|---|---|
| Precisión de respuestas (LoCoMo, LongMemEval) | empate | empate |
| Llamadas a LLM para almacenar un mensaje | 0 | 1+ |
| Velocidad de escritura | ~10 ms | ~2.000 ms |
| Funciona sin conexión / aislado | sí | no (necesita una API de LLM) |
| Coste de ingesta (despliegue de 10k usuarios) | ~190 $ / año | 159k-1,6M $ / año |
| "¿Qué era verdad en marzo?" (puntual) | sí | no |
| Memoria determinista y auditable | sí | no |
Cada número se mide dentro de un mismo entorno: mismo respondedor, juez, incrustador y top-k;
solo cambia la capa de memoria, con pruebas de significación pareadas. Detalle completo y procedencia
de cada número: benchmarks/RESULTS.md. Informe formateado:
benchmarks/GENOME-LoCoMo-Report.pdf.
Por qué es ~1.000× más barato: nunca llama a un LLM para recordar
Almacenar un mensaje cuesta una llamada a LLM en Mem0, cero en GENOME (solo una incrustación local). Eso no es una evaluación discutible: es aritmética, y se mantiene sin importar con qué LLM lo compare. Con 10.000 usuarios × 50 mensajes/día (15M de mensajes/mes):
| Modelo que Mem0 usa para extraer | Factura anual de ingesta de Mem0 | GENOME |
|---|---|---|
| Claude Haiku | 1.601.757 $ | 190 $ |
| gpt-4o-mini | 238.596 $ | 190 $ |
| modelo alojado más barato | 159.064 $ | 190 $ |
La brecha sobrevive al modelo más barato y crece en producción (Mem0 reenvía los recuerdos almacenados
al LLM a medida que el almacén se llena). Reproduzca: python benchmarks/tco_project.py (sin clave API).
Funciona aislado
El incrustador predeterminado de GENOME es local. Demostramos que la ruta de escritura es genuinamente sin conexión al bloquear toda la red durante las escrituras: aun así tienen éxito:
- ~10 ms/mensaje, 0 llamadas de red, 0 llamadas a LLM (
python benchmarks/local_writepath.py) - Mem0 no puede hacer esto: necesita una llamada a API de LLM para ingerir.
Eso hace que GENOME sea utilizable on-prem, en entornos regulados o totalmente sin conexión. Es una capacidad de sí/no, no un punto de precio.
Cómo funciona
- Escritura: incruste el mensaje localmente y almacénelo. Sin LLM, sin red. (~10 ms)
- Lectura: búsqueda vectorial sobre sus recuerdos, con un reranker local opcional de codificador cruzado para consultas más difíciles.
- Capa bi-temporal opcional: rastree cómo cambian los hechos con el tiempo y responda "qué era verdad en el momento T": consulte abajo.
Qué le aporta el determinismo
Como nada en la ruta de escritura interpreta su contenido, GENOME puede hacer cosas que un sistema de memoria con ingesta por LLM no puede hacer en principio:
-
Cortafuegos de memoria (
genome.firewall): etiquete cada escritura con su origen (user,agent,tool,web), ponga en cuarentena los orígenes de baja confianza del recuerdo y aplique autoridad vinculada al origen: el contenido web nunca puede ACTUALIZAR ni ELIMINAR lo que su usuario dijo, incluso cuando un solucionador de conflictos con inyección de prompt lo pida. Tampoco hay paso de extracción que el contenido inyectado pueda atacar: la ruta de escritura no tiene LLM.from genome import Memory from genome.firewall import TrustPolicy m = Memory(trust_policy=TrustPolicy(recall_min_trust=1)) m.add("I live in Anchorage", user_id="u1", provenance="user") m.add(scraped_page_text, user_id="u1", provenance="web") # quarantined -
Recuerdo explicable (
genome.explain):explain_search()informa de la puntuación densa de cada candidato, el rango BM25, la puntuación fusionada y, cuando no se devolvió, la razón exacta (filtrado por padre, en cuarentena, más allá del límite). Dos ejecuciones coinciden, así que un error de recuerdo puede fijarse como prueba de regresión en lugar de un encogimiento de hombros. -
Diario + reproducción (
genome.journal): registre cada mutación y reproduzca de forma demostrable el almacén:verify_journal()reproduce el historial y compara hashes canónicos. Reproduzca un prefijo para revertir; reproduzca en un almacenamiento diferente para ramificar una memoria para una ejecución hipotética. El diario se sitúa tras la extracción, así que la reproducción es determinista incluso si configuró un extractor con LLM. Cada línea se encadena con su predecesora, así que una línea eliminada o editada se detecta incluso cuando el cambio se anula en el estado final.# Tamper-EVIDENT by default. Pass a key (kept outside the journal's directory) # to make it tamper-PROOF: an unkeyed chain can be recomputed by anyone with # write access, an HMAC chain cannot. m = Memory(journal="mem.journal", journal_key=os.environb[b"GENOME_JOURNAL_KEY"]) -
Atribución de creencias multiagente (
record_fact(..., believed_by="agent-a")): los agentes que comparten un almacén mantienen sus propias líneas de tiempo de creencias: que el agente B discrepe no pisa el hecho del agente A, ybelief_conflicts()saca a la luz los desacuerdos para resolverlos deliberadamente en lugar de elegir un ganador en silencio. -
Un entorno de evaluación neutral (
benchmarks/neutral/): ejecute GENOME, Mem0 y una línea base de contexto completo con el mismo respondedor, juez e incrustador, con una matriz de McNemar por pares y un bloque de divulgación completa. GENOME es una fila en la tabla, no la casa.
Instalación
pip install genome-memory
El incrustador predeterminado es local (sentence-transformers/all-MiniLM-L6-v2): sin clave API,
funciona sin conexión; la primera ejecución descarga el modelo de ~90 MB una vez. Las incrustaciones de OpenAI son
opcionales para recuperación de mayor dimensionalidad.
Huella de dependencias, con honestidad: la instalación central es numpy, sentence-transformers,
scikit-learn y rank-bm25. Las incrustaciones locales se ejecutan en PyTorch (incorporado por
sentence-transformers), así que no es una instalación pequeña: es la compensación deliberada por
incrustación sin conexión y de coste cero. Las dependencias de gráficos/evaluación viven en un extra opcional [viz],
no en el núcleo. ¿Migra desde Mem0? Consulte
docs/migrating_from_mem0.md.
Inicio rápido (totalmente local, sin clave API)
from genome import Memory
mem = Memory(storage="genome.db") # local embedder by default; ":memory:" for ephemeral
# Store a message -- embedded locally, no LLM call, no network
mem.add("Ada met Lin at the robotics summit in Berlin.", user_id="u1")
mem.add("They are collaborating on an open-source planning library.", user_id="u1")
# Retrieve the most relevant memories
for hit in mem.search("Where did Ada meet Lin?", user_id="u1", limit=5):
print(f"{hit.score:.3f} {hit.content}")
Memory refleja la API de Mem0 (add / search / get / delete / reset): un
reemplazo casi directo. Para usar incrustaciones de OpenAI en su lugar (establezca OPENAI_API_KEY):
from genome import Memory, EmbeddingProvider
mem = Memory(storage="genome.db",
embedding_provider=EmbeddingProvider(model_name="openai:text-embedding-3-small"))
Úselo como servidor MCP (memoria totalmente local para cualquier agente)
GENOME incluye un servidor MCP, así que cualquier cliente MCP (Claude Desktop, Claude Code, Cursor, ...) obtiene memoria persistente entre sesiones que se ejecuta enteramente en la máquina local: sin llamadas a LLM, sin claves API, sin que los datos salgan de la caja. La mayoría de los MCP de memoria no pueden decir eso.
Instale con el extra mcp y luego añádalo a la configuración de su cliente:
pip install "genome-memory[mcp]"
{
"mcpServers": {
"genome": { "command": "genome-mcp" }
}
}
Herramientas que recibe el agente: remember (almacenar un hecho/preferencia, local + 0 LLM), recall
(búsqueda semántica), forget (eliminar el recuerdo que coincida con una consulta), reset_memories
(borrar los recuerdos de un usuario). Los recuerdos persisten en ~/.genome/memories.db (anule con la
variable de entorno GENOME_MCP_DB). Ejecútelo de forma independiente con genome-mcp o python -m genome.mcp.server.
Ejecútelo como API HTTP
¿Prefiere HTTP? GENOME incluye un servidor FastAPI que refleja la biblioteca 1:1 (add / search /
get / update / delete / reset / synthesize), con una especificación OpenAPI autogenerada en
/docs.
pip install "genome-memory[fastapi]"
Pruébelo localmente (sin clave, solo bucle local: una bandera hace explícita la intención de "sin autenticación"):
GENOME_ALLOW_NO_AUTH=1 python -m genome.server # serves on 127.0.0.1:8080
curl -X POST localhost:8080/v1/memories \
-H 'Content-Type: application/json' \
-d '{"text": "Ada met Lin at the robotics summit in Berlin.", "user_id": "u1"}'
curl -X POST localhost:8080/v1/search \
-H 'Content-Type: application/json' \
-d '{"query": "Where did Ada meet Lin?", "user_id": "u1", "limit": 5}'
Seguro por defecto. El servidor se niega a servir sin autenticación salvo que opte por ello
como arriba, y no vinculará una interfaz que no sea de bucle local sin una clave. Para exponerlo, establezca una
clave API (enviada como X-API-Key), necesaria para vincular más allá de localhost:
GENOME_API_KEY=$(openssl rand -hex 32) GENOME_HOST=0.0.0.0 python -m genome.server
# then add: -H "X-API-Key: $GENOME_API_KEY" to every request
Para despliegues multiinquilino, establece GENOME_REQUIRE_SCOPE=1 para requerir user_id/agent_id en
cada llamada y deshabilita el reinicio global. Docker: docker-compose up (necesita GENOME_API_KEY
y POSTGRES_PASSWORD; Postgres se publica solo en loopback). Guía completa, incluyendo el
backend de Postgres y cada variable de entorno: docs/tutorial_quickstart.md.
Cliente TypeScript / JavaScript
@northtek/genome-memory refleja la
forma de la API de Python Memory contra este servidor (ESM, Node 20+ o navegador):
npm install @northtek/genome-memory
import { Memory } from "@northtek/genome-memory";
const mem = new Memory({ baseUrl: "http://localhost:8080" });
await mem.add({ text: "Ada met Lin in Berlin.", userId: "u1" });
const hits = await mem.search({ query: "Where did Ada meet Lin?", userId: "u1" });
Documentación completa del cliente: sdks/typescript/README.md.
Los resultados honestos
Mismo respondedor + juez + incrustador para cada sistema; solo cambia la capa de memoria.
| Lo que medimos | Resultado | Veredicto |
|---|---|---|
| Precisión de respuestas, dentro de ventana (LoCoMo) | GENOME 0.851 vs Mem0 0.855 (p > 0.23) | Empate |
| Precisión de respuestas, benchmark más difícil (LongMemEval, n=90 y n=205) | direccionalmente superior, no significativo (p = 0.14-0.19) | Empate |
| Precisión cuando el historial desborda la ventana de contexto | +0.409 con 80× menos contexto (p = 8e-10) | Victoria |
| Costo de almacenar un mensaje | 0 llamadas LLM vs 1+; 837-8,433× más barato | Victoria |
| Ruta de escritura | ~10 ms, aislada de red, 0 llamadas de red | Victoria |
| Punto en el tiempo ("qué era verdad en T") | estado de creencia 0.870 vs Mem0 0.676 (datos sintéticos) | Victoria, con advertencia |
| Tasa de acierto de recuperación con reranking | mejora hit@10 (hasta 0.943); local y gratuito | Victoria |
Lo que probamos que no ayudó (para que no tengas que hacerlo)
Publicamos nuestros nulos: así sabes que las victorias son reales:
- Síntesis / consolidación: neutral en precisión con presupuesto de tokens igual (p = 0.86).
- Híbrido (BM25 + denso) y recuperación por grafo: el híbrido rindió por debajo del denso simple en LoCoMo; el grafo no fue validado aquí.
- La ganancia de precisión del reranking depende del incrustador: mejora de forma fiable la tasa de acierto de recuperación, pero su efecto en la precisión final de respuestas depende del incrustador: trátalo como una herramienta de calidad de recuperación, no como una victoria garantizada de precisión.
Memoria bi-temporal: "qué era verdad en el tiempo T"
GENOME puede rastrear cómo cambian los hechos con el tiempo y responder preguntas de punto en el tiempo, algo que la memoria basada en sobrescritura estructuralmente no puede hacer (solo conserva el último valor):
from genome.memory.belief import ingest_belief_turn, answer_belief_context
mem = Memory(storage="genome.db", llm_call=my_llm_fn)
# facts land at their DOMAIN time (parsed from the text), not wall-clock ingest time
ingest_belief_turn(mem, "In March 2024, Jordan moved to Seattle.", session_time=t0, user_id="u")
ingest_belief_turn(mem, "Jordan just moved to Austin.", session_time=t2, user_id="u")
answer_belief_context(mem, "Where does Jordan live now?", user_id="u") # -> Austin
answer_belief_context(mem, "Where did Jordan live in early 2024?", user_id="u") # -> Seattle
answer_belief_context(mem, "List every city Jordan has lived in.", user_id="u") # -> Seattle; Austin
En el benchmark TempBelief responde consultas "as of" con 0.870 frente a 0.676 de Mem0, con el grafo de conocimiento auditado con 0.97 de precisión / 0.96 de recall. Advertencia: TempBelief es texto sintético con fechas explícitas; la ventaja se reduce en habla natural. Capacidad real, prueba limitada.
Características opcionales
Opt-in; la ruta predeterminada permanece sin LLM y local en la ingesta.
mem = Memory(
storage="genome.db",
llm_call=my_llm_fn, # LLM-based fact extraction on add()
resolve_conflicts=True, # ADD/UPDATE/DELETE vs existing memories
auto_extract_entities=True, # entity graph for graph retrieval
auto_consolidate_threshold=200, # summarize-or-prune when a scope grows past N
)
mem.search("...", user_id="u1", mode="hybrid") # modes: "dense" (default), "hybrid", "graph"
Reranking (local, gratuito, sin API):
from genome.memory.rerank import CrossEncoderReranker
mem = Memory(storage="genome.db", reranker=CrossEncoderReranker()) # lazy-loaded
mem.search("Where did the user go on vacation?", user_id="u1", limit=5) # reranked
Reproduce los benchmarks
Los conjuntos de datos LoCoMo y LongMemEval no están incluidos (tienen sus propias licencias:
LoCoMo es CC BY-NC 4.0). Consulta benchmarks/data/README.md para
descargarlos. Las dos primeras líneas no necesitan conjunto de datos ni claves API:
python benchmarks/local_writepath.py # local write path: ~10ms/msg, 0 network
python benchmarks/tco_project.py # deployment cost projection
python benchmarks/verdict.py # in-window accuracy + McNemar
python benchmarks/haystack_report.py # overflow / context-window crossover
python benchmarks/ingest_cost.py --n 80 # measured ingestion cost vs Mem0
python benchmarks/lme_qa.py --n 90 # LongMemEval head-to-head vs Mem0
python benchmarks/tempbelief_run.py --convs 6 # bi-temporal point-in-time vs baselines
Soporte y nivel comercial
Errores y preguntas: issues y discussions. El soporte comunitario es de mejor esfuerzo: consulta SUPPORT.md.
GENOME Enterprise es un producto comercial separado para compradores regulados y on-premise que deben responder ante un auditor sobre qué sabía un sistema de IA y cuándo: un registro de auditoría encadenado por hash a prueba de manipulaciones, reconstrucción de punto en el tiempo, informes de cumplimiento, retención con pruebas de borrado, RBAC y SSO. Autoalojado y licenciado por despliegue: no hay versión alojada, deliberadamente, porque el valor es que tus datos nunca salen. Ese nivel es lo que financia este. ¿Evaluarlo o quieres soporte comercial en el núcleo abierto? info@northtek.io
Licencia
Licencia Apache 2.0 - consulta LICENSE y NOTICE.
GENOME es gratuito y de código abierto: léelo, modifícalo, autoalójalo e intégralo en tus propias aplicaciones, incluido el uso comercial, bajo los términos de Apache 2.0. No hay "cebo y cambio de núcleo abierto" planeado: el núcleo permanece bajo Apache-2.0.
La concesión Apache-2.0 cubre el código, no el nombre: consulta TRADEMARKS.md, que comienza con lo que puedes hacer sin pedir permiso. Preguntas: info@northtek.io.
Copyright 2026 Northtek (FrostByte Digital LLC). mcp-name: io.github.NORTHTEKDevs/genome