Skip to content

Parameters and loops

Two features cover most of the dynamic behaviour in a workflow: parameters, which let you pass values in and reference them anywhere, and loops, which run one node many times. Guards round it out by deciding whether a node runs at all.

A parameter is a named workflow input with a default value. You add parameters in the Inspector’s Parameters section when no node is selected. Each one has a name, a value, and an optional description.

Reference a parameter anywhere a field takes text with:

{{workflow.parameters.<name>}}

For example, a parameter named image can fill the Image field of a run-container node as {{workflow.parameters.image}}, so the same graph runs against a different image without editing the node. Parameters compile to the workflow’s spec.arguments.parameters, so callers can override them at submit time.

A loop runs a single node once per item instead of once. Open a node’s “Run this once per item…” section and pick how the items are supplied:

  • Just once. The default. No loop.
  • Once per item in a list. Supply a list expression: a JSON list, a workflow parameter, or a list output from an earlier step. This compiles to Argo Workflows’ withParam.
  • Once per item I type here. A fixed list, one item per line. Compiles to withItems.
  • Once per number in a range. Give a count, or a start and end, plus an optional printf format like testuser%02d. Compiles to withSequence.

In every case you refer to the current item as {{item}} inside the node’s fields. A run-container node looping over ["dev", "staging", "prod"] can pass --env {{item}} to run three times, once per environment.

Loops are how you fan work out. A node that produces a list on its result output feeds directly into a downstream node’s “Once per item in a list” loop, so one step’s output becomes the next step’s iteration.

A guard decides whether a node runs. Open a node’s “Only run this when…” section and enter an expression. When it evaluates false, the node is skipped; leave it blank and the node always runs.

Guards read the outputs of earlier steps. For example:

{{tasks.flip.outputs.result}} == heads

runs the node only when the upstream flip step produced heads. Guards and loops compose: a guarded node inside a loop is evaluated per item.