# Workflow Steps
{{< tier level="sovereign" note="Workflow steps combine Valdr actions, agents, reviews, decisions, and reusable workflows into one process." >}}

Build workflows from actions, sessions, reviews, waits, approvals, outcome routes, and reusable workflows. Choose **Valdr Tools**, **Git**, **GitHub**, or **Command** for the action you need.

{{< cards >}}
  {{< card link="tool/" title="Valdr Tools" subtitle="Call supported Valdr actions from the workflow catalog" icon="code" >}}
  {{< card link="git/" title="Git" subtitle="Inspect repositories and integrate reviewed delivery" icon="code" >}}
  {{< card link="github/" title="GitHub" subtitle="Publish an approved exact branch as a pull request" icon="code" >}}
  {{< card link="command/" title="Command" subtitle="Run a trusted non-interactive shell command" icon="terminal" >}}
  {{< card link="session/" title="Session" subtitle="Launch or continue an agent session" icon="terminal" >}}
  {{< card link="review/" title="Review" subtitle="Launch an independent reviewer" icon="check-circle" >}}
  {{< card link="await-condition/" title="Await Condition" subtitle="Pause for expected evidence or an outcome" icon="clock" >}}
  {{< card link="human-gate/" title="Human Gate" subtitle="Require an operator approval or rejection" icon="user" >}}
  {{< card link="condition/" title="Outcome route" subtitle="Route work or repeat a bounded correction loop" icon="switch-horizontal" >}}
  {{< card link="subworkflow/" title="Run Workflow" subtitle="Compose an exact version of another workflow" icon="arrows-expand" >}}
{{< /cards >}}

## Shared fields

Every step uses the same outer fields, plus configuration for its selected kind:

| Field | Required | Purpose |
| --- | --- | --- |
| `key` | Yes | Unique name used by dependencies and expressions |
| `name` | Yes | Human-readable label shown in Valdr UI |
| `kind` | Yes | Selects the step behavior |
| `needs` | No | Steps that must finish before this step can run |
| `when` | No | Conditions that must pass, otherwise the step is skipped |
| `inputs` | Depends on kind | Values supplied to a tool or child workflow |
| `outputs` | No | Named values made available to later steps |
| `onFailure` | No | Block, fail, or use a supported bounded loop |

## Connect steps with expressions

```yaml
- key: load_task
  name: Load Task
  kind: tool
  tool:
    id: pm_task
    action: get
  inputs:
    taskKey: "${workflow.inputs.taskKey}"
  outputs:
    status: "$.normalized.task.status"

- key: route_task
  name: Route Task
  kind: condition
  needs: [load_task]
  checks:
    - kind: value_equals
      value: "${steps.load_task.outputs.status}"
      equals: ready
```

The producing step declares `status`; the consuming step names `load_task` in `needs` and reads the declared output.

## Route with `when`

```yaml
when:
  - kind: value_equals
    value: "${steps.review.outputs.outcome}"
    equals: review_approved
```

All `when` checks must pass. A false check skips the step; it does not fail the run.

## Handle failure deliberately

```yaml
onFailure:
  action: block
```

- `block` stops at a recoverable point.
- `fail` ends the run as failed.
- `loop_back` is available only on an Outcome route and must set a maximum number of passes.

Valdr UI shows **Retry step** only when the current or latest attempt is failed or blocked and its error category is safe to repeat. Authored `retry.maxAttempts` is a reported attempt count; it neither caps manual recovery nor schedules automatic retries or backoff.

## Validate before running

The Workflow Builder validates supported fields continuously and offers action-specific inputs and outputs. Diagnostics link back to the affected step or field. For YAML definitions, `pm_workflow validate` applies strict validation automatically:

```text
pm_workflow { action: "validate", definitionYaml: "..." }
```

## Next step

Start with [Valdr Tools](tool/) for the action-based MCP surface, use [Git](git/) for repository operations, [GitHub](github/) for pull-request publication, [Command](command/) for a trusted shell command, or choose another step above.

