> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Implementing State Reducers

> Explains how LangGraph uses state reducers to control merging, accumulation, and cleanup of shared graph state.

State reducers in LangGraph are the gatekeepers for your shared graph state. They define exactly how the global state should change in response to node outputs, ensuring predictable, consistent updates across the graph.

Why it matters: without reducers, nodes can overwrite or duplicate data, resulting in an unreliable state and hard-to-debug behavior.

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/A72Yow2kiLd9Lv77/images/LangGraph/State-Management-and-Iterative-Loops/Implementing-State-Reducers/state-reducers-shared-state-nodes.jpg?fit=max&auto=format&n=A72Yow2kiLd9Lv77&q=85&s=a544227d1331df101494a31fdbb674c4" alt="The image illustrates the concept of using state reducers by showing a shared state connected to three nodes (A, B, and C) with issues like &#x22;Overwrite&#x22; and &#x22;Duplicate&#x22; indicated." width="1920" height="1080" data-path="images/LangGraph/State-Management-and-Iterative-Loops/Implementing-State-Reducers/state-reducers-shared-state-nodes.jpg" />
</Frame>

## How reducers introduce discipline

A reducer is a simple function that receives the current state and a node's output, then returns the updated state. This is the place to enforce rules like:

* Only add a field if it doesn't already exist.
* Append results to a list instead of replacing the list.
* Prune temporary or sensitive values before they persist.

Think of the reducer as an editor: it inspects node outputs and applies business rules before those outputs are committed.

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/A72Yow2kiLd9Lv77/images/LangGraph/State-Management-and-Iterative-Loops/Implementing-State-Reducers/state-reducer-function-explanation.jpg?fit=max&auto=format&n=A72Yow2kiLd9Lv77&q=85&s=6c11cab2715a224ecf1e6ed3ce503709" alt="The image explains a &#x22;State Reducer&#x22; function, highlighting its roles: adding a field only if it doesn't exist and adding to a list without overwriting." width="1920" height="1080" data-path="images/LangGraph/State-Management-and-Iterative-Loops/Implementing-State-Reducers/state-reducer-function-explanation.jpg" />
</Frame>

LangGraph uses the reducer after each node runs to decide what actually becomes part of the global state. This keeps node implementations simple—nodes return outputs, and reducers control how those outputs are merged into the graph.

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/A72Yow2kiLd9Lv77/images/LangGraph/State-Management-and-Iterative-Loops/Implementing-State-Reducers/state-reducer-diagram-langgraph-nodes.jpg?fit=max&auto=format&n=A72Yow2kiLd9Lv77&q=85&s=fd520c726008b0b297e2717f794e11e7" alt="The image explains &#x22;What is a State Reducer?&#x22; with a diagram showing nodes A, B, and C, each connected to a state. It illustrates how a &#x22;State Reducer&#x22; edits and commits state after each node in the LangGraph system." width="1920" height="1080" data-path="images/LangGraph/State-Management-and-Iterative-Loops/Implementing-State-Reducers/state-reducer-diagram-langgraph-nodes.jpg" />
</Frame>

## Field-level reducers (custom merging)

By default, LangGraph performs a shallow merge when a node returns a field. For many workflows—chat history, tool logs, or aggregated analytics—you want accumulation instead of replacement. Field-level reducers let you define exactly how a single key is merged.

Example: annotate a `messages` field with a reducer that appends new messages rather than replacing the list.

```python theme={null}
from typing_extensions import TypedDict, Annotated
from langgraph.graph.message import add_messages

class GraphState(TypedDict):
    messages: Annotated[list, add_messages]
```

Why use field-level reducers? They enable granular control: treat some keys as accumulators (history, logs) and others as unique values (intent, status).

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/A72Yow2kiLd9Lv77/images/LangGraph/State-Management-and-Iterative-Loops/Implementing-State-Reducers/state-merging-langgraph-intelligent-update.jpg?fit=max&auto=format&n=A72Yow2kiLd9Lv77&q=85&s=8bff87966fe10465c5a4b77b3e688fd7" alt="The image explains state merging in LangGraph, highlighting that data should be merged intelligently rather than overwritten. It describes actions based on node output, such as updating intent or appending messages." width="1920" height="1080" data-path="images/LangGraph/State-Management-and-Iterative-Loops/Implementing-State-Reducers/state-merging-langgraph-intelligent-update.jpg" />
</Frame>

