LangChain 1.0 Removed ConversationBufferMemory. Here Is the Memory Map That Actually Works
LangChain 1.0 Removed ConversationBufferMemory. Here Is the Memory Map That Actually Works Every couple of years, LangChain renames memory. ConversationBufferMemory becomes a deprecation warning, becomes a removal, becomes something you install separately under the name langchain-classic. If you run a scheduled agent through those cycles, you pick up a useful habit: stop memorizing class names and learn the jobs instead. There are only three things agent memory ever does. Everything in the curr
LangChain 1.0 Removed ConversationBufferMemory. Here Is the Memory Map That Actually Works
Every couple of years, LangChain renames memory. ConversationBufferMemory becomes a deprecation warning, becomes a removal, becomes something you install separately under the name langchain-classic. If you run a scheduled agent through those cycles, you pick up a useful habit: stop memorizing class names and learn the jobs instead. There are only three things agent memory ever does. Everything in the current API is one of those three wearing a new name.
The three jobs
Job one: remember what was said. The conversation, in order, reloadable by session.
Job two: resume where the run stopped. Not the transcript, the actual state: which tools were called, what came back, the step the agent was on when the process ended.
Job three: remember what is true. Facts and corrections that outlive any single conversation: preferences, decisions, "we don't do it that way anymore."
The old code collapsed all three into one object, and that is why the tutorials felt simple while production felt broken. One object cannot have three different lifetimes. A conversation belongs to a session. A run's state belongs to a thread. A fact belongs to a user. The moment your agent needs more than one of those, the single memory object starts lying to you.
Job one: the conversation
The current answer is RunnableWithMessageHistory from langchain_core. You wrap your chain or agent, hand it a function that returns a history object per session id, and every invocation loads that session's messages and appends the new ones. For local work, an in-memory history is fine. For anything that matters, the history backend has to survive restarts: the langchain_community package ships Redis and Postgres backed histories for this.
The failure mode that bites scheduled operators is embarrassingly common. The in-memory version works perfectly in development. Every test passes. Then the container restarts on a schedule you did not choose, the dict is gone, and the agent that handled a hundred sessions yesterday starts this morning as a stranger. If your memory backend is a Python dict, you do not have memory. You have a cache with no eviction policy and a surprise expiration date.
Job two: the run
This is the one the old ConversationBufferMemory could never do, and it is the one scheduled agents need most. If your agent runs nightly and must pick up where last night left off, you need the run's state, not just its transcript.
In the current API that means building the agent with create_agent and giving it a checkpointer:
from langgraph.checkpoint.sqlite import SqliteSaver
memory = SqliteSaver.from_conn_string("/data/checkpoints.db")
agent = create_agent(model="gpt-5", tools=[...], checkpointer=memory)
agent.invoke(
{"messages": [{"role": "user", "content": "compile the nightly digest"}]},
config={"configurable": {"thread_id": "nightly-digest"}},
)
The thread_id is the run's primary key. Same id tonight as last night, and the agent resumes the thread with everything intact: messages, tool calls, intermediate steps. MemorySaver is the in-memory checkpointer for tests. SQLite or Postgres is what runs in production.
Notice the path in that snippet: /data/checkpoints.db, not a relative file in the working directory. That is deliberate. The most common silent failure in scheduled LangChain agents is a checkpointer file on an ephemeral disk. The container rebuilds, the file evaporates, and the agent wakes up blank with no error anywhere in the logs. Memory that lives on a disk that gets wiped is not memory, it is a wish. Mount persistent storage or use the Postgres checkpointer, then prove it by killing the process mid-run and watching the agent resume.
Job three: the facts
Some things must survive every thread. A client corrects the agent: reports go out on Mondays, not Fridays. That correction cannot live in one conversation's history, or the next thread starts the argument over.
The current API splits this off into the Store: a namespaced key-value layer keyed by user or tenant, separate from any thread's state. Namespaces like ("preferences",) hold the durable facts; the agent reads them at the start of a run and updates them when corrected. The rule of thumb: State is what happened in this thread, Store is what is true across threads. Keep thread trivia out of the Store and it stays small and fast. Let corrections die with the thread and your users will correct the same thing forever.
The same persistence caveat applies here in miniature. The in-memory store dies with the process. Production pairs the Store with a persistent backend, or the facts evaporate exactly when the conversations do.
The option the class diagrams never list
Every option above has one thing in common: you own the storage. You choose the database, keep it reachable, back it up, and the memory is fenced inside whatever can connect to that database. Run a LangChain agent on a cron box plus a couple of other tools, and you are maintaining several silos of context that never meet.
There is a fourth shape that sidesteps the whole storage question. Vilix AI is a cloud-hosted memory layer your agent reaches over MCP, so there is no database to run at all. Every connected tool shares the same memory: Claude, Codex, Cursor, OpenClaw, Hermes, anything MCP-compatible. The agent stores full conversation history rather than just extracted facts, and retrieval is semantic plus keyword search, so each run pulls the relevant slice of context instead of the entire archive. Your data exports in a portable format whenever you want it. Individual memories delete on demand, or the whole account wipes instantly. A free plan runs forever, and the 7-day Pro trial never asks for a card.
The tradeoff is the one you would expect: it is cloud-hosted, and it is a service you subscribe to rather than code you own. If your constraints say agent memory never leaves your infrastructure, the checkpointer and Store options above are the honest answer. If the part you dread is becoming the database administrator for your agent's brain, the hosted route removes that job entirely.
Which jobs do you actually need?
Class names will change again. The jobs will not. Before touching the API, answer three questions about your agent.
Does it hold conversations with people? Then job one, with a persistent history backend, not a dict.
Does it run on a schedule and need to pick up where it stopped? Then job two: one thread id per recurring job, and the checkpointer on storage that survives a redeploy.
Do humans correct it and expect the correction to stick? Then job three, facts in the Store, never in thread state.
Most scheduled agents need jobs two and three and skip job one entirely, which surprises people who started from chatbot tutorials. And if you run agents across more than one tool and refuse to maintain a database per tool, there is now a hosted answer for that too. Pick the jobs, then pick the machinery. The API will rename itself again next year. The map holds.