# Run Workflow Steps
{{< tier level="sovereign" note="Run Workflow steps let you reuse proven processes without hiding their progress or results." >}}

Use a `subworkflow` step when one workflow should run another saved workflow. In Valdr UI, this step is labeled **Run workflow**.

## Configuration

```yaml
- key: verify_delivery
  name: Verify Delivery
  kind: subworkflow
  workflow:
    key: example.task.verify-delivery
    version: 1.0.0
  inputs:
    taskKey: "${workflow.inputs.taskKey}"
  outputs:
    status: "$.normalized.child.outputs.status"
```

| Field | Required | Purpose |
| --- | --- | --- |
| `workflow.key` | Yes | Saved child workflow |
| `workflow.version` | Yes | Exact child version |
| `inputs` | Depends on child | Values bound to the child's declared inputs |
| `outputs` | No | Child results mapped into parent-local names |
| `onFailure.action` | No | Block by default, or fail the parent run |

## Bind child inputs

The child receives only the inputs it declares. Bind every required child input that has no default:

```yaml
inputs:
  taskKey: "${workflow.inputs.taskKey}"
  includeEvidence: true
```

Valdr validates unknown inputs and incompatible literal types before the run starts.

## Map child outputs

The child must declare and publish an output before the parent can select it:

```yaml
outputs:
  childRunUlid: "$.normalized.child.runUlid"
  verdict: "$.normalized.child.outputs.verdict"
```

Downstream parent steps then use `${steps.verify_delivery.outputs.verdict}`.

## Version selection

The parent selects an exact child version. Publishing a newer child does not silently change the parent. Update the selected version deliberately when you want the new behavior.

The run inspector links parent and child runs so you can inspect the child steps without losing the context of the larger process.

## Child failure

By default, a failed, blocked, or cancelled child blocks the parent at this step. Set `onFailure.action: fail` when the parent should end as failed instead.

Use the linked child run to diagnose the underlying issue. Authored `retry` policies are rejected on Run Workflow steps, but **Retry step** can add a new parent-step attempt after a blocked or failed child when manual retry is eligible. You can also recover the child or start a separate parent run as appropriate.

## Run once for each item

Use `forEach` for a bounded list when the same child workflow should process each value in order:

```yaml
forEach:
  items: "${workflow.inputs.targets}"
  itemName: target
  maxConcurrent: 1
```

`items` must be an exact reference to an array workflow input or earlier step output. `itemName` is required, must be a declared child input, and cannot also appear in the step's explicit `inputs`. Current execution is sequential; if present, `maxConcurrent` must be `1`.

Map the ordered child results when later steps need them:

```yaml
outputs:
  children: "$.normalized.children"
```

## In Valdr UI

Choose **Run workflow**, select an active saved definition and exact version, then bind its required inputs and desired outputs. The builder reports unavailable targets and missing bindings before launch.

## Next step

Return to [Workflow Steps](../) or read [From Idea to Verified Sprint](../../idea-to-sprint/) to see child workflows compose a complete lifecycle.