## Example: custom merge for tool results

Below is a concrete reducer example that accumulates tool results instead of overwriting them, plus a sample node that returns the `tool_results` field.

```python theme={null}
from typing_extensions import TypedDict, Annotated

def merge_tool_results(old, new):
    # Accumulate results instead of overwriting
    return (old or []) + (new or [])

class GraphState(TypedDict):
    question: str
    tool_results: Annotated[list, merge_tool_results]

def search_web(state: GraphState) -> dict:
    # Example implementation: call a search tool and return its results for the
    # "tool_results" field. Replace tavily.search with your own tool invocation.
    results = tavily.search(query=state["question"], max_results=3)["results"]
    return {"tool_results": results}

# Create a graph builder that uses this state shape
builder = StateGraph(GraphState)
```

## Benefits and common reducer patterns

Reducers are plain functions—easy to write, test, and reuse. They help with:

* Accumulation (lists of messages, logs, search results)
* Idempotence (avoid duplicate entries)
* Cleanup (remove or redact temporary or sensitive fields)
* Centralized business logic (same reducer reused across graphs)

|      Pattern | Use case                                   | Example                                             |
| -----------: | ------------------------------------------ | --------------------------------------------------- |
|   Accumulate | Keep chat history or logs                  | `messages: Annotated[list, add_messages]`           |
|  Merge lists | Combine tool outputs over time             | `tool_results: Annotated[list, merge_tool_results]` |
| Prune/Redact | Remove diagnostics or transient fields     | Reducer that returns `None` or filters keys         |
|      Replace | Single authoritative value (intent/status) | Default merge or reducer that returns `new`         |

## Reuse and modularity

Because reducers are normal functions, you can import them across graphs to keep merging logic centralized. This enforces consistent state behavior across different flows and makes testing straightforward.

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/A72Yow2kiLd9Lv77/images/LangGraph/State-Management-and-Iterative-Loops/Implementing-State-Reducers/reusing-reducers-across-graphs-diagram.jpg?fit=max&auto=format&n=A72Yow2kiLd9Lv77&q=85&s=3808c9edef827de63e200501f096acea" alt="The image is about reusing reducers across graphs, highlighting that reducers are functions that can be imported and plugged into different flows and keep business logic centralized." width="1920" height="1080" data-path="images/LangGraph/State-Management-and-Iterative-Loops/Implementing-State-Reducers/reusing-reducers-across-graphs-diagram.jpg" />
</Frame>

This separation promotes modular design: the graph describes structure and control flow, while reducers encapsulate state semantics. Nodes stay focused on producing outputs; reducers define how those outputs become part of the canonical state.

<Callout icon="lightbulb" color="#1CB2FE">
  Use field-level reducers to centralize accumulation and cleanup logic (e.g., chat history, tool logs, diagnostic traces). This avoids ad-hoc state manipulation inside nodes and prevents accidental overwrites.
</Callout>

## Best practices

* Define reducers for any field that represents accumulated history or logs.
* Keep reducers small and focused so they are easy to unit test.
* Use reducers to strip or redact sensitive data before it becomes persistent.
* Reuse reducers across graphs to maintain consistent state behavior.

## Summary

State reducers are foundational for predictable state evolution in LangGraph. They let you implement intelligent merging, prevent accidental overwrites, and keep your nodes simple. Use field-level reducers to centralize accumulation, cleanup, and deduplication logic so your graph's shared state remains reliable and auditable.

## Links and references

* [LangGraph documentation](https://langgraph.example/docs)
* Python: `typing_extensions` documentation
* Pattern references: accumulation, idempotence, and cleanup techniques in stateful systems

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/langgraph/module/7a80b285-b366-4c4d-95d0-bce0c24aaf58/lesson/d4a0ce6a-78a6-41e5-8802-89f7b76e974c" />
</CardGroup>
