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.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

No tool schema history has been recorded yet.

Maintenance

ActivitySlowing
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Nas01010101/tenet'

If you have feedback or need assistance with the MCP directory API, please join our Discord server