Code Intermediate medium · 5 min

get_state(): reading current state

What you will learn
Use get_state() inside a node to read the complete current state without waiting for the graph to finish executing.

Why this matters

In a running graph, you often need to inspect or react to the current state mid-execution: whether to make a conditional decision, log state for debugging, or prepare data for the next node. get_state() lets you read state synchronously during node execution without graph callbacks.

Skip if: Don't use get_state() if you only need the final state after graph.invoke() completes: just use the return value. Also avoid it in nodes that don't need to inspect intermediate state; it's unnecessary overhead and makes logic harder to trace.

Explanation

What it is: get_state() is a method available on compiled langgraph graphs that returns the current state dictionary at the moment you call it. It gives you a snapshot of all state values without blocking execution.

How it works mechanically: When you call graph.get_state(config), where config contains a thread_id or other runtime identifier, langgraph queries its checkpoint store and returns the latest recorded state for that execution thread. This is synchronous and non-blocking: it doesn't wait for the graph to finish. The state it returns reflects what was persisted the last time any node updated state.

When to use it: Use get_state() when you need to inspect state from outside a running graph (e.g., in a separate monitoring thread), inspect state in your main code after a pause/resumption, or debug by checking what values were actually stored. Inside a node function, you already have state as a parameter: use that instead.

Analogy

It's like checking your bank balance mid-transaction. You can look up your current balance (get_state()) without waiting for the entire transaction to complete, but you're reading whatever was last recorded, not a live value being computed right now.

Code

python
import json
from typing import TypedDict
from langgraph.graph import StateGraph, START, END
from langgraph.checkpoint.memory import MemorySaver

class State(TypedDict):
    value: int
    name: str

def increment_node(state: State) -> State:
    return {"value": state["value"] + 1, "name": state["name"]}

def double_node(state: State) -> State:
    return {"value": state["value"] * 2, "name": state["name"]}

graph = StateGraph(State)
graph.add_node("increment", increment_node)
graph.add_node("double", double_node)
graph.add_edge(START, "increment")
graph.add_edge("increment", "double")
graph.add_edge("double", END)

compiled = graph.compile(checkpointer=MemorySaver())

initial_state = {"value": 5, "name": "test_run"}
config = {"configurable": {"thread_id": "thread_1"}}

result = compiled.invoke(initial_state, config=config)
print(f"Final result: {result}")

current_state = compiled.get_state(config)
print(f"Current state via get_state(): {current_state.values}")
print(f"State keys: {current_state.values.keys()}")
print(f"Value from get_state(): {current_state.values['value']}")
Output
Final result: {'value': 12, 'name': 'test_run'}
Current state via get_state(): {'value': 12, 'name': 'test_run'}
State keys: dict_keys(['value', 'name'])
Value from get_state(): 12

What just happened?

The code defined a two-node graph that increments then doubles a value. After invoking the graph with an initial value of 5, it called get_state() with the same thread config and retrieved the persisted state. The state object returned has a .values attribute containing the final state dictionary with value=12 (5 incremented to 6, then doubled to 12) and name='test_run'. This state matches what was returned by invoke() because both read from the same checkpoint store.

Common gotcha

get_state() returns a StateSnapshot object, not the state dict directly. You must access .values to get the actual state dictionary. Many developers try to do compiled.get_state(config)["key"] and get an AttributeError because StateSnapshot is not subscriptable: you need compiled.get_state(config).values["key"].

Error recovery

ValueError: config must have configurable with thread_id
You called get_state() with a config dict that's missing the configurable.thread_id key. Pass config={'configurable': {'thread_id': 'your_thread_id'}}: the same config you used to invoke.
AttributeError: 'dict' object has no attribute 'values'
You're calling get_state() without a checkpointer configured on your compiled graph. Always compile with checkpointer=MemorySaver() or another checkpoint implementation so get_state() has data to retrieve.
KeyError when accessing state values
The state key you're trying to access doesn't exist in the current state. Check the actual keys in current_state.values.keys(): the key may not have been set by any node yet.

Experienced dev note

get_state() is crucial for debugging long-running graphs or graphs with conditional branches. In production, you'll often need to inspect state to understand why a graph took a certain branch or got stuck. However, remember that get_state() is only as fresh as the last checkpoint: if a node hasn't completed and persisted its state yet, get_state() won't see it. For truly live state inspection during a node's execution, pass state as a function parameter and log it directly inside the node.

Check your understanding

Why would calling get_state() immediately after invoking a graph with a different thread_id (different config) return empty or old state, and how would you fix it?

Show answer hint

The answer requires understanding that get_state() queries the checkpoint store based on the thread_id in the config. If you invoke with thread_id='run_1' but call get_state() with thread_id='run_2', you're looking up a different execution thread. Fix: use the same config dict (with the same thread_id) for both invoke() and get_state().

VERSION get_state() and StateSnapshot were stabilized in langgraph 0.2.0. In earlier versions (0.1.x), state inspection patterns were less consistent. Ensure you're using langgraph >= 0.2.0.
NEXT

Next, explore how to pause and resume graph execution mid-stream using interrupt() and how get_state() pairs with it to inspect state across resumptions.

Community Notes

No notes yetBe the first to share a version-specific fix or tip.