--- title: "LangChain memory in 2026: what replaced it" description: "LangChain deprecated its memory classes in favor of LangGraph persistence. What changed, what each option stores, and how to add temporal memory via API." canonical: https://past.dev/integrations/langchain last-updated: 2026-10-15 --- # Memory for LangChain agents Source: https://past.dev/integrations/langchain LangChain's classic memory classes, ConversationBufferMemory and its relatives, are deprecated: the framework moved persistence to LangGraph, and long-term memory to stores and the LangMem SDK. Those layers persist conversation state and extracted memories. What none of them model is time: which fact is current, what superseded what, and what was true on a date. This page maps the 2026 options and shows the API pattern for adding temporal, evidence-backed memory to any LangChain agent. ## LangChain memory options in 2026 | Layer | What it stores | Scope | | --- | --- | --- | | LangGraph checkpointers | Full graph state per thread | One thread; resume and replay | | LangGraph store | Key-value and vector memories | Cross-thread, per namespace | | LangMem SDK | Extracted memories over the store | Cross-thread, app-managed | | past.dev via tool | Timestamped source text and grouped recall documents | Cross-user and cross-app with identity scoping | The deprecation is documented in LangChain's own guides: legacy memory classes were removed in the 1.0 line, with [long-term memory](https://docs.langchain.com/oss/python/langchain/long-term-memory) now described in terms of LangGraph persistence and stores, plus the [LangMem SDK](https://langchain-ai.github.io/langmem/). If a migration brought you here, the practical translation: buffer memory became checkpointed thread state, and everything long-term became your choice of store. ## What the native layers do not model - **Currency.** Writing two budget values creates two store entries. Similarity scores do not identify which value is current. - **Original time.** Store records use write time unless the application adds event-time fields. Backfilled history therefore needs explicit timestamp handling. - **Identity.** Namespaces do not automatically join an email signature to a chat handle for the same customer. ## The pattern: memory as a tool ```python import os, requests from dataclasses import dataclass from langchain.agents import create_agent from langchain.tools import ToolRuntime, tool BASE = "https://api.past.dev/api/v1" HEADERS = {"Authorization": f"Bearer {os.environ['PAST_API_KEY']}"} @dataclass class UserContext: user_id: str # the signed-in user, set by your application @tool def recall_memory(question: str, runtime: ToolRuntime[UserContext]) -> str: """Look up source-backed documents relevant to a question.""" r = requests.post(f"{BASE}/recall", headers=HEADERS, json={"query": question, "identity": runtime.context.user_id}).json() return str(r) @tool def store_memory(text: str, happened_at: str, runtime: ToolRuntime[UserContext]) -> str: """Save timestamped source text, readable by the whole project, authored by the current user.""" r = requests.post(f"{BASE}/ingest", headers=HEADERS, json={"content": text, "timestamp": happened_at, "identity": runtime.context.user_id}).json() return r.get("sourceId", "stored") agent = create_agent( model, # any chat model LangChain supports tools=[recall_memory, store_memory], context_schema=UserContext, ) result = agent.invoke( {"messages": [{"role": "user", "content": "What did we decide about the Q4 budget?"}]}, context=UserContext(user_id="demo-user"), ) ``` LangChain hides the `runtime` parameter from the model, and each `invoke` passes the signed-in user as its `context` ([tools](https://docs.langchain.com/oss/python/langchain/tools)). Use the LangGraph checkpointer for thread state and past.dev for durable, timestamped facts. > **Identity** > > The application sets the identity. The model never chooses it. Recall returns what the identity in the request may read, so take the identity from the signed-in user in code, and keep it out of every value that the model fills. Recall returns ranked documents with dates and source excerpts. The application decides whether those documents support an answer, contain a disagreement, or are insufficient; HTTP failures are handled separately. ## Or connect the MCP server LangChain's MCP client is `MCPAdapter` in the `langchain.mcp` namespace, installed with `langchain[mcp]` 1.4 or later. It replaces the standalone `langchain-mcp-adapters` package, infers the transport from the URL, and is in beta ([migration guide](https://docs.langchain.com/oss/python/migrate/langchain-mcp-adapters)). The project's end-user MCP server then gives the agent `recall`, `answer` and `who_am_i`, plus `remember` while the project's write toggle is on, with no tool code to write. 1. Turn on the project's end-user MCP server on **Build › MCP server** in the console. 2. Mint an access link there, or with the account server's `create_mcp_access_link` tool. The link has the form `https://api.past.dev/mcp//link/`. It is one URL that is one identity, and the server answers it with no sign-in step. 3. Keep the link in a secret store, such as the `PAST_MCP_URL` environment variable that the code below reads. The secret in its path is the credential. ```python import asyncio, os from langchain.agents import create_agent from langchain.mcp import MCPAdapter async def main(): async with MCPAdapter(os.environ["PAST_MCP_URL"]) as adapter: tools = await adapter.list_tools() agent = create_agent(model, tools) # model: any chat model LangChain supports result = await agent.ainvoke( {"messages": [{"role": "user", "content": "What did we decide about the Q4 budget?"}]} ) print(result["messages"][-1].content) asyncio.run(main()) ``` Every call through the link runs as its identity, with that identity's audiences. Mint one link per install, so that a revoked link stops one agent only. When the agent serves several people, mint one link per end user, and connect each request with the link of the user who makes it. Never share one link between users. `remember` writes to the identity's own private audience, and only that identity recalls it. Send data that the whole project must recall through the ingest call. The [end-user server documentation](/docs/mcp/serving-your-own-users) describes the tools, the links and revocation. ## When to use which - Resuming and replaying a conversation: checkpointer. That is its job and it is good at it. - Small per-user preferences in one app: the LangGraph store is the lightest path. - Facts that change, histories that backfill, answers that need dates and sources, memory shared beyond one app: the API pattern above. Start at the [quickstart](/docs/memory-api/quickstart); the [benchmarks](/benchmarks) document how recall is measured, and [what is agent memory](/what-is-agent-memory) covers the concepts behind the division. ## Frequently asked questions ### I migrated off ConversationBufferMemory. Do I need anything else? If your agent only needs to resume conversations, no: checkpointers cover it. You need a memory layer when answers depend on facts that change over time, arrive from multiple sources, or must carry dates and evidence. ### Does this work with LangGraph too? Yes. The same tools can run in LangGraph nodes. The LangGraph guide explains how to combine checkpointers, stores, and the past.dev API. ## Related - [Memory for LangGraph](https://past.dev/integrations/langgraph) - [past.dev and LangMem](https://past.dev/compare/langmem) - [Memory for n8n](https://past.dev/integrations/n8n) - [What is agent memory?](https://past.dev/what-is-agent-memory) - [Quickstart](https://past.dev/docs/memory-api/quickstart)