Skip to main content
Parallel execution allows multiple branches of your graph to run concurrently, improving performance and enabling complex workflows where independent tasks can be processed simultaneously.

Overview

GraphAI supports parallel execution in two main scenarios:
  1. Graph-level parallelism: When a node has multiple outgoing edges, all successor nodes execute concurrently
  2. Router-level parallelism: When a router returns multiple choices, all selected branches execute concurrently

Parallel Branches with Edges

When you add multiple edges from a single source node to different destination nodes, those destinations will execute in parallel.

Basic Example

In this example, branch_a and branch_b execute concurrently after start completes. Their outputs are merged into the final state.

Using add_parallel()

For convenience, you can use the add_parallel() method to create multiple edges at once:

Joining Parallel Branches

By default, when parallel branches converge to a common node, that node executes once for each incoming branch. To ensure the convergence node executes only once after all branches complete, use add_join().

Without Join (Multiple Executions)

With Join (Single Execution)

The add_join() method ensures that:
  • All specified branches must complete before the destination node executes
  • The destination node executes exactly once
  • State from all branches is merged before continuing

Nested Parallel Execution

You can create parallel branches at multiple levels in your graph:

Router Parallel Execution

Routers can also trigger parallel execution by returning multiple choices instead of a single choice.

Single Choice (Standard Behavior)

The standard router behavior selects one branch:

Multiple Choices (Parallel Execution)

Return choices (a list) instead of choice to execute multiple branches concurrently:

Full Example

Note: When a parallel router shares an edge with a node that is not included in the router’s choices array, that node will not be executed. Only nodes whose names appear in the returned choices list will run. In the example above, tool_c has an edge from the router but is not included in choices, so it does not execute.

Router with Join (Iterative Patterns)

Use add_join() to control where execution continues after parallel branches complete. This enables iterative workflows where a router can evaluate results and decide whether to run more parallel branches:
The join pattern with routers is useful for:
  • Iterative workflows that may need multiple rounds of parallel execution
  • Gathering results from parallel branches before deciding next steps
  • Implementing tool-calling agents that can invoke multiple tools simultaneously

State Merging

When parallel branches complete, their outputs are merged into the state:
  1. Output merging: Each branch’s return values are merged into the final state
  2. Conflict resolution: If branches return the same key, the last branch to complete wins

Best Practices

  1. Use add_join() for convergence: When multiple branches should synchronize before continuing, always use add_join() to prevent duplicate execution of downstream nodes.
  2. Keep parallel branches independent: Parallel branches execute concurrently with copied state. Avoid relying on one branch’s state changes being visible to another.
  3. Use add_join() for iterative patterns: When a router needs to make decisions after parallel execution, use add_join() to route back to the router node. This keeps flow control in the graph structure rather than in node return values.
  4. Name nodes explicitly for routers: When using router parallel execution, ensure destination nodes have explicit names that match the choices returned by the router.

Next Steps

  • Learn about Graphs for general graph construction
  • Explore State management for understanding how state flows through parallel branches
  • Check out Callbacks for monitoring parallel execution progress