Lesson 2.2 The Solution: Reducers

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: int means “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:

  1. The Type: This variable is a list.
  2. The Instruction (Reducer): “When a node returns a new value for this variable, DO NOT overwrite it. Instead, use operator.add to 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

Leave a Comment