Skip to content

Chapter 4 of 8

Memory and Conversation History

Conversational applications need to remember what the user has already said, and LangChain offers a layered set of tools, ranging from legacy Memory classes to the modern RunnableWithMessageHistory pattern. ConversationBufferMemory stores the entire conversation as a list of messages — simple, but its token cost grows unboundedly. ConversationBufferWindowMemory keeps only the last k turns, a useful middle ground. ConversationSummaryMemory periodically asks an LLM to compress the running transcript into a summary, while ConversationSummaryBufferMemory keeps recent messages in full and summarizes older ones once a token limit is reached, balancing fidelity with token efficiency. ConversationEntityMemory extracts named entities mentioned in the conversation and stores facts about each so the assistant can recall user-specific details, and VectorStoreRetrieverMemory stores each turn in a vector database and pulls the most semantically similar past turns at query time, which scales to very long histories without saturating the context window.

The recommended modern pattern is to manage messages yourself and inject them with structured primitives. ChatMessageHistory is a simple in-memory message store with helpers to add user messages, AI messages, or arbitrary BaseMessage instances; you can swap it for persistent implementations such as RedisChatMessageHistory, PostgresChatMessageHistory, or SQLChatMessageHistory without changing the surrounding code. To plug history into a chain, insert a MessagesPlaceholder into your ChatPromptTemplate (typically named chat_history) and wrap the chain with RunnableWithMessageHistory, supplying a get_session_history factory keyed on a session_id in the config. This wrapper handles loading, appending, and saving the history automatically, so the chain's invoke signature stays clean and free of memory-management boilerplate.

A subtle distinction is between session history and the long-term store — a cross-session BaseStore for facts like user preferences or accumulated knowledge. LangChain exposes both through separate callbacks on RunnableWithMessageHistory, and you can use them together: per-thread conversation on one side, persistent user facts on the other. The legacy Memory classes in langchain.memory remain available but are slated for deprecation; new code should prefer ChatMessageHistory plus RunnableWithMessageHistory for transparency, testability, and straightforward persistence swaps.

All chapters
  1. 1Foundations of LangChain and the Runnable Interface
  2. 2Prompts, Chat Models, and Output Parsers
  3. 3Composing Runnables and Controlling Execution
  4. 4Memory and Conversation History
  5. 5Documents, Embeddings, and Vector Stores
  6. 6RAG Pipelines and Document Processing
  7. 7Tools, Agents, and LangGraph
  8. 8Observability, Evaluation, Deployment, and Caching

Drill it

Reading is not remembering. These come from the LangChain deck:

Q

What is LangChain?

LangChain is an open-source Python framework for building applications powered by large language models (LLMs). It provides modular components for prompts, chai...

Q

What is LCEL (LangChain Expression Language)?

LCEL is a declarative syntax for composing LangChain components using the pipe operator (|). It creates RunnableSequence chains that support streaming, batching...

Q

How do you create a ChatPromptTemplate?

Use ChatPromptTemplate.from_messages() with a list of (role, template) tuples. Variables are wrapped in curly braces.from langchain_core.prompts import ChatProm...

Q

How do you invoke a ChatModel in LangChain?

Instantiate the model class and call .invoke() with a list of messages or a prompt value. The model returns an AIMessage.from langchain_openai import ChatOpenAI...