# Workflows

> Durable execution on append-only run streams.

Source: https://docs.pyrula.io/workflows/

Straight-line async Python that survives crashes. Finished steps are read back from the run's journal, not re-run.

```python
from pyrula.workflows import step, workflow

@step
def reserve(order: str) -> None:
    reserve_inventory(order)

@step
def charge(order: str) -> None:
    charge_card(order)

@step
def receipt(order: str) -> dict:
    return send_receipt(order)

@workflow(name="checkout")
async def checkout(ctx, order: str) -> dict:
    await reserve(order)
    await charge(order)
    await ctx.sleep(3600)                       # the worker is freed while it waits
    return await receipt(order)
```

Start with the [Quickstart](https://docs.pyrula.io/workflows/quickstart.md).

| You want to | Use | Guide |
|---|---|---|
| Start runs, signal, query, update, wait for results | `WorkflowClient` | [Starting and talking to runs](https://docs.pyrula.io/workflows/guides/client.md) |
| Run a side effect once | `@step`, `ctx.once` | [Steps](https://docs.pyrula.io/workflows/guides/steps.md) |
| Retry, or fail fast on bad input | `RetryPolicy`, `Transient` / `Poison` / `Fatal` | [Errors and retries](https://docs.pyrula.io/workflows/guides/errors-and-retries.md) |
| Wait for time | `ctx.sleep`, `ctx.sleep_until` | [Timers](https://docs.pyrula.io/workflows/guides/timers.md) |
| Wait for an outside event, expose state | `ctx.wait_for_signal`, `ctx.on_query`, `ctx.on_update` | [Signals, queries and updates](https://docs.pyrula.io/workflows/guides/signals.md) |
| Ask a human | `ctx.interrupt` | [Human-in-the-loop](https://docs.pyrula.io/workflows/guides/human-in-the-loop.md) |
| Run steps in parallel, start sub-workflows | `ctx.gather`, `ctx.run_child` | [Parallel steps and child runs](https://docs.pyrula.io/workflows/guides/parallel-and-children.md) |
| Cap per-tenant concurrency or rate, batch events | `Limit`, `Rate`, `Collect`, `Debounce` | [Flow control](https://docs.pyrula.io/workflows/guides/flow-control.md) |
| Run on a schedule | `Schedule` | [Schedules](https://docs.pyrula.io/workflows/guides/worker.md#schedules) |
| Ship code with runs in flight | `version=`, `ctx.patched` | [Versioning and deploys](https://docs.pyrula.io/workflows/guides/versioning.md) |
| Process a Kafka topic | `@kafka_workflow` | [Kafka](https://docs.pyrula.io/workflows/guides/kafka.md) |
| Serve runs over HTTP | `RunRouter` | [Serving over HTTP](https://docs.pyrula.io/workflows/guides/http.md) |
| Trace and measure | OpenTelemetry | [Observability](https://docs.pyrula.io/workflows/guides/observability.md) |

[Agents](https://docs.pyrula.io/agents.md) are built on this engine.
