You built an agent. It's good for one conversation. Then the session ends and it forgets your name, your repo, the bug you spent forty minutes describing. So now you're shopping for a memory layer, and the three names everyone throws at you are Mem0, Zep, and Letta.

If you're still deciding where in your stack memory should sit before you pick a tool, start with three places to keep an agent's memory; this piece is about the frameworks themselves. They get filed together — "agent memory frameworks" — and compared on the wrong axis. People ask which one remembers best, run a recall benchmark, and pick the winner. That's the wrong question, because these three don't disagree about how to remember. They disagree about where memory should live and who decides what's worth keeping. Pick one and you're not choosing a feature. You're choosing how much of your agent's architecture you're handing over.

Mem0: memory as a layer you bolt on#

extraction + retrieval memory layer for agents
★ 59kPythonmem0ai/mem0

Mem0 is the least invasive of the three. It sits beside your agent. You pass it conversations; it runs an extraction pass to decide which facts are worth saving ("user prefers TypeScript," "deploys on Fridays"), stores them, and on the next turn retrieves the relevant ones via a mix of semantic search, BM25 keyword matching, and entity linking. You keep your own agent loop, your own model calls, your own everything. Mem0 just hands you back a list of remembered facts to stuff into the prompt.

It's Apache-2.0, Python and TypeScript SDKs, and ships three ways: a library for prototyping, a self-hosted Docker server, and a managed cloud at app.mem0.ai. The bet here is minimal surrender. You give up the question of "what should I remember," and nothing else. If you already have an agent and just want it to stop being amnesiac, this is the smallest change to your codebase.

The cost of that smallness: Mem0's model of memory is a flat-ish store of extracted facts. It knows what is true. It's less interested in how things relate or when they stopped being true.

Zep / Graphiti: memory as a temporal knowledge graph#

bi-temporal knowledge graph engine for agent memory
★ 28kPythongetzep/graphiti

Graphiti — the open-source engine under Zep's managed product — makes the opposite bet on structure. Memory isn't a list of facts; it's a graph of entities and relationships that evolves over time. Its defining feature is bi-temporal tracking: every fact carries a validity window, so when something changes, the old fact isn't deleted — it's marked invalid, with the new one recorded alongside. The graph can answer "what's true now" and "what was true in March" from the same store, and every derived fact traces back to the raw "episode" that produced it.

The question isn't which framework remembers best. It's whether you want a retrieval add-on, a temporal graph, or an agent that runs inside someone else's server.

This is the right tool when change itself is the signal — a customer whose plan, address, and sentiment shift over months, and you need to reason about the trajectory, not just the latest snapshot. It's Apache-2.0 and Python, backs onto Neo4j, FalkorDB, or Amazon Neptune, and is self-host for Graphiti / managed-or-cloud for Zep. The price of admission is conceptual: you're now operating a graph database and thinking in nodes and edges. That's real architecture, not a bolt-on.

Letta: memory as part of the agent runtime#

stateful agent server with self-editing memory
★ 23kPythonletta-ai/letta

Letta — the framework formerly known as MemGPT — takes the most opinionated position. Memory isn't a service your agent calls. The agent lives inside Letta, and managing its own memory is part of what the agent does. It descends from the MemGPT paper's idea of treating the context window like virtual memory: a small core memory block in-context (the RAM), searchable recall memory for conversation history, and archival memory queried by tool calls (cold storage). The agent edits its own core memory through tools, paging things in and out as it decides what matters.

The consequence is that Letta is a stateful server, not a library you sprinkle in. Agents persist between calls; you send new messages, not the whole history rebuilt each time. Apache-2.0, almost entirely Python, self-host or managed cloud.


So which one#

Map it to surrender, not recall:

The honest tell is this: the more of the remembering a framework does for you, the more of your architecture it owns. Mem0 borrows a corner of your prompt. Graphiti asks for a database and a worldview. Letta asks to be the agent. None of that shows up in a recall score. It shows up six months later when you want to change something and find out who's actually in charge of your agent's mind.

Choose the one whose level of surrender you can live with. The benchmarks will be obsolete by then anyway.