Siglo. They execute a series of steps in strict order, passing accumulated context forward.
1. Constructing Steps
UseStep.create(name, action) to define an isolated step:
2. Composing Sequences with flow()
Compose multiple steps into a sequential pipeline using flow(...steps):
3. Step Lifecycles
Every step supports declarative lifecycle hooks and validation rules:spec(field, rules) and schema(StandardSchema)
Validate input context before running the step action:
onBefore(predicate)
Conditionally execute or skip the step action based on context:
onSkip(fallbackAction)
Provide fallback data when a step is skipped by onBefore:
onAfter(transformer)
Enrich or transform step output before context assignment:
cache(ttlMs)
Cache step output in memory or across distributed storage:
Minimal Example
Failure Example: Handling Validation & Lifecycle Rejections
Testing Example
createWorkflowHarness records both start and complete phases in its execution trace:
Operational Caveats
- Step Granularity: Do not make every line of code its own step. Separate steps by logical domain boundaries, external I/O operations, or rollback requirements.
- Deterministic Inputs: Keep input parameters serializable JSON objects. Avoid passing database connection instances, sockets, or open file descriptors directly through the workflow context. Use dependency injection instead (
step.withDependencies()oroptions.services). - Execution Mode (
pojo): By default,run()wraps return values with metadata accessors ($steps,$attempt, etc.). Pass{ pojo: true }in HTTP endpoints to strip helper accessors and return plain JSON directly.
