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

# Run

> A run is one agent working from one wake to one ending, with a derived status, an exit reason, a trigger source and an optional approval or question it waits on.

A run is one agent working from one wake to one ending. Its id is `run_` plus 16 base62 characters. Inside a run, `current` names that run. For how wakes, retries and carry-over work, see [Runs](/concepts/runs).

## States

| State | Meaning | Ends here |
| - | - | - |
| `queued` | Created, and no device or cloud sandbox holds it yet. | No |
| `running` | A device or cloud sandbox holds it. | No |
| `succeeded` | It finished, or stopped to wait on you. | Yes |
| `failed` | It ended for any other reason. | Yes |
| `cancelled` | Someone stopped it, or a pause or setting ended it. | Yes |

| From | To | Trigger |
| - | - | - |
| none | `queued` | A wake creates the run. |
| `queued` | `running` | A device or cloud sandbox claims it. |
| `queued` or `running` | `succeeded`, `failed` or `cancelled` | The run ends. The exit reason picks the status. |

The status is derived, not stored. A run with an end time takes its status from `exitReason`. An ended run with no known exit reason is `failed`. A retry never reopens a run. It creates a new run whose `parentRunId` names the old one.

Two conditions are derived at read time:

* `gateReason` names what holds a queued run. `gateDescription` says what would release it. Values: `rate_limit`, `capacity`, `no_device`, `task_locked`, `no_ready_route`, `pinned_route_not_ready`, `governance_refused`, `provider_overloaded`.
* `waitingOn` is set while an open approval (`apr_…`) or question (`qst_…`) holds the run.

### Exit reasons

| Group | Status | Exit reasons |
| - | - | - |
| Finished | `succeeded` | `completed`: the agent finished its turn. |
| Waiting on you | `succeeded` | `approval_requested`, `question_asked`: it stopped for an approval or an answer. |
| Stopped | `cancelled` | `interrupted`: a person cancelled it. `agent_paused`, `company_paused`: the agent or the workspace's agents were paused. |
| Not allowed to run | `cancelled` | `cloud_disabled`: cloud runs are off. `billing_locked`: the plan is not paid. `duplicate_trigger`: its trigger went stale before it started. |
| Too long | `failed` | `timeout`, `budget_exceeded`: it ran too long. `no_progress`: it stopped producing output. `gate_timeout`: it waited too long to start. |
| Did not start | `failed` | `dispatch_timeout`: no device picked it up. `dispatch_error`: it could not be started. `harness_start_failed`: the harness never started. |
| Lost | `failed` | `runner_lost`: the device stopped reporting. `sandbox_lost`: the cloud sandbox disappeared. `crashed`: the agent process died. |
| Provider or error | `failed` | `rate_limited`: the provider rate-limited it. `circuit_breaker`: the provider circuit was open. `error`: it failed with an error. |
| Bad input | `failed` | `agent_deleted`: the agent was deleted. `invalid_task`: the task was not valid. |
| Backfill | `failed` | `zombie_pre_lease_backfill`, `zombie_undispatched`, `migration_backfill`: closed by cleanup, not by the run. |

### Trigger sources

`triggerSource` says what woke the run.

| Value | Woken by |
| - | - |
| `assignment` | A task assignment. |
| `mention` | An @mention. |
| `channel_message` | A conversation message. |
| `fan_in` | The last subtask closing. |
| `dependency_resolved` | A blocking task clearing. |
| `task_watched` | A watched task changing. |
| `approval_resolved` | An answered approval or question. |
| `webhook` | A webhook or a GitHub event. |
| `cron` | A scheduled automation, or idle compaction. |
| `workflow_step` | A workflow step. |
| `agent_request` | Another run spawning it. |
| `manual` | A person, a retry, or an automation run by hand. |
| `heartbeat` | No current wake sets it. |
| `unknown` | No source was recorded. |

## Fields

<ResponseField name="object" type="string" required>Always `run`.</ResponseField>
<ResponseField name="id" type="string" required>Public id, `run_…`.</ResponseField>
<ResponseField name="status" type="string" required>`queued`, `running`, `succeeded`, `failed` or `cancelled`.</ResponseField>
<ResponseField name="agent" type="object">`id` (`agt_…`), `handle` and `name`. Null when the agent row is missing.</ResponseField>
<ResponseField name="task" type="object">`id` (the task key, such as `PIN-12`) and `title`. Null for a run with no task.</ResponseField>
<ResponseField name="triggerSource" type="string" required>What woke the run.</ResponseField>
<ResponseField name="errorCode" type="string">Stored error code. Null on a live run.</ResponseField>
<ResponseField name="gateReason" type="string">Why a queued run waits. Null when nothing holds it.</ResponseField>
<ResponseField name="gateDescription" type="string">Plain words for `gateReason`. Null when nothing holds it.</ResponseField>

