Lesson 11: Multi-Agent Patterns: Graph Workflows
Code for this lesson can be found here.
The Limitation of “Agents as Tools”
Section titled “The Limitation of “Agents as Tools””The agent as a tool pattern works well when tasks are completely independent and you want the main agent to have the maximum amount of adaptability. However, it is not the best choice for every workload.
With that pattern, there is no way to express direct dependencies or ensure agents execute in a specific, predictable order.
Graphs solve this. You define the execution order of your agents explicitly. In this paradigm, each node of the graph is a full agent (which can have its own tools, MCP servers, skills, plugins, or whatever else they need), and you connect these agents through edges which express dependencies. The graph structure in Strands resolves what can run in parallel and what has to wait based on how you define it.
Building a Graph with Graph Builder
Section titled “Building a Graph with Graph Builder”Let’s build a graph to see how it works. Imagine we have four agents:
- A researcher
- An analyst
- A summarizer
- A report writer
We want the researcher to run first. When it finishes, we want the analyst and summarizer to branch off and run in parallel. Once both of those are finished, the report writer should combine everything into the final output.
To enforce that exact order, we use the GraphBuilder:
builder = GraphBuilder()
# Register each agent as a node in the graph (executor first, node id second)builder.add_node(researcher_agent, "researcher")builder.add_node(analyst_agent, "analyst")builder.add_node(summarizer_agent, "summarizer")builder.add_node(writer_agent, "writer")
# Connect them using edgesbuilder.add_edge("researcher", "analyst")builder.add_edge("researcher", "summarizer")builder.add_edge("analyst", "writer")builder.add_edge("summarizer", "writer")
# Compile into an executable workflowworkflow = builder.build()A downstream target node cannot execute until all of its upstream dependencies complete.
We defined our edges so the researcher runs first, the analyst and summarizer execute in
parallel, and the report writer waits for both of them before running. Calling .build()
validates the graph structure and returns an executable workflow.
You can execute the completed graph just like a function, passing in a task string and getting back a graph result.
Data Flow and State Management in Graphs
Section titled “Data Flow and State Management in Graphs”When executing a graph, data flows through the nodes systematically:
- Entry Points: Entry point nodes receive the original user task directly.
- Downstream Nodes: Downstream nodes receive the original task plus the outputs from their dependency nodes.
- Automatic Stitching: Each dependency result is labeled with its respective node ID and combined into the downstream prompt automatically.
In our example, the report writer receives the original task, the analyst’s output, and the summarizer’s output all stitched together into one structured input. You can design downstream prompts to expect and reason over these multiple labeled inputs.
Sometimes you need to share information across the graph without exposing it directly to the model’s prompt. That is where invocation state comes in. Invocation state is a shared dictionary passed into the graph at runtime that every node can access. This is useful for passing user IDs, feature flags, configurations, or metadata that components attached to each agent need, but the model itself doesn’t need to read.
Four Common Graph Patterns
Section titled “Four Common Graph Patterns”There are four common graph patterns you’ll see repeatedly in multi-agent systems:
- Sequential Pipeline: One agent runs after another in a strict sequence. This is the simplest graph pattern.
- Parallel Fan-Out with Aggregation: One node fans work out to multiple parallel agents, and an aggregator node waits for all of them to finish before combining the results.
- Conditional Branching: Agents can have conditions attached to them so that different branches execute depending on runtime decisions or outputs.
- Feedback Loops: The graph becomes cyclic. For example, a writer agent produces a draft, a reviewer agent evaluates it, and if revisions are needed, the workflow loops back to the writer before eventually continuing to the publisher.
For cyclic graphs, there are two important safety controls worth knowing about:
set_max_node_executions: Limits the total number of node runs to prevent infinite loops.reset_on_revisit: Clears a node’s conversation history each time it re-enters the cycle so that context doesn’t grow uncontrollably across multiple revisions.
Both of these are important for controlling reliability and cost in iterative or long-running workflows.
When to Use Graphs (and Their Trade-offs)
Section titled “When to Use Graphs (and Their Trade-offs)”The main trade-off of using graphs is that you have to predefine the structure up front.
If the optimal execution path depends heavily on what the agents discover dynamically during runtime, graphs can become too rigid. This is exactly why the next pattern exists: agent swarms. Instead of predefining the workflow structure, swarms allow the execution path to emerge dynamically as the agents collaborate and make decisions in real time. We will cover that in the next lesson.
Learn more: Graph Multi-Agent Pattern