Workflows
Write straight-line async Python that survives the process it started in. A worker that dies mid-run doesn’t lose the run or redo finished work: completed steps are read back from the run’s journal instead of executed again.
from pyrula.workflows import step, workflow
@stepdef reserve(order: str) -> None: reserve_inventory(order)
@stepdef charge(order: str) -> None: charge_card(order)
@stepdef 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.
| You want to | Use | Guide |
|---|---|---|
| Start runs, signal, query, update, wait for results | WorkflowClient | Starting and talking to runs |
| Run a side effect once | @step, ctx.once | Steps |
| Retry, or fail fast on bad input | RetryPolicy, Transient / Poison / Fatal | Errors and retries |
| Wait for time | ctx.sleep, ctx.sleep_until | Timers |
| Wait for an outside event, expose state | ctx.wait_for_signal, ctx.on_query, ctx.on_update | Signals, queries and updates |
| Ask a human | ctx.interrupt | Human-in-the-loop |
| Run steps in parallel, start sub-workflows | ctx.gather, ctx.run_child | Parallel steps and child runs |
| Cap per-tenant concurrency or rate, batch events | Limit, Rate, Collect, Debounce | Flow control |
| Run on a schedule | Schedule | Schedules |
| Ship code with runs in flight | version=, ctx.patched | Versioning and deploys |
| Process a Kafka topic | @kafka_workflow | Kafka |
| Serve runs over HTTP | RunRouter | Serving over HTTP |
| Trace and measure | OpenTelemetry | Observability |
Agents are built on this engine.