Anatomy of a workflow
A workflow is a graph you can read at a glance: boxes that each do one thing, wires that connect them. This page names the parts — at exactly the depth that changes what you do on the canvas. If you haven't built one yet, start with Build your first workflow and come back.
Execution order comes from the Exec spine. Everything else on this page hangs off that fact.
The graph
Every node is one step: read a file, call a model, pause for your approval, write a result. Each node carries two execution pins, in and out. Chain out to in and you get the Exec spine — the thread a run follows from first node to last. When you wonder "what runs next?", follow the spine, not the layout.
The palette offers 138 node types across 17 categories — see The node palette for the full index. Control constructs — gates, branches, loops, fan-out — are structural tiles with a page of their own: Control flow.
Pins carry typed data
Around the execution pins, nodes carry data pins. Every pin has a kind, and wires only connect compatible kinds — the editor won't let you plug a String into a Bool.
Six kinds are in use:
| Kind | What it carries |
|---|---|
Exec | Nothing — execution order only. |
Context | The mission's working context, consumed by the generative nodes. |
String | Plain text. |
Bool | True or false. |
Json | Structured data — the workhorse. |
Artifact | A produced bundle (a coder's output, a compiled report), passed by reference. |
One convention worth knowing: 125 of the 138 node types expose a result output pin of kind Json carrying the node's outcome. Wire it into the next step when you need it; leaving it unwired is fine.
The three generative primitives
Exactly three generative primitives call a model to produce something new:
- llm — one bounded turn: input in, answer out. It has no tools, so it can only answer — it can't touch your workspace or anything else.
- agent — a multi-turn loop with an explicit toolset and a mandatory budget. Several built-in
sys-flows now run on it — the aspect-onboarding flow alone dispatches ten agent nodes. For your own graphs, llm or coder is still the simpler first reach. - coder — a full coding session in its own container, working in a workspace that exists only for the run.
On the palette these three map to more than three tiles: the coder ships as a synchronous and an asynchronous tile, and domain-flavored model call-sites — mission decomposition, review — are configurations of a site, never new primitives.
The rule that ties them together: primitives propose, verbs commit. A generative node never writes anywhere durable on its own. Writes happen in separate action nodes, and every path to a write passes a gate — nothing a model produces lands without a decision point in front of it.
Outcome arms
Most nodes have a single out pin: they succeed and continue, or they fail. One node is different. The asynchronous coder finishes in one of three ways — Success, Failure, or Refusal — and each way is its own execution pin, an outcome arm: onSuccess, onFailure, onRefusal. You wire each arm to whatever should happen in that case.
One rule changes how you draw: arms never reconverge. The paths downstream of two arms stay separate; the validator rejects wiring that merges them back together.
In practice, wire each arm to an explicit next step — every built-in template that uses the asynchronous coder routes all three.
Two nodes carry outcome arms today — the asynchronous coder and service:mission:integrate; you won't meet arms on other tiles.
Sub-workflows
A workflow can embed another published workflow as a single node — a FlowRef tile. On the canvas it looks like one box. The child workflow decides which inputs and outputs to expose; that small pin surface is its tunnel signature, and you wire it like any other node's pins.
A sub-workflow shares its parent's run and its parent's acceptance. It's composition, not a call: no second run to accept, no second branch to watch.
The sys- tiles in the palette — sys-research-codebase, sys-decompose-propose and friends — are published building blocks designed for exactly this. See System templates.
Params and slots
Two mechanisms keep a graph reusable. Run parameters are declared on the workflow and bound to values when a run starts — same graph, different inputs each run.
A slot is a typed hole you declare where generation is allowed to fill in structure. Generation fills the hole and nothing else: it never rewrites the topology around it, and the structure you already committed stays untouchable.
What publishing freezes
When you Publish a draft, the graph is frozen: a published version is immutable and checksummed, and nobody — ARDS included — can silently change it. At run time, each node also gets a frozen execution snapshot of its own: retrying a step re-runs exactly that snapshot rather than renegotiating it.
The day-to-day consequences are on the lifecycle page; the full mechanics are in the architecture chapter.