Skip to content

Fan-out Node

The Fan-out node runs a sub-graph (its template) once per element of an input array. Each instance runs in its own scope with isolated state, and the fan-out finalizes once the configured number of instances has settled.

Use Fan-out when the number of work items is only known at runtime — e.g. “for each item returned by the previous step, run these three skills” — and you want the instances to progress independently. If the count is fixed at design time, straight-line edges are simpler.

FieldDescription
fan_out_sourceDot-path into the input data pointing at the array to iterate over. Example: .items, .data.results.
templateThe sub-graph executed per item. Edit it via the Edit Sub-graph → button in the property panel.
join_modeWhen the fan-out itself transitions to completed. One of all (default), any, majority.
on_failureWhat to do when some instances fail. fail_all (default) fails the fan-out, ignore continues with whatever succeeded, collect passes failures through for downstream inspection.
max_concurrency (optional)Cap on concurrent running instances.

Each template instance receives the following in its input data:

KeyMeaning
_itemThe array element for this instance.
_indexZero-based position in the source array.
_totalTotal number of items being expanded.

When the fan-out aggregates, the output carries:

KeyMeaning
_itemsOutputs from each template instance, ordered by _index.
_total / _completed / _failedCounts across instances.
  1. When cascade reaches the fan-out, it is inserted as running.
  2. The array at fan_out_source is resolved from the input data. If it is empty, the fan-out immediately finalizes with empty aggregation and cascade continues.
  3. Otherwise, for each item, the template’s entry nodes are inserted as pending in a fresh scope (…/<fan-out-id>[index]), carrying _item, _index, _total in their input data.
  4. As instances finish, the orchestrator checks completion against join_mode. Once met, the fan-out transitions to completed (or failed, per on_failure) with aggregated output, and cascade continues downstream from the fan-out’s own scope.
  • fan_out_source is required.
  • template sub-graph is required.
  • template must not contain start or end nodes — templates use In/Out markers connected via io-edges for entry/exit detection. Use skill, conditional, transform, etc. as roots and exits.
  • The template must have at least one enabled exit node.
  • Template In/Out markers must be connected via io-edges to the enabled roots/exits.
  • join_mode must be one of all, any, majority.
  • If the incoming edge declares a contract, fan_out_source must target an array-typed field of that contract. This catches the silent-0-items failure mode where upstream output doesn’t carry the expected list.
flowchart LR
Fetch["Skill: fetch-items"] --> FO[["Fan-out: .items"]]
subgraph Template
direction LR
Process["Skill: process-item"] --> Verify["Skill: verify-item"]
end
FO --> Process
Verify --> J(("Join"))
FO --> J

The fan-out re-enters once all template exit nodes across all instances have settled. Use a Join downstream when you need to aggregate results from multiple parallel branches of the outer graph; for simple per-item processing the fan-out’s own aggregation is usually enough.