# Outcome route
{{< tier level="sovereign" note="Evaluate an outcome, select follow-up work, or repeat a bounded correction loop." >}}

Use **Outcome route** to evaluate a value and make it available to later work. Downstream branch conditions decide what runs next; an optional bounded loop sends requested changes back for another pass. In YAML, an Outcome route uses `kind: condition`.

## Configuration

```yaml
- key: route_review
  name: Route Review Outcome
  kind: condition
  needs: [await_review]
  checks:
    - kind: value_equals
      value: "${steps.await_review.outputs.outcome}"
      equals: review_approved
  outputs:
    outcome: "${steps.await_review.outputs.outcome}"
```

Without `onFailure`, the route completes whether its checks match or not. It publishes only the outputs you declare; the match result is recorded as execution evidence, not an automatic output. Set `onFailure.action` to `block` or `fail` when a mismatch should stop the run; declared outputs are retained. Use `loop_back` for the bounded repetition described below.

Downstream steps depend on the route and use their own `when` checks to choose their path:

```yaml
- key: verify_task
  name: Verify Task
  kind: tool
  needs: [route_review]
  when:
    - kind: value_equals
      value: "${steps.route_review.outputs.outcome}"
      equals: review_approved
  tool:
    id: pm_task
    action: change_status
  inputs:
    taskKey: "${workflow.inputs.taskKey}"
    to: verified
```

A false `when` skips the downstream step; it does not fail the run. Each branch is evaluated independently: more than one branch can run, or all can skip. Use mutually exclusive checks when only one branch should run. A route does not choose a branch automatically.

## Supported checks

| Check | Use it to |
| --- | --- |
| `value_equals` | Set `value` and `equals` to compare one value with an expected value |
| `value_in` | Set `value` and `allowed` to require membership in an allowed list |
| `array_unique_nonempty_strings` | Set `value` to require a non-empty list of unique text values |
| `array_permutation_equals` | Set `value` and `expected` to compare two text lists while ignoring order |

Values can come from literals, workflow inputs, upstream outputs, or runtime loop values. All authored checks must match for the route to report a match; no checks means a match.

## Bounded loop back

Add `loop_back` when a failed check should return to a strict earlier step:

```yaml
- key: route_review
  name: Route Review
  kind: condition
  needs: [await_review]
  checks:
    - kind: value_equals
      value: "${steps.await_review.outputs.outcome}"
      equals: review_approved
      domain: [review_approved, review_changes_requested]
  outputs:
    outcome: "${steps.await_review.outputs.outcome}"
  onFailure:
    action: loop_back
    to: request_revision
    max: 3
    exhausted: block
```

| Field | Purpose |
| --- | --- |
| `to` | Earlier step that begins the repeated correction path |
| `max` | Total passes, including the first; must be from 1 to 10 |
| `exhausted` | `block` or `fail` after the last unsuccessful pass |

The loop target must be a strict dependency ancestor of the route. A loop-back check uses one `value_equals` check with a non-empty, unique `domain` that contains `equals` and lists every possible observed value; a value outside that closed domain blocks the run. Keep the repeated path between the target and route narrow: its steps cannot declare `retry`, its child workflows cannot use `forEach` or `detached`, and loops cannot overlap. Side branches cannot read outputs from the repeated path or rejoin work that depends on the route. Valdr preserves every attempt, so the run inspector shows each implementation and review pass.

Inside the loop, `${runtime.loop.currentPass}` and `${runtime.loop.maxPasses}` are available when a prompt or output needs the pass number.

## In Valdr UI

Add **Outcome route** from the Builder library. Select **Add closed condition check**, then set **Outcome to evaluate**, **Outcome that continues**, and **Allowed outcomes**. This guided form edits one `value_equals` check; other check types or multiple checks use **Authored checks JSON**.

Under **Routing**, choose **When outcome does not continue**. For **Repeat** (`loop_back` in YAML), select **Repeat from**, **Total passes (includes first)**, and **When exhausted**. Connect downstream work and configure its branch conditions separately.

## Next step

Return to [Workflow Steps](../) or use [Run Workflow Steps](../subworkflow/) to compose a reusable process into the selected branch.

