Orchestration nodes: subgraph, loop, map¶
These three nodes compose other saved agents into a larger one: subgraph runs another agent once, loop runs one repeatedly, and map runs one across every item in a list. They are how you build agents out of smaller, reusable agents instead of one giant graph.
All three are durable-only — they run only on the durable runtime. The reason is practical: each of them drives one or more child runs, which can take real time, and the durable runtime journals every completed step so a crash resumes from where it left off instead of restarting the whole thing. A bounded loop halfway through its iterations, or a fan-out with some branches still running, must survive a restart without redoing finished work. See Durable runs for the full picture, and Agents and graphs for what "a saved agent" means.
How you pin the child agent
Every one of these nodes runs a saved agent version, pinned so composition is immutable. In the inspector you pick the child agent and then a body version (newest first). Pinning by content hash instead of version is available through the node's Code view. You must pin exactly one of version or contentHash — the editor flags it as an error otherwise. Publishing a new version of the child later does not change what a pinned node runs.
subgraph — run another agent once¶
Runs a saved agent as a single step and returns its output. A boundary node.
Ports¶
| Port | Direction | Required | Description |
|---|---|---|---|
in |
in | yes | The input passed to the child agent. |
out |
out | — | The child agent's output. |
err |
out | — | Carries the failure if the child run fails (error-typed handle). |
Configuration¶
| Field | Type | Default | Description |
|---|---|---|---|
agent |
string | — (required) | The saved agent id to run. |
version |
string | null |
The child version to pin. Pin exactly one of version / contentHash. |
contentHash |
string | null |
Pin the child by content hash instead (set via the Code view). |
maxDepth |
integer | 8 |
Maximum nesting depth. A subgraph that nests deeper than this fails honestly rather than recursing without bound. |
Behavior¶
- The child agent runs to completion; its output flows out
out. - If the child run fails, the failure is bound to
err— wireerrto anoutput(or a recovery branch) to handle it instead of failing the parent. - The pin is folded into the parent's own content — composing a child version is itself immutable. Exceeding
maxDepth(for example, a subgraph that transitively includes itself) is a clean failure, not a hang.
loop — run an agent repeatedly¶
Runs a saved agent in sequence, feeding each iteration's output into the next, up to a bounded number of iterations. An orchestration node.
Ports¶
| Port | Direction | Required | Description |
|---|---|---|---|
in |
in | yes | The input to the first iteration. |
out |
out | — | The final iteration's output. |
Configuration¶
| Field | Type | Default | Description |
|---|---|---|---|
agent |
string | — (required) | The saved agent to run each iteration. |
maxIterations |
integer | — (required, ≥ 1) | The hard cap on iterations. There are no unbounded loops; the default of 0 is invalid and must be raised to at least 1. |
condition |
string | null |
An optional $in reference over the iteration's output; the loop stops early when it resolves truthy. |
version / contentHash |
string | null |
Pin exactly one. |
maxDepth |
integer | 8 |
Maximum nesting depth. |
Behavior¶
- Each iteration's output becomes the next iteration's input.
- The loop stops at whichever comes first:
maxIterationsreached, orconditionresolving truthy on an iteration's output. The last output flows outout. - Completed iterations are journaled — on a crash-resume they are never re-run.
condition uses the same input-reference grammar as everywhere else. For example, $in.done stops the loop as soon as an iteration returns an object with a truthy done field.
map — fan out across a list¶
Runs a saved agent once per element of a list — the fan-out primitive. An orchestration node.
Ports¶
| Port | Direction | Required | Description |
|---|---|---|---|
in |
in | yes | Must be a list. One child run is started per element. |
out |
out | — | The collected results (one per element). |
Configuration¶
| Field | Type | Default | Description |
|---|---|---|---|
agent |
string | — (required) | The saved agent to run for each element. |
concurrency |
integer | null |
Maximum child runs in flight at once. null means unbounded. |
onError |
enum fail_fast | collect |
fail_fast |
fail_fast stops on the first failing element; collect gathers successes alongside per-element errors. |
version / contentHash |
string | null |
Pin exactly one. |
maxDepth |
integer | 8 |
Maximum nesting depth. |
Behavior¶
- The input must be a list; each element becomes the input to one child run.
concurrencybounds how many run at the same time; leave itnullto let them all run at once.- With
onError: "fail_fast"the map fails as soon as any element fails. WithonError: "collect"it finishes and returns every success plus a per-element error for the ones that failed. - On a crash, only the incomplete branches resume — finished elements are not re-run.
Example: summarize each document in a batch¶
A parent agent takes a list of documents and maps a saved summarize-one agent over them.
graph LR
input --> map[map · summarize-one]
map --> output
The map node's configuration:
{
"type": "map",
"kind": "orchestration",
"config": {
"agent": "summarize-one",
"version": "1.2.0",
"concurrency": 4,
"onError": "collect"
}
}
Give this agent a list as input (a multi-input agent drills in with $in.in.<field> — see input references); it runs up to four summaries at a time and collects the results, recording per-element errors instead of failing the whole batch.
Running an agent that uses these nodes¶
Because all three are durable-only, run them the durable way:
- From the interface: save the agent, then use Run durably on the Agents page (a single Run durably button appears for any agent containing a durable-only node). This needs the control plane started with
THEYGENT_DURABLE=1. - Unattended: deploy the agent behind a schedule or webhook trigger — in durable mode, triggered runs are durable automatically.
Works well with¶
- Saving agents — the child agents these nodes compose must be saved and versioned first.
- Versioning — why pinning a child by version or content hash keeps composition immutable.
- Durable runs — the runtime these nodes require, and how to enable it.
- Human node — the fourth durable-only node, for pausing on human input.