<ResponseField name="waitingOn" type="object">
  Null unless an open approval or question holds the run.

  <Expandable title="properties">
    <ResponseField name="kind" type="string" required>`approval` or `question`.</ResponseField>
    <ResponseField name="id" type="string" required>`apr_…` or `qst_…`.</ResponseField>
    <ResponseField name="label" type="string" required>What you are being asked.</ResponseField>
    <ResponseField name="since" type="string" required>When it was raised.</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="harness" type="object" required>`id` of the harness that ran it.</ResponseField>
<ResponseField name="environment" type="object" required>`id`, plus `deviceName`, `deviceId` and `deviceLiveness` for a device run.</ResponseField>
<ResponseField name="costUsd" type="string">Cost as a decimal string. Null when not measured.</ResponseField>
<ResponseField name="createdAt" type="string" required>When the wake created it.</ResponseField>
<ResponseField name="startedAt" type="string">Null until it starts.</ResponseField>
<ResponseField name="completedAt" type="string">Null until it ends.</ResponseField>

`GET /runs/{runId}` adds these fields:

<ResponseField name="exitReason" type="string">One of the exit reasons above. Null on a live run.</ResponseField>
<ResponseField name="errorMessage" type="string">Error text. Null when there is none.</ResponseField>
<ResponseField name="parentRunId" type="string">The run this one continued. Null when it started fresh.</ResponseField>
<ResponseField name="successorRunId" type="string">The run that continued this one. Null when none did.</ResponseField>
<ResponseField name="conversationId" type="string">`cnv_…` of the run's conversation. Null when headless.</ResponseField>

<ResponseField name="effectiveSettings" type="object">
  Settings the run resolved. Null when the run has no session.

  <Expandable title="properties">
    <ResponseField name="modelId" type="string">Model the run used.</ResponseField>
    <ResponseField name="accessMode" type="string" required>`credits`, `byok` or `subscription`.</ResponseField>
    <ResponseField name="providerKeyId" type="string">Provider key, for `byok` and `subscription`. Null for `credits`.</ResponseField>
    <ResponseField name="reasoningEffort" type="string">Resolved reasoning effort.</ResponseField>
    <ResponseField name="mode" type="string" required>`agent_default`, `plan`, `ask` or `full`.</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="toolCallCount" type="integer">Tool calls made. Null when not counted.</ResponseField>
<ResponseField name="terminalAt" type="string">When it ended. Null while live.</ResponseField>

## Start a run

`POST /api/v1/agents/{agentId}/runs` starts a run. The body takes `taskId`, `prompt`, `source` and `idempotencyKey`. `taskId` takes a `tsk_…` id, a task key or `current`. `source` is `on_demand` by default, or `assignment` or `mention`. The response `kind` is one of these:

| `kind` | Means |
| - | - |
| `queued` | A new run is queued. `runPublicId` names it. |
| `pending` | A new run exists, and `gateReason` holds it. |
| `coalesced` | No new run. The wake folded into `coalescedIntoRunPublicId`. |
| `declined` | The run was created and ended at once. `exitReason` says why. |
| `not_dispatched` | No run was created. `reason` and `message` say why. |

For `not_dispatched`, `reason` names the cause. With `task_hitl_open`, `blockedBy` names the open approval or question. Values: `agent_inactive`, `agent_tombstoned`, `workspace_agents_paused`, `budget_blocked`, `timer_all_tasks_hitl_paused`, `task_hitl_open`, `task_blocked_dependency`, `task_already_finished`, `task_not_started`, `task_unassigned`, `folder_bind_failed`, `route_gate_declined`, `internal_error`, `dispatch_build_failed`.

## CLI

| Command | Does |
| - | - |
| `pinework run create` | Start a run. `--agent` is required. `--wait` blocks until it ends. |
| `pinework run list` | List runs, newest first. Filter with `--agent`, `--task` or `--status`. |
| `pinework run get <run> …` | Read one or more runs with their status and reason. |
| `pinework run read <run>` | Print the final answer. `--full` prints the transcript. |
| `pinework run events <run>` | List events, oldest first. `--sort desc` reads the tail. |
| `pinework run context <run>` | Print the prompt the run received. |
| `pinework run manifest <run>` | Print the redacted record of the run's setup. |
| `pinework run cancel <run>` | Cancel a run. Refuses a run waiting on you unless `--force`. |
| `pinework run retry <run>` | Retry a failed or cancelled run. |
| `pinework run output` | Record this run's typed output from `--file`. Only the run itself can call it. |

