LangChain Tutorial (Python): adding memory to agents for beginners

By Cyprian AaronsUpdated 2026-04-21
langchainadding-memory-to-agents-for-beginnerspython

This tutorial shows you how to give a LangChain agent short-term memory in Python so it can remember prior turns in a conversation. You need this when your agent must keep context across messages, like tracking a customer’s claim number, a policy type, or a troubleshooting flow without asking the same question twice.

What You'll Need

  • Python 3.10+
  • A working OpenAI API key set as OPENAI_API_KEY
  • LangChain packages:
    • langchain
    • langchain-openai
  • Basic familiarity with:
    • ChatOpenAI
    • tools in LangChain
    • Python functions and classes
  • A terminal and virtual environment

Install the packages:

pip install langchain langchain-openai

Set your API key:

export OPENAI_API_KEY="your-key-here"

Step-by-Step

  1. Start with a simple tool the agent can call.

We’ll use a tiny calculator tool so the agent has something concrete to do. The point is not the tool itself; it’s to show that memory works while the agent is using tools and chatting.

from langchain_core.tools import tool

@tool
def add_numbers(a: int, b: int) -> int:
    """Add two integers together."""
    return a + b

tools = [add_numbers]
  1. Create the model and prompt template.

For beginners, keep the prompt simple and explicit. The key detail is that we include MessagesPlaceholder("chat_history"), which is where conversation memory gets injected.

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder

llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)

prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a helpful assistant. Use chat history when relevant."),
    MessagesPlaceholder(variable_name="chat_history"),
    ("human", "{input}"),
    MessagesPlaceholder(variable_name="agent_scratchpad"),
])
  1. Build an agent that can use tools.

This is the standard LangChain pattern for tool-calling agents. We wrap the model and tools into an executor so we can run it like a normal callable object.

from langchain.agents import create_tool_calling_agent, AgentExecutor

agent = create_tool_calling_agent(llm=llm, tools=tools, prompt=prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
  1. Add memory with RunnableWithMessageHistory.

This is the part most beginners miss: the agent itself does not magically remember anything between calls. RunnableWithMessageHistory stores messages per session and injects them back into the prompt on the next turn.

from langchain_core.chat_history import InMemoryChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory

store = {}

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

agent_with_memory = RunnableWithMessageHistory(
    agent_executor,
    get_session_history,
    input_messages_key="input",
    history_messages_key="chat_history",
)
  1. Run two turns in the same session.

The first message creates history. The second message reuses that same session ID, so the agent can answer follow-up questions without you repeating context.

config = {"configurable": {"session_id": "user-123"}}

response1 = agent_with_memory.invoke(
    {"input": "My name is Priya. Remember that."},
    config=config,
)
print(response1["output"])

response2 = agent_with_memory.invoke(
    {"input": "What is my name?"},
    config=config,
)
print(response2["output"])
  1. Verify memory is isolated per session.

If you switch session IDs, the new session should not know Priya’s name. That’s the production pattern you want when multiple users talk to the same backend at once.

other_config = {"configurable": {"session_id": "user-456"}}

response3 = agent_with_memory.invoke(
    {"input": "What is my name?"},
    config=other_config,
)
print(response3["output"])

Testing It

Run the script and watch the second response in user-123. It should refer back to Priya without being told again. Then check user-456; that session should behave like a fresh conversation.

If you want to confirm the history is actually stored, print out store["user-123"].messages after a few turns. You should see alternating human and AI messages in order.

Also test a tool call like: “What is 12 plus 8?” The agent should use add_numbers, then still remember earlier chat context on later turns.

Next Steps

  • Replace InMemoryChatMessageHistory with Redis or Postgres-backed storage for persistence across app restarts.
  • Add token-aware trimming so long conversations don’t blow up context windows.
  • Move from short-term chat memory to structured state for workflows like claims intake or policy underwriting.

Keep learning

By Cyprian Aarons, AI Consultant at Topiax.

Want the complete 8-step roadmap?

Grab the free AI Agent Starter Kit — architecture templates, compliance checklists, and a 7-email deep-dive course.

Get the Starter Kit

Related Guides