1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
38 small wins to finish your pathNext lesson →
Nodes: what a node sees and returns
A node is a function LangGraph runs: it is handed the whole state dictionary and returns only the keys it wants to change.
Last updated: 27 Sep, 2026 · LangGraph 1.2
Print the state from inside a node and there is no mystery left about what a node knows and what it gives back.
The state
Describe a state with two keys: the ticket that comes in and the category a node will fill.
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START
class State(TypedDict):
ticket: str # comes in
category: str # a node fills thisThe categorise node
Write one node. It prints the whole state it was handed, then returns only the key it changes.
def categorise(state):
print("the node sees:", state) # show the dict as it arrived
return {"category": "billing"} # return only the key we changeBuilding the graph
Build the graph with that one node and start the run at it.
builder = StateGraph(State)
builder.add_node("categorise", categorise)
builder.add_edge(START, "categorise")
graph = builder.compile()Running the graph
Run it with a ticket and an empty category, and print what comes back.
print("we get back:", graph.invoke({"ticket": "charged twice", "category": ""}))One node filling a key
The same pieces in one file, ready to run.
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START
class State(TypedDict):
ticket: str
category: str
def categorise(state):
print("the node sees:", state)
return {"category": "billing"}
builder = StateGraph(State)
builder.add_node("categorise", categorise)
builder.add_edge(START, "categorise")
graph = builder.compile()
print("we get back:", graph.invoke({"ticket": "charged twice", "category": ""}))What the two prints showed
- The first line printed inside the node shows the dictionary as it arrived: the ticket you passed in and an empty category.
- The second line is what came back: the ticket untouched, the category filled in.
- The node returned one key and you got a two-key dictionary back. LangGraph merged what you returned into what was already there. That merge is the only thing it did.
What a node returns
| A node returns | LangGraph does |
|---|---|
A dict of changed keys, e.g. {"category": "billing"} | Merges those keys into the state |
An empty dict {} | Changes nothing; the state passes through |
A bare value, e.g. "billing" | Error: a node must return a dict or nothing |
Nothing, after state["category"] = ... | Nothing changes; an in-place edit is not an update |
Where the return rule applies
- Every step of every graph is a node, so this return-a-dict rule is the one you use most.
- Nodes that classify, look something up, or call a model all follow it.
Watch out. The most common first bug: a node computes the right answer, forgets to
return it, and the next node sees an empty string. Print the state when something is missing and you find it in seconds.Related
- Previous: StateGraph: your first graph
- Next: add_edge: two steps in a row
Try it yourself
- Add a key
priorityto the state and set it inside the node. Does it appear in the output? - Return
{}from the node. What does the final state look like? - Set
state["category"] = "billing"instead of returning it. What does the next print show, and why?
This is what real progress feels like.