docs: describe map branches as per-item subgraph chains in graph.example.yaml

Comment-only rewrite of the map/branch and teammates comments: a branch is
the entry of a per-item chain; chain nodes may use next, state_updates,
output_schema, fallback and script _next inside the chain; output_key is
removed from the fork and must be written by the chain; max_concurrency
accepts an integer or a template; a teammate identity spans the item's
whole chain.
This commit is contained in:
Dark-Alex-17 committed 2026-09-11 10:56:27 -06:00
1 parent c10965cd71
commit d8f1778bc7
1 file changed
+61 -24
+61 -24
View File
@@ -343,7 +343,13 @@ nodes:
# super-step frontier form two separate teams and cannot # super-step frontier form two separate teams and cannot
# message each other. Peers only span a single map # message each other. Peers only span a single map
# node's branches or a single super-step's flagged # node's branches or a single super-step's flagged
# agent nodes. # agent nodes. Inside a map branch chain the identity
# belongs to the ITEM, not the node: it lives for the
# item's whole chain, is handed to each `teammates: true`
# agent step in that chain (unflagged steps never see it),
# and is retired when the chain ends. A message delivered
# after the chain's last flagged agent step is accepted
# but never read.
output_schema: # Optional. Same extraction as llm nodes output_schema: # Optional. Same extraction as llm nodes
type: object type: object
properties: properties:
@@ -357,9 +363,20 @@ nodes:
next: review # Required for agent nodes next: review # Required for agent nodes
# --- map node (Dynamic fan-out. Think: LangGraph's `Send` API) ---------------- # --- map node (Dynamic fan-out. Think: LangGraph's `Send` API) ----------------
# Spawns one parallel sub-branch per item in `over`. Each sub-branch runs # Spawns one parallel sub-branch per item in `over`. Each sub-branch runs a
# the node referenced by `branch:` with the item bound to `as:`. Outputs # per-item CHAIN of nodes on a private fork of the state: it starts at the
# collect into the array named by `collect_into:`, preserving input order. # node referenced by `branch:` (with the item bound to `as:`) and follows
# that node's `next:` / script `_next` / `fallback` edges until it reaches a
# node with no `next` and no `_next`. When every chain has finished, the
# value of `output_key` from each item's final fork state is collected into
# the array named by `collect_into:`, preserving input order. Everything
# else the chain wrote is fork-local scratch and is discarded at collect.
#
# Not supported inside a branch chain (validator errors): fan-out `next:`
# lists, another `map`, `end`, `approval`, `input`. A branch node must not
# also be reachable from `start` on the main flow. Per-item loops are script
# `_next` loops (bounded by settings.max_loop_iterations on the fork); a
# declared `next`/`fallback` edge back to an earlier chain node is a cycle.
# #
# Reach via `synthesize`'s `_next: subjects_map`. The producer is expected # Reach via `synthesize`'s `_next: subjects_map`. The producer is expected
# to have written a list at `subjects` (e.g. an upstream LLM node with an # to have written a list at `subjects` (e.g. an upstream LLM node with an
@@ -371,31 +388,51 @@ nodes:
# Empty list is allowed. It means no branches spawn, # Empty list is allowed. It means no branches spawn,
# and thus `collect_into` is written as []. # and thus `collect_into` is written as [].
as: subject # Required. Per-branch state key holding the as: subject # Required. Per-branch state key holding the
# current item. Read with {{subject}} inside # current item. Read with {{subject}} from any
# the branch node's prompt. # node in the branch chain.
branch: research_subject # Required. Node id to invoke per item. branch: research_subject # Required. ENTRY node of the per-item chain.
# Must point to an llm | agent | rag | script # Every node reachable from it via `next:` /
# node satisfying the map branch contract: # `fallback:` is part of the chain and must be
# - no `next:` (atomic, joined at map exit) # an llm | agent | rag | script node. Chain
# - no `state_updates:` other than via the # nodes may use `next:`, `state_updates:`
# map's `collect_into` channel # (fork-local scratch such as a draft or a
# - no `output_schema:` (top-level merge # retry counter), `output_schema:`, and
# would clash with collect_into) # `fallback:` (honored per item; it must point
# Validator enforces all three. # at a node inside the chain, never at an
# `end_*` node). A script's `_next` must also
# stay inside the chain; routing out of it
# fails the item.
collect_into: subject_findings # Required. State key for the array of collect_into: subject_findings # Required. State key for the array of
# per-branch outputs, in input order # per-branch outputs, in input order
# (not spawn-finish order). # (not spawn-finish order).
max_concurrency: 3 # Optional per-map cap. Defaults to max_concurrency: 3 # Optional cap on items in flight (one slot is
# settings.max_concurrency above. # held for an item's WHOLE chain). Defaults to
output_key: subject_summary # Optional. State key the branch's output # settings.max_concurrency above. Accepts an
# appears under. Default "output". Useful # integer or a "{{key}}" template that must
# only if the branch reads its own bound # resolve to a positive integer at run time,
# name back (rare). # e.g. `max_concurrency: "{{research_budget}}"`.
output_key: subject_summary # Optional. State key whose value in the item's
# FINAL fork state becomes the item's result.
# Default "output". The key is removed from the
# fork before the chain starts, so the chain
# must write it (via state_updates, an
# output_schema property, or a script's JSON);
# an item that never writes it is an error, and
# a chain that reads it before writing it sees
# it absent (prompts fail, state_updates render
# "", scripts get no key) - seed per-item input
# through `as:` instead. Prefer a named key: with
# the default, an llm/agent/rag step whose
# state_updates do not name `output` leaves
# `output: null` and null is what gets collected.
next: aggregate_subjects # Where to go after all sub-branches finish. next: aggregate_subjects # Where to go after all sub-branches finish.
# Branch node for subjects_map. Each invocation receives a different # Entry node of subjects_map's per-item chain. Each item gets its own copy
# `subject` in state. The branch is "atomic", meaning it cannot route on # of this node with a different `subject` in state. With no `next:` it is
# its own; the surrounding `map` joins after all invocations finish. # also the LAST chain node, so the chain is a single step; give it `next:`
# (or emit `_next` from a script step) to extend the chain, e.g.
# research -> verify -> gate-script that re-emits `_next: research_subject`
# until the draft passes or a retry counter in fork state runs out.
research_subject: research_subject:
id: research_subject id: research_subject
type: llm type: llm