# Workflows

URL: /code/platform/workflows · Id: `capability:workflows`

> Workflows run the durable body of one Action: steps, waits, retries and hand-offs that survive restarts.

[Workflows](/business/nouns/workflow) run the durable body of one [Action](/business/nouns/action): steps, waits, retries and hand-offs that survive restarts. Each step's result is recorded before the next step starts.

## Contract
A [Process](/business/nouns/process) names one or more Workflows and the [Trigger](/business/nouns/trigger) that starts each: an [Event](/business/nouns/event), a schedule, or a [Thing](/business/nouns/thing) entering a state. Each step calls one [Function](/business/nouns/function) and declares what happens when it fails.

| Guarantee | Detail |
| --- | --- |
| Durable | After a crash, the run resumes at the first unrecorded step; finished steps never run again |
| Exactly once outside | A step that reaches the outside world carries an idempotency key, so a retry never charges or sends twice |
| Free waits | `sleep('30d')` and `waitForEvent` consume nothing while waiting |
| Delay windows | A one-way step waits as `pending` with reason `awaitingTime`, so a watcher can intervene |
| Readable status | `pending` names its reason: `queued`, `running`, `retrying`, `awaitingWorker`, `awaitingInput`, `awaitingSource`, `awaitingAction` or `awaitingTime` |
| Final status | `done`, `failed`, `canceled` (compensation ran) or `refused` (a check stopped it first) |
| Steerable | [Cancel](/business/nouns/action/cancel), [retry](/business/nouns/action/retry) as a new linked Action, or [redirect](/business/nouns/action/redirect) with new inputs |

A wait on a [Worker](/business/nouns/worker) is a [Task](/business/nouns/task) in that Worker's inbox. A caller picks a [Mode](/business/nouns/mode) per call: `do` waits for the result, and `send` returns the `pending` Action at once. [Functions](/code/platform/capabilities/functions) covers what runs each step.

## Verbs
| Verb | Object | Event |
| --- | --- | --- |
| [Workflow.create](/business/nouns/workflow/create) | [Workflow](/business/nouns/workflow) | `Workflow.created` |
| [Workflow.get](/business/nouns/workflow/get) | [Workflow](/business/nouns/workflow) | None. |

## Interfaces
- [API](/code/api/reference)
- [SDK](/code/sdk/reference)
- [CLI](/code/cli/reference)
- [MCP](/code/mcp/reference)

## Example
```ts
// minutely.app, a meeting-notes App, converts trials with one Workflow.
import { $, workflow } from 'startup-builder'

export default workflow({
  name: 'trial-to-paid',
  execute: async (ctx, { customer }) => {
    await ctx.step('welcome', () => $.Message.create({ medium: 'email', direction: 'outbound', to: customer, purpose: 'onboarding', body: 'Welcome aboard.' }))
    const paid = await ctx.waitForEvent('Order.paid', { where: { customer }, timeout: '14d' })
    if (!paid) {
      const task = await ctx.step('check-in', () => $.do.Task.create({ for: customer, priority: 1 }))
      await ctx.step('route', () => $.Task.delegate({ task: task.$id, role: 'success-lead' }))
    }
  },
})
```