🎯 By the end of this module, you will:
Building a Chatbot Agent in LangGraph
Most tutorials show stateless single-shot agents. Real chatbots need 4 layers: a checkpointer to persist state, a thread_id to isolate users, an add_messages reducer to accumulate history, and a production backend that survives server restarts.
# Layer 1: Checkpointer — the state persistence engine
from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import StateGraph, MessagesState, START
model = ChatOpenAI(model="gpt-4o-mini", temperature=0)
def chatbot_node(state: MessagesState):
return {"messages": [model.invoke(state["messages"])]}
builder = StateGraph(MessagesState)
builder.add_node("chatbot", chatbot_node)
builder.add_edge(START, "chatbot")
# MemorySaver = in-memory (dev/testing only)
# Use PostgresSaver or RedisSaver in production!
memory = MemorySaver()
app = builder.compile(checkpointer=memory)🧠 Mental Model: Stateless vs. Stateful Chatbot
Like talking to someone with severe anterograde amnesia — every message is a fresh start. You say "My name is Alice" and on the very next turn they say "Nice to meet you, I don't know your name."
Like a trusted personal assistant who takes notes during every conversation. They remember your name, preferences, and prior decisions across multiple sessions — even after the server restarts.
🔬 LangGraph Chatbot Studio
LangGraph Chatbot State StudioMemorySaver & Threads
Experience multi-turn conversation persistence powered by LangGraph state checkpointers and thread IDs
from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import StateGraph
# 1. In-memory checkpointer for multi-turn sessions
memory = MemorySaver()
# 2. Compile graph with checkpointer
app = workflow.compile(checkpointer=memory)
# 3. Thread configuration isolates each user's history
config = {"configurable": {"thread_id": "thread_user_101"}}
# Multi-turn stateful invocation
app.invoke({"messages": [("user", "Where is my order?")]}, config)thread_id allows thousands of concurrent users to have completely isolated, persistent state snapshots without colliding.Stateful Chatbot Traps
If your state field is just messages: list without the Annotated[list, add_messages] reducer, each node update REPLACES the entire list. Turn 2 erases Turn 1. Always use the add_messages reducer for conversational state.
Without a trim strategy, a chatbot's message list grows indefinitely. After 100 turns, you're sending 50,000+ tokens on every request — hitting context limits and spending $0.30+ per user message. Implement token-aware trimming from day one.
Key Takeaways
- 1.Checkpointer + thread_id = Memory: These two components together are all you need for a stateful multi-turn chatbot. Checkpointer stores state; thread_id routes each user to their own namespace.
- 2.add_messages Reducer is Critical: Without Annotated[list, add_messages] on your messages field, node updates silently erase conversation history. This is the #1 mistake beginners make with LangGraph chatbots.
- 3.MemorySaver → PostgresSaver Before Launch: MemorySaver is fine for local development and testing. The moment you deploy to more than one server, switch to a shared persistence backend or users will randomly lose their conversation history.
Implementing Streaming Output for Real-Time Responses
Stream tokens as they're generated to slash perceived latency — delivering the ChatGPT-like typing experience your users expect.