LangChain LangGraph
Module 1 Module 2 Module 3
Module 1 · Basic abilities
1 1.1a Foundation Model
2 1.1b Prompting
3 1.2a Tools
4 1.2b Web Search
5 1.3 Memory
6 1.4 Multimodal
7 1.5 Personal Chef
SUM Module Summary
HomeLangChainModule 1 · Basic abilities1.3 Memory
📓 Notebook 📖 Explained
LANGCHAIN MODULE 1 · LESSON 1.3

Agent memory
InMemorySaver · thread_id · Cross-call persistence

An Agent without memory starts every conversation from scratch. passInMemorySaver + thread_id, allowing the Agent to remember the conversation history of each user.

1Memoryless Agent: every invoke is a new conversation

By default,create_agentCreated Agentno memory. every timeagent.invoke()They are all completely independent: the Agent does not know what was said before, nor does it know the user's name.

agent = create_agent(deepseek_model())

# 第一次对话:告诉 Agent 我的名字和爱好
response1 = agent.invoke({
    "messages": [HumanMessage(content="Hello my name is Seán and my favourite colour is green")]
})
print(response1['messages'][-1].content)

# 第二次对话(独立的 invoke):问 Agent 我的爱好
response2 = agent.invoke({
    "messages": [HumanMessage(content="What's my favourite colour?")]
})
print(response2['messages'][-1].content)
Execution output (no memory)
First time: Hello Seán! Green is a wonderful colour...

Second time:I don't have information about your favourite colour. Could you please tell me?

The second time it was called, the agent had no memory of the first conversation—it didn’t know the user’s name was Seán or that he loved the color green. every timeinvokeIt's all a new, context-free conversation.

2With memory vs without memory: intuitive comparison

No memory Agent (default)

User: My name is Seán, I love green the most
AI: Hello Seán! Green looks good...
— next call —
User: What is my favorite color?
AI: I don't know your favorite color...
✗ Unable to remember user information across calls

There is a memory Agent (InMemorySaver)

User: My name is Seán, I love green the most
AI: Hello Seán! Green looks good...
— Next call (same as thread_id) —
User: What is my favorite color?
AI: Your favorite color is green! 😊
✓ Complete memory of conversation history

3checkpointer: LangGraph’s state persistence mechanism

LangGraph’s memory mechanism is calledcheckpointer. How it works is simple:

checkpointer is not a "memory model"

checkpointer does not let LLM itself remember anything - LLM is stateless on every call. What checkpointer does is: convert historical messagesas contextPass it to LLM together so that LLM can "see" what was said before. Essentially, the historical message is put into the context window of this call.

checkpointer typestorage locationApplicable scenarios
InMemorySaver Python process memory Development/testing, disappears after process restart
SqliteSaver SQLite file Local persistence, stand-alone production environment
PostgresSaver PostgreSQL database Multi-instance, high-concurrency production environment
LangGraph Cloud Hosted cloud storage Fully managed cloud deployment

4InMemorySaver: the simplest memory storage solution

existcreate_agentIncomingcheckpointer=InMemorySaver(), you can enable the memory function for Agent:

from langgraph.checkpoint.memory import InMemorySaver
from langchain.agents import create_agent

agent = create_agent(
    deepseek_model(),
    checkpointer=InMemorySaver(),   # 开启内存记忆
)

It’s not enough to have a checkpointer—it also needs to passconfigParameters passed inthread_id, telling the Agent which "thread" this conversation belongs to (that is, which user).

5thread_id: distinguish the conversation context of different users

thread_idIs the unique identifier of the conversation. same onethread_idmany timesinvokeShared message history; differentthread_idThe conversations are completely isolated and do not interfere with each other.

# config 字典:指定这次 invoke 属于哪个线程
config = {"configurable": {"thread_id": "1"}}

# 第一次调用:告知名字和爱好
response1 = agent.invoke(
    {"messages": [HumanMessage(content="Hello my name is Seán and my favourite colour is green")]},
    config   # 传入 config
)

# 第二次调用:同一个 config(同一个 thread_id)
response2 = agent.invoke(
    {"messages": [HumanMessage(content="What's my favourite colour?")]},
    config   # 同一个 config = 同一个对话历史
)

print(response2['messages'][-1].content)
Execution output (with memory)
Based on what you told me earlier, your favourite colour is **green**! 😊
thread_id naming

In practical applications,thread_idusuallyUser ID or session ID,For example"user_12345"or"session_abc123". In this way, different users have independent conversation histories without interfering with each other. Multiple conversations with the same user (same session) use the samethread_id, you can continue to remember the context.

6Complete multi-turn dialogue demonstration

Here is the complete two-turn conversation code, showing how memory works in an actual multi-turn conversation:

from langgraph.checkpoint.memory import InMemorySaver
from langchain.agents import create_agent
from pprint import pprint

# 创建有记忆的 Agent
agent = create_agent(
    deepseek_model(),
    checkpointer=InMemorySaver()
)

config = {"configurable": {"thread_id": "1"}}

# 轮次 1:建立上下文
response1 = agent.invoke(
    {"messages": [{"role": "user", "content": "Hello my name is Seán and my favourite colour is green"}]},
    config
)

# 轮次 2:利用上下文
response2 = agent.invoke(
    {"messages": [{"role": "user", "content": "What's my favourite colour?"}]},
    config
)

# 查看第二次 invoke 的完整消息历史
for msg in response2["messages"]:
    pprint(msg.content)
    print()
Complete message history (4 messages, spanning two invokes)
'Hello my name is Seán and my favourite colour is green'

"Hello Seán! It's nice to meet you. Green is a wonderful favourite colour—it's associated with nature, growth, and harmony..."

"What's my favourite colour?"

'Based on what you told me earlier, your favourite colour is **green**! 😊'

Note that the message history includesAll messages from two invokes(4 items in total). On the second call, the Agent saw the color green mentioned by Seán in the first conversation, so it answered correctly.

Only send new messages each time, do not repeat the history

When using an Agent with memory, each timeinvokeJust need to sendNew news for the current round, no need to manually splice historical messages. checkpointer will automatically load the history. If you manually transfer historical messages, the messages will appear twice, causing abnormal behavior.

7Limitations of memory and production environment solutions

Limitations of InMemorySaver

Comparison of production environment memory solutions

StrategyprincipleApplicable scenarios
InMemorySaver Full message history stored in memory Development testing, Demo
SqliteSaver / PostgresSaver Full message history database Persistence requirements, small and medium-sized applications
Message summary Regularly compress historical messages into summaries to save context space Long-term dialogue, context-limited models
sliding window Only keep the latest N messages Scenarios that require only short-term context
vector database memory Embedding historical conversations into a vector library and retrieving related history Ultra-long-term dialogue, intelligent memory retrieval
Lesson 1.3 Core Points
InMemorySaver
  • checkpointer=InMemorySaver()
  • • Process memory, disappears after restart
  • • Quickest way to get started with development and testing
thread_id
  • config = {"configurable": {"thread_id": "1"}}
  • • Same as thread_id = shared conversation history
  • • Actual user ID or session ID