In this blog weâll walk through practical steps to add longâterm memory to your AI agents using Mem0 and LangGraph. Weâll build incrementally, tackling one section at a time so you can follow along and run the code as you read.
Table of Contents
Mem0 Basics â Adding, updating, and searching memories
LangGraph Integration â Wiring Mem0 into a LangGraph agent
Vector DB Setup â Swapping the default SQLite store for Qdrant
Cloud Usage â Using the Mem0 Cloud Platform for scalable memory management
Why do AI agents need memory?
When an LLMâpowered agent starts a brandânew conversation it has no context about who itâs talking to or what happened in earlier sessions. Relying on the raw chat history works only inside a single session and quickly bloats your prompt window.
Longâterm memory lets the agent:
Remember userâlevel facts (name, preferences, past actions) across sessions
Personalise responses without reâasking the same questions
Stay efficient by storing distilled facts instead of the entire transcript
Chat history vs memory
| Aspect | Chat history (session) | Longâterm memory (Mem0) |
| Lifespan | Only current session | Persists across sessions |
| Granularity | Full message text | Distilled facts & metadata |
| Storage | Inâprompt list of messages | External DB / vector store |
| Cost impact | Grows token count quickly | Minimal extra tokens |
1. Mem0âŻBasics â Adding, Updating & Searching Memories
Quick setup
from mem0 import Memory
memory = Memory.from_config({"history_db_path": "history.db"})
Why the explicit config? Mem0 defaults to a readâonly temp database, so writes will fail. Pointing it to history.db (or any path you prefer) gives the library a place to persist memories. You can extend the same config dict to
Override the LLM (provider, model, temperature, etc.)
Plug in a vector store for semantic search (weâll wire up Qdrant in Section 3).
Example â switching to GPTâ4.1âmini:
config = {
"history_db_path": "history.db",
"llm": {
"provider": "openai",
"config": {
"model": "gpt-4.1-mini",
"temperature": 0.2,
"max_tokens": 2000
}
}
}
memory = Memory.from_config(config)
Add your first memories
memory.add([
{"role": "user", "content": "Hi, I'm Pradip Nichite. I run FutureSmart AI, where we build custom AI solutions."}
], user_id="pradip")
memory.add([
{"role": "user", "content": "I love building RAG and AI Agent solutions that actually work in production."}
], user_id="pradip", metadata={"category": "preferences"})
Sample response:
{'results': [{'id': '5408e326âb26bâ4737âa404â299887b8d597',
'memory': 'Loves building RAG and AI Agent solutions that work in production',
'event': 'ADD'}]}
Mem0 distills each raw chat message into a concise fact so retrieval stays lightweight.
Search
related = memory.search("who am i", user_id="pradip")
related
Full output:
{'results': [{'id': '647935d5-f913-496d-96e3-2233d7459f38',
'memory': 'Name is Pradip Nichite',
'hash': 'fa942a6331bb89da286d4a9e296d1008',
'metadata': None,
'score': 0.2294486506181006,
'created_at': '2025-07-12T10:58:49.132915-07:00',
'updated_at': None,
'user_id': 'pradip'},
{'id': 'c763c19a-7e9f-4180-8c82-012f4da5f637',
'memory': 'Runs FutureSmart AI',
'hash': '68a143a88a3e67ae9ebfb9575bcf49a7',
'metadata': None,
'score': 0.1551292009096673,
'created_at': '2025-07-12T10:58:49.158843-07:00',
'updated_at': None,
'user_id': 'pradip'},
{'id': '5408e326-b26b-4737-a404-299887b8d597',
'memory': 'Loves building RAG and AI Agent solutions that work in production',
......
'user_id': 'pradip'},
{'id': '1baa6793-507f-46b1-8e01-b90dfa1e73b6',
'memory': 'Builds custom AI solutions',
.......
'user_id': 'pradip'}]}
score is cosine similarityâhigher means closer semantic match.
Get all memories for a user
all_memories = memory.get_all(user_id="pradip")
Returns the full list (same schema as search, without scores).
Retrieve a single memory
mem_id = "1baa6793-507f-46b1-8e01-b90dfa1e73b6"
memory.get(mem_id)
Full output:
{'id': '1baa6793-507f-46b1-8e01-b90dfa1e73b6',
'memory': 'Builds custom Gen AI solutions',
'hash': '502bdf5771e4ef9a812453b51870f0b2',
'metadata': None,
'score': None,
'created_at': '2025-07-12T10:58:49.182159-07:00',
'updated_at': '2025-07-12T11:02:34.594521-07:00',
'user_id': 'pradip'}
{'id': '1baa...73b6',
'memory': 'Builds custom Gen AI solutions',
'created_at': ..., 'updated_at': ...}
Update a memory
memory.update(memory_id=mem_id, data="Builds custom Gen AI solutions")
View change history
history = memory.history(memory_id=mem_id)
Full output:
[{'id': 'e7242249-430a-4bf2-b4df-ca0e4b99e69a',
'memory_id': '1baa6793-507f-46b1-8e01-b90dfa1e73b6',
'old_memory': None,
'new_memory': 'Builds custom AI solutions',
'event': 'ADD',
'created_at': '2025-07-12T10:58:49.182159-07:00',
'updated_at': None,
'is_deleted': False,
'actor_id': None,
'role': None},
{'id': '9d2e9706-b0c2-480b-b37a-07bb6143767d',
'memory_id': '1baa6793-507f-46b1-8e01-b90dfa1e73b6',
'old_memory': 'Builds custom AI solutions',
'new_memory': 'Builds custom Gen AI solutions',
'event': 'UPDATE',
'created_at': '2025-07-12T10:58:49.182159-07:00',
'updated_at': '2025-07-12T11:02:34.594521-07:00',
'is_deleted': False,
'actor_id': None,
'role': None}]
Each entry records the old & new value plus timestampâhandy for auditing:
[{'event': 'ADD', 'old_memory': None, 'new_memory': 'Builds custom AI solutions'},
{'event': 'UPDATE', 'old_memory': 'Builds custom AI solutions',
'new_memory': 'Builds custom Gen AI solutions'}]
That wraps up the core CRUD API.
2. LangGraphâŻIntegration â Wiring Mem0 into an Agent
New to LangGraph? Watch my YouTube walkthrough that covers LangGraph basics all the way to advanced patterns.
Below we build the simplest possible LangGraph agent that:
Accepts user messages.
Retrieves relevant memories from Mem0.
Injects them into the system prompt for personalised replies.
Writes the new interaction back to Mem0.
a) Define the shared state
from typing import Annotated, TypedDict
from langgraph.graph.message import add_messages
from langchain_core.messages import BaseMessage
class State(TypedDict):
"""Conversation state passed between nodes"""
messages: Annotated[list[BaseMessage], add_messages]
mem0_user_id: str
b) Init the LLM
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4.1-mini", temperature=0.7)
c) Create the chatbot node
from langchain_core.messages import HumanMessage, AIMessage, SystemMessage
def chatbot(state: State):
global memory
msgs = state["messages"]
uid = state["mem0_user_id"]
mems = memory.search(msgs[-1].content, user_id=uid)
print(f"Retrieved Memories: {mems}")
if mems["results"]:
context = "
".join(f"- {m['memory']}" for m in mems["results"])
else:
context = "No relevant information found."
system = SystemMessage(content=f"""You are a helpful assistant. Use the provided context to personalise your responses.
Relevant information from previous conversations:
{context}""")
response = llm.invoke([system] + msgs)
memory.add([
{"role": "user", "content": msgs[-1].content},
{"role": "assistant", "content": response.content}
], user_id=uid)
return {"messages": [response]}
How the node uses Mem0
Search: For every incoming user message, we call memory.search() with the text and user_id. This performs a vectorâsimilarity lookup and returns any facts previously stored about the user.
Prompt injection: Those facts are concatenated into a bullet list (context) and inserted into a system prompt so the LLM can personalise its reply.
Add: After the LLM responds, we persist both the latest user message and the assistant reply via memory.add(). Mem0 distils them into new memories ready for the next turn.
d) Build & compile the graph
from langgraph.graph import StateGraph, START, END
graph_builder = StateGraph(State)
graph_builder.add_node("chatbot", chatbot)
graph_builder.add_edge(START, "chatbot")
graph_builder.add_edge("chatbot", END)
graph = graph_builder.compile()
print("Graph compiled successfully â
")
e) Commandâline loop for quick testing
from langgraph_core.messages import HumanMessage
def run_conversation(user_input: str, mem0_user_id: str):
state = {"messages": [HumanMessage(content=user_input)], "mem0_user_id": mem0_user_id}
result = graph.invoke(state)
print("đ¤", result["messages"][-1].content)
if __name__ == "__main__":
uid = "customer_pradip"
while True:
inp = input("You: ")
if inp.lower() in {"quit", "exit", "bye"}:
break
run_conversation(inp, uid)
Run it, send two or three messages, then restart the script and ask âwho am I?ââyouâll see the agent recall facts from the earlier run thanks to Mem0âs longâterm store.
3. VectorâŻDB Setup â Configuring Mem0 with Qdrant
SQLite works for quick tests, but once memories grow youâll want a proper vector store. Qdrant Cloud offers a generous free tier and plugs straight into Mem0.
a) Spin up / locate a Qdrant Cloud cluster
Grab the cluster URL and create an API key from the Qdrant dashboard.
!pip -q install qdrant_client
b) Verify connectivity (optional)
from qdrant_client import QdrantClient
qdrant = QdrantClient(
url="https://<cluster-id>.<region>.aws.cloud.qdrant.io:6333",
api_key=userdata.get("Qdrant_API_KEY")
)
print(qdrant.get_collections())
c) Tell Mem0 to use Qdrant
collection_name = "mem0_yt"
config = {
"vector_store": {
"provider": "qdrant",
"config": {
"collection_name": collection_name,
"host": "<cluster-host>",
"port": 6333,
"api_key": userdata.get("Qdrant_API_KEY")
}
}
}
memory = Memory.from_config(config)
d) Oneâtime payload index
Mem0 filters by user_id when searching, so Qdrant needs a keyword index on that field. If you skip this step youâll get:
400 Bad Request â Index required but not found for "user_id" of type [keyword]
Create it once, then youâre good:
qdrant.create_payload_index(
collection_name=collection_name,
field_name="user_id",
field_schema="keyword"
)
e) Insert and query as usual
messages = [
{"role": "user", "content": "Hi, I'm Pradip Nichite. I run FutureSmart AI."},
{"role": "user", "content": "I love building RAG and AI Agent solutions that work in production."}
]
memory.add(messages, user_id="pradip")
From here all CRUD and LangGraph logic stays exactly the sameâonly the storage layer has changed.
If youâd rather skip managing your own DBs, Mem0 offers a hosted platform with a clean UI to inspect and edit memories.
a) Authenticate
from mem0 import MemoryClient
client = MemoryClient(api_key=userdata.get("Mem0_API_KEY"))
b) Add messages (same schema as before)
messages = [
{"role": "user", "content": "Hi, I am Pradip. I am Founder of FutureSmart AI"},
{"role": "assistant", "content": "Hi Pradip"}
]
client.add(messages, user_id="Pradip_Founder")
c) Inspect in the dashboard

Youâll see two distilled memories automatically extracted, complete with timestamps and editable fields.
The hosted store supports the same search/update/history API, so you can swap Memory for MemoryClient with minimal changes.
Watch the full walkthrough
Prefer video? I recorded a stepâbyâstep YouTube demo that mirrors this blog, including live coding and UI tours â check it out here đ
Need a Custom AI Solution?
At FutureSmart AI we specialise in designing and shipping productionâgrade AI systemsâRAG agents, document parsers, NL2SQL bots, multiâagent workflows, and more.
â See our case studies: https://futuresmart.ai/case-studies
â Try the LangGraphâpowered FutureSmart Agent: https://agent.futuresmart.ai/
â Get in touch: email us at contact@futuresmart.ai to discuss how we can build or fineâtune an AI solution for your business.