Authoring Workflows
Use this sequence for every durable workflow family.
1. Name Stable Payloads
Create reusable Schema values for input, success, and expected failure. Validation belongs here when it is intrinsic to the payload.
2. Declare Definitions
Use Workflow, Operation, Work, and Event. Treat code + version and name + version as published identities.
3. Implement the Workflow
Call definition.implement(...). Keep the handler deterministic:
- branch only on input or recorded results;
- use a stable
idfor every durable operation; - call
workflow.perform(...)for automated work; - call
request,waitForEvent,query,workflow,spawn,join,sleep, and structured-concurrency operations directly on the same workflow scope; - never call databases, HTTP, wall clocks, randomness, or mutable globals.
4. Implement Operations
Call Operation.implement(...) for each real handler. Forward operation.context.idempotencyKey to the external system or effect receipt.
5. Compose a Module
final module = WorkflowModule(
name: 'orders',
workflows: [orderHandler],
operations: [reserveHandler, publishHandler],
work: [approveOrder],
events: [orderChanged],
);Install modules when constructing the runtime or server. Do not mutate registries after startup.
6. Version Deliberately
Changing orchestration behavior requires a new workflow version. Changing a data incompatibly requires a new schema version and usually a new workflow or operation version.
Review Checklist
- Every await has a stable semantic ID.
- Every external effect is in an operation handler.
- Every handler can safely replay or retry.
- Expected failures use the typed
Echannel. - Work audiences come from trusted product policy.
- The module installs every referenced handler and interaction contract.
- Tests cover replay across every blocking boundary.