# Action

URL: /business/nouns/action · Id: `noun:action`

> An Action is one Verb performed by a Worker on a Thing, recorded with its status and every Event it emits.

An Action is one [Verb](/business/nouns/verb) performed by a [Worker](/business/nouns/worker) on a [Thing](/business/nouns/thing), recorded with its status and every [Event](/business/nouns/event) it emits. Its [Approvals](/business/nouns/approval) and [Costs](/business/nouns/cost) attach to it, so one record shows who did what, and why.

## Properties
| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `status` | `string` | Yes | One of `pending`, `done`, `failed`, `canceled`, or `refused`. |
| `reason` | `string` | No | Why a pending Action waits: `queued`, `running`, `retrying`, `awaitingWorker`, `awaitingInput`, `awaitingSource`, `awaitingAction`, or `awaitingTime`. |
| `mode` | `string` | Yes | How the caller invoked it: `try`, `send`, or `do`. |
| `by` | [Worker](/business/nouns/worker) | No | The Worker that performed it. |
| `for` | [Party](/business/nouns/party) | No | The Party it was done on behalf of. |
| `via` | `string` | No | The Interface or request it arrived through. |
| `on` | `string` | No | The Action or Event that caused it, such as the failed attempt a retry follows. |
| `thing` | `string` | No | The record, at the Version the Action was decided against. |
| `input` | `json` | No | The input it was called with. |
| `createdAt` | `datetime` | No | When it was called. |
| `reserved` | `money` | No | The most this Action may cost, held against its Limits from the check until it settles, billed misses included. |

## Object
```json
{
  "$id": "https://api.sb/quietcopy.com/actions/action_1",
  "$type": "Action",
  "status": "pending",
  "reason": "queued",
  "mode": "try",
  "by": "worker_1",
  "for": "party_1",
  "via": "API",
  "on": "Invoice.overdue",
  "thing": "invoice_1@v3",
  "input": {},
  "createdAt": "2026-10-22T12:00:00Z",
  "reserved": {
    "amount": 39,
    "currency": "USD"
  }
}
```

