Foundations
Step Types: normal, sequential, group
Step Types: normal, sequential, group
Three step types control how nodes execute: normal (parallel), sequential (ordered), and group (multiple steps at once). This article is the quick-reference for when to use each and how they differ in execution behavior.
normal (parallel, default)
The default step type. All nodes execute in parallel batches of up to 20. Each node is an independent LLM call with the same prompt (except for nodeInfo fields which inject the node number).
- id: generate
type: normal # "normal" is the default; can be omitted
nodes: 5
fields:
- { name: Question, type: text, from: input.context }
- { name: BranchNumber, type: nodeInfo }
systemPrompt: "Generate an independent solution."Execution:
- 5 nodes dispatched in parallel (batch of 5, all at once since 5 < 20).
- Each node sees
BranchNumber: 1,BranchNumber: 2, etc. - Outputs stored as nodes 1-5.
- Gate evaluation (if declared) prunes per-node.
Use when: You want independent candidates for selection (Tree-of-Thoughts, self-consistency, parallel evaluation). The nodes don't depend on each other; they're alternatives.
Key property: Nodes are interchangeable. Downstream ingest with nodeRef: current aligns by position (verifier 3 reads generator 3). multi_ingest with nodeRef: accumulate reads all survivors.
sequential (ordered chain)
Nodes execute one after another. Each node can read the previous node's output via nodeRef: previous. This creates a chain of refinement.
- id: refine
type: sequential
nodes: 3
fields:
- { name: Question, type: text, from: input.context }
- name: Previous
type: ingest
from: { stepId: refine, loopRef: current, nodeRef: previous }
skipFirstNode: true
systemPrompt: "Improve the answer. If Previous is available, build on it."Execution:
- Node 1 runs first.
Previousis empty (skipFirstNode: truesuppresses the error). - Node 2 runs.
Previousreads node 1's output. - Node 3 runs.
Previousreads node 2's output. - The step's combined output is all 3 nodes joined.
Use when: Each pass genuinely improves on the previous one (iterative refinement, chain-of-thought, progressive summarization). The nodes are not alternatives; they're a sequence.
Key property: Nodes are ordered and dependent. nodeRef: previous is the primary addressing mode. The last node's output is often the best (it had the most context).
skipFirstNode: true: Essential for sequential steps. Without it, node 1 would try to read a nonexistent previous node and error. With it, node 1 runs without a Previous field (empty string).
Exit step behavior: For sequential exit steps, the runtime returns the last surviving node's output (not the combined output). This ensures the caller gets the most refined version.
group (parallel sub-steps)
A group step wraps multiple child steps that execute in parallel. Each child is a full step with its own fields, system prompt, and optional nodes. Groups cannot be nested.
- id: reviewers
type: group
steps:
- id: security
fields: [{ name: Input, type: text, from: input.context }]
systemPrompt: "Review for security issues."
- id: style
fields: [{ name: Input, type: text, from: input.context }]
systemPrompt: "Review for style issues."
- id: correctness
fields: [{ name: Input, type: text, from: input.context }]
systemPrompt: "Review for correctness."
- id: synthesize
fields:
- { name: Security, type: ingest, from: { stepId: security, loopRef: current } }
- { name: Style, type: ingest, from: { stepId: style, loopRef: current } }
- { name: Correctness, type: ingest, from: { stepId: correctness, loopRef: current } }
systemPrompt: "Merge the three reviews into one report."Execution:
- All child steps start simultaneously (using Go's
errgroup). - Each child runs independently: resolves fields, dispatches LLM calls, evaluates gates.
- The group step completes when all children complete.
- Downstream steps can ingest any child's output by step ID.
Use when: You want multiple independent perspectives or tasks executed at the same time (parallel review, multi-modal analysis, fan-out to different specialists).
Key constraints:
- Groups cannot be nested. A group step's children cannot themselves be groups.
- Children are addressed by their own step ID, not the group's ID.
- The group step itself has no
fields,systemPrompt, ornodes— it's just a container.
For deeper composition: Use cross-ladder jumps instead of nested groups. A child step can fire { jump: { ladderId: "@alice/specialist" } } to hand off to another ladder.
Choosing a step type
| Pattern | Step type | Why |
|---|---|---|
| Generate N independent candidates | normal with nodes: N | Candidates are alternatives; all run at once |
| Score N candidates in parallel | normal with nodes: N | Each verifier reads its corresponding candidate |
| Chain of N refinements | sequential with nodes: N | Each pass builds on the previous |
| Multi-perspective review | group with N children | Each reviewer has a different prompt |
| Single LLM call | normal (or omit type) with no nodes: | Simplest case; one call, one output |
| Iterative decomposition | normal + recursion | Each recursive child handles a sub-problem |
Rule of thumb:
- If the nodes are alternatives (pick the best) →
normal - If the nodes are a chain (each improves the last) →
sequential - If the children are different tasks (security, style, correctness) →
group - If it's one call → omit type and nodes (defaults to
normalwith 1 node)