> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.runtype.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.runtype.com/_mcp/server.

# Using conditional steps

Conditional steps route Flow execution through different paths based on a condition. To gate one step instead of creating branches, use a `when` condition. For more information, see [Skip a single step with when](#skip-a-single-step-with-when).

## Before you begin

Open a Flow in the Flow editor.

## Add a conditional step

To add a conditional step, follow these steps:

1. In the Flow editor, click **Add step** (the plus button between steps).
2. Select **Conditional Logic**.
3. In **Condition**, build the condition with the visual builder, or click **Code** to enter a JavaScript expression.
4. Add steps to **If true**. These steps run when the condition passes.
5. Add steps to **Otherwise**. These steps run when no path passes.
6. Optional: To add another path, click **Add path**, then enter its condition and add its steps.
7. Optional: To name a path, type in its name field. To remove a path, click its delete button.
8. In the Flow editor toolbar, click **Save**.

Runtype checks paths from top to bottom. The first path whose condition passes runs, and the other paths don't. If no path passes, **Otherwise** runs. Because the first match wins, the order of paths matters. To change the order, drag a path by its handle.

## Write a condition

A condition passes when its result is truthy: any value other than `false`, `0`, `''`, `null`, `undefined`, or `NaN`. Any other result fails.

The **Condition** field has two modes:

* **Visual builder**: Select a variable, an operator such as **is equal to**, **contains**, **is at least**, **exists**, or **is empty**, and a value. After a run, the builder shows whether the condition is **True** or **False** with your last run's data.
* **Code**: Enter any JavaScript expression that returns a value. To return to the visual builder, click **Visual Mode**.

To generate a condition from a description, click **Describe** and enter the rule in plain English, for example "the lead score is at least 80 and the country is the US". Review the generated rules before you save.

The examples on this page use code mode. Reference variables from earlier steps by their `outputVariable` names. You can write a variable path such as `sentiment.score`, or use a template reference such as `{{sentiment.score}}`. Runtype resolves template references before it evaluates the expression.

For example, this condition routes scores above 0.5 to the true path:

```plaintext
sentiment.score > 0.5
```

Common operators in code mode include:

* `===` and `!==` for strict equality and inequality.
* `<`, `>`, `<=`, and `>=` for numeric comparisons.
* `&&` and `||` for logical AND and OR.
* `!` for negation.

The following rules apply when Runtype evaluates a condition:

* Each condition has a 2-second time limit.
* Runtype converts the result to true or false by truthiness. The string `'false'` is truthy, so compare string values explicitly, for example `'{{approved}}' === 'true'`.
* For logic that needs several statements, start the expression with `return`.

## Examples

Use these conditions to route common Flow decisions.

### Check AI confidence

Route a high-confidence response to one path with this condition:

```plaintext
analysis_result.confidence > 0.8
```

Use the AI response in the true path. Route the request to human review in **Otherwise**.

### Route by user tier

Quote the template reference when you compare a string value:

```plaintext
'{{customer_data.tier}}' === 'premium'
```

Use the priority support path for premium customers. Use **Otherwise** for standard support.

### Detect an API error

Route the response to error handling when its status differs from 200:

```plaintext
api_result.status !== 200
```

Handle the error in the true path. Process the response in **Otherwise**.

### Combine conditions

Combine numeric and string comparisons with `&&`:

```plaintext
order_total > 1000 && '{{customer_data.tier}}' === 'standard'
```

Require approval in the true path. Auto-approve in **Otherwise**.

## Compare strings

Put quotes around a template reference when the resolved value is a string. This keeps the substituted value valid JavaScript:

```plaintext
'{{sentiment_result.label}}' === 'negative'
'{{process_status}}' !== 'completed'
```

## Check whether a value exists

Use `undefined` and `null` checks to test for a nested value. Compare an array's `length` to zero when you need to check whether it contains items:

```plaintext
customer_data.email !== undefined && customer_data.email !== null
order_history.length > 0
```

## Nest conditional steps

Add a conditional step inside a branch when you need another decision. This structure runs VIP processing only when both conditions pass:

```plaintext
Main conditional: Is the tier premium?
  If true:
    Nested conditional: Is the order greater than $5000?
      If true: VIP processing
      Otherwise: Premium processing
  Otherwise: Standard processing
```

A Flow can nest conditional steps up to 10 levels deep. Saving a Flow with more levels fails validation. If you need deeper branching, use a `transform-data` step to calculate a boolean and reference it from one conditional.

## Access branch outputs

Steps inside conditional branches write variables in the same Flow-level scope as other steps. Set an `outputVariable` on a branch step, then reference that name in a later step:

```plaintext
{{branch_result}}
```

Only the selected path runs, so a later step can read a branch variable only when that path writes it. To expose one result from the conditional, set the conditional's `outputVariable`. Runtype sets it to the value of the last enabled step in the selected path that wrote a named output. A step that a `when` condition skipped doesn't count.

If a step inside a path pauses the Flow, the Flow resumes on the same path. Runtype doesn't evaluate the conditions again, so variable changes during the pause don't switch paths.

## Handle errors inside a branch

By default, a failed step inside a branch doesn't stop the branch, and the next step in the path runs. A `tool-call` step is the exception: it fails the branch unless you set its **On error** setting to **Continue with error output**. To make a failed branch step fail the whole conditional step, set that step's error handling to **Stop on error**.

## Define a conditional step in JSON

When you create a Flow through the API, the Runtype MCP server, or code, a conditional step has the type `conditional`. For multi-path routing, set `branches` and `otherwiseSteps`. Each branch has an `id`, an optional `name`, a `condition`, and its `steps`.

The following step routes urgent tickets to one prompt and all other tickets to another:

```json
{
  "id": "route_ticket",
  "type": "conditional",
  "name": "Route ticket",
  "order": 2,
  "enabled": true,
  "config": {
    "outputVariable": "reply",
    "branches": [
      {
        "id": "urgent",
        "name": "Urgent",
        "condition": "'{{ticket.priority}}' === 'urgent'",
        "steps": [
          {
            "id": "urgent_reply",
            "type": "prompt",
            "name": "Draft urgent reply",
            "order": 1,
            "enabled": true,
            "config": {
              "model": "claude-sonnet-5",
              "userPrompt": "Draft an urgent reply to: {{ticket.body}}",
              "outputVariable": "urgent_reply"
            }
          }
        ]
      }
    ],
    "otherwiseSteps": [
      {
        "id": "standard_reply",
        "type": "prompt",
        "name": "Draft standard reply",
        "order": 1,
        "enabled": true,
        "config": {
          "model": "claude-haiku-4-5",
          "userPrompt": "Draft a reply to: {{ticket.body}}",
          "outputVariable": "standard_reply"
        }
      }
    ]
  }
}
```

For a two-way decision, you can set `condition`, `trueSteps`, and `falseSteps` instead. When `branches` isn't empty, Runtype ignores `condition`, `trueSteps`, and `falseSteps`. The TypeScript SDK's `conditional()` method builds the two-way form. For more information, see [Manage flows as code](/user-guide/flows/manage-flows-as-code).

## Test conditional branches

To test every path, follow these steps:

1. Run the Flow with input that makes the first condition pass.
2. In the execution results, check the conditional step's output. `matchedBranch` is the ID of the path that ran, and `conditionResult` is `true` when any path passed.
3. Repeat the test for each additional path.
4. Run the Flow with input that matches no path.
5. Confirm that `matchedBranch` is `otherwise`.

A conditional step without added paths doesn't report `matchedBranch`. For that step, `conditionResult` is `true` when **If true** ran and `false` when **Otherwise** ran. Review the execution results to confirm that the selected steps ran.

## Troubleshoot a condition that fails

If Runtype can't evaluate a condition, the **Conditional Logic** step fails with an error that starts with the following text:

```plaintext
Conditional evaluation failed:
```

Common causes include the following:

* A string template reference without quotes, such as `{{ticket.priority}} === 'urgent'`. For more information, see [Conditional compares an unquoted template against a string](/user-guide/flows/flow-validation-warnings#conditional-compares-an-unquoted-template-against-a-string).
* A variable that no earlier step writes.
* A JavaScript syntax error.
* An expression that runs longer than 2 seconds.

## Common patterns

Use these patterns to organize validation, input-based routing, and fallback behavior.

### Validate input

Continue processing when the input is valid and log an error otherwise:

```plaintext
Conditional: Is the input valid?
  If true: Continue processing
  Otherwise: Log the validation error
```

When the validation logic needs several checks, use a `transform-data` step to calculate one boolean first.

### Route by a Flow input

Choose an implementation based on a Flow input such as `use_beta`:

```plaintext
use_beta === true
```

Use the alternate implementation in the true path. Use the standard implementation in **Otherwise**.

### Add fallback logic

Call a backup API when the primary API fails:

```plaintext
Conditional: Did the primary API succeed?
  If true: Use the primary response
  Otherwise: Call the backup API
```

## Skip a single step with when

Add an optional `when` condition to any step when you need to run that step only for certain inputs. When the condition fails, the step is skipped and the Flow continues. You don't need to wrap the step in a conditional branch.

Use `when` for a single conditional action, such as a retry after a failure or an enrichment step that runs when data is present.

### Set a when condition in the editor

To add a `when` condition in the Flow editor, follow these steps:

1. Find the step that you want to gate.
2. Click **Always run** on the step.
3. In the **Run Condition** sheet, build the condition, or click **Code** and enter an expression of up to 500 characters.
4. Click **Save**.

After you save a condition, the control changes to **Runs conditionally**. On a narrow step card, it shows **Conditional**, and the step inspector shows **Conditional run**. The editor adds an amber border to the step and groups consecutive steps that use the same condition.

### How skipping works

When a `when` condition fails, the following behavior applies:

* The step doesn't write its `outputVariable`. If an earlier step wrote the same variable, that value remains.
* The Flow continues to the next step.
* The execution results show the step as skipped.

Use the same condition syntax as a **Conditional Logic** step. For example, this step runs only when `needs_retry` is true:

```plaintext
needs_retry === true
```

### Handle condition errors

If a `when` expression throws an error, the step is skipped by default. For example, an invalid expression or a missing variable can cause an evaluation error. The Flow continues after the step is skipped.

When a Flow runs as a tool, a parameter that the tool schema declares but the calling agent omits has the value `undefined`. For example, `plan === 'pro'` is false when the agent omits `plan`. A name that the schema doesn't declare and no earlier step writes still causes an error.

To stop the Flow when a `when` expression throws an error, set the step's error handling to **Stop on error**.

### Choose between when and a conditional step

Use the following table to choose between a `when` condition and a conditional step:

| Feature     | `when` condition                                        | Conditional step                              |
| ----------- | ------------------------------------------------------- | --------------------------------------------- |
| Scope       | Gates one step.                                         | Selects one path.                             |
| Branches    | Runs or skips the step.                                 | Runs the first passing path or **Otherwise**. |
| Output      | Doesn't write the step's `outputVariable` when skipped. | Branch steps write their own outputs.         |
| Use it when | One step needs a condition.                             | You need separate paths.                      |

## Next steps

* [Flow step types overview](/user-guide/flows/flow-step-types-overview): choose other steps for your Flow.
* [Flow variables and templates](/user-guide/flows/flow-variables-and-templates): reference inputs and step outputs.
* [Using transform-data steps](/user-guide/flows/using-transform-data-steps): calculate values before a condition.
* [Using bounded loops](/user-guide/flows/using-bounded-loops): repeat steps with the same condition syntax.
* [Debugging flows](/user-guide/flows/debugging-flows): verify branch execution and skipped steps.
* [Judgments](/user-guide/flows/judgments): branch on a label or a probability that a judgment model returns.