## Relationships
- <a id="rel-acts-on"></a>An Action **acts on** one [Thing](/business/nouns/thing): the [Thing](/business/nouns/thing) an Action changes; a Thing’s history is the Actions that acted on it. `actsOn`, inverse [`actedOnBy`](/business/nouns/thing#rel-acted-on-by).
- <a id="rel-approvals"></a>An Action **has** many [Approvals](/business/nouns/approval): an [Approval](/business/nouns/approval) holds one pending Action that exceeds a [Limit](/business/nouns/limit) or [Mandate](/business/nouns/mandate) until someone allows or refuses it. `approvals`, inverse [`gates`](/business/nouns/approval#rel-gates).
- <a id="rel-asks"></a>An Action **asks** many [Questions](/business/nouns/question): a pending Action asks [Questions](/business/nouns/question) and waits `awaitingInput` until each is answered or its deadline passes. `asks`, inverse [`action`](/business/nouns/question#rel-action).
- <a id="rel-emits"></a>An Action **emits** many [Events](/business/nouns/event): a completed Action emits its [Events](/business/nouns/event), which [Triggers](/business/nouns/trigger), [Watches](/business/nouns/watch) and [Metrics](/business/nouns/metric) read. `emits`, inverse [`emittedBy`](/business/nouns/event#rel-emitted-by).
- <a id="rel-executed-by"></a>An Action **is executed by** one [Workflow](/business/nouns/workflow): a [Workflow](/business/nouns/workflow) is the durable body of one Action: its steps, retries and waits. `executedBy`, inverse [`executes`](/business/nouns/workflow#rel-executes).
- <a id="rel-invokes"></a>An Action **invokes** one [Verb](/business/nouns/verb): each Action performs one [Verb](/business/nouns/verb), which fixes its inputs, the [Event](/business/nouns/event) it emits and its delay window. `invokes`, inverse [`invokedAs`](/business/nouns/verb#rel-invoked-as).
- <a id="rel-posts"></a>An Action **posts** many [Costs](/business/nouns/cost): every [Cost](/business/nouns/cost) an Action causes posts to the [Startup](/business/nouns/startup) it ran in, so each Startup’s P&L is complete. `posts`, inverse [`postedBy`](/business/nouns/cost#rel-posted-by).
- <a id="rel-runs-in"></a>An Action **runs in** one [Mode](/business/nouns/mode): the [Mode](/business/nouns/mode) the caller chose: `try` stores nothing, `send` returns a pending Action, `do` waits for the result. `runsIn`, inverse [`modeOf`](/business/nouns/mode#rel-mode-of).

## Lifecycle

| State | Meaning | Moves to |
| --- | --- | --- |
| `pending` (first) | Accepted and not finished; its `reason` names who holds the ball. | `done` on [`Action.done`](/business/nouns/action#actiondone); `failed` on [`Action.failed`](/business/nouns/action#actionfailed); `canceled` by [Action.cancel](/business/nouns/action/cancel); `refused` on [`Approval.refused`](/business/events/Approval.refused) when the Approval holds this Action |
| `done` | It finished and its effects are written. | None: it ends here. |
| `failed` | It stopped with an error; a retry is a new Action linked to this one. | None: it ends here. |
| `canceled` | It was stopped before it finished, and its compensation ran. | None: it ends here. |
| `refused` | A Guard, a Limit or an Approval refused it, with the reason. | None: it ends here. |

## Verbs
| Verb | Description | Subject | Event | Class |
| --- | --- | --- | --- | --- |
| [Action.answer](/business/nouns/action/answer) | Answer gives the reply to an Action’s open Question, through any Interface, and the Action resumes. | [Party](/business/nouns/party) | [`Action.answered`](/business/events/Action.answered) | Two-way: `try`, `send`, `do` |
| [Action.ask](/business/nouns/action/ask) | Ask puts a Question to a Party, a Role, or a Worker and holds the Action `pending` with reason `awaitingInput`. | [Worker](/business/nouns/worker) | [`Action.asked`](/business/events/Action.asked) | Two-way: `try`, `send`, `do` |
| [Action.attest](/business/nouns/action/attest) | Attest records a credentialed Human’s signed performance of a Reserved Act that an Action needs to finish. | [Legal Lead](/agents/legal/legal-lead) | [`Action.attested`](/business/events/Action.attested) | None. |
| [Action.cancel](/business/nouns/action/cancel) | Cancel stops a pending Action, sets its status to `canceled`, and runs its compensation. | [Risk Analyst](/agents/operations/risk-analyst) | [`Action.canceled`](/business/events/Action.canceled) | None. |
| [Action.evaluate](/business/nouns/action/evaluate) | Evaluate grades an Action’s output against a rubric and records the verdict as an Event. | [Quality Lead](/agents/quality/quality-lead) | [`Action.evaluated`](/business/events/Action.evaluated) | None. |
| [Action.pause](/business/nouns/action/pause) | Pause holds a pending Action past the close of its delay window until a watcher resumes, redirects, or cancels it. | [Worker](/business/nouns/worker) | [`Action.paused`](/business/events/Action.paused) | None. |
| [Action.redirect](/business/nouns/action/redirect) | Redirect changes a pending Action’s inputs or target inside its delay window, before it runs. | [Operations Lead](/agents/operations/operations-lead) | [`Action.redirected`](/business/events/Action.redirected) | None. |
| [Action.resume](/business/nouns/action/resume) | Resume ends a pause and lets the Action run as reviewed, or reopen what remained of its delay window. | [Worker](/business/nouns/worker) | [`Action.resumed`](/business/events/Action.resumed) | None. |
| [Action.retry](/business/nouns/action/retry) | Retry runs a failed Action again as a new Action linked to the one that failed. | [Reliability Engineer](/agents/engineering/reliability-engineer) | [`Action.retried`](/business/events/Action.retried) | None. |
| <a id="create"></a>[Action.create](/business/nouns/action/create) | Creates an Action. Inherited from [Noun](/business/nouns/noun). | None. | `Action.created` | Two-way: `try`, `send`, `do` |
| <a id="get"></a>[Action.get](/business/nouns/action/get) | Returns one Action by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` |
| <a id="list"></a>[Action.list](/business/nouns/action/list) | Returns Actions, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` |

An Action is kept forever and never edited: it has no `update` or `delete`.

## Events
Events no Verb emits. Each Verb’s Event is in the Verbs table above; every Event is delivered in the same shape.

### Action.done
An Action’s work finished and its effects are written. Raised by the runtime.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | `string` | Yes | `Action.done`. |
| `at` | `datetime` | Yes | When it happened. |
| `seq` | `integer` | No | Its position in the namespace, one more than the Event before; any seq is a cursor into the history. |
| `data` | `json` | Yes | The Thing as the Action left it. |
| `data.action` | [Action](/business/nouns/action) | Yes | The Action as the change left it. |
| `data.action.status` | `string` | Yes | One of `pending`, `done`, `failed`, `canceled`, or `refused`. |
| `data.action.reason` | `string` | No | Why a pending Action waits: `queued`, `running`, `retrying`, `awaitingWorker`, `awaitingInput`, `awaitingSource`, `awaitingAction`, or `awaitingTime`. |
| `data.action.mode` | `string` | Yes | How the caller invoked it: `try`, `send`, or `do`. |
| `data.action.by` | [Worker](/business/nouns/worker) | No | The Worker that performed it. |
| `data.action.for` | [Party](/business/nouns/party) | No | The Party it was done on behalf of. |
| `data.action.via` | `string` | No | The Interface or request it arrived through. |
| `data.action.on` | `string` | No | The Action or Event that caused it, such as the failed attempt a retry follows. |
| `data.action.thing` | `string` | No | The record, at the Version the Action was decided against. |
| `data.action.input` | `json` | No | The input it was called with. |
| `data.action.createdAt` | `datetime` | No | When it was called. |
| `data.action.reserved` | `money` | No | The most this Action may cost, held against its Limits from the check until it settles, billed misses included. |
| `data.previous.status` | `string` | Yes | The `status` before this Event: `pending`. |

```json
{
  "$id": "https://api.sb/quietcopy.com/events/event_1",
  "$type": "Event",
  "name": "Action.done",
  "at": "2026-10-22T12:00:00Z",
  "data": {
    "action": {
      "$id": "https://api.sb/quietcopy.com/actions/action_1",
      "$type": "Action",
      "status": "done",
      "reason": "queued",
      "mode": "try",
      "by": "worker_1",
      "for": "party_1",
      "via": "API",
      "on": "Invoice.overdue",
      "thing": "invoice_1@v3",
      "input": {},
      "createdAt": "2026-10-22T12:00:00Z",
      "reserved": {
        "amount": 39,
        "currency": "USD"
      }
    },
    "previous": {
      "status": "pending"
    }
  },
  "seq": 1
}
```

### Action.failed
An Action stopped with an error before it finished; a retry is a new Action. Raised by the runtime.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | `string` | Yes | `Action.failed`. |
| `at` | `datetime` | Yes | When it happened. |
| `seq` | `integer` | No | Its position in the namespace, one more than the Event before; any seq is a cursor into the history. |
| `data` | `json` | Yes | The Thing as the Action left it. |
| `data.action` | [Action](/business/nouns/action) | Yes | The Action as the change left it. |
| `data.action.status` | `string` | Yes | One of `pending`, `done`, `failed`, `canceled`, or `refused`. |
| `data.action.reason` | `string` | No | Why a pending Action waits: `queued`, `running`, `retrying`, `awaitingWorker`, `awaitingInput`, `awaitingSource`, `awaitingAction`, or `awaitingTime`. |
| `data.action.mode` | `string` | Yes | How the caller invoked it: `try`, `send`, or `do`. |
| `data.action.by` | [Worker](/business/nouns/worker) | No | The Worker that performed it. |
| `data.action.for` | [Party](/business/nouns/party) | No | The Party it was done on behalf of. |
| `data.action.via` | `string` | No | The Interface or request it arrived through. |
| `data.action.on` | `string` | No | The Action or Event that caused it, such as the failed attempt a retry follows. |
| `data.action.thing` | `string` | No | The record, at the Version the Action was decided against. |
| `data.action.input` | `json` | No | The input it was called with. |
| `data.action.createdAt` | `datetime` | No | When it was called. |
| `data.action.reserved` | `money` | No | The most this Action may cost, held against its Limits from the check until it settles, billed misses included. |
| `data.error` | `string` | Yes | The error it stopped with; its page gives the fix. |
| `data.previous.status` | `string` | Yes | The `status` before this Event: `pending`. |

```json
{
  "$id": "https://api.sb/quietcopy.com/events/event_1",
  "$type": "Event",
  "name": "Action.failed",
  "at": "2026-10-22T12:00:00Z",
  "data": {
    "action": {
      "$id": "https://api.sb/quietcopy.com/actions/action_1",
      "$type": "Action",
      "status": "failed",
      "reason": "queued",
      "mode": "try",
      "by": "worker_1",
      "for": "party_1",
      "via": "API",
      "on": "Invoice.overdue",
      "thing": "invoice_1@v3",
      "input": {},
      "createdAt": "2026-10-22T12:00:00Z",
      "reserved": {
        "amount": 39,
        "currency": "USD"
      }
    },
    "error": "conflict",
    "previous": {
      "status": "pending"
    }
  },
  "seq": 1
}
```

## Permissions
Which Access level may call each Verb. One-way Verbs wait their delay window.

| Operation | `owner` | `admin` | `member` | `viewer` |
| --- | --- | --- | --- | --- |
| `Action.create` | Yes | Yes | Yes | No |
| `Action.get` | Yes | Yes | Yes | Yes |
| `Action.list` | Yes | Yes | Yes | Yes |
| `Action.answer` | Yes | Yes | Yes | No |
| `Action.ask` | Yes | Yes | Yes | No |
| `Action.attest` | Yes | Yes | Yes | No |
| `Action.cancel` | Yes | Yes | Yes | No |
| `Action.evaluate` | Yes | Yes | Yes | No |
| `Action.pause` | Yes | Yes | Yes | No |
| `Action.redirect` | Yes | Yes | Yes | No |
| `Action.resume` | Yes | Yes | Yes | No |
| `Action.retry` | Yes | Yes | Yes | No |

## Call it

**Ask**

```text
Cancel the latest action.
```

**API**

```bash
curl -X POST https://api.sb/petpantry.shop/actions/action_1/cancel \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"
```

```json
{
  "api": "https://api.sb/petpantry.shop",
  "action": {
    "$id": "https://api.sb/petpantry.shop/actions/action_1",
    "$type": "Action",
    "status": "done",
    "mode": "try",
    "operation": "Action.cancel"
  },
  "links": {
    "self": "https://api.sb/petpantry.shop/actions/action_1"
  }
}
```

**SDK**

```ts
import { $ } from 'startup-builder'

const action = await $.Action.cancel({ action: 'action_1' })
```

**CLI**

```bash
npx startup-builder do Action.cancel --json '{"action":"action_1"}'
```

**MCP**

```json
{
  "name": "do",
  "arguments": {
    "code": "return await $.Action.cancel({ action: 'action_1' })"
  }
}
```

## Example
Bea, the [Billing Specialist](/agents/finance/billing-specialist) at a voice-actor marketplace, runs [`Order.refund`](/business/nouns/order/refund) on a $90 [Order](/business/nouns/order). The Action records `by: Bea`, `for` the game studio that asked, `mode: do` and `status: Done`, and emits `Order.refunded`.