> For the complete documentation index, see [llms.txt](https://developer.harness.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.harness.io/harness-platform/3.0/harness-platform-resources/overview/yaml-reference.md).

# YAML reference

Complete YAML reference for Harness v1 pipelines: every key, its type, and a minimal example.

This page is a flat reference for all YAML keys supported in Harness v1 pipelines. Keys are grouped by scope: pipeline root, stage, step, and execution controls. Each section shows the key, its type, whether it is required, and a verified example.

## What you will learn

* The complete YAML structure for the pipeline root, stages, and steps
* How to configure clone, inputs, notifications, and execution controls in YAML
* The keys for strategies, failure handling, conditional execution, and timeout
* YAML syntax for run steps, group steps, and parallel step groups

***

## Pipeline root

The root key is always `pipeline:`.

```yaml
pipeline:
  id: my_pipeline
  name: My Pipeline
  description: Optional description
  clone:
    enabled: false
  inputs:
    env:
      type: string
      default: production
      desc: Target environment
      required: false
  delegate: my-delegate
  timeout: 2h
  allow-stage-executions: true
  fixed-inputs-on-rerun: false
  notifications:
    - on:
        - pipeline:
            - failed
      uses: slack
      with:
        url: https://hooks.slack.com/services/your-webhook
  stages: []
```

| Key                      | Type           | Required | Description                                                                  |
| ------------------------ | -------------- | -------- | ---------------------------------------------------------------------------- |
| `id`                     | string         | Yes      | Unique identifier for the pipeline. Used in expressions.                     |
| `name`                   | string         | Yes      | Display name shown in the UI.                                                |
| `description`            | string         | No       | Free-text description.                                                       |
| `clone`                  | object         | No       | Controls source repository cloning. See [Clone](#clone).                     |
| `inputs`                 | map            | No       | Typed runtime parameters. See [Inputs](#inputs).                             |
| `delegate`               | string or list | No       | Delegate name or tag list for routing execution.                             |
| `timeout`                | duration       | No       | Maximum pipeline run time. Default: `24h`.                                   |
| `allow-stage-executions` | boolean        | No       | When `true`, allows selective stage execution at runtime.                    |
| `fixed-inputs-on-rerun`  | boolean        | No       | When `true`, locks inputs to original values on rerun.                       |
| `notifications`          | list           | No       | Notification rules for pipeline events. See [Notifications](#notifications). |
| `stages`                 | list           | Yes      | The ordered list of stages.                                                  |

***

## Clone

Controls whether and how Harness clones a source repository before running steps. The repo is cloned into `/harness` inside the runner.

```yaml
clone:
  enabled: true
  repo: deployment-samples
  depth: 1
```

To skip cloning entirely (common for pipelines that do not need source code):

```yaml
clone:
  enabled: false
```

| Key       | Type    | Default | Description                                                            |
| --------- | ------- | ------- | ---------------------------------------------------------------------- |
| `enabled` | boolean | `true`  | Set to `false` to skip cloning.                                        |
| `repo`    | string  | none    | Harness Code repository name to clone.                                 |
| `depth`   | integer | full    | Commit depth. `1` for a shallow clone (faster); omit for full history. |

***

## Inputs

Pipeline inputs are typed parameters collected at runtime.

```yaml
inputs:
  env:
    type: string
    default: production
    desc: Target environment
    required: false
  version:
    type: string
    required: true
```

Reference inputs in steps and conditions using `${{ inputs.<name> }}` (CEL) or `<+inputs.<name>>` (JEXL in `if` conditions).

| Field      | Type    | Description                                                           |
| ---------- | ------- | --------------------------------------------------------------------- |
| `type`     | string  | `string`, `number`, `boolean`, `secret`, `environment`, or `duration` |
| `default`  | value   | Value used when none is provided at runtime.                          |
| `desc`     | string  | Label shown in the run form.                                          |
| `required` | boolean | Whether a value must be supplied before running.                      |

{% hint style="info" %}
In `if` conditions (JEXL context), wrap input references in single quotes to avoid identifier errors: `"'<+inputs.env>' == 'production'"`.
{% endhint %}

***

## Notifications

```yaml
notifications:
  - on:
      - pipeline:
          - start
          - failed
    uses: email
    with:
      recipients:
        - user@example.com

  - on:
      - stage:
          - failed
    uses: slack
    with:
      url: https://hooks.slack.com/services/your-webhook
```

**Events**

| Event               | YAML value          |
| ------------------- | ------------------- |
| Pipeline starts     | `pipeline: start`   |
| Pipeline succeeds   | `pipeline: success` |
| Pipeline fails      | `pipeline: failed`  |
| Pipeline ends (any) | `pipeline: end`     |
| Stage starts        | `stage: start`      |
| Stage succeeds      | `stage: success`    |
| Stage fails         | `stage: failed`     |
| Step fails          | `step: failed`      |
| Trigger fails       | `trigger: failed`   |

**Channels**

| Channel         | `uses` value | Required `with` fields           |
| --------------- | ------------ | -------------------------------- |
| Email           | `email`      | `recipients: [user@example.com]` |
| Slack           | `slack`      | `url: <webhook-url>`             |
| PagerDuty       | `pager-duty` | `key: <integration-key>`         |
| Microsoft Teams | `ms-teams`   | `url: <incoming-webhook-url>`    |
| Webhook         | `webhook`    | `url: <webhook-url>`             |

***

## Stages

Each entry in `pipeline.stages` is a stage.

```yaml
stages:
  - name: build
    id: build
    timeout: 30m
    on-failure:
      - errors:
          - all
        action: fail
    if: <+OnPipelineSuccess>
    strategy:
      matrix:
        env:
          - staging
          - production
    steps: []
```

| Key          | Type     | Required               | Description                                                                                                         |
| ------------ | -------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `name`       | string   | Yes                    | Display name.                                                                                                       |
| `id`         | string   | Yes                    | Unique identifier within the pipeline. Used in expressions.                                                         |
| `timeout`    | duration | No                     | Maximum stage run time. Default: `24h`. Status on expiry: `Expired`.                                                |
| `on-failure` | list     | No                     | Failure rules. See [On failure](#on-failure).                                                                       |
| `if`         | string   | No                     | JEXL condition. Stage is skipped when it evaluates to `false`. See [Conditional execution](#conditional-execution). |
| `strategy`   | object   | No                     | Looping strategy. See [Strategy](#strategy).                                                                        |
| `steps`      | list     | Yes (for plain stages) | The steps to run inside the stage.                                                                                  |
| `group`      | n/a      | n/a                    | Not valid at the stage level. Groups exist at the step level.                                                       |
| `parallel`   | object   | No                     | Parallel stage group. See [Parallel stage group](#parallel-stage-group).                                            |
| `chain`      | object   | No                     | Chained pipeline. See [Chained pipeline](#chained-pipeline).                                                        |

### Parallel stage group

Runs multiple child stages simultaneously.

```yaml
stages:
  - name: parallel-group
    id: parallel_group
    parallel:
      stages:
        - name: branch-a
          id: branch_a
          steps:
            - name: step-a
              id: step_a
              run:
                script: echo "branch A"
        - name: branch-b
          id: branch_b
          steps:
            - name: step-b
              id: step_b
              run:
                script: echo "branch B"
```

### Chained pipeline

Runs another pipeline as a stage.

```yaml
stages:
  - name: deploy
    id: deploy
    chain:
      uses: my-org/my-project/child_pipeline
      with:
        inputs:
          env: production
        outputs:
          - name: image_tag
            value: ${{ stages.run.outputs.image_tag }}
```

| Key                  | Type   | Description                                          |
| -------------------- | ------ | ---------------------------------------------------- |
| `chain.uses`         | string | Child pipeline reference: `org/project/pipeline_id`. |
| `chain.with.inputs`  | map    | Input values to pass to the child pipeline.          |
| `chain.with.outputs` | list   | Output mappings to read from the child pipeline.     |

***

## Steps

Each entry in `stage.steps` is a step. Steps run sequentially by default.

```yaml
steps:
  - name: my-step
    id: my_step
    timeout: 10m
    on-failure:
      - errors:
          - all
        action: ignore
    if: <+OnPipelineSuccess>
    strategy:
      for:
        iterations: 3
    run:
      script: echo "hello"
```

| Key          | Type     | Required | Description                                                                                            |
| ------------ | -------- | -------- | ------------------------------------------------------------------------------------------------------ |
| `name`       | string   | Yes      | Display name.                                                                                          |
| `id`         | string   | Yes      | Unique identifier within the stage.                                                                    |
| `timeout`    | duration | No       | Maximum step run time. Default: `2h`. Status on expiry: `Expired`.                                     |
| `on-failure` | list     | No       | Failure rules. See [On failure](#on-failure).                                                          |
| `if`         | string   | No       | JEXL condition. Step is skipped when it evaluates to `false`.                                          |
| `strategy`   | object   | No       | Looping strategy. See [Strategy](#strategy).                                                           |
| `run`        | object   | No       | Run step. Executes a shell script. See [Run step](#run-step).                                          |
| `group`      | object   | No       | Group step. Runs child steps sequentially. See [Group step](#group-step).                              |
| `parallel`   | object   | No       | Parallel step group. Runs child steps simultaneously. See [Parallel step group](#parallel-step-group). |

### Run step

```yaml
- name: compile
  id: compile
  run:
    script: |
      echo "building..."
      make build
    shell: sh
```

| Key          | Type   | Required | Description                                                                |
| ------------ | ------ | -------- | -------------------------------------------------------------------------- |
| `run.script` | string | Yes      | Shell commands to execute. Multi-line supported with `\|`.                 |
| `run.shell`  | string | No       | Shell to use: `sh`, `bash`, `powershell`, `pwsh`, `python`. Default: `sh`. |

### Group step

Runs child steps sequentially inside a named container.

```yaml
- name: setup
  id: setup
  group:
    steps:
      - name: install
        id: install
        run:
          script: npm install
      - name: build
        id: build
        run:
          script: npm run build
```

| Key           | Type | Required | Description                                 |
| ------------- | ---- | -------- | ------------------------------------------- |
| `group.steps` | list | Yes      | Steps to run sequentially inside the group. |

The `group` key supports all step-level advanced settings: `timeout`, `on-failure`, `strategy`, `if`.

### Parallel step group

Runs child steps simultaneously.

```yaml
- name: parallel-tasks
  id: parallel_tasks
  parallel:
    steps:
      - name: task-a
        id: task_a
        run:
          script: ./task-a.sh
      - name: task-b
        id: task_b
        run:
          script: ./task-b.sh
```

| Key              | Type | Required | Description                  |
| ---------------- | ---- | -------- | ---------------------------- |
| `parallel.steps` | list | Yes      | Steps to run simultaneously. |

The `parallel` key supports all step-level advanced settings: `timeout`, `on-failure`, `strategy`, `if`.

### Jira approval step

Pauses the pipeline and polls a Jira issue until the approval criteria are met, the reject criteria are met, or the step times out. Go to [Jira approval step](/harness-platform/3.0/harness-platform-resources/overview/overview-1/approvals/jira-approval.md) for the full guide.

```yaml
pipeline:
  id: my-pipeline
  name: My Pipeline
  clone:
    enabled: true
    repo: my-repo
    depth: 1
  stages:
    - name: my-stage
      id: my_stage
      steps:
        - name: my-step
          id: my_step
          deploy:
            uses: jiraApproval
            with:
              connector: account.my-jira-connector
              issue: PROJ-1234
              retry: 1m
              approve:
                match-any-condition: true
                conditions:
                  - status:
                      eq: "Done"
              log_level: error
```

| Key                           | Required | Type     | Description                                                                                    |
| ----------------------------- | -------- | -------- | ---------------------------------------------------------------------------------------------- |
| `connector`                   | Yes      | string   | Identifier of the Jira connector. Use `account.`, `org.`, or no prefix for the matching scope. |
| `issue`                       | Yes      | string   | Jira issue key (for example, `PROJ-1234`).                                                     |
| `approve`                     | Yes      | object   | Criteria that advance the pipeline.                                                            |
| `approve.match-any-condition` | No       | boolean  | `true` for OR logic; `false` or absent for AND logic.                                          |
| `approve.conditions`          | No       | list     | Field conditions. Each entry: `field-name: { operator: value }`.                               |
| `retry`                       | No       | duration | Polling interval. Default: `1m`.                                                               |
| `reject`                      | No       | object   | Criteria that fail the pipeline. Same structure as `approve`.                                  |
| `log_level`                   | No       | string   | Log verbosity: `info`, `warn`, `error`. Default: `info`.                                       |

Supported operators: `eq`, `not_eq`, `in`, `not_in`.

### ServiceNow approval step

Pauses the pipeline and polls a ServiceNow ticket until the approval criteria are met, the reject criteria are met, or the step times out. Go to [ServiceNow approval step](/harness-platform/3.0/harness-platform-resources/overview/overview-1/approvals/service-now-approval.md) for the full guide.

```yaml
pipeline:
  id: my-pipeline
  name: My Pipeline
  clone:
    enabled: true
    repo: my-repo
    depth: 1
  stages:
    - name: my-stage
      id: my_stage
      steps:
        - deploy:
            uses: serviceNowApproval
            with:
              connector: account.my-servicenow-connector
              ticket_type: change_request
              ticket_number: CHG0000001
              retry: 1m
              log_level: error
```

| Key                           | Required | Type     | Description                                                                                          |
| ----------------------------- | -------- | -------- | ---------------------------------------------------------------------------------------------------- |
| `connector`                   | Yes      | string   | Identifier of the ServiceNow connector. Use `account.`, `org.`, or no prefix for the matching scope. |
| `ticket_type`                 | Yes      | string   | ServiceNow table or ticket type to poll.                                                             |
| `ticket_number`               | Yes      | string   | Specific ticket number to poll.                                                                      |
| `approve`                     | Yes      | object   | Criteria that advance the pipeline.                                                                  |
| `approve.match-any-condition` | No       | boolean  | `true` for OR logic; `false` or absent for AND logic.                                                |
| `approve.conditions`          | No       | list     | Field conditions. Each entry: `field-name: { operator: value }`.                                     |
| `retry`                       | No       | duration | Polling interval. Default: `1m`.                                                                     |
| `reject`                      | No       | object   | Criteria that fail the pipeline. Same structure as `approve`.                                        |
| `change_window_start`         | No       | string   | ISO 8601 datetime or expression. Approval only accepted on or after this time.                       |
| `change_window_end`           | No       | string   | ISO 8601 datetime or expression. Approval rejected after this time.                                  |
| `log_level`                   | No       | string   | Log verbosity: `info`, `warn`, `error`. Default: `info`.                                             |

Supported operators: `eq`, `not_eq`, `in`, `not_in`.

***

## Execution controls

### Strategy

Applies to stages and steps. Runs the stage or step multiple times.

```yaml
strategy:
  max-parallel: 2     # max simultaneous instances (0 = unlimited)
  fail-fast: true     # cancel all on first failure
  for:
    iterations: 3
```

**For loop:** runs a fixed number of times in parallel.

```yaml
strategy:
  for:
    iterations: 3
```

| Expression                   | Resolves to                       |
| ---------------------------- | --------------------------------- |
| `${{ strategy.iteration }}`  | Current iteration index (0-based) |
| `${{ strategy.iterations }}` | Total number of iterations        |

**While loop:** runs sequentially up to a maximum number of iterations.

```yaml
strategy:
  while:
    iterations: 5
```

**Matrix:** fans out across all combinations of the defined axes.

```yaml
strategy:
  max-parallel: 2
  matrix:
    region:
      - us-east-1
      - eu-west-1
    env:
      - staging
      - production
```

| Expression                  | Resolves to                         |
| --------------------------- | ----------------------------------- |
| `${{ matrix.<axis> }}`      | Value of the axis for this instance |
| `${{ strategy.iteration }}` | Instance index (0-based)            |

Stage naming for matrix:

* Single axis: `<id>_0`, `<id>_1`, …
* Multiple axes: `<id>_0_0`, `<id>_0_1`, …
* With `node-name`: `<id>_<node-name-value>` (hyphens converted to underscores)

***

### On failure

Controls what Harness does when a stage or step fails. Always a **list**.

```yaml
on-failure:
  - errors:
      - all
    action: fail
```

**Error types**

| Value                   | Description                             |
| ----------------------- | --------------------------------------- |
| `all`                   | Matches any failure                     |
| `timeout`               | Step or stage exceeded its timeout      |
| `authentication`        | Authentication failure                  |
| `authorization`         | Authorization failure                   |
| `connectivity`          | Network or connectivity failure         |
| `unknown`               | Unclassified error                      |
| `verification`          | Verification step failure               |
| `approval-rejection`    | An approval step was rejected           |
| `delegate-provisioning` | Delegate could not be provisioned       |
| `delegate-restart`      | Delegate restarted during execution     |
| `input-timeout`         | Manual intervention wait timed out      |
| `policy-evaluation`     | OPA policy evaluation failed            |
| `user-mark-fail`        | User manually marked the step as failed |

**Actions**

| Value                 | Description                                              |
| --------------------- | -------------------------------------------------------- |
| `fail`                | Mark as failed and stop the pipeline (default)           |
| `abort`               | Abort the entire pipeline                                |
| `ignore`              | Continue execution; pipeline shows `IgnoreFailed` status |
| `success`             | Treat the failure as success                             |
| `retry`               | Retry with backoff. See below.                           |
| `manual-intervention` | Pause for user action. See below.                        |
| `stage-rollback`      | Roll back the current stage                              |
| `pipeline-rollback`   | Roll back the entire pipeline                            |

**Retry with backoff**

```yaml
on-failure:
  - errors:
      - all
    action:
      retry:
        attempts: 3
        interval: 30s
        failure-action: fail
```

**Retry then manual intervention**

```yaml
on-failure:
  - errors:
      - all
    action:
      retry:
        attempts: 2
        interval: 15m
        failure-action:
          manual-intervention:
            timeout: 20m
            timeout-action: fail
```

`timeout-action` valid values: `fail`, `ignore`, `abort`, `success`, `stage-rollback`, `pipeline-rollback`.

When `manual-intervention` is triggered, Harness pauses execution and displays a popup with options: **Mark as Success**, **Ignore**, **Retry**, **Abort**, **Rollback Stage**.

***

### Conditional execution

The `if` key takes a JEXL expression that is evaluated at runtime. The stage or step runs only when the expression evaluates to `true`.

**Base conditions**

| Expression             | When it runs                                 |
| ---------------------- | -------------------------------------------- |
| `<+OnPipelineSuccess>` | All prior stages succeeded                   |
| `<+OnPipelineFailure>` | One or more prior stages failed              |
| `<+Always>`            | Always runs regardless of prior stage status |

```yaml
if: <+OnPipelineSuccess>
if: <+OnPipelineFailure>
if: <+Always>
```

**Combined expressions**

```yaml
if: <+OnPipelineSuccess> && false
```

**Input variable comparison** (quotes required)

```yaml
if: "'<+inputs.env>' == 'production'"
```

{% hint style="warning" %}
Always wrap `<+inputs.varName>` in single quotes inside the expression. Without them, the resolved value is treated as a JEXL identifier (undefined variable) rather than a string literal, causing an expression evaluation error.
{% endhint %}

***

### Timeout

Sets the maximum run time for a stage or step. Accepts duration strings.

```yaml
timeout: 30m
```

| Format   | Example  | Equivalent        |
| -------- | -------- | ----------------- |
| Seconds  | `90s`    | 1 min 30 sec      |
| Minutes  | `30m`    | 30 minutes        |
| Hours    | `2h`     | 2 hours           |
| Days     | `1d`     | 24 hours          |
| Combined | `1h 30m` | 1 hour 30 minutes |

* Stage default: `24h`. Step default: `2h`.
* When a stage or step times out it is marked as **Expired**.
* Handle timeouts specifically with `errors: [timeout]` in `on-failure`.

***

### Concurrency

Limits how many instances of a strategy run simultaneously within a single execution. Applies at the stage level alongside a `strategy`.

```yaml
strategy:
  matrix:
    region:
      - us-east-1
      - eu-west-1
      - ap-southeast-1
      - ap-northeast-1
  max-parallel: 2
```

`max-parallel: 0` means unlimited (all instances start at once). `max-parallel: 1` forces serial execution.

***

## Duration format reference

All `timeout` and `interval` fields accept the following formats:

| Format   | Example  |
| -------- | -------- |
| Seconds  | `30s`    |
| Minutes  | `15m`    |
| Hours    | `2h`     |
| Days     | `1d`     |
| Combined | `1h 30m` |

***

## Next steps

* Go to [Pipeline settings](/harness-platform/3.0/harness-platform-resources/overview/pipeline-settings.md) to configure inputs, delegate, notifications, and more.
* Go to [Strategy](/harness-platform/3.0/harness-platform-resources/overview/strategy.md) to review looping strategy details and verified expressions.
* Go to [On failure](/harness-platform/3.0/harness-platform-resources/overview/strategy/on-failure.md) to review the full failure handling reference.
* Go to [Conditional execution](/harness-platform/3.0/harness-platform-resources/overview/strategy/conditional-execution.md) to review JEXL condition details.
* Go to [Timeout](/harness-platform/3.0/harness-platform-resources/overview/strategy/timeout.md) to review timeout behavior and status codes.
* Go to [Steps overview](/harness-platform/3.0/harness-platform-resources/overview/overview-1.md) to review step types and advanced settings.
