Guides / Frameworks

LangChain and LangGraph

For LangChain and LangGraph developers who want an agent to remember each user across threads. langchain-recall adds Recall as middleware for create_agent, as tools, as a retriever and as a chat history, in a few lines. This guide is for Python; for TypeScript see LangChain.js.

What memory adds

A checkpointer keeps one thread's state. Everything the user said in other threads is out of reach. With Recall:

Checkpointer onlyWith Recall
A new threadThe agent starts from the system prompt.The system prompt already holds the user's peer card and the facts that relate to their first message.
"I'm vegetarian," said onceGone when the thread ends.Learned in the background from the recorded conversation, or saved at once by the model with recall_remember.
"What did we decide about the hotel?"Only if it is in this thread.recall_ask answers from every earlier conversation with the user.

Recall is memory, not the agent: it does not run tools or replace your checkpointer. Keep the checkpointer for graph state and use Recall for what the agent should remember about people.

How it maps onto Recall

In LangChainIn RecallWhy
Your appWorkspace, from RECALL_WORKSPACE_IDMemory stays inside it.
The user, context={"user_id": ...}Peer user-8412Recall learns about this person. Use your own stable user id, not an email address.
The agentPeer assistant, not learned aboutIts answers are read as context, but facts are learned about the user, not from the agent's own statements.
A thread, thread_idSession with the same idEach thread's exchanges in order. Thread ids with characters other than letters, digits, _ and - are made valid with a short hash.

Build it

Install the package with pip install "langchain-recall[agents]" and set RECALL_API_KEY (create one at app.recallmem.dev/keys), or RECALL_URL for a server of your own.

An agent with memory

One agent serves every user. RecallMiddleware reads memory before each run and records the exchange after it; the toolkit gives the model recall_search, recall_ask and recall_remember. Both read the user from the run's context.

from langchain.agents import create_agent
from langchain_recall import RecallMiddleware, RecallRetriever, RecallToolkit
from langgraph.checkpoint.memory import InMemorySaver
from recall_memory import Recall

recall = Recall(workspace_id="travel-agent")

# `model` is your chat model, e.g. init_chat_model(...). One agent serves every user: the
# middleware and the tools read the user from each run's context.
agent = create_agent(
    model,
    tools=RecallToolkit(client=recall).get_tools(),
    system_prompt="You are a travel assistant.",
    middleware=[RecallMiddleware(recall)],
    checkpointer=InMemorySaver(),  # the thread's own state; Recall is long-term memory
)

Each run. The middleware adds the user's peer card and the facts that relate to the new message to the system prompt, then stores the user's message and the final answer in the thread's Recall session. Tool calls and their results are not recorded.

# The thread id names the Recall session; the user id is the person Recall learns about.
first = agent.invoke(
    {"messages": [{"role": "user", "content": "I'm vegetarian. Plan a weekend in Lisbon."}]},
    {"configurable": {"thread_id": "trip-lisbon"}},
    context={"user_id": "user-8412"},
)

Another thread. The checkpointer has nothing for a new thread, but Recall has the user:

# A new thread weeks later: the prompt already holds what Recall knows about the user.
recall.wait_for_idle()  # only for this demo: learning runs in the background
later = agent.invoke(
    {"messages": [{"role": "user", "content": "Where should we eat in Porto?"}]},
    {"configurable": {"thread_id": "trip-porto"}},
    context={"user_id": "user-8412"},
)

Tools, retriever and chat history

Each component also works on its own, in a chain or a graph node: give it user_id, or leave it out inside a LangGraph run with a context.

ComponentUse it for
RecallToolkitrecall_search (facts and the user's messages, no model call), recall_ask (an answer from memory), recall_remember (save facts the user stated, searchable at once).
RecallRetrieverFacts (source="facts"), messages or both as Documents, for retrieval in a chain.
RecallChatMessageHistoryA BaseChatMessageHistory kept in a Recall session, for code that still uses one. LangChain deprecates that interface in favour of LangGraph persistence, so prefer the middleware for new agents.
# Facts about the user as documents, for a chain or a graph node of your own. No model call.
retriever = RecallRetriever(user_id="user-8412", source="facts", k=5, client=recall)
docs = retriever.invoke("food preferences")

Why no store or checkpointer. LangGraph's BaseStore is a key-value document store and a checkpointer saves graph state. Recall is neither: it learns from conversations and answers with what it learned, so it plugs in as middleware, tools and a retriever instead.

Settings that matter

SettingUse
user_id or context={"user_id": ...}Whose memory. Fixed for one user, or per run for many (user_id_key changes the context key).
session_id or thread_idWhere the middleware records. Without either it refuses to run, unless record=False.
recall=False, record=FalseOnly record, or only recall.
max_conclusionsMost facts in the prompt (20 by default).
k, reasoning_levelResults per search, and how hard recall_ask thinks: low by default. See Reasoning levels and models.

Cost and speed

The middleware reads memory once per run, with a context request and no model call: context reads took 0.3 to 0.7 seconds, measured from Europe against the hosted API (Frankfurt), October 2026. recall_search and the retriever search facts and messages without a model call, in about a second. recall_ask is one model call of 2 to 4.5 seconds at low. Recording returns at once; learning runs in the background.

Context, search and storage are included. Learning from the recorded messages and answering questions are charged; see pricing and Cost and speed for worked examples.

Privacy and forgetting

The middleware sends the user's message and the agent's final answer to Recall, not tool calls or tool output. RecallChatMessageHistory stores every message you give it, tool messages included, but Recall learns only from the user's. Tell users what the agent remembers. To forget someone:

# The user deletes their account: erase them, then the threads that hold the agent's replies.
user = recall.peer("user-8412")
threads = list(user.sessions())
user.delete()
for thread in threads:
    thread.delete()

See Forget a person and Privacy, consent and forgetting.

Pitfalls

Next: OpenAI Agents SDK · LangChain.js