Skip to main content
Parallel execution is the core reason to use a DAG instead of a linear chain. When you have independent subtasks — researching different angles, translating into multiple languages, scoring several candidates — dagraph runs them all at once in the same wave, then feeds their combined outputs to a downstream node only when every dependency has finished. This guide walks you through building fan-out/fan-in workflows, controlling concurrency, and scaling to dynamic lists with the map node.

How waves work

dagraph uses a topological sort (Kahn’s algorithm) to group your nodes into waves. Every node whose depends_on list is empty fires in wave 1. Once wave 1 is complete, any node whose dependencies are now all satisfied fires in wave 2, and so on. Nodes within the same wave run simultaneously. You can preview the wave plan without spending any tokens:
Output:

Fan-out/fan-in with depends_on

The research.yaml example spins up three independent agents in parallel, each researching a different angle of the same topic, then passes all three outputs to a single synthesizer.
Run it with:
Each node’s output is stored as an artifact and referenced by its id in downstream prompts — {{ research_a }}, {{ research_b }}, {{ research_c }}. You never pass raw text between nodes directly; dagraph resolves references from the artifact store.

Creating sequential dependencies

Add depends_on to any node to make it wait for one or more predecessors. Dependencies are additive — a node won’t start until every ID in its list has completed successfully.
You can mix sequential and parallel paths in the same DAG. Any node that doesn’t share a dependency chain with another node will run in parallel with it.

Capping concurrent LLM calls

By default dagraph allows up to 10 simultaneous in-flight LLM calls. Use --max-concurrent to lower that ceiling, for example to stay within provider rate limits or control costs during development:
Combine with --rpm when using the --backend api option to add a requests-per-minute cap:

Dynamic fan-out with the map node

When you don’t know your list of items at design time, use a map node to fan out over a runtime list. Each item in the list gets its own agent call, and the results are collected into a JSON array available to downstream nodes.
Pass the list as an input:
max_concurrency on a map node is independent of --max-concurrent on the CLI. The node-level cap is useful when you know one specific fan-out should stay narrow regardless of the global setting.

Visualizing your DAG

Render the full graph structure as a Mermaid diagram to verify your dependency layout before running:
This prints a Mermaid flowchart you can paste into any Mermaid renderer to see the wave groupings and edges at a glance.

Human approval gates

Pause a workflow mid-run for human review before continuing downstream nodes.

Evaluator loops

Automatically iterate on generated content until a separate evaluator approves it.