AI Agents Memory: Mem0 + LangGraph Agent Integration

Pradip NichitePradip Nichite
8 min read

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

  1. Mem0 Basics – Adding, updating, and searching memories

  2. LangGraph Integration – Wiring Mem0 into a LangGraph agent

  3. Vector DB Setup – Swapping the default SQLite store for Qdrant

  4. 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

AspectChat history (session)Long‑term memory (Mem0)
LifespanOnly current sessionPersists across sessions
GranularityFull message textDistilled facts & metadata
StorageIn‑prompt list of messagesExternal DB / vector store
Cost impactGrows token count quicklyMinimal 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.


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:

  1. Accepts user messages.

  2. Retrieves relevant memories from Mem0.

  3. Injects them into the system prompt for personalised replies.

  4. 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

  1. 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.

  2. Prompt injection: Those facts are concatenated into a bullet list (context) and inserted into a system prompt so the LLM can personalise its reply.

  3. 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.

0
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.