> ## Documentation Index
> Fetch the complete documentation index at: https://www.shipfox.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Use Gate Conditions and Retry Loops in Shipfox Workflows

> Use Shipfox gate blocks to evaluate step success with CEL expressions and automatically retry from an earlier keyed step when a condition fails.

A **gate** block on a step lets you define a success condition and a retry strategy. When the condition fails, Shipfox restarts execution from an earlier keyed step in the same job — creating a loop that continues until the condition is met or the job times out. Pair it with an agent step and the loop does real work: the agent edits code, a shell step verifies it, and the gate loops back — no scripting.

## Gate schema

A gate block sits directly on a step and supports two fields:

```yaml theme={null}
gate:
  success_if: exit_code == 0   # CEL expression evaluated against the step outcome
  on_failure:
    restart_from: install      # must reference an earlier step that has a `key:` field
```

`success_if` and `on_failure` are both optional individually, but at least one must be present. A gate with only `success_if` marks the step as failed without retrying. A gate with only `on_failure` always retries. Use both together for a conditional retry loop.

## Basic retry loop

The canonical pattern installs dependencies, runs an agent to fix failing tests, then verifies:

```yaml theme={null}
jobs:
  fix:
    steps:
      - key: install
        run: npm ci
      - model: claude-opus-4-8
        prompt: Fix the failing tests in the repository.
      - run: npm test
        gate:
          success_if: exit_code == 0
          on_failure:
            restart_from: install
```

On each iteration, the agent reads the updated codebase and attempts another fix. The loop continues until `npm test` exits `0`. The loop is **bounded automatically**: a gating step gets 3 attempts by default before its restart budget is exhausted and the job stops. The job-level `execution_timeout` adds a second, outer bound — see Loop bounds.

## success\_if expressions

The `success_if` field accepts a [CEL (Common Expression Language)](https://cel.dev) expression that is evaluated after the step completes. The only variable available today is `exit_code`, which holds the integer exit code of the step's shell command.

Common patterns:

| Expression       | Meaning                                   |
| ---------------- | ----------------------------------------- |
| `exit_code == 0` | Step succeeded (standard Unix convention) |
| `exit_code != 1` | Any exit code except a hard failure       |

More CEL variables (stdout content, step duration, etc.) are planned for future releases.

## Rules for restart\_from

<Warning>
  The step referenced by `restart_from` must appear **before** the gate step in the same job. Forward references are not allowed.
</Warning>

* The target step must have a `key:` field — `restart_from` matches keys, not display names. (`name:` is a separate, display-only label.)
* The reference is matched by step key, not by position — reordering steps changes which step is targeted.
* `restart_from` must reference a step within the **same job**. Cross-job retries are not supported; use `needs` to express job dependencies instead.

## Job execution timeout

A gating step already stops after a bounded number of restarts (3 by default). On top of that, `execution_timeout` sets an **outer wall-clock bound** on the whole job — useful when steps are slow and even a few attempts could run long:

```yaml theme={null}
jobs:
  fix:
    execution_timeout: "30m"
    steps:
      - key: install
        run: npm ci
      - model: claude-opus-4-8
        prompt: Fix the failing tests in the repository.
      - run: npm test
        gate:
          success_if: exit_code == 0
          on_failure:
            restart_from: install
```

The value is a duration string. When the timeout is reached, the job is cancelled and marked as failed regardless of where execution is in the loop.

## Next steps

* [Jobs & Steps](/guides/multi-job-pipeline) — understand job isolation, `needs`, and parallel execution.
* [Agent Steps](/guides/agent-steps) — configure the model, thinking level, and provider for agent steps.
