Create a sequence of steps
Prerequisites
This guide assumes familiarity with Define and update state.
add_sequence shorthand for the same pattern.
Add a sequence of nodes with add_node and add_edge on a StateGraph:
.add_sequence:
Why split application steps into a sequence with LangGraph?
Why split application steps into a sequence with LangGraph?
LangGraph can add a persistence layer under the graph. State is checkpointed between nodes, so those nodes govern:
- How state updates are checkpointed
- How interruptions resume in human-in-the-loop workflows
- How to rewind and branch executions with time travel
- Populate a value in a key of the state
- Update the same value
- Populate a different value
Each node update can name only the keys it changes.By default, that overwrites the previous value for those keys. Use reducers when updates should append or combine instead. See Process state updates with reducers.
add_node and add_edge to populate the graph and define its control flow.
add_edgetakes node names. For bare functions, the default name isnode.__name__.- The graph needs an entry point: add an edge from the START node.
- The graph halts when there are no more nodes to execute.
- This invoke passes a value for one state key. Nodes can also write keys that were not in the input.
- The first node overwrites the value that was passed in.
- The second node updates that value.
- The third node populates a different key.
Create branches
Parallel node execution speeds up graph runs. LangGraph fans out and fans in with standard edges and conditional_edges. The following examples build branching dataflows. For map-reduce fan-out to dynamic targets, see Use Send and Command.Run graph nodes in parallel
This example fans out fromNode A to B and C, then fans in to D. The state uses a reducer so values accumulate for that key instead of overwriting. For lists, that means concatenating the new list onto the existing list. See Process state updates with reducers.
In the above example, nodes
"b" and "c" are executed concurrently in the same superstep. Because they are in the same step, node "d" executes after both "b" and "c" are finished.Importantly, updates from a parallel superstep may not be ordered consistently. If you need a consistent, predetermined ordering of updates from a parallel superstep, you should write the outputs to a separate field in the state together with a value with which to order them.Exception handling
Exception handling
LangGraph runs nodes in supersteps. Parallel branches in a superstep run concurrently, but the superstep is transactional: if any branch raises, none of that superstep’s updates apply to state.With a checkpointer, results from successful nodes in a completed superstep are saved and do not repeat when the run resumes.For flaky work such as unreliable API calls, use either:
- Ordinary
try/except(or equivalent) inside the node. - A
RetryPolicyon the node so LangGraph retries selected exceptions. Only failing branches retry, so successful siblings are not re-run.
Defer node execution
Deferring node execution delays a node until all other pending tasks are completed. This matters when branches have different lengths, which is common in map-reduce workflows. The parallel example above fans out and fans in when each path is one step. Add a node"b_2" on the "b" branch so the paths have unequal length. Node d uses defer so it waits for the longer branch:
"b" and "c" run concurrently in the same superstep. defer=True on node d keeps it from running until all pending tasks finish, so "d" waits for the full "b" branch.
When every branch always runs, you can wait with a list-form edge instead of defer=True. add_edge also accepts a list of start nodes. This is not shorthand for separate add_edge calls; the two forms behave differently:
- A list of start nodes runs
donce, after all of the listed nodes have completed. If one of them never runs (for example, a conditional edge does not select its branch),dnever runs and no error is raised. State updates from branches that did complete remain in the graph state, butddoes not consume them. - Separate edges run
donce per superstep in which any incoming branch completes. With branches of equal length, that is a single run; with branches of different lengths,druns more than once. - Separate edges with
defer=True(the pattern in the example above) rundonce, after every selected branch has completed, whether the fan-out selected all of the branches or only some of them.
defer=True postpones the node until no tasks are pending anywhere in the graph, not only in the branches that feed it. A Send addressed to the node still invokes it separately.
Conditional branching
Route to different nodes at runtime from state. Nodea updates state, then a conditional edge chooses b or c:
Dashed edges are conditional routes.
If your fan-out should vary at runtime based on the state, you can use add_conditional_edges to select one or more paths using the graph state. See the following example, where node a generates a state update that determines the next node.
Create and control loops
A loop needs a way to stop. The usual pattern is a conditional edge that routes to END when a termination condition is met. You can also set a recursion limit when invoking or streaming. The limit is the number of super-steps allowed before LangGraph raises an error. See the recursion limit concept. The following examples use a simple looping graph. Nodea either continues to b (which returns to a) or exits:
Dashed edges are conditional routes.
Add a conditional edge that encodes the termination condition:
"recursion_limit" in the config. This will raise a GraphRecursionError, which you can catch and handle:
"a" is a tool-calling model, and node "b" represents the tools.
The route conditional edge ends the run after the "aggregate" list passes a threshold length.
When you invoke the graph, it alternates between nodes "a" and "b" until that condition is met.
Impose a recursion limit
When a termination condition is not guaranteed, set the graph’s recursion limit. LangGraph raisesGraphRecursionError after that many supersteps. Catch and handle the exception:
Extended example: loops with branches
Extended example: loops with branches
A more complex loop fans out one step into two nodes:Dashed edges are conditional routes from This graph is a loop of supersteps: Node A, then B, then C and D concurrent, then back to A. The list-form edge waits for both With the recursion limit set to four, only one lap completes because each lap is four supersteps:
a."c" and "d" before returning to "a". For how list-form edges differ from separate edges into the same node, see Defer node execution.Invoking without a recursion limit completes two full laps before the termination condition:Access and handle the recursion counter
Nodes can read the current step from run metadata. Use that to react before the limit is hit.Handle recursion with RemainingSteps
RemainingSteps is a Python-only managed value for how many steps remain before the recursion limit. Use it to route to a completion path before LangGraph raises GraphRecursionError:
RemainingSteps, or catch GraphRecursionError outside the graph:
Related metadata keys include
langgraph_node, langgraph_triggers, langgraph_path, and langgraph_checkpoint_ns.
Async
Async helps when IO-bound work can run concurrently. To convert a sync graph to async:- Define nodes with
async definstead ofdef. - Use
awaitfor async calls inside those nodes. - Invoke with
.ainvokeor.astream.
See also
Connect these docs to your agent of choice via MCP for real-time answers.

