StateGraph: your first graph
A StateGraph is LangGraph's builder: you add nodes and edges to it, then compile it into a runnable app.
Last updated: 27 Sep, 2026 · LangGraph 1.2
In the last lesson you called a function yourself. With a StateGraph you hand the function to LangGraph and let it run it. To do that you first describe the program, then run the description.
The StateGraph API
from langgraph.graph import StateGraph, START, END
builder = StateGraph(State) # describe a program whose state has the shape State
builder.add_node("name", fn) # register a function under a name
builder.add_edge(START, "name") # say which node runs first
graph = builder.compile() # turn the description into a runnable app
graph.invoke(initial_state) # run itThe state
First describe the shape of the state. This graph carries one key, greeting, a string.
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START
class State(TypedDict):
greeting: str # the one key this graph's state holdsThe greet node
Write the one node. It takes the state and returns the key it wants to change.
def greet(state):
return {"greeting": "Hello!"} # change only the greeting keyBuilding the graph
Now describe the program: make a builder for this state shape, register the node under a name, and say the run starts at it.
builder = StateGraph(State) # a builder for state shaped like State
builder.add_node("greet", greet) # register greet under the name "greet"
builder.add_edge(START, "greet") # the run begins at greet
graph = builder.compile() # turn the description into a runnable graphRunning the graph
Run it with a starting state. invoke hands that dictionary in and returns the final state.
print(graph.invoke({"greeting": ""})) # start with an empty greeting, run the graphA one-node graph end to end
The same pieces in one file, ready to run.
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START
class State(TypedDict):
greeting: str
def greet(state):
return {"greeting": "Hello!"}
builder = StateGraph(State)
builder.add_node("greet", greet)
builder.add_edge(START, "greet")
graph = builder.compile()
print(graph.invoke({"greeting": ""}))What the run produced
The same answer as calling greet by hand, but this time LangGraph ran it. You described the program with four lines, compiled it, and invoked it with a starting state.
The five lines, one at a time
| Line | What it does |
|---|---|
StateGraph(State) | Start describing a program whose dictionary has the shape State. |
add_node("greet", greet) | Register the function greet under the name greet. |
add_edge(START, "greet") | Say the run begins at greet. |
compile() | Turn the description into a runnable graph. |
invoke({...}) | Run it with a starting state and get the final state back. |
A node is a step: a function with a name. An edge is a connection between steps. A graph is the whole description once compiled. The pattern never changes: describe, compile, run.
StateGraph vs calling functions yourself
| Plain Python | StateGraph | |
|---|---|---|
| Who runs the function | You call it | LangGraph runs it |
| Order of steps | The order you write the calls | The edges you add |
| Loops and branches | You write loops and if-statements | Edges can branch and point backwards |
| State between steps | You pass variables around | One state dictionary is carried for you |
When to build a StateGraph
- Every LangGraph program starts by building a StateGraph.
- Reach for it the moment a task has more than one step or a decision.
compile() leaves you with a builder, not a graph, and invoke will not exist on it. A node with no outgoing edge quietly ends the run.Related
- Add a second node
shoutthat returns{"greeting": "HELLO!"}and an edge fromgreetto it. Whose greeting comes back? - Remove the
compile()line and callinvokeon the builder. Read the error. - Swap the order of the two
add_nodelines. Does the output change?
Slow is fine. Stopping is the only problem.