# Runs and recovery

A run holds one workflow’s work for one owner. Each request opens a turn; a turn that fails keeps its record and can be resumed from where it stopped.

Start: Run created → Turn: Running → Wait: Waiting → Turn: Running → Done: Completed

One turn of a run. The next request to the run opens another turn beneath this one.

## Runs and turns

Starting a run creates it; a request opens its first turn. A run has no natural end: every later request opens another turn, and each turn reads the earlier ones as its history. The newest turn is the run’s tip, and at most one turn of a run is running or waiting at a time.

## Turn states

| State | What it means |
| --- | --- |
| `Running` | Steps are advancing. |
| `Waiting` | A step is waiting for an answer. |
| `Completed` | The workflow committed a successful result. |
| `Failed` | An attempt failed. The turn can be resumed while it has attempts left. |
| `Cancelled` | The owner cancelled it. |
| `Superseded` | A newer request replaced it under the workflow’s Mode. |
| `Timeout` | The engine’s ceiling on a turn’s working time ended it. |
| `Unrecoverable` | It failed as many times as the deployment allows and cannot be resumed. |
| `Dead` | An edit replaced it while it was still running or waiting. |

## Failed attempts and recovery

When an attempt fails, the turn records the failure and becomes `Failed`. Each failure counts once, whatever caused it: an unsuccessful result, a step that ran out of attempts, or a lost worker. At the deployment’s limit, three failures by default, the turn becomes `Unrecoverable`.

| RecoveryMode | What happens to a failed turn |
| --- | --- |
| `Manual` | The default. It waits for its owner to call POST /workflow/runs/{runId}/resume, while it is still the run’s tip. |
| `Auto` | The engine retries it shortly after the failure while it has attempts left. |

A resumed turn runs the same version of the workflow it opened on, and continues from the first step that did not finish. A turn that stops making progress for an hour, by default, is treated as a lost attempt.

## Editing, forking, cancelling and deleting

| Operation | Endpoint | Does |
| --- | --- | --- |
| Resume | `POST /workflow/runs/{runId}/resume` | Continues the tip, or begins its next attempt where it failed. Opens no turn. |
| Edit | `POST /workflow/runs/{runId}/turns/{turnId}/edit` | Runs a turn again with a replacement request, as a sibling. A running or waiting turn it replaces becomes Dead. |
| Fork | `POST /workflow/runs/{runId}/turns/{turnId}/fork` | Opens a new turn beneath an earlier, finished turn. Refused while a turn is live. |
| Cancel | `POST /workflow/runs/{runId}/cancel` | Ends the tip as Cancelled and lets the next queued request open. |
| Delete | `DELETE /workflow/runs/{runId}` | Deletes the run with its turns, its events and its own graph, ending any open wait, and answers 204. Refused with 409 while its tip is running: cancel it first. |

Edit, fork and resume answer with the turn they affected. Asked for with `Accept: text/event-stream`, they follow that turn to its end instead.

## How long a run is kept

A run is `Permanent` unless it is started with `?persistence=Ephemeral`. A permanent run is kept until its owner deletes it. An ephemeral run, with everything it recorded, is deleted after 30 minutes without activity by default. An organization admits ephemeral runs only where its `AllowEphemeralRuns` setting is on; otherwise the run is stored as permanent.
