In Argo, we can use ‘withParam’ to create loop logic:

    - - name: generate
        template: gen-number-list
    # Iterate over the list of numbers generated by the generate step above
    - - name: sleep
        template: sleep-n-sec
        arguments:
          parameters:
          - name: seconds
            value: "{{item}}"
        withParam: "{{steps.generate.outputs.result}}"

But in my YAML, it also use when in Argo:

    - - name: generate
        template: gen-number-list
        when: "{{workflow.parameters.NEED_RUN}} == 1"
    # Iterate over the list of numbers generated by the generate step above
    - - name: sleep
        template: sleep-n-sec
        arguments:
          parameters:
          - name: seconds
            value: "{{item}}"
        withParam: "{{steps.generate.outputs.result}}"
        when: "{{workflow.parameters.NEED_RUN}} == 1"

When the NEED_RUN is 0, the Argo will report error since it can’t find the {{steps.generate.outputs.result}}. Seems the YAML parser of Argo will try to parse withParam before when phrase.
Fortunately we don’t need to modify Argo or Kubernetes to solve this problem — we just need to let template gen-number-list generate a fake output (empty array):

      script:
        image: "{{workflow.parameters.BASEIMAGE}}"
        command: [bash]
        source: |
            if [ $NEED_RUN -eq 1 ]; then
                python3 -u output.py
            else
                echo "[]"
            fi
        env:
          - name: NEED_RUN
            value: "{{workflow.parameters.NEED_RUN}}"