Production Memory Frameworks: MemGPT/Letta, mem0, Zep, Graphiti
How Letta, mem0, Zep, and Graphiti differ in storage, retrieval, and operational cost.
Production memory requires more than a vector store: write gates, episode formats, retrieval policy, tenant isolation, and maintenance jobs all need an owner. Letta, mem0, Zep, and Graphiti package different subsets of that work and impose different storage and retrieval contracts.
What a memory framework owns
A production memory framework is a runtime that bundles the write pipeline, storage substrate(s), read pipeline, multi-tenancy primitives, and maintenance passes into a single SDK. A substrate (pgvector, Qdrant) is unopinionated; a framework picks an episode shape, a write gate, a retrieval blend, a tier policy, and a tenant model, then exposes them as a coherent add/search/update/delete API. Adopting a framework is buying its opinions.
Four define the field in 2026. MemGPT/Letta is the productized version of the original MemGPT paper; three-tier hierarchical memory (core/recall/archival) with the agent self-managing tier promotion via tool calls. mem0 is the distill-at-write vector layer with an optional graph extension (Mem0g); the LLM-gated fact-extraction pipeline runs on every add. Zep is the graph-first hybrid: a bi-temporal knowledge graph wraps vector and BM25 indexes, all retrieval fused, no LLM in the read path. Graphiti is Zep’s open-source temporal-graph engine, usable standalone when you want the bi-temporal substrate without the cloud product on top.
Compare the operating models
| Dimension | Letta (MemGPT) | mem0 | Zep | Graphiti |
|---|---|---|---|---|
| Primary substrate | Hierarchical (core/recall/archival) | Vector + optional graph | Graph + vector + BM25 | Bi-temporal graph |
| Write path cost | Low (DB write + tool call) | High (LLM fact extraction per turn) | Very high (entity + relation extraction + bi-temporal stamping) | Very high (same as Zep) |
| Read path cost | Low (tool calls, no LLM in core) | Low (vector search + optional graph traversal) | Low (pure traversal + RRF, no LLM) | Low (pure traversal + RRF) |
| Bi-temporal | No (single transaction clock) | No | Yes (valid + transaction time) | Yes |
| Self-managed by agent | Yes (agent calls tier-promotion tools) | No (harness-driven) | No (harness-driven) | No |
| Multi-tenancy | Per-agent state (built-in) | user_id required parameter | user_id / session_id (built-in) | group_id namespace |
| Hosted option | Letta Cloud + self-host | mem0 Cloud + open-source | Zep Cloud + open-source community edition | Self-host only |
| 2026 benchmark anchor | ~83% LongMemEval (community report) | 94.4% LongMemEval (token-efficient algorithm, mem0.ai/research) | 71.2% LongMemEval (Zep paper) | Same substrate as Zep |
| Best-fit workload | Long-running stateful agents where the agent itself manages context | Chatbots and assistants with high user-fact density | CRM, compliance, healthcare; relational + temporal queries dominate | Greenfield graph-first builds, self-hosted |
| Worst-fit workload | Stateless or short-lived agents | Workloads where raw episodes matter more than distilled facts | Workloads with no relational structure | Same as Zep, plus teams who want a managed product |
The benchmark numbers in that row are the most volatile entry in the table. Mem0’s LoCoMo score went from 66.9% in 2025 to 92.5% in 2026; partly genuine algorithm improvement, partly protocol stabilization, partly hill-climbing. Read protocols (judge model, ingest pipeline, top-K) before comparing across rows. The memory evaluation article is the detailed treatment on why direct cross-framework comparison is harder than it looks.
Decide what to build
Reach for a framework when (a) your team has fewer than two engineers who can own a memory subsystem long-term, (b) your workload fits within ±20% of one of the four frameworks’ opinions, and (c) you don’t have an existing storage layer the framework would fight. Hand-roll when (a) you have those engineers, (b) your defining write or read pattern isn’t covered (per-document write policies for a legal-research agent, custom segmentation for a code-review agent, or a graph schema that doesn’t fit Graphiti’s entity-relation model), or (c) you already operate a vector store and a graph store and the framework’s opinions about both fight your data model.
The most common mistake: adopting a framework, then writing so much code around it to make it fit that you would have been better off rolling your own. mem0 and Letta both have escape hatches; custom prompts, overrideable extraction, custom tools; but every escape hatch is a place the next breaking change will land. If you find yourself overriding more than two defaults, the framework is wrong for your workload.
The escape from the binary: roll your own on a store primitive and adopt a framework only for the layer where its opinions are critical. LangGraph stores give you a tuple-namespaced KV/vector store; you build the write policy, retrieval blend, and tier topology yourself, and adopt Graphiti only for the graph layer if your workload needs bi-temporal queries. Most teams converge on this after a year.
Letta integration in Python
The Letta integration pattern is the framework owns the agent state, the application owns the message routing. You call the SDK with messages; Letta manages the memory blocks, the recall/archival tiers, and the persistence behind a client.agents.create / client.agents.messages.create surface. Install: pip install letta-client and run a local server (docker run -d -p 8283:8283 letta/letta:latest) or use Letta Cloud.
| |
The key property: there is no explicit memory.add() call. The agent decides what to remember, and the framework records what it decided. This is Letta’s central opinion; agent-driven memory management; and it is either exactly right (long-running stateful agents that learn from their interactions) or exactly wrong (workflows where the harness, not the agent, owns the write policy).
mem0 integration in TypeScript
The mem0 integration pattern is the inverse: the application owns the message routing, mem0 owns the memory write/read on every turn. You call memory.add(messages, { userId }) after each user turn and memory.search(query, { userId }) before each model call. The framework extracts facts during add and serves the relevant subset during search. Install: npm install mem0ai (open-source mode) or use Mem0 Cloud.
| |
The opinion this framework ships: the unit of long-term memory is the distilled fact, not the raw turn. If you want the raw turns preserved verbatim, mem0 fights you; that’s not what the framework optimizes for. The escape hatch is memory.add with infer: false, which skips extraction and stores the raw text, but that path is not what the LoCoMo and LongMemEval numbers in the marketing are measured on.
Graphiti integration sketch
Graphiti’s contract is give me episodes with timestamps, I’ll give you a temporally-correct knowledge graph and a fused vector+BM25+graph retriever. Install: pip install graphiti-core and run Neo4j (docker run -d -p 7687:7687 -e NEO4J_AUTH=neo4j/password neo4j:5).
| |
The bi-temporal property is critical: the “as of March 20” query returns Priya (the manager as-of that date), not Devansh (the current one). Vector-only stores cannot answer that question correctly regardless of how their retrieval is scored. If your workload doesn’t include point-in-time queries, this property is wasted complexity; if it does, no other framework ships it as a first-class concept.
Further reading
- State of AI Agent Memory 2026 (mem0.ai): the most current cross-framework benchmark report, with explicit protocols. Pair with Letta’s controlled-benchmark response for the inevitable vendor-disagreement view.
- MemGPT: Towards LLMs as Operating Systems (Packer et al., 2023): the founding paper for hierarchical memory and the OS-paging analogy. Letta is its production embodiment.
- Mem0: Building Production-Ready AI Agents with Scalable Long-Term Memory (Chhikara et al., 2025): the standard reference for distill-at-write and Mem0g graph-augmented retrieval.
- Zep: A Temporal Knowledge Graph Architecture for Agent Memory (Rasmussen et al., 2025): the bi-temporal-graph-as-primary-substrate case, with the LongMemEval breakdown that motivates the design.