LangChain Memory
Give any LangChain chain or agent persistent memory with two packages: langchain-memorysync for Python and memorysync-langchain for Node.js. Both work on langchain-core 0.3.x and 1.x.
What the integration provides
| Piece | What it does |
|---|---|
MemorySyncChatMessageHistory | A BaseChatMessageHistory implementation, so RunnableWithMessageHistory persists transcripts in MemorySync instead of process memory. |
| Context provider | One call that returns a grouped, prompt-ready context block from hierarchical recall, for personalising a system prompt. |
| Agent tools | Five structured memory tools for agents, covered in LangChain Tools. |
Install
pip install langchain-memorysync
Set MEMORYSYNC_API_KEY in the environment, or pass the key explicitly. Keys come from the dashboard or npx memorysync-cli init. The cURL tabs on this page show the REST call each operation makes.
Persist chat history
Wrap any runnable with RunnableWithMessageHistory and hand it a MemorySync-backed history per session. Each exchange is written as soon as the chain finishes the turn and read back in order, so a restarted process resumes where the conversation left off.
from langchain_core.runnables.history import RunnableWithMessageHistoryfrom langchain_memorysync import MemorySyncChatMessageHistorychain_with_history = RunnableWithMessageHistory(chain,lambda session_id: MemorySyncChatMessageHistory(session_id=session_id,user_id="user-123",),input_messages_key="input",history_messages_key="history",)chain_with_history.invoke({"input": "My name is Ada."},config={"configurable": {"session_id": "thread-42"}},)
Each message is kept in the session’s conversation history exactly as written, so short answers like "yes" survive. The full LangChain message — tool calls included — is stored with the turn and reconstructed exactly on read. The transcript is not part of the user’s memories: MemorySync extracts the durable facts from the user’s messages and stores those as memories, which is what recall and the context provider return.
Sessions and users
| Parameter | Meaning |
|---|---|
session_id | The conversation thread. Reads and clear() touch only this thread. |
user_id | The end user the turns belong to. Defaults to the session id; pass a stable user id to share memory across that user’s sessions. |
max_messages | Cap on how many trailing messages a read returns, so a long transcript cannot blow the prompt budget. Writes are unaffected. |
read_only | Blocks writes and clear() for safe transcript inspection. |
Prompt-ready recall context
For personalisation beyond the current thread, the context provider returns a grouped, type-labelled block built by hierarchical recall — ready to place in a system prompt. It returns an empty string when the user has no relevant memories, because a new user is a normal state, not an error.
from langchain_memorysync import MemorySyncContextProviderprovider = MemorySyncContextProvider(user_id="user-123")context = provider.get_context("What should I cook tonight?")prompt = f"Relevant memories:\n{context}\n\nAnswer the user."
Complete example: a chatbot that remembers
Everything above in one runnable program: per-session transcripts through the history class, cross-session personalisation through the context provider, and an LLM in the middle. Stop the process, start it again, and the conversation resumes where it left off — with what the user told you last week already in the system prompt.
import osfrom langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholderfrom langchain_core.runnables.history import RunnableWithMessageHistoryfrom langchain_openai import ChatOpenAIfrom langchain_memorysync import (MemorySyncChatMessageHistory,MemorySyncContextProvider,)USER_ID = "customer-7"llm = ChatOpenAI(model="your-model")provider = MemorySyncContextProvider(user_id=USER_ID)prompt = ChatPromptTemplate.from_messages([("system","You are a helpful travel assistant.\n""Relevant memories about this user:\n{memories}",),MessagesPlaceholder(variable_name="history"),("human", "{input}"),])chat = RunnableWithMessageHistory(prompt | llm,lambda session_id: MemorySyncChatMessageHistory(session_id=session_id,user_id=USER_ID,max_messages=30,),input_messages_key="input",history_messages_key="history",)def chat_turn(text: str, session_id: str) -> str:# Long-term memories from every past session, not just this thread.memories = provider.get_context(text) or "None yet."reply = chat.invoke({"input": text, "memories": memories},config={"configurable": {"session_id": session_id}},)return reply.contentif __name__ == "__main__":print("Travel assistant (empty line to quit)")while True:text = input("you: ").strip()if not text:breakprint("assistant:", chat_turn(text, session_id="trip-planning-1"))
Supported versions
| Package | Registry | langchain-core | Runtime |
|---|---|---|---|
langchain-memorysync 1.2.0 | PyPI | 0.3+ (tested on 0.3.x and 1.x) | Python 3.10+ |
memorysync-langchain 1.2.0 | npm | 0.3+ peer dependency (tested on 0.3.x and 1.x) | Node 18+ |
Both packages run their full test suites against langchain-core 0.3.x and 1.x on every commit, so an upgrade on your side is not a leap of faith.