Agents

Memory and Chat History

Add persistent memory to your LangChain applications for multi-turn conversations.

Memory in LangChain

LangChain provides several approaches for conversation memory:

Message History (Recommended)

Store messages and inject them into the prompt.

Memory Types (Legacy)

  • ConversationBufferMemory: Store all messages
  • ConversationSummaryMemory: Summarize old messages
  • ConversationBufferWindowMemory: Keep last N messages

RunnableWithMessageHistory

The modern approach wraps any chain with message history management. You provide:

  • get_session_history: Function that returns a message store for a given session ID
  • input_messages_key: Which input key contains the new message
  • history_messages_key: Where to inject history in the prompt

Example

python
from langchain_anthropic import ChatAnthropic
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.output_parsers import StrOutputParser
from langchain_core.chat_history import BaseChatMessageHistory, InMemoryChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory

llm = ChatAnthropic(model="claude-3-5-haiku-20241022")

# In-memory store (use Redis/DB in production)
store: dict[str, InMemoryChatMessageHistory] = {}

def get_session_history(session_id: str) -> BaseChatMessageHistory:
    if session_id not in store:
        store[session_id] = InMemoryChatMessageHistory()
    return store[session_id]

# Create a chain with memory
prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a helpful assistant. Remember details from the conversation."),
    MessagesPlaceholder(variable_name="history"),
    ("human", "{input}"),
])

chain = prompt | llm | StrOutputParser()

# Wrap with message history
chain_with_memory = RunnableWithMessageHistory(
    chain,
    get_session_history,
    input_messages_key="input",
    history_messages_key="history",
)

# Use with session IDs for multi-user support
def chat(session_id: str, message: str) -> str:
    return chain_with_memory.invoke(
        {"input": message},
        config={"configurable": {"session_id": session_id}}
    )

# Session 1: Alice
print(chat("alice", "Hi! My name is Alice and I love Python."))
print(chat("alice", "What programming language did I just mention?"))

# Session 2: Bob (separate memory)
print(chat("bob", "Hi! I'm Bob and I prefer JavaScript."))
print(chat("bob", "What's my name and preferred language?"))

# Summary memory pattern
from langchain_core.messages import trim_messages

# Trim messages to avoid context overflow
trimmer = trim_messages(
    max_tokens=2000,
    strategy="last",
    token_counter=llm,
    include_system=True,
)

trimmed_chain = (
    {"input": lambda x: x["input"], "history": lambda x: trimmer.invoke(x["history"])}
    | prompt
    | llm
    | StrOutputParser()
)
Try it yourself — PYTHON