← Back to Blog

Add Long-Term Memory to Your AI Agent with Mem0

Your chatbot asks for your name every session. It asked yesterday, it asked last week, and it will ask tomorrow, because nothing survives between conversations. Each request starts from zero. Everything the agent learned about the user disappears the moment the chat ends. That is the problem a memory layer fixes.

Mem0 is an open-source project built exactly for this: long-term memory for AI agents. The repository describes itself as a "universal memory layer for AI Agents". It had 63,485 stars on August 18, 2026, is Apache-2.0 licensed, and comes from Y Combinator's S24 batch. You can use it three ways: as a Python or TypeScript library, as a self-hosted Docker server, or as a managed platform. Everything below was checked against mem0ai 2.0.18.

The idea is simple. When a conversation happens, Mem0 extracts the stable facts, embeds them, and stores them in a vector database. Later you ask "what do I know about this user?" and it returns the relevant memories as plain text you can drop into a system prompt.

One detail worth knowing before you start: since April 2026 the extraction step is a single LLM call that only adds facts. Retrieval combines semantic search, BM25 keyword matching, and entity matches, with time-aware ranking. The team reports LoCoMo 92.5 and LongMemEval 94.4 on the managed platform, with a caveat in the README that open source users should expect directionally similar but not identical numbers. The evaluation framework is public if you want to reproduce the benchmarks.

Prerequisites

  • Python 3.10+
  • pip
  • An OpenAI API key for the default setup, or Ollama installed if you jump straight to Step 4

Step 1: Install and store your first memory

export OPENAI_API_KEY="sk-..."
pip install mem0ai

Then store a memory:

from mem0 import Memory

m = Memory()

messages = [
    {"role": "user", "content": "Hi, I'm Alex. I love basketball and gaming."},
    {"role": "assistant", "content": "Hey Alex! Nice to meet you."},
]
m.add(messages, user_id="alex")

That is the whole API: messages in, memories out. The constructor checks your key immediately, so set OPENAI_API_KEY before creating Memory, or it raises an OpenAIError. The defaults are fine for a first run: gpt-5-mini as the LLM, text-embedding-3-small for embeddings, a local Qdrant at /tmp/qdrant, and a SQLite history store at ~/.mem0/history.db.

Step 2: Search memories back

result = m.search("What do I know about Alex?", filters={"user_id": "alex"})
for item in result["results"]:
    print(item["memory"], item["score"])

The query gets embedded and matched against the stored memories. Each result carries the memory text, a relevance score, and metadata. Note the filters argument: memories are scoped per user_id, and a search without filters can pull memories from every user in the store.

Step 3: Wire it into an agent loop

The pattern is: search before you answer, add after you answer. This is the full loop, adapted from the README example:

from openai import OpenAI
from mem0 import Memory

client = OpenAI()
memory = Memory()

def chat(message: str, user_id: str = "default") -> str:
    relevant = memory.search(query=message, filters={"user_id": user_id})
    memories = "\n".join(f"- {item['memory']}" for item in relevant["results"])

    system = f"You are a helpful assistant.\nUser memories:\n{memories}"
    messages = [
        {"role": "system", "content": system},
        {"role": "user", "content": message},
    ]
    answer = client.chat.completions.create(
        model="gpt-5-mini", messages=messages
    ).choices[0].message.content

    messages.append({"role": "assistant", "content": answer})
    memory.add(messages, user_id=user_id)
    return answer

Each turn costs two extra calls on top of the chat call: one search, one add. The add re-reads the exchange, extracts facts, and stores them, so the next turn can find them. If most of your turns are trivial, skip the add on those turns. Keep the messages you feed to add small; there is no point paying the LLM to extract facts from a wall of logs.

Step 4: Go fully local with Ollama and Chroma

You can run the whole thing without a single cloud call: Ollama serves both the LLM and the embeddings, Chroma stores the vectors on disk.

curl -fsSL https://ollama.com/install.sh | sh
ollama pull qwen2.5:7b
ollama pull mxbai-embed-large
pip install mem0ai ollama chromadb

Then build Memory from a config instead of the defaults:

from mem0 import Memory

config = {
    "vector_store": {
        "provider": "chroma",
        "config": {"collection_name": "memories", "path": "./mem0_chroma"},
    },
    "llm": {
        "provider": "ollama",
        "config": {"model": "qwen2.5:7b", "temperature": 0.1, "max_tokens": 2000},
    },
    "embedder": {
        "provider": "ollama",
        "config": {"model": "mxbai-embed-large"},
    },
}

m = Memory.from_config(config)

The add and search calls from Steps 1 and 2 work unchanged after this. Two gotchas on this path, and I hit both while testing the setup for this article. First, the provider packages are optional dependencies, so chromadb and the Ollama client must be installed separately even though most examples only show mem0ai. Second, the embedder checks the Ollama server at localhost:11434 when it starts, so Ollama has to be running and both models must be pulled before the first call.

Step 5: Production notes

  • One user_id per person, on every add and every search. That is the whole multi-tenant story, and the easiest thing to get wrong.
  • Keep the extraction temperature low. The docs recommend 0.2 or below so stored facts stay deterministic, and only raise it when you notice facts being missed.
  • Narrow your search results. top_k defaults to 20. If you enable the reranker, the docs suggest keeping it between 10 and 20, because more results add latency without meaningful gains.
  • Tag facts with metadata. m.add accepts a metadata dict, and the feature list includes metadata filters for retrieval.
  • Memories can expire. The add call accepts an expiration_date if you want facts to age out.
  • For a team, skip the library and self-host the server variant. A docker compose stack with a dashboard and per-user API keys beats teaching everyone to write Python.

When to use Mem0 vs alternatives

  • Plain chat history in a database: cheapest to build, but every turn re-reads or re-embeds everything, and you get no extraction, no entity linking, and no time-aware ranking.
  • LangChain memory buffers: fine for keeping the recent window inside one session, but they are a buffer, not long-term memory. Nothing survives across sessions on its own.
  • MemGPT or Letta: a full agent runtime that pages memory in and out of context. Powerful, but a lot more machinery than a memory layer.
  • Rolling your own on a vector database: doable, but you end up writing the extraction, scoping, and update logic yourself, which is the entire point of the library.
  • Verdict: reach for the library when you already have an agent loop and just need "remember this user" in two calls. Reach for the self-hosted server or the managed platform when you need auth, a dashboard, and isolated user data without building them.

Common pitfalls

  1. Missing key at construction. Memory() raises OpenAIError when OPENAI_API_KEY is not set. Export it before creating the instance.
  2. Forgetting the user_id filter. A search without filters can return memories from every user. Scope every call.
  3. Skipping provider packages. chromadb and the Ollama client are optional dependencies, and the import fails with ModuleNotFoundError until you install them.
  4. Embedding dimension mismatch. Switching to an embedding model with different dimensions throws a ValueError like "shapes (0,1536) and (768,) not aligned". The docs say to add "embedding_model_dims": 768 to the vector store config.
  5. Ollama not running. The local setup fails while building the embedder with a connection error to localhost:11434. Start the server and pull the models first.

Next steps

  • Read the configuration docs before pointing this at production data, especially the vector store and reranker sections.
  • Check the LangGraph and CrewAI integration guides if you build agents with those frameworks.
  • Browse the cookbooks for ready-made patterns: companion chatbots, support agents, and research tools.
  • Read the paper on arXiv (2504.19413) if you want the details behind the memory algorithm.

References

Need Help Implementing This?

I help teams design and build scalable cloud infrastructure, DevOps pipelines, and production-grade systems.

Book a Free Consultation