```bash theme={null}
pinework run create --agent @builder --task PIN-42 --prompt "Fix the flaky login test" --wait
pinework run list --agent @builder --status failed
pinework run get run_AbCdEfGh12345678 --expand latestEvents
pinework run retry run_AbCdEfGh12345678 --reason "Provider outage is over"
```

## API

| Method | Path | Does |
| - | - | - |
| POST | `/api/v1/agents/{agentId}/runs` | Start a run. |
| POST | `/api/v1/agents/{agentId}/wakeup` | Older path with the same body and result. `run create` uses it. |
| GET | `/api/v1/runs` | List runs. Filter by `agent`, `task`, `status`, `triggerSource`, `since`, `until`. `ids=a,b` reads several. |
| GET | `/api/v1/runs/{runId}` | Read one run. `expand[]` takes `latestEvents` or `transcriptRead`. |
| GET | `/api/v1/runs/{runId}/events` | List events. Pages with `limit` and `after`. |
| GET | `/api/v1/runs/{runId}/events/{eventId}` | Read one event. |
| GET | `/api/v1/runs/{runId}/context` | Read the prompt the harness received. |
| GET | `/api/v1/runs/{runId}/manifest` | Read the redacted setup: rules, skills, permissions, env key names. |
| GET | `/api/v1/runs/{runId}/change-set` | Read the diff against the commit the run began on. |
| POST | `/api/v1/runs/{runId}/cancel` | Cancel a live run. Body `{reason}`. |
| POST | `/api/v1/runs/{runId}/retry` | Retry a failed or cancelled run. Returns the new `runId`. |
| POST | `/api/v1/runs/{runId}/output` | Record typed output. Only the run's own token may call it. |

A workspace admin can cancel or retry any run. So can the owner of the run's agent, or of an agent above it. An agent can cancel or retry only its own runs.

## Errors

| Code | HTTP | When | What to do |
| - | - | - | - |
| `run.not_cancellable` | 409 | The run has already ended. | Nothing to cancel. |
| `run.not_retriable` | 409 | The run is live, or it `succeeded`. | Retry only a failed or cancelled run. |
| `run.not_retriable` | 503 | The retry wake was not dispatched. The message gives the reason. | Fix the reason, then retry. |
| `run.cancel_forbidden` | 403 | You may not cancel or retry this run. | Ask a workspace admin or the agent's owner. |
| `run.manifest_not_pinned` | 404 | The run has no stored manifest. | Older runs have none. |
| `run.context_not_stored` | 404 | The run has no stored prompt. | Older and coalesced runs have none. |
| `expand.not_allowed_on_list` | 400 | `GET /runs` got `expand[]`. | Expand on `GET /runs/{runId}`. |
| `expand_unknown` | 400 | `expand[]` named an unknown value. | Use `latestEvents` or `transcriptRead`. |
| `too_many_ids` | 400 | `ids` held more than 100 values. | Split the request. |
| `run_output.not_this_run` | 403 | A caller other than the run recorded output. | Call it from inside the run. |
| `run_output.run_terminal` | 409 | The run has ended. | Output is final once the run ends. |
| `run_output.invalid` | 422 | The data does not match the named schema. | Fix the field named in `param`. |
| `credits_harness_unsupported` | 422 | A credits cloud run named a harness other than Claude Code or OpenCode. | Change the harness, or pay with a key or subscription. |
| `credential_unbrokerable` | 422 | A cloud run's API key cannot be used on that harness. | Run on a device, or change model or harness. |

`GET /runs/{runId}/change-set` can also return `source_unknown` (404), `repo_unavailable` (409), `too_large` (413) or `diff_unavailable` (502). Shared codes are in [API errors](/reference/api#errors).

## Limits

* Max turns per run: the agent's `maxTurns` (1 to 1,000), else the workspace's `defaultMaxTurns`, else no cap.
* A run's timeout is 23 hours 55 minutes.
* Recovery treats a run claimed more than 23 hours 50 minutes ago as expired.
* One command in a cloud sandbox runs at most 5 hours.
* A run may make 1,000 tool calls. A cloud run warns the agent at 800.
* A device runs 3 runs at once by default. You can set 1 to 10.
* `run create --wait` waits 300,000 ms by default and 86,400,000 ms at most.
* `GET /runs` returns 25 per page by default and 100 at most. Events return 100 by default and 500 at most.

<CardGroup cols={2}>
  <Card title="Runs" href="/concepts/runs">
    What a run carries from one wake to the next.
  </Card>

  <Card title="Agent" href="/reference/agent">
    The settings a run starts from.
  </Card>

  <Card title="Approval" href="/reference/approval">
    What a run waits on when it asks first.
  </Card>

  <Card title="Environment and device" href="/reference/environment-and-device">
    Where a run executes.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.