Workflow Variables

June 18, 2026 ยท View on GitHub

Some fields in a workflow specification allow for variable references which are automatically substituted by Argo.

How to use variables

Variables are enclosed in curly braces:

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: hello-world-parameters-
spec:
  entrypoint: print-message
  arguments:
    parameters:
      - name: message
        value: hello world
  templates:
    - name: print-message
      inputs:
        parameters:
          - name: message
      container:
        image: busybox
        command: [ echo ]
        args: [ "{{inputs.parameters.message}}" ]

The following variables are made available to reference various meta-data of a workflow:

Template Tag Kinds

There are two kinds of template tag:

  • simple The default, e.g. {{workflow.name}}
  • expression Where{{ is immediately followed by =, e.g. {{=workflow.name}}.

Simple

The tag is substituted with the variable that has a name the same as the tag.

Simple tags may have white-space between the brackets and variable as seen below. However, there is a known issue where variables may fail to interpolate with white-space, so it is recommended to avoid using white-space until this issue is resolved. Please report unexpected behavior with reproducible examples.

args: [ "{{ inputs.parameters.message }}" ]

Expression

v3.1 and after

The tag is substituted with the result of evaluating the tag as an expression.

Note that any hyphenated parameter names or step names will cause a parsing error. You can reference them by indexing into the parameter or step map, e.g. inputs.parameters['my-param'] or steps['my-step'].outputs.result.

Learn more about the expression syntax.

Examples

Plain list:

[1, 2]

Filter a list:

filter([1, 2], { # > 1})

Map a list:

map([1, 2], { # * 2 })

Cast to int:

asInt(inputs.parameters['my-int-param'])

Cast to float:

asFloat(inputs.parameters['my-float-param'])

Cast to string:

string(1)

We provide some additional functions:

Convert to a JSON string (needed for withParam):

toJson([1, 2])

toJson is the same as expr's built-in toJSON function, except toJson does not add indentation.

Extract data from JSON:

jsonpath(inputs.parameters.json, '$.some.path')

You can also use Sprig functions:

Trim a string:

sprig.trim(inputs.parameters['my-string-param'])

!!! Warning "Sprig error handling" Sprig functions often do not raise errors. For example, if int is used on an invalid value, it returns 0. Please review the Sprig documentation to understand which functions raise errors and which do not.

Reference

All Templates

VariableDescription
inputs.parameters.<NAME>Input parameter to a template
inputs.parametersAll input parameters to a template as a JSON string
inputs.artifacts.<NAME>Input artifact to a template
node.nameFull name of the node

Steps Templates

VariableDescription
steps.nameName of the step
steps.<STEPNAME>.idunique id of container step
steps.<STEPNAME>.ipIP address of a previous daemon container step
steps.<STEPNAME>.statusPhase status of any previous step
steps.<STEPNAME>.exitCodeExit code of any previous script or container step
steps.<STEPNAME>.startedAtTime-stamp when the step started
steps.<STEPNAME>.finishedAtTime-stamp when the step finished
steps.<STEPNAME>.hostNodeNameHost node where step ran (available from version 3.5)
steps.<STEPNAME>.outputs.resultOutput result of any previous container, script, or HTTP step
steps.<STEPNAME>.outputs.parametersWhen the previous step uses withItems or withParams, this contains a JSON array of the output parameter maps of each invocation
steps.<STEPNAME>.outputs.parameters.<NAME>Output parameter of any previous step. When the previous step uses withItems or withParams, this contains a JSON array of the output parameter values of each invocation
steps.<STEPNAME>.outputs.artifacts.<NAME>Output artifact of any previous step

Note: If a step was Skipped (its when condition was false), references to its outputs resolve according to the rules in Outputs of Skipped and Omitted Nodes.

DAG Templates

VariableDescription
tasks.nameName of the task
tasks.<TASKNAME>.idunique id of container task
tasks.<TASKNAME>.ipIP address of a previous daemon container task
tasks.<TASKNAME>.statusPhase status of any previous task
tasks.<TASKNAME>.exitCodeExit code of any previous script or container task
tasks.<TASKNAME>.startedAtTime-stamp when the task started
tasks.<TASKNAME>.finishedAtTime-stamp when the task finished
tasks.<TASKNAME>.hostNodeNameHost node where task ran (available from version 3.5)
tasks.<TASKNAME>.outputs.resultOutput result of any previous container, script, or HTTP task
tasks.<TASKNAME>.outputs.parametersWhen the previous task uses withItems or withParams, this contains a JSON array of the output parameter maps of each invocation
tasks.<TASKNAME>.outputs.parameters.<NAME>Output parameter of any previous task. When the previous task uses withItems or withParams, this contains a JSON array of the output parameter values of each invocation
tasks.<TASKNAME>.outputs.artifacts.<NAME>Output artifact of any previous task

Note: If a task was Skipped (its when condition was false) or Omitted (its depends condition was not satisfied), references to its outputs resolve according to the rules in Outputs of Skipped and Omitted Nodes.

Outputs of Skipped and Omitted Nodes

v3.7.16, v4.0.7, and after

A step or task that was Skipped (its when condition was false) or Omitted (its depends condition was not satisfied) never ran, so it produced no outputs. References to its declared output parameters and outputs.result resolve as follows:

  1. If the producing template declares a valueFrom.default for the output parameter, every reference resolves to that default.
  2. Otherwise the output is absent, which is not the same as an empty string. An absent output must be handled by one of the following, or the referencing node fails with a terminal error:
    • If an argument consists solely of such a reference and the consuming template's input parameter declares a default, the argument is omitted so that input default applies.
    • An expression tag sees the value as nil. Use the ?? operator to choose a fallback, e.g. {{= steps.producer.outputs.parameters.msg ?? 'fallback'}}.
    • In template outputs, a valueFrom.default declared on the aggregating output parameter applies when its valueFrom.parameter reference is absent or its valueFrom.expression fails.
  3. An unhandled reference to an absent output fails the node with a terminal error (it is not retried): a simple tag such as {{steps.producer.outputs.parameters.msg}} with no consumer input default, a bare {{= steps.producer.outputs.parameters.msg}}, or an operation on the nil such as + '-suffix'.

These rules apply wherever the reference appears: step and task arguments, when clauses, LifecycleHook and exit handler arguments and expressions, the enclosing template's outputs.parameters, spec.volumes, and artifact subPath fields. The exception is a step or task whose own when evaluates to false: it never runs, so absent references in its body are left unresolved instead of failing the workflow.

A legitimately empty output is not absent: if the producer ran and wrote an empty string, ?? does not fire and the empty string is substituted. For the same reason, an expression comparison such as {{= steps.producer.outputs.parameters.msg == ''}} is false when the producer was skipped, because nil is not equal to ''. Declare valueFrom.default: "" on the producer's output if you want a skipped output to behave exactly like an empty one.

See the skipped output defaults examples for runnable workflows demonstrating each rule.

HTTP Templates

v3.3 and after

Only available for successCondition

VariableDescription
request.methodRequest method (string)
request.urlRequest URL (string)
request.bodyRequest body (string)
request.headersRequest headers (map[string][]string)
response.statusCodeResponse status code (int)
response.bodyResponse body (string)
response.headersResponse headers (map[string][]string)

CronWorkflows

v3.6 and after

VariableDescription
cronworkflow.nameName of the CronWorkflow (string)
cronworkflow.namespaceNamespace of the CronWorkflow (string)
cronworkflow.labels.<NAME>CronWorkflow labels (string)
cronworkflow.labels.jsonCronWorkflow labels as a JSON string (string)
cronworkflow.annotations.<NAME>CronWorkflow annotations (string)
cronworkflow.annotations.jsonCronWorkflow annotations as a JSON string (string)
cronworkflow.lastScheduledTimeThe time since this workflow was last scheduled, value is nil on first run (*time.Time)
cronworkflow.failedCounts how many times child workflows failed
cronworkflow.succeededCounts how many times child workflows succeeded

RetryStrategy

When using the expression field within retryStrategy, special variables are available.

VariableDescription
lastRetry.exitCodeExit code of the last retry
lastRetry.statusStatus of the last retry
lastRetry.durationDuration in seconds of the last retry
lastRetry.messageMessage output from the last retry (available from version 3.5)

Note: These variables evaluate to a string type. If using advanced expressions, either cast them to int values (expression: "{{=asInt(lastRetry.exitCode) >= 2}}") or compare them to string values (expression: "{{=lastRetry.exitCode != '2'}}").

Container/Script Templates

VariableDescription
pod.namePod name of the container/script
retriesThe retry number of the container/script if retryStrategy is specified
lastRetryThe last retry is a structure that contains the fields exitCode, status, duration and message of the last retry
inputs.artifacts.<NAME>.pathLocal path of the input artifact
outputs.artifacts.<NAME>.pathLocal path of the output artifact
outputs.parameters.<NAME>.pathLocal path of the output parameter

Loops (withItems / withParam)

VariableDescription
itemValue of the item in a list
item.<FIELDNAME>Field value of the item in a list of maps

Metrics

When emitting custom metrics in a template, special variables are available that allow self-reference to the current step.

VariableDescription
statusPhase status of the metric-emitting template
durationDuration of the metric-emitting template in seconds (only applicable in Template-level metrics, for Workflow-level use workflow.duration)
exitCodeExit code of the metric-emitting template
inputs.parameters.<NAME>Input parameter of the metric-emitting template
outputs.parameters.<NAME>Output parameter of the metric-emitting template
outputs.resultOutput result of the metric-emitting template
resourcesDuration.{cpu,memory}Resources duration in seconds. Must be one of resourcesDuration.cpu or resourcesDuration.memory, if available. For more info, see the Resource Duration doc.
retriesRetried count by retry strategy

Real-Time Metrics

Some variables can be emitted in real-time (as opposed to just when the step/task completes). To emit these variables in real time, set realtime: true under gauge (note: only Gauge metrics allow for real time variable emission). Metrics currently available for real time emission:

For Workflow-level metrics:

  • workflow.duration

For Template-level metrics:

  • duration

Global

VariableDescription
workflow.nameWorkflow name
workflow.namespaceWorkflow namespace
workflow.mainEntrypointWorkflow's initial entrypoint
workflow.serviceAccountNameWorkflow service account name
workflow.uidWorkflow UID. Useful for setting ownership reference to a resource, or a unique artifact location
workflow.parameters.<NAME>Input parameter to the workflow
workflow.parametersAll input parameters to the workflow as a JSON string (this is deprecated in favor of workflow.parameters.json as this doesn't work with expression tags and that does)
workflow.parameters.jsonAll input parameters to the workflow as a JSON string
workflow.outputs.parameters.<NAME>Global parameter in the workflow
workflow.outputs.artifacts.<NAME>Global artifact in the workflow
workflow.annotations.<NAME>Workflow annotations
workflow.annotations.jsonall Workflow annotations as a JSON string
workflow.labels.<NAME>Workflow labels
workflow.labels.jsonall Workflow labels as a JSON string
workflow.creationTimestampWorkflow creation time-stamp formatted in RFC 3339 (e.g. 2018-08-23T05:42:49Z)
workflow.creationTimestamp.<STRFTIMECHAR>Creation time-stamp formatted with a strftime format character.
workflow.creationTimestamp.RFC3339Creation time-stamp formatted with in RFC 3339.
workflow.priorityWorkflow priority
workflow.durationWorkflow duration estimate in seconds, may differ from actual duration by a couple of seconds
workflow.scheduledTimeScheduled runtime formatted in RFC 3339 (only available for CronWorkflow)

Exit Handler

VariableDescription
workflow.statusWorkflow status. One of: Succeeded, Failed, Error
workflow.failuresA list of JSON objects containing information about nodes that failed or errored during execution. Available fields: displayName, message, templateName, phase, podName, and finishedAt.

Knowing where you are

The idea with creating a WorkflowTemplate is that they are reusable bits of code you will use in many actual Workflows. Sometimes it is useful to know which workflow you are part of.

workflow.mainEntrypoint is one way you can do this. If each of your actual workflows has a differing entrypoint, you can identify the workflow you're part of. Given this use in a WorkflowTemplate:

apiVersion: argoproj.io/v1alpha1
kind: WorkflowTemplate
metadata:
  name: say-main-entrypoint
spec:
  entrypoint: echo
  templates:
  - name: echo
    container:
      image: alpine
      command: [echo]
      args: ["{{workflow.mainEntrypoint}}"]

I can distinguish my caller:

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: foo-
spec:
  entrypoint: foo
  templates:
    - name: foo
      steps:
      - - name: step
          templateRef:
            name: say-main-entrypoint
            template: echo

results in a log of foo

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: bar-
spec:
  entrypoint: bar
  templates:
    - name: bar
      steps:
      - - name: step
          templateRef:
            name: say-main-entrypoint
            template: echo

results in a log of bar

This shouldn't be that helpful in logging, you should be able to identify workflows through other labels in your cluster's log tool, but can be helpful when generating metrics for the workflow for example.