If you ship an agent with memory, the part that quietly decides whether it feels smart or senile is not the vector database — it's what happens the instant a conversation ends and something has to be written down. Mem0's 2.x line rewrote exactly that step, and the change is big enough that a mental model built on older Mem0 will lead you wrong. This is how the current engine writes and reads, with the API you'll actually type.
The old loop: read, reconcile, sometimes delete the wrong thing#
Older Mem0 treated every write as a reconciliation. When you called add(), it pulled your existing memories, then ran a multi-step LLM loop deciding, fact by fact, whether to ADD a new memory, UPDATE one already there, or DELETE one that the new turn contradicted. It was clever, and on a good day it kept the store tidy.
The bad days were the problem. Reconciliation is a judgment call made by a model, and a wrong call didn't just skip an update — it could delete a true memory because the model misread a contradiction. Multiply that across thousands of turns and you get the failure every memory system dreads: the agent confidently forgets something the user definitely told it.
The 2.x write path: one call, ADD-only, nothing overwritten#
The 2.x engine (current release v2.0.12) throws that loop out. Writes are now single-pass and ADD-only — Mem0's own description is blunt about it: "one LLM call, no UPDATE/DELETE. Memories accumulate; nothing is overwritten."
The write is as small as it looks:
from mem0 import Memory
m = Memory()
# messages is your turn(s); user_id scopes the memory
m.add(
messages=[
{"role": "user", "content": "I'm allergic to peanuts and I run a two-person SaaS."},
{"role": "assistant", "content": "Noted — I'll keep recipes and vendor gifts peanut-free."},
],
user_id="rosa",
)
One call extracts the facts and stores them. There's no hidden pass deleting anything, which means the whole category of "the reconciliation loop ate a real memory" is gone. The trade you accept in return is explicit below — accumulation isn't free.
Entity linking is now in the box — the graph store comes out#
The second change matters just as much for retrieval quality. Earlier, getting relationship-aware recall ("what's connected to this person / this project") often meant standing up a separate graph database alongside your vectors and keeping the two in sync. That's a second system to run, secure, and pay for.
In 2.x, that capability moved inside the main store. Per the project: "Entities are extracted, embedded, and linked across memories for retrieval boosting." You get the connective tissue — this fact is about the same person as that one — without a Neo4j-shaped dependency hanging off your stack. If you've been comparing memory frameworks partly on "does it force me to run a graph DB," that column just changed; see Cognee vs Graphiti vs Mem0 and Mem0 vs Zep vs Letta for where the others land.
Retrieval: three signals, fused, time-aware#
Reading is where the accumulated store earns its keep. 2.x doesn't rely on vector similarity alone — it scores three signals in parallel and fuses them: semantic vector similarity, BM25 keyword matching, and entity matching, with a time-aware pass so recent, relevant memories rank up. Pure semantic search misses exact tokens (a SKU, an error code, a name spelled oddly); BM25 catches those; entity matching pulls in the connected facts. Fusing them is why recall holds up on the queries that embarrass a single-signal retriever.
The read API stays as small as the write:
hits = m.search(
query="what should I avoid when ordering the team lunch?",
filters={"user_id": "rosa"},
top_k=3,
)
for h in hits["results"]:
print(h["memory"], h["score"])
filters scopes the search (here, one user); top_k bounds how much context you spend. That last point is a real budget lever — every returned memory is tokens you pay for on the next model call, a cost we broke down in the token cost of agent memory.
One API note worth catching on upgrade: Memory.update() (and AsyncMemory.update()) now take a text= argument. The old data= still works but is deprecated, so prefer text in new code.
The last-mile precision pass: reranking (Node SDK)#
If you're on the TypeScript stack, the Node SDK v3.1.0 adds an optional reranking step on retrieval, with four providers to choose from: Cohere, ZeroEntropy, a cross-encoder, and an LLM-based reranker. The pattern is the familiar two-stage one — let the fused search pull a wide candidate set fast and cheap, then rerank the top slice for precision before it hits your prompt. Cross-encoders are the accuracy-per-dollar sweet spot; an LLM reranker is the most capable and the most expensive; a hosted API (Cohere, ZeroEntropy) is the least code. Reach for it when a few extra points of top-3 precision are worth the added latency — not by default.
What to actually watch: ADD-only means you own pruning#
Here's the honest cost of the redesign. Because writes never delete, an old fact and its correction can both sit in the store, and retrieval can surface either one. "I use Postgres" and next month "we migrated to SQLite" will co-exist until something removes the stale one. The engine won't do it for you on write — that was the whole point.
So budget for it. Run pruning as a deliberate operation, lean on the time-aware ranking and (where it helps) reranking to keep the fresher memory on top, and evaluate recall the way you'd evaluate any retriever — with a fixed question set, not vibes. Mem0 reports gains on the standard suites (its published numbers cite double-digit jumps on LoCoMo and LongMemEval), but those are the vendor's figures; the number that matters is the one you measure on your own traffic. Our walkthrough on how to evaluate agent memory is the harness to do it, and the agent-memory benchmarks explained is what those leaderboards actually test.
The shape to take away: 2.x made writes dumb and fast (one pass, no deletes) and reads smart (three fused signals, built-in entity links, optional rerank). That's a good trade for most agents — you stop losing memories to a reconciliation model, and you pay for it with a store you have to prune on your own schedule. If you're still deciding whether any of this belongs in a vector database at all, start one level up with agent memory vs RAG and the types of agent memory.



