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

# Runs and states

> A run is one turn of a conversation. It has five states, and two of them mean the run is waiting on you.

Posting a message starts a run. The response is `202` — the turn is accepted, not finished:

```json theme={null}
{ "run_id": "7c9e6679-…", "thread_id": "3fa85f64-…", "state": "running" }
```

From there the run either finishes on its own or stops and waits for you. Knowing which is the whole job of this page.

## The five states

| State | Meaning | Your move |
| - | - | - |
| `running` | The agent is working. | Wait. |
| `awaiting_input` | The run is paused and needs something from you. | **Two possibilities — see below.** |
| `awaiting_outcome` | The agent proposed an action you must carry out. | Report what happened. |
| `closed` | The turn finished. | None. |
| `failed` | The turn failed. | None. |

`closed` and `failed` are terminal — the run will never change again, and the `terminal` field on the run object is `true`. Everything else can still move:

```
running ──▶ awaiting_input ──▶ running ──▶ closed
   │                                          
   ├──────▶ awaiting_outcome ──▶ running ──▶ failed
   │
   └──────▶ closed | failed
```

A paused run always returns to `running` before it can close. Nothing transitions directly out of `awaiting_input` to a terminal state except `failed`.

## `awaiting_input` is two different situations

This is the part worth reading twice. A run pauses in `awaiting_input` for either of two reasons, and they need **different API calls** to resume.

| Situation | What happened | How you resume |
| - | - | - |
| **A question** | The agent asked something — `ask_user`, `ask_choice`. | Post a normal message to the thread. |
| **A write confirmation** | The agent wants to perform a write held at an approval gate. | `POST /v1/loom/runs/:run_id/confirm`. See [Confirmations](/guides/confirmations). |

The state string is identical in both cases. Posting a message to resolve a confirmation does not work — you get `422 awaiting_confirmation` telling you a decision is pending.

## Telling them apart

`GET /v1/loom/threads` returns three fields that name exactly what each thread is waiting for. At most one is ever non-null.

<ResponseField name="pending_elicitation" type="object">
  A question is waiting. Resume by posting a message.

  <Expandable title="properties">
    <ResponseField name="run_id" type="uuid">The paused run.</ResponseField>
    <ResponseField name="kind" type="string">`ask_user` or `ask_choice`.</ResponseField>
    <ResponseField name="prompt" type="object">What the agent asked.</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="pending_confirmation" type="object">
  A write is held at an approval gate. Resume by approving or rejecting.

  <Expandable title="properties">
    <ResponseField name="run_id" type="uuid">The paused run.</ResponseField>
    <ResponseField name="tool_call_id" type="uuid">Pass this to the confirm endpoint.</ResponseField>
    <ResponseField name="patch_ref" type="string">The patch the agent wants to call.</ResponseField>
    <ResponseField name="summary" type="object">A human-readable description of the write, for your approval UI.</ResponseField>
    <ResponseField name="risk" type="string">The effective risk level of the call.</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="pending_action" type="object">
  The agent proposed an action for **you** to perform. Resume by reporting the outcome.

  <Expandable title="properties">
    <ResponseField name="run_id" type="uuid">The waiting run.</ResponseField>
    <ResponseField name="tool_call_id" type="uuid">Pass this to the outcome endpoint.</ResponseField>
    <ResponseField name="patch_ref" type="string">The proposed action.</ResponseField>
    <ResponseField name="args" type="object">What the agent proposed doing.</ResponseField>
  </Expandable>
</ResponseField>

<Note>
  `GET /v1/loom/runs/:id` returns the run's `state` but not these fields. If you are polling and need to resume a paused run, poll `GET /v1/loom/threads` — that is where the `tool_call_id` lives.
</Note>

If you subscribe to [realtime](/api-reference/realtime), the same information arrives as events the moment the run pauses, and you do not need to poll at all.

## Confirm versus outcome

Both pause a run, both take a `tool_call_id`, and they are easy to confuse. The difference is **who performs the work**.

| | Confirmation | Outcome |
| - | - | - |
| **State** | `awaiting_input` | `awaiting_outcome` |
| **Field** | `pending_confirmation` | `pending_action` |
| **Who executes** | Patchwork, after you approve | You, before you report |
| **Endpoint** | `POST /v1/loom/runs/:run_id/confirm` | `POST /v1/loom/runs/:run_id/outcome` |
| **Body** | `decision: approve \| reject` | `state: occurred \| failed` |

A confirmation asks permission before we act. An outcome asks what happened after you acted.

## Watching a run finish

Three options, in order of how much work they cost you:

1. **Realtime.** Subscribe to the thread channel and receive `run.completed`, `run.failed`, and the pause events as they happen.
2. **Webhooks.** Register an endpoint for `run.completed` and `run.failed` — and, if you are headless, for the pause events too. A run parked at one of those waits until you answer.
3. **Polling.** `GET /v1/loom/runs/:id` until `terminal` is `true`. Poll `GET /v1/loom/threads` instead if the run might pause.

## What a finished run tells you

`GET /v1/loom/runs/:id` returns the final state, the assistant's message, the connection used, and `cost_credits` for the turn.

For the full picture — every model call, every tool call, arguments, results, risk, and timings — fetch `GET /v1/loom/runs/:id/trace`. The trace is the record of what the agent actually did, and it is the first place to look when a run did something you did not expect.


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