Skip to content

Join Node

The Join node is a generic N-input barrier. It waits until its upstream nodes settle according to join_mode, bundles their outputs per aggregation, and optionally feeds the bundle into a skill before cascading downstream.

Unlike the name might suggest, Join is not paired to any specific Fan-out — it is a plain N-input merge point you can use anywhere you have multiple parallel branches converging.

  • Multiple independent branches of work need to finish before the next step (e.g. gather research from three sources, then write a summary).
  • You want to aggregate per-item outputs from a Fan-out — drop a Join after the fan-out and use aggregation: array or merge.
  • You need a weaker sync than “all branches succeed” — e.g. continue as soon as the first returns (join_mode: any) or when a majority is in.
FieldDescription
aggregationHow upstream outputs are bundled. array (default) wraps them as { _items, _sources, _total, _completed, _failed }; merge does a shallow key merge of object-typed outputs.
join_modeWhen the barrier releases. all (default), any, or majority.
on_failurefail_all (default) fails the join if any upstream failed; ignore continues with whatever succeeded; collect passes failures through.
skill_id / skill_version_id (optional)If set, the aggregated input is passed to this skill instead of auto-completing. Useful when you need an LLM to synthesize the branch outputs.
  1. Readiness is checked against join_mode:
    • all — every non-revision upstream must be in a terminal state.
    • any — at least one upstream is completed and approved.
    • majority — more than half of upstreams are completed and approved.
  2. Once ready, the Join bundles upstream outputs per aggregation into the input data, attaching _items (or merged keys), _sources, _total, _completed, _failed.
  3. If any upstream failed and on_failure === "fail_all", the Join is recorded as failed and cascade stops.
  4. Otherwise:
    • If a skill is configured, the Join is inserted as pending with the aggregated input, and runs on the assigned minion.
    • If no skill is configured, the Join auto-completes with the bundle as both input and output, and cascade continues.
  • join_mode, if set, must be one of all, any, majority.
  • aggregation, if set, must be one of array, merge, pick_first.
flowchart LR
A["Skill: research-a"] --> J(("Join"))
B["Skill: research-b"] --> J
C["Skill: research-c"] --> J
J --> Sum["Skill: summarize"]

With aggregation: array, summarize receives _items as a three-element list in the order of the incoming edges.