Skip to content

Hello World

Let’s take a look at the Workflow from the Quick Start guide:

from hera.workflows import Steps, Workflow, WorkflowsService, script


@script()
def echo(message: str):
    print(message)


with Workflow(
    generate_name="hello-world-",
    entrypoint="steps",
    namespace="argo",
    workflows_service=WorkflowsService(host="https://localhost:2746")
) as w:
    with Steps(name="steps"):
        echo(arguments={"message": "Hello world!"})

w.create()

Wait, What’s a Workflow?

If you’re new to Argo Workflows, it helps to first understand that it runs on Kubernetes. In Kubernetes, a Custom Resource Definition (CRD) is how you define a new type of object. Argo Workflows adds its own CRD for Workflow, which lets you create Workflow objects in the same way you create Pods, Deployments, or other Kubernetes resources.

The Workflow Controller is a Kubernetes application that watches for new or updated Workflow objects. When it sees one, it schedules and manages the steps of that Workflow by updating its status on the cluster. A Workflow is therefore a live object on the cluster that represents an individual (past or present) run – it contains the templates that are running or have run, their statuses and outputs, the amount of resources used, and more – all stored within its YAML specification.

Hera Classes

Hera provides many specialised classes in hera.workflows. You will see the Argo Workflows spec has been transformed into powerful Python classes. Hera also provides classes autogenerated from the spec in hera.workflows.models.

Use Any Function on Argo

We can use Hera’s script decorator to turn any user-defined function into a Script template, which is mirrored in Hera as the Script class.

The script Decorator

The script decorator can take the kwargs that a Script can take, including image, volumes, env, and many more. This is how we can specify a different image of Python to use instead of the default python:3.10 for your script:

@script(image="python:3.13")
def echo(message: str):
    print(message)

Alternatively, you can specify this image just once by using the global_config.image variable, and it will be used for all script templates automatically:

from hera.shared import global_config
global_config.image = "python:3.13"

@script()  # "echo" will use python:3.13
def echo(message: str):
    print(message)

@script()  # "echo_twice" will also use python:3.13
def echo_twice(message: str):
    print(message)
    print(message)

The Workflow Context Manager

The Workflow context manager acts as a scope under which template Hera objects can be declared, which include Containers, Scripts, DAGs and more. You can provide values for the Workflow itself:

  • generate_name is used by Argo to create a name by appending a random 5 character suffix, so you may see this Workflow run with a name like hello-world-vmsz5.
  • entrypoint tells Argo which template to run upon submission.
  • namespace is the Kubernetes namespace you want to run the Workflow in.
  • workflows_service is Hera’s REST API submission service.

The Steps Context Manager

A Steps template is the second template type of this example. The Steps template is known as a “template invocator”, which is used to coordinate other templates, mainly Containers and Scripts, to do the actual work. In Hera, the Steps class is a context manager; it automatically arranges your templates in the order that you add them, with each template invocation known as a Step.

Clearly, echo takes a message, but we are passing in an arguments; this is actually syntactic sugar. Compare the two snippets below which are functionally equivalent:

with Steps(name="steps"):
    echo(arguments={"message": "Hello world!"})
with Steps(name="steps"):
    Step(
        name="echo",
        template=Script(name="echo", source=echo, inputs=[Parameter(name="message")]),
        arguments={"message": "Hello world!"},
    )

The “callable” syntax for your script templates intends to cut down boilerplate as much as possible, while keeping the code intuitive.

Submit the Workflow

Finally, with the workflow defined, the actual submisson occurs on

w.create()

This uses the WorkflowsService to submit to Argo using its REST API, so w.create() can be thought of as running argo submit from the CLI.

Generate the YAML

It’s important to recognise that Hera is a translation layer for Argo Workflows, which only understands YAML – the YAML Workflow should be considered the golden source when debugging.

You can generate the YAML for this Workflow using w.to_yaml(), or w.to_file(name="hello-world.yaml"):

print(w.to_yaml())
See the YAML for this Workflow.
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: hello-world-
  namespace: argo
spec:
  entrypoint: steps
  templates:
  - name: steps
    steps:
    - - name: echo
        template: echo
        arguments:
          parameters:
          - name: message
            value: Hello world!
  - name: echo
    inputs:
      parameters:
      - name: message
    script:
      image: python:3.10
      source: |-
        import os
        import sys
        sys.path.append(os.getcwd())
        import json
        try: message = json.loads(r'''{{inputs.parameters.message}}''')
        except: message = r'''{{inputs.parameters.message}}'''

        print(message)
      command:
      - python

Comments