Table of Contents
To fix the overwrite issue in lesson 1, we need to tell LangGraph: “When you receive new data for ‘topics’, do not replace the old data. Add it to the old data.”
We do this using a Reducer. In Python, the operator.add function adds two lists together (['a'] + ['b'] = ['a', 'b']). We can attach this function to our State definition using Annotated.
The Fixed Code
import operator
from typing import TypedDict, Annotated
from langgraph.graph import StateGraph, END
# --- 1. The "Smart" State ---
class SmartState(TypedDict):
# SYNTAX: Annotated[Type, Reducer_Function]
# This tells LangGraph: "Whenever a node returns 'topics',
# execute: old_list + new_list"
topics: Annotated[list[str], operator.add]
# --- 2. The Nodes (Exactly the same as before!) ---
def node_a(state):
return {"topics": ["AI"]}
def node_b(state):
return {"topics": ["Crypto"]}
# --- 3. Build Graph ---
builder = StateGraph(SmartState)
builder.add_node("A", node_a)
builder.add_node("B", node_b)
builder.set_entry_point("A")
builder.add_edge("A", "B")
builder.add_edge("B", END)
app = builder.compile()
# --- 4. Run ---
result = app.invoke({"topics": []})
print(f"Final Topics: {result['topics']}")What is the Annotated type?
In standard Python, Annotated is just a way to attach metadata (extra notes) to a type hint. It doesn’t do anything by itself. It’s like sticking a Post-it note on a folder label.
- Standard Python:
x: intmeans “x is an integer.” - Annotated Python:
x: Annotated[int, "must be positive"]means “x is an integer, and by the way, here is a note saying it must be positive.”
How LangGraph Uses It
LangGraph reads that “Post-it note” and treats it as an instruction manual for how to update that variable.
When you write:
messages: Annotated[list, operator.add]
You are telling LangGraph:
- The Type: This variable is a
list. - The Instruction (Reducer): “When a node returns a new value for this variable, DO NOT overwrite it. Instead, use
operator.addto combine the old value and the new value.”
The Result
Final Topics: ['AI', 'Crypto']
Why is this Critical? (The Chatbot Use Case)
This mechanism is the backbone of almost every AI Agent. Agents are essentially loops that generate a stream of messages.
Without operator.add, your agent would only remember the last sentence spoken. With it, the State accumulates the entire conversation history automatically.
Real-World Example: Chat State
This is the standard boilerplate you will use for 99% of your LangGraph agents:
from langchain_core.messages import BaseMessage
class AgentState(TypedDict):
# Holds the full conversation history
messages: Annotated[list[BaseMessage], operator.add]
# These are singular values (we WANT them to be overwritten)
current_step: str
user_name: str
I build softwares that solve problems. I also love writing/documenting things I learn/want to learn.