Skip to main content

Workflow Step Kinds

A workflow definition has steps, Groups, For each containers and one execution graph (entry and edges source → outcome → target). There are no phases. The Workflow Builder guide shows how to build them in the UI; this page is the stored-name lookup for Flow Steward 0.7.27.

Steps​

Builder namestep_kindUse it forKey configuration
AgentagentRun an agent/skill pair.Agent, skill, input/output mappings, error policy.
System tools, Extension tools, MCP toolsconnectorCall a built-in tool, an extension action or a connected MCP server tool.Connector, install, connection binding, operation.
HTTP requesthttp_requestCall an HTTP/HTTPS endpoint or download a bounded file.Method, URL, headers, query, body, auth, timeout, expected statuses, response mode, response target.
Invoke workflowinvoke_workflowRun a child workflow and map its results back; also the stored form of a hook.Child workflow_id, input/output/returned-file mappings.
Set variableset_variableWrite values into workflow state.Assignments (state.path → literal or {"source": "state.…"}).
TransformtransformMap and reshape JSON with typed actions.Source, fields, result target.
Tabular feedtabular_feedProcess CSV, TSV, JSON, NDJSON, Parquet or XLSX feeds without loading all rows into state.Operation, input, actions, result target.
DataSetdataset_queryRun a saved dataset query.Query template, params, row limit, result target.
File from base64file_from_base64Turn base64 data into a file artifact.Base64 source, file name, content type, file handle target, size limit.
TemplatetemplateRender one text from declared inputs.Text, format, inputs, result target.
CollectcollectAdd one value to an existing list or object. For each body only.Target, source, mode (append or set_key), key.
IfifBranch on a condition.Selector, operator, value; routes true and false.
SwitchswitchRoute by value to one of several cases.Selector, cases with a stable case_id; routes each case and default.
ApprovalapprovalWait for a person to approve or reject.Message, outputs shown to the reviewer; routes approved and rejected.
WaitwaitPause the run for a duration.Duration.
BatchbatchSplit a list into batches.Source path, batch size, partial-batch behaviour, result target.
BreakbreakEnd the For each now. For each body only.None.
ContinuecontinueEnd the current item. For each body only.None.
Stop · successstop_successEnd the run successfully and return the outputs.Optional message.
Stop · failstop_failEnd the run as failed.Optional message.

These twenty kinds are the complete list. Validation refuses any other step_kind (workflow.step.kind_unsupported); a step stored without a kind is an agent step.

batch only groups data; it does not run an operation per batch. To run steps per item or per batch, put them in a For each.

Builder entries that are not step kinds​

Add step also offers entries that are stored differently:

Builder nameStored asUse it for
For eachA for_each containerRun the steps inside once per item.
Inline loopA for_each container shown inside its cardRepeat a few simple steps per item.
GroupA Group with a sequence bodySteps that belong together; can become a child workflow.
Parallel lanesA Group with a lanes bodyLanes that run side by side.
HookAn invoke_workflow step with a hook declarationA place where a project adds its own steps (workflow authors only).
NoteA canvas noteText and images on the canvas; saved separately and never run.

Custom code (code step)​

Flow Steward has no inline code step. n8n (Code), Zapier (Code by Zapier), Make (custom JavaScript) and similar tools let you type a script into a workflow step; Flow Steward deliberately does not.

Custom logic belongs in an extension instead, because there:

  • the developer owns the code in a repository and can review every change;
  • it is covered by its own tests (extensions test) and passes the same validation as any extension before it can be installed;
  • it is versioned and released, so a workflow run uses a known version and an update is a deliberate install;
  • it runs out of process with its own pinned dependencies, not inside the workflow engine.

To add custom logic to a workflow:

  1. Generate an extension: ./flow-steward extensions create <extension_id>, or ask a coding agent with the Extension Authoring Skill. Build An Extension describes the bundle.
  2. Write the logic as an action handler and expose it to workflows: mark the action workflow_visible: true and declare an operation with the same id, its inputs and outputs, in the extension's Contract v2 operation manifest. See Use An Action As A Workflow Step.
  3. Validate, test, bundle and install the extension.
  4. In the workflow, add an Extension tools step (step_kind: connector), pick the extension and its operation, and map inputs from workflow state. The operation's outputs land in state like any other step's.

For small data changes you may not need code at all: Set variable, Transform, Template, If and Switch cover mapping, reshaping, text and branching.

Outcomes​

SourceOutcomes it must route
Ordinary step, including Waitsuccess (shown as Next)
Iftrue and false
Switchone case per case, plus default
Approvalapproved and rejected
Stop · success, Stop · failnone
Any step or group with an On error routeadditionally error

One outcome leads to exactly one target. Every root path ends at a Stop step; a step with no continuation is a definition issue, never an implicit success.

Containers​

Group​

A Group runs its body once. Its body is a sequence ({kind: sequence, entry}) or lanes ({kind: lanes, lanes: [{lane_id, entry}], concurrency_limit}). The body or each lane ends at the group exit; the Group then leaves on success. A lanes body runs its lanes in parallel up to concurrency_limit and joins when all have finished; each lane lands only the values it changed, and for the same field the later lane in lane order wins.

For each​

A For each runs its body once per item of a ready collection:

for_each:
- for_each_id: each_order
group_id: orders_batch # optional: the sequence Group it sits in
over: state.orders # a ready collection in state
item_name: order # the current item, read as state.order
index_name: order_index # optional: its position, from 0
body: {kind: sequence, entry: {kind: step, id: build_shipment}}

Items run one at a time. A list is walked as it is, a missing value is an empty pass, any other value is one item. At most FS_DATASET_QUERY_MAX_RUNTIME_ROWS items (1000 by default) are walked and the run reports truncation. A dataset cursor is refused as a source: read the rows first.

Placement​

PlacementSupported
Root sequence, If/Switch branchesYes
Group with a sequence or lanes bodyYes
For each at the root or in a sequence GroupYes
Collect, Break, Continue in a sequence For each bodyYes
Approval and Wait at the root, in a sequence Group or a sequence For each bodyYes
Hook (invoke_workflow with a hook declaration) at the rootYes
If, Switch, Approval, Wait or Stop in a parallel laneNo
A Group in a Group, a For each in a For each, parallel itemsNo
A hook inside a Group, For each or laneNo

Validation refuses an unsupported placement before the workflow can be saved or run.