Mem0, an agent that remembers the previous conversation
A language model remembers nothing. Every call starts from a blank slate, and the impression of continuity comes purely from you appending conversation history to the prompt. At the fifth exchange that works; at the five hundredth it costs more than the answer itself.
Mem0 solves this differently from appending everything. It extracts facts worth keeping from a conversation, stores them separately, and on the next question supplies only those bearing on the matter. The project is open source, backed by a funding round near twenty four million dollars, and is today the most widely used library in its category.
What the problem actually is
The naive solution looks like this: keep the whole history and send it with every question. It breaks on three levels at once.
Cost grows linearly with conversation length, so the hundredth message costs a hundred times the first. Quality drops, since the model loses relevant detail in a wall of text, particularly detail sitting in the middle of the input. Finally the context window has a limit and eventually something must go, and dropping the oldest messages means forgetting exactly what the user said about themselves at the start.
The second approach, summarising history, only moves the problem. A summary of a summary after ten iterations holds nothing concrete, and the fact "the user is allergic to nuts" vanishes in the third round of compression.
A memory layer inverts that logic. Rather than asking what fits, it asks what is relevant to the current question and supplies only that.
How it works inside
The flow has two sides. On write, the library analyses the exchange and extracts facts from it, for instance that the user works in Kraków or prefers answers in Polish. Those facts land in a vector database along with an embedding, while the system checks whether a new fact contradicts one stored earlier.
That second step is what separates a memory layer from plain search. If in March the user said they live in Warsaw and in July that they moved to Gdańsk, a simple database returns both facts and the model gets confused. A memory layer has to recognise the update, though it does so differently from what intuition suggests. The hosted service’s current algorithm deletes nothing: it stores both facts with temporal context and ranks the current one higher on retrieval.
On read, a query goes to the database, the facts closest to the question come back, and you append them to the prompt. Instead of fifty thousand tokens of history you send five hundred tokens of facts, which translates directly into the bill and into response time.
In April 2026 the project shipped a new algorithm built on single pass hierarchical extraction and multi signal retrieval. Multi signal here means the ranking combines vector similarity, keyword matching, and entity links rather than resting on embeddings alone. The improvement concerns primarily questions about time and ones requiring two facts to combine into a single conclusion.
Getting started
pip install mem0aifrom mem0 import Memory
memory = Memory()
memory.add(
"I work in Krakow as a backend developer, mostly in Python",
user_id="anna",
)
results = memory.search("What does this person do?", user_id="anna", limit=3)
for entry in results["results"]:
print(entry["memory"])The user identifier is critical here and appears in both calls for a reason. Memory belongs to a person, so omitting the field or passing a constant value makes every user share one set of facts. That is the most common beginner mistake and also the most serious, since it means data leaking between accounts.
Wiring it into a conversation looks like this: before the model call you fetch relevant facts, after the call you store the new exchange.
def reply(question: str, user_id: str) -> str:
facts = memory.search(question, user_id=user_id, limit=5)
context = "\n".join(f["memory"] for f in facts["results"])
result = client.messages.create(
model="claude-sonnet-5",
max_tokens=2000,
system=f"What you know about the user:\n{context}",
messages=[{"role": "user", "content": question}],
)
text = result.content[0].text
memory.add(
[{"role": "user", "content": question},
{"role": "assistant", "content": text}],
user_id=user_id,
)
return textRun the write in the background rather than before returning the answer. Fact extraction is another model call, so waiting on it adds a second to the time before the user sees a result.
Graph memory
A vector database alone answers "what do I know about this topic" well and "how are these people connected" poorly. A graph layer adds relations between entities, so alongside a fact about a person it records that they work at a given company and that this company is a client of another.
That matters for questions needing two steps. Asking who on the team knows a given programming language requires joining facts about people with facts about the team, which vector similarity alone will not provide.
The price of that capability is double. Extracting relations means extra model calls on write, and in the hosted version the graph arrives only from the Pro plan at 249 dollars a month. Start without the graph and turn it on once you see questions in your logs that the vector layer alone cannot answer.
OpenMemory and local mode
A separate branch of the project is a memory layer running locally, aimed at developer tooling. The idea is that context travels between assistants rather than living separately in each of them.
Integration happens through the MCP protocol, so the same fact set is visible to Claude and to any editor supporting the standard. In practice that means an architectural decision recorded in one tool is known in the other, with no manual copying.
Local mode also carries an obvious advantage for data that cannot leave the machine. Embeddings can be computed by a model served through Ollama and the database kept in a file, so nothing goes out.
Pricing
| Plan | Cost | What it covers |
|---|---|---|
| Hobby | 0 USD | 10k writes and 1k retrievals monthly, one project |
| Starter | 19 USD monthly | 50k writes and 5k retrievals, one project |
| Pro | 249 USD monthly | 500k writes and 50k retrievals, unlimited projects, graph memory |
| Enterprise | custom quote | Unlimited writes and retrievals, on premise deployment, SSO, audit logs |
The tiers are fixed and writes and retrievals are counted separately, so the plan follows whichever of the two runs out first. Anybody who does not fit that arrangement agrees usage based billing with the vendor, since the price list has no automatic top up.
The open source version is free without limits and you run it yourself, paying only for the vector database and for model calls during fact extraction. That second cost gets skipped in estimates, and at high traffic it exceeds the subscription price, since every write is a separate call.
A simple way to estimate: count how many exchanges a day the application handles, multiply by the cost of one extraction, and compare with what sending full history would cost. For short conversations memory does not pay off; for long ones it repays quickly.
Memory scopes and many users
Beyond a person identifier the library also accepts an agent and a session identifier. Three levels let you separate things that turn into a mess when kept in one bucket.
User memory holds durable facts: preferences, role, professional context. Agent memory holds what the agent learned itself, for instance that a given procedure ends in an error and another route is needed. Session memory concerns the current task and usually has no reason to outlive it.
memory.add(text, user_id="anna", agent_id="support-assistant", run_id="ticket-1841")Separating those layers pays off at deletion time. A closed ticket can be removed wholesale by run identifier without touching what the system knows about the user. Without that split, clearing data comes down to picking entries by hand.
In an application with several agents, settle up front whether they share user memory. Usually they do, since that is the point of the whole layer, but an agent handling sensitive matters is sometimes the exception, and then its records belong apart.
What to measure
A memory layer sits between question and answer, so its quality shows only in numbers. Three indicators suffice to tell whether it works.
The first is retrieval accuracy, meaning how often the needed fact is among those returned. Check it on a few dozen real questions by reviewing what the layer supplied. If facts are random in half the cases, the problem usually lies in too general a query rather than in the database.
The second is context token count before and after rollout. It is the only measure showing whether the saving is real and the only one convertible straight into money.
The third is entries per user over time. A database growing by a hundred facts a month per person signals that you store too much, and excess entries lower retrieval accuracy, since similar facts keep piling up.
Measure all three before deploying the layer, on the same set of questions. Without a reference point what remains is an impression that things are better, which usually suffices to make the decision but not to defend it when somebody asks about the cost.
Mem0 against the alternatives
| Tool | Strength | Weakness | Pick it when |
|---|---|---|---|
| Mem0 | Widest adoption, many integrations, local mode | Extraction cost at high volume | Application with returning users |
| Zep | Strong handling of time and fact versions | Smaller ecosystem | Data where chronology matters |
| Letta | Agent managing its own memory | More complex operating model, Python server retired | Long lived autonomous agent |
| Pinecone | The vector database itself, full control | You write the memory logic | Custom memory layer for a specific case |
Note that the last row is a different category. A vector database is a component, and a memory layer is a finished solution built on such a database. If you have unusual requirements about what to remember and when, your own implementation over a vector database gives more freedom at the cost of work.
When memory is not needed
Not every application requires it, and that is worth settling before deployment. A tool answering single questions with no continuity, a classifier or a product description generator for instance, gains nothing.
The same goes for a conversation fitting in a dozen or so exchanges. With current context windows, sending the whole history is simpler, cheaper to maintain, and introduces no risk of the memory layer recording something wrongly.
The third case is data requiring strict correctness, such as an account balance or an order status. Those things do not go into a memory layer; they are fetched from the source system on every question, because a state remembered from last week is worse than no answer.
Common mistakes
The first is not separating users. A shared identifier means one person's facts reach another person's prompt, which is a data leak rather than a convenience defect.
The second is storing everything. Every exchange passed to the writer is a model call and more rows in the database. Store what carries a fact about the user, not acknowledgements and pleasantries.
The third is too high a retrieval limit. Twenty facts in the prompt is again the wall of text memory was meant to prevent. Five apt entries beat twenty random ones.
The fourth is no way to inspect and delete stored data. Users have a right to know what the system knows about them, so an interface for reviewing and clearing entries belongs in the plan from the start rather than after the first complaint.
The fifth is writing synchronously before the answer. It adds latency the user sees while contributing nothing that cannot happen after the result is sent.
FAQ
How does Mem0 differ from a plain vector database?
A vector database stores and searches chunks, while a memory layer adds fact extraction from conversation, contradiction detection, and updating of stale entries. You can write that yourself over Pinecone or Qdrant, only it is several hundred lines of logic you then maintain.
Is Mem0 free?
The open source version is, you run it yourself and pay only for the database and for model calls during extraction. The hosted version has a free plan capped at ten thousand writes and a thousand retrievals a month, and paid plans start at 19 dollars. Graph memory arrives on the Pro plan at 249 dollars, above which sits Enterprise on a custom quote.
How much does it actually save?
It depends on conversation length. With fifty thousand tokens of history replaced by five hundred tokens of facts, the input saving runs into tens of times, but the extraction cost on write comes off that. For short conversations the balance lands at zero or below.
What does it integrate with?
The documentation covers more than twenty frameworks and platforms across Python and TypeScript, among them LangChain, LangGraph, and CrewAI. Separately there is an MCP server connecting memory to assistants and editors.
Can data stay on my own infrastructure?
Yes, the open source version runs entirely locally. You host the vector database yourself and compute embeddings with a local model, so conversation content never leaves your environment. That is the standard choice under compliance requirements.
Documentation sits on the project site, and the source code in the GitHub repository.