# Runs and turns

Understand durable runs, individual turns, sandboxes, and cancellation.

A run is the durable agent context. A turn is one accepted unit of work inside
that run.

## Ownership

| Object     | Owns                                                         |
| ---------- | ------------------------------------------------------------ |
| Deployment | Immutable agent and sandbox configuration                    |
| Run        | Pi session, workspace, active sandbox, and pinned deployment |
| Turn       | One input, its execution state, output, and error            |
| Sandbox    | Replaceable compute for the run                              |

## Turn states

| Status        | Meaning                                      |
| ------------- | -------------------------------------------- |
| `queued`      | Accepted and waiting to start                |
| `in_progress` | Provider or tool execution is active         |
| `cancelling`  | Cancellation is accepted and is settling     |
| `completed`   | Work and required durability steps completed |
| `failed`      | Execution or required durability work failed |
| `cancelled`   | The turn was intentionally cancelled         |
| `incomplete`  | Execution stopped without a complete result  |

`completed`, `failed`, `cancelled` and `incomplete` are final. See
[Statuses and errors](/docs/reference/statuses-errors) for what each one returns in
`output` and `error`.

## Run and turn states can differ

The run state reports whether the durable context can accept work. The turn
status reports the selected unit of work.

For example, a cancelled turn can leave its run `idle`. The client can then
submit a new turn to the same run. A run can stay `busy` after one queued turn
is cancelled because another turn is still active.

## Cancellation

Cancel current work:

```http
POST /api/v1/runs/{runId}/cancel
```

Cancel a selected active or queued turn:

```json
{
  "turn_id": "turn_01J..."
}
```

What the request returns depends on the selected turn:

| Selected turn                       | Response | Result                                                                               |
| ----------------------------------- | -------- | ------------------------------------------------------------------------------------ |
| Active                              | `202`    | The turn is `cancelling` until the runtime stops the work, cleans up, and settles it |
| Queued                              | `200`    | The turn is `cancelled` immediately and never starts                                 |
| Already finished                    | `200`    | The turn exactly as it settled; it is never relabelled `cancelled`                   |
| None: an idle run without `turn_id` | `200`    | Nothing is stopped and the run's latest turn is returned unchanged                   |

Cancellation:

* requests an abort for active provider and tool work;
* removes a selected queued turn;
* settles the turn lifecycle;
* stops active sandbox compute through run cleanup when required.

A request affects one turn. Other queued turns are separate work, and the run
can accept a new turn once the cancelled turn settles.

An accepted cancellation is durable. If recording its events or notifying the
runtime fails, the request still succeeds. Repeat the request with the same
`Idempotency-Key` to repeat those steps; a repeated request always returns the
turn it first selected, never a later one. Disconnecting your HTTP client does
not cancel work.

## Deletion

Deletion is cleanup for an idle run. Do not use deletion as a substitute for
cancellation of active work.
