# Actions

URL: /code/sdk/guides/actions · Id: `page:code/sdk/guides/actions`

> Every write returns an Action, one record of which Verb ran on what, by whom and for whom, and where it stands until it settles.

An [Action](/business/nouns/action) is the record of one [Verb](/business/nouns/verb) run on one [Thing](/business/nouns/thing). Every write on every [Interface](/business/nouns/interface) returns one, whether code, a model, an [Agent](/business/nouns/agent) or a [Human](/business/nouns/human) does the work.

## Anatomy of an Action
`tutorloop.com` is a [Startup](/business/nouns/startup) that matches students with tutors. Its booking Agent places an [Order](/business/nouns/order) for an algebra hour on behalf of a [Customer](/business/nouns/customer), and no tutor has claimed it:

```json
{
  "api": "https://api.sb/tutorloop.com",
  "action": {
    "$id": "https://api.sb/tutorloop.com/actions/action_42",
    "$type": "Action",
    "operation": "Order.place",
    "status": "pending",
    "reason": "awaitingWorker",
    "mode": "send",
    "by": "https://api.sb/tutorloop.com/agents/booking",
    "for": "https://api.sb/tutorloop.com/customers/customer_9",
    "via": "mcp",
    "on": null,
    "thing": "https://api.sb/tutorloop.com/orders/order_17@1",
    "input": { "offer": "offer_algebra_hour", "slot": "2026-10-23T16:00:00Z" },
    "createdAt": "2026-10-22T14:03:11Z"
  }
}
```

| Field | Holds |
| --- | --- |
| `operation` | The Verb, as `Noun.verb` |
| `status`, `reason` | Where the Action stands, and who holds the ball while it is `pending` |
| `mode` | How it was invoked: `try`, `send` or `do` |
| `by` | The [Worker](/business/nouns/worker) that performs it |
| `for` | The [Party](/business/nouns/party) it is done on behalf of |
| `via` | The Interface or request it arrived through |
| `on` | The Action or [Event](/business/nouns/event) that caused it, such as the failed attempt a retry follows |
| `thing` | The record at the [Version](/business/nouns/version) the Action was decided against |
| `error` | The problem document, once the Action is `refused` or `failed` |

The Action never says which [Function](/business/nouns/function) did the work. `tutorloop.com` can move tutor matching from a human to an Agent, and no caller sees a change.

## Five statuses
An Action is `pending` until it settles as `done`, `failed`, `canceled` or `refused`. A settled Action is final, and every status change appends an Event. While `pending`, its `reason` says who holds the ball:

| Reason | Waiting on |
| --- | --- |
| `queued`, `running`, `retrying` | The platform, which is doing the work |
| `awaitingWorker` | A Worker to claim it, such as a tutor |
| `awaitingInput` | An answer from the caller or the Customer |
| `awaitingSource` | An outside system to respond |
| `awaitingAction` | Another Action, such as an [Approval](/business/nouns/approval) |
| `awaitingTime` | A time: a schedule or a delay window |

A caller that sees `awaitingInput` acts. A caller that sees any other reason waits.

## Rejected at the door, or refused on the record
Where a call fails decides whether an Action exists. Malformed input, an unknown Verb, a missing key and a throttled request are rejected at the door. They return a problem document and record nothing.

A call the Thing itself declines is an Action born `refused`, with the reason on the record. A booking for a slot already taken, or a [Mandate](/business/nouns/mandate) that does not cover the Customer, refuses this way. The refusal stays in history next to every Action that succeeded.

## Waiting for the result
In `do` [Mode](/business/nouns/mode) the call holds until the Action settles. In `send` Mode the call answers `202` at once, with the Action's URL in `Location`.

To follow a sent Action, read it again. `Prefer: wait=30` holds the read for up to 30 seconds until the Action settles:

```bash
curl https://api.sb/tutorloop.com/actions/action_42 \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Prefer: wait=30"
```

In the SDK, `.settled` resolves to the final Action whatever its status. For work that takes hours, a [Watch](/business/nouns/watch) on `Order.placed` delivers the Event when it lands. [Webhooks](/code/api/guides/webhooks) covers delivery.

## Windows and Approvals
Some Actions wait on purpose. A one-way Verb, such as a refund or an ad spend, waits `awaitingTime` in its [delay window](/agents/autonomy-levels/delay-windows). [Watchers](/agents/autonomy-levels/watchers) can [pause](/business/nouns/action/pause), [redirect](/business/nouns/action/redirect) or [cancel](/business/nouns/action/cancel) it, and with no intervention it runs when the window closes.

An Action over a [Limit](/business/nouns/limit) waits `awaitingAction` on an Approval. The Approval covers exactly the input and Thing Version the approver saw. If the Thing changes first, the Action is `refused` and a fresh call needs a fresh Approval.

To learn whether a call waits before making it, preview it in `try` Mode. The preview returns the status the Action would reach, its window, and whether it needs an Approval.

## Retries and history
A `failed` Action stays failed. [`Action.retry`](/business/nouns/action/retry) starts a new Action whose `on` points at the old one, so the record shows both attempts. To undo a `done` Action, run the Verb that reverses it, such as a refund after a payment.

Nothing rewrites an Action. Every Action is kept forever, and its Events replay the history of every Thing it touched.

## Next
- [Idempotency](/code/api/guides/idempotency): send a write twice and get one Action.
- [Modes](/code/api/guides/modes): how `try`, `send` and `do` change what a caller sees.
- [The response envelope](/code/api/guides/envelope): the response an Action arrives in.