Skip to main content
Glama

tests license python release Qwen Cloud MCP

Agent memory that stays true as your life changes: a self-consistent, bi-temporal belief state instead of retrieval over a log, with zero LLM calls on the read path.

Most agent memory is retrieval over a growing log of turns, and that log silently breaks the moment a fact changes. Tenet gives every fact two clocks, event time and transaction time, so a new value supersedes the old one instead of sitting beside it: current vs. superseded, always queryable, always human-readable.

English · 简体中文


pip install git+https://github.com/Nas01010101/tenet.git
from tenet import Tenet

mem = Tenet()
mem.ingest("I live in Boston")              # needs an LLM key (distills the raw message)
mem.ingest("I moved to Seattle")            # supersedes: Boston kept in history
mem.recall("where do I live?")              # → [Seattle]  (current beliefs, no LLM call)
mem.recall("where do I live?", as_of=t0)    # → [Boston]   (time-travel, no LLM call)
mem.navigate("where do I live and work?")   # → adaptive multi-hop recall, no LLM call

Everything except ingest is LLM-free (embeddings + closed-form math, low-milliseconds; fully offline with EMBED_PROVIDER=local). Only ingest needs a model key, because turning free-form text into atomic facts is the one judgment call that needs one. The 60-second zero-key demo shows exactly where that line sits.

Tenet vs Zep · Mem0 · Letta

The 2026 agent-memory field splits by job: Mem0 for per-user personalization, Zep/Graphiti for facts that change over time, Letta for self-managing long-horizon agents. Tenet targets Zep's job (temporal correctness when facts change) but removes its cost of entry.

Tenet

Zep / Graphiti

Mem0

Letta

Facts that change over time

✅ bi-temporal supersession

✅ bi-temporal graph

❌ create-ts only

agent-managed

Infra to run it

pip install: sqlite + numpy

graph DB (Neo4j / FalkorDB)

vector DB

agent server + Postgres

Read path cost

no LLM call

no LLM call

no LLM call

an LLM call per op

Read what it knows?

plain belief state (get_all())

❌ graph nodes

❌ opaque vectors

❌ state blocks

Drop-in API

Mem0-compatible (add/search/get_all/delete)

graph API

add/search/…

full runtime

Time-travel (as_of)

The one-liner: Zep's temporal correctness, Mem0's drop-in API, and a belief state you can actually open and read, with zero infrastructure. Full honest matrix + comparability caveats: docs/COMPARISON.md.

Related MCP server: Engram-Mem

What you'd build on it

The general primitive for any state that must be currently true while its history stays auditable. Every pattern below runs on a surface that already ships in this repo:

You're building

The failure Tenet removes

Shipped surface

An agent in Claude Desktop / an IDE / any MCP client

memory that silently goes stale as facts change

MCP server (learn/recall/time_travel/doubts)

A LangGraph / LlamaIndex / LangChain / Mem0-style app

framework memory that keeps both the old and new value

BaseStore · BaseMemoryBlock · TenetMemory adapters, Mem0-compatible API

A support / CRM / ops bot over account state

answering from a superseded plan, address, or entitlement

keyed supersession + the churn result (RAG collapses 100→50%, Tenet holds 100%)

A multi-agent system with shared state

concurrent writers trampling each other's facts

the Majalis pattern: supersession as the write-arbitration rule

Anything audited or regulated

"what did we believe when we decided X?" is unanswerable

provenance + recall(as_of=…) + tenet timeline/export

And it scales like a library, not a service: reads are ~9–12 ms flat from 1k to 100k facts on a laptop (one SQLite file), so "add memory" never becomes "operate a database cluster."

Reproducibility is the pitch. Independent 2026 audits found the field's headline numbers don't survive reproduction (Mem0's 93.4% on LongMemEval reproduces at 73.8%; LoCoMo's answer key is 6.4% wrong). Tenet reports every number with a Wilson 95% CI, ships five flags default-OFF because we measured them as no-benefit, and falsified its own churn claim in public before fixing it. Built 100% on Qwen Cloud. Every result reproduces from one command.

Results at a glance

benchmark

metric

Tenet

comparison

source

MemoryAgentBench FactConsolidation (arXiv:2507.05257), single-hop

SubEM, pooled 6K–262K

97.0 [94.8, 98.3]

> published gpt-4o-tier 94.8 · mini-tier SOTA 78.0 · naive-RAG 47.8

BENCHMARK.md §6

MAB FactConsolidation, multi-hop

SubEM, pooled 6K–262K

45.8 [40.9, 50.6]

1.5× published mini SOTA 30.2 (CI excludes) · every published memory system ≤7

BENCHMARK.md §6

MAB Accurate-Retrieval

avg. official metric

59.3 (2nd of all published systems)

Mem0 32.6 · Zep 37.5

BENCHMARK.md §7

MAB Test-Time Learning (5 ICL cells, n=500)

official substr-EM, avg

77.2 [73.3, 80.7] (local 7B reader, $0)

> BM25 75.4 · MemGPT 67.6 · Zep 62.8 · Mem0 32.4

BENCHMARK.md §16

Knowledge-churn horizon (fact updated 2→12×)

current-value accuracy

100% throughout

naive-RAG collapses 100%→50%

BENCHMARK.md §3

LongMemEval_S (n=100, qwen3.7-plus reader)

QA accuracy

81.0%

≥ matched RAG 79.0% · 100% recall@10 · 98.5% less context than full

BENCHMARK.md §1–2

Head-to-head vs ReMe (Alibaba's memory framework), LME_S n=100

QA acc, same reader/judge

67.0% [57.3, 75.4]

ReMe 34.0% · matched RAG 64.0% · McNemar p≈2×10⁻⁶

reme_h2h_results.json

Local LoRA distiller (offline, zero-cloud)

key-consistency, decontaminated

0.775

cloud reference (qwen3.7-plus) 0.707

BENCHMARK.md §10

Honest weak spots (multi-session synthesis, multi-hop chaining) are reported, not hidden. Full tables, protocol notes (including the 2026-07-19 ingestion-keyer fix our own miss-file audit exposed), and every reproduction command: docs/BENCHMARK.md.

Memory reads shouldn't cost an LLM call

Most memory systems architect the read path around an LLM in the loop: a rerank call, a synthesis pass, an agent deciding what to fetch next. Tenet's bet is the opposite: the one judgment call (distilling a message into keyed facts) happens once, at write time; every read is pure vector similarity + closed-form math. Supersession itself is deterministic bi-temporal bookkeeping; no model is in that loop either.

system

read/retrieval latency

LLM in read path

infra to run

Tenet

~11 ms (@100k facts, flat)

no

none: sqlite + numpy

Zep / Graphiti

~150–300 ms (graph search)

no

graph DB (Neo4j / FalkorDB)

Mem0

~1.44 s p95 (base)

no

vector DB

Letta

model-dependent (an LLM call per op)

yes

agent server + Postgres

Flat ~9–12 ms from 1k to 100k facts (docs/SCALE.md). Latency scopes differ across systems; competitor figures are each project's own published retrieval latency. The point isn't a race: temporal correctness here costs no graph database and no inference call.

Real recorded session: facts change, the belief state supersedes them, time-travel recalls what was true before, and the read path never calls an LLM.

The failure mode nobody benchmarks

knowledge churn

As one templated fact is updated 2→12 times, RAG-memory falls 100%→50%. Tenet holds 100%.

The single-attribute churn primitive (bench_horizon), pre-registered to favor Tenet. Under harder paraphrased churn (ChurnBench §9), the honest picture: read-time fixes lift Tenet's half-life <2→32; it ties an idealized delete-arm but beats the real mem0ai package. Falsification and fix reported in full.

Why it's different

retrieval memory (RAG)

Tenet

abstraction

document index of turns

bi-temporal belief state

a changed fact

two similar passages

superseded (bi-temporal, history kept)

stale evidence

retrieved forever

retired (belief–evidence consistency)

write policy

store everything

surprise-gated (predictive coding)

forgetting

none (grows forever)

salience-decay sweep

fact drift

unmodeled

staleness hints: learned P(still-valid) per attribute, tenet doubts

queryable across time

no

time-travel (recall(as_of=t))

multi-hop bridging

fixed-depth k, or none

adaptive navigate(): LLM-free, gated by relevance gain

read path

n/a

no LLM call

Quickstart

1. One command, no API key

git clone https://github.com/Nas01010101/tenet && cd tenet
pip install -e ".[local]"                   # bge-small embedder, CPU; offline after install
python examples/00_zero_key_demo.py         # supersession + time-travel + doubts, zero LLM calls

Walks the entire LLM-free read path end to end against a pre-formed fact ledger. The one thing it can't show is ingest() turning conversation into facts; that's the one call that needs a model (next step). First-ever install downloads ~1 GB of wheels; every run after is offline.

2. The full agent (needs an API key)

cp .env.example .env && chmod 600 .env      # add DASHSCOPE_API_KEY (Qwen Cloud)
pip install -e ".[all]"                     # base + api/mcp/oss/local/cli/langgraph extras
python scripts/smoke_test.py                # verify connectivity
uvicorn tenet.api:app --host 0.0.0.0 --port 8000  # HTTP API incl. POST /chat
python -m tenet.mcp_server                   # or the MCP server (learn/recall/navigate/forget/stats)

No key yet? tenet recall / navigate / stats / doubts / timeline / export work fully offline with EMBED_PROVIDER=local. tenet timeline --all is the fastest way to see the bi-temporal chain: current value highlighted, retired values dimmed. Default DB: data/tenet.db (override with TENET_DB_PATH; falls back to ~/.tenet/tenet.db).

Works with: any MCP client (Claude Desktop, IDEs) · LangChain · LangGraph · LlamaIndex · plain HTTP (tenet.api:app, POST /chat). All examples: examples/.

LangGraph BaseStore adapter

Tenet drops in as a LangGraph BaseStore so a LangGraph agent's long-term memory gets bi-temporal supersession for free:

pip install "tenet-memory[langgraph] @ git+https://github.com/Nas01010101/tenet.git"
from tenet.integrations.langgraph import TenetStore

store = TenetStore(db_path="data/agent.db")
store.put(("users", "alex"), "residence", {"city": "Montreal"})
store.put(("users", "alex"), "residence", {"city": "Toronto"})  # supersedes, not overwritten
store.get(("users", "alex"), "residence").value                # -> {"city": "Toronto"}

3. Fully local / air-gapped

Both write-path calls (ingest()'s fact-distillation and embed_texts()) can run against a local model, so the whole loop works with zero cloud calls:

LLM_PROVIDER=ollama OLLAMA_MODEL=tenet-distiller-1.5b-v2 EMBED_PROVIDER=local \
  tenet remember "I moved from Boston to Seattle"   # distilled + embedded 100% locally

tenet-distiller-1.5b-v2 is our LoRA-tuned Qwen2.5-1.5B distiller: on a decontaminated held-out eval it supersedes 6/6 clean-churn cases (untuned base: 0/6) at 0.775 key-consistency, beating the cloud reference's 0.707. Trained on one RTX 3080; the full reproducible pipeline lives in scripts/distiller_lora/ and the measurement caveats in BENCHMARK.md §10.

The agent

Tenet ships as a personal assistant (src/tenet/agent.py) on Qwen Cloud:

you › Hi! I'm Alex, I live in Montreal and work as a data analyst.
assistant › Nice to meet you, Alex! How's the analyst work in Montreal?   [remembered 2 facts]
… weeks later …
you › I moved to Toronto and got promoted to senior analyst!
you › Where do I live and what's my job now?
assistant › You live in Toronto and you're a senior analyst. Congrats on the promotion!
python -m tenet.agent          # interactive assistant (or: tenet-agent)
python scripts/demo_agent.py   # the scripted story (video walkthrough)

Architecture

architecture

Two layers over one bi-temporal store (beliefs + evidence), two surfaces (MCP + HTTP), powered by Qwen Cloud. Component diagram + key equations: docs/ARCHITECTURE.md · original scoping: docs/DESIGN.md · positioning: docs/COMPARISON.md.

Reproduce the paper

Every benchmark is one CLI command: provider preset + config + git-sha logged to data/bench_runs.jsonl.

tenet bench list                        # all benchmarks + which figure/§ each reproduces
tenet bench run <name> --dry-run ...     # print the exact command+env, run nothing
tenet bench run churn --provider ollama --principals 12 --k 6 --updates 2,4,6,8,10,12   # Fig.1

--provider presets: ollama (fully offline), openrouter, local, qwen (Qwen Cloud). Full matrix: docs/BENCHMARK.md · docs/HARNESS.md.

Repository

paper/      tenet.md tenet.pdf                        the paper
src/tenet/  core.py memory.py distill.py navigate.py  the belief-state memory engine
            agent.py mcp_server.py api.py             the assistant + MCP/HTTP surfaces
            integrations/                             LangGraph + LlamaIndex adapters
examples/   00_zero_key_demo.py … 06_llamaindex_memory.py
scripts/    bench_*.py test_*.py demo_agent.py        benchmarks, tests, walkthrough
docs/       BENCHMARK.md COMPARISON.md ARCHITECTURE.md DESIGN.md DEPLOY.md

Citation

@misc{tenet2026,
  title  = {Tenet: Agent Memory as a Self-Consistent Belief State},
  author = {Elghoudane, Anas},
  year   = {2026},
  note   = {Global AI Hackathon with Qwen Cloud, Track 1},
  url    = {https://github.com/Nas01010101/tenet}
}

Origin

Tenet started as a Global AI Hackathon with Qwen Cloud (Track 1: MemoryAgent) entry. Hackathon materials: docs/hackathon/. Majalis, our Track 3 agent society, runs its shared belief board on Tenet's exact supersession design; the mechanism is load-bearing in a second product.

License

MIT. See LICENSE.

Maintenance

ActivitySlowing
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers