AI Agents Memory: Mem0 + LangGraph Agent Integration


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"}) # local SQLite file
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")
# → {'message': 'Memory updated successfully!'}
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] # chat history for this request
mem0_user_id: str # maps to Mem0 user record
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 # re‑use the Mem0 instance from Section 1
msgs = state["messages"]
uid = state["mem0_user_id"]
# 1️⃣ Retrieve memories relevant to the latest user msg
mems = memory.search(msgs[-1].content, user_id=uid)
print(f"Retrieved Memories: {mems}")
# Build context string
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}""")
# 2️⃣ Invoke the LLM
response = llm.invoke([system] + msgs)
# 3️⃣ Persist the new turn
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 anduser_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.
# Install the Python client
!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()) # sanity‑check
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.
4. Cloud Usage – Using the Mem0 Cloud Platform
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.
Subscribe to my newsletter
Read articles from Pradip Nichite directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Pradip Nichite
Pradip Nichite
🚀 I'm a Top Rated Plus NLP freelancer on Upwork with over $300K in earnings and a 100% Job Success rate. This journey began in 2022 after years of enriching experience in the field of Data Science. 📚 Starting my career in 2013 as a Software Developer focusing on backend and API development, I soon pursued my interest in Data Science by earning my M.Tech in IT from IIIT Bangalore, specializing in Data Science (2016 - 2018). 💼 Upon graduation, I carved out a path in the industry as a Data Scientist at MiQ (2018 - 2020) and later ascended to the role of Lead Data Scientist at Oracle (2020 - 2022). 🌐 Inspired by my freelancing success, I founded FutureSmart AI in September 2022. We provide custom AI solutions for clients using the latest models and techniques in NLP. 🎥 In addition, I run AI Demos, a platform aimed at educating people about the latest AI tools through engaging video demonstrations. 🧰 My technical toolbox encompasses: 🔧 Languages: Python, JavaScript, SQL. 🧪 ML Libraries: PyTorch, Transformers, LangChain. 🔍 Specialties: Semantic Search, Sentence Transformers, Vector Databases. 🖥️ Web Frameworks: FastAPI, Streamlit, Anvil. ☁️ Other: AWS, AWS RDS, MySQL. 🚀 In the fast-evolving landscape of AI, FutureSmart AI and I stand at the forefront, delivering cutting-edge, custom NLP solutions to clients across various industries.