Skip to main content

API Reference: Step Methods (Step)

The Step class is the fundamental execution unit in Siglo. A step encapsulates an async action, parameter validation contracts, lifecycle hooks, structured retry policies, SLA deadlines, idempotency locks, caching, and saga compensations.

Table of Contents


The 5-Phase Step Lifecycle

Every step executes through five distinct, deterministic phases:
  1. Validation: Enforces parameter constraints declared via .schema() or .spec(). Rejections throw ValidationException.
  2. Pre-Execution Guard (onBefore): Evaluates whether the step should run. Returning false bypasses the action and triggers onSkip.
  3. Action Execution: Runs the step action under the configured timeout, idempotent lock, and onFail retry strategy.
  4. Post-Execution Transform (onAfter): Modifies or enriches the raw output before merging.
  5. Context Merge: Merges step output into the accumulated workflow context (or assigns it to a target property if .reduce() was configured).
[!NOTE] Network Guardrails Across Lifecycle Phases: When .allowNetwork(), .allowUnixSockets(), .denyNetwork(), or .networkPolicy() is declared, the network egress policy governs phases 2 (onBefore/onSkip), 3 (action), 4 (onAfter), and onFail through Node’s AsyncLocalStorage. Any unauthorized outbound call triggers a NetworkPolicyViolationException tagged with the active phase (before, action, or after).

Instantiating Steps

Step.create(name?, action)

Instantiates a typed Step execution unit with input and output contracts.

Signatures

Example


Validation and Contracts

step.schema(schema)

Validates the incoming execution context against standard schema validators supporting the Standard Schema specification (~standard), including Zod, Valibot, and ArkType.

Signature

Example with Zod

If validation fails, a ValidationException is thrown before the step action executes, containing detailed issue descriptions in err.errors.

step.spec(field, options)

Declares granular parameter constraints, default values, transforms, and translations for a specific context field.

Signature

Example


step.strict()

Enforces strict parameter filtering on incoming parameters, selecting only declared spec fields and filtering out undeclared properties before the action executes.

Signature

Example


Lifecycle Hooks

step.onBefore(hook)

Pre-execution guard hook. Evaluates the incoming parameter context before the action executes. If it returns false, step action execution is skipped and control transfers to onSkip (or context passes through unchanged).

Signature

Example


step.onSkip(hook)

Fallback hook that executes if and only if onBefore returns false. Its returned value is merged into the context in place of the step action output.

Signature

Example


step.onAfter(hook)

Post-execution transformation hook. Receives the raw output produced by the step action and the input parameters, returning an enriched or transformed output.

Signature

Example


Fault Tolerance and Resilience

step.timeout(ms)

Enforces a per-step SLA deadline in milliseconds. If the step action takes longer than ms, the action is aborted via AbortSignal and throws a StepTimeoutException.

Signature

Example


step.onFail(config)

Configures structured retry policies or custom error fallback handlers when the step action throws.

Signatures

Example with Exponential Backoff & Jitter

Example with OnFail Fallback

To provide a graceful fallback return value when errors occur, use the callback form:

step.compensate(handler, options?)

Registers a saga compensation rollback handler. If downstream steps in the workflow fail, registered compensation handlers execute automatically in reverse order (LIFO).

Signature

Example


Optimization and Deduplication

step.idempotent(keyOrFn?, options?)

Guarantees step deduplication and concurrent claim locking using deterministic idempotency keys and TTL storage.

Signature

Semantics

  1. Claiming: Before execution, attempts to claim the key in the configured IdempotencyStore.
  2. Conflict: If already in-progress, throws IdempotencyConflictException.
  3. Cache Hit: If previously completed and within TTL, returns cached output without re-executing.
  4. Completion: Upon successful execution, records output and marks status COMPLETED.

Example


step.cache(msOrOptions)

Caches step output in memory or persistent storage (StorageAdapter) based on input parameters.

Signatures

Example


Dependency Injection

step.withDependencies(deps)

Attaches runtime dependencies and service repositories directly to the step.

Signature


step.requireDependency(key)

Retrieves a required injected dependency or throws a descriptive error if missing.

Signature

Example


Context Transformation

step.reduce(field)

Assigns the step output directly to a designated field in the accumulated context instead of shallow-merging properties.

Signature

Example


Network Egress Guardrails

Steps can declare granular network egress permissions enforced via Node’s AsyncLocalStorage (ASL). In flows with an outer network policy, the flow supersedes the step; steps can only narrow permissions within what the flow permits. By default, loopback addresses (localhost, 127.0.0.1, ::1, 0.0.0.0) and local Unix domain socket IPC are allowed.

Lifecycle Hook Governance

The network policy boundary wraps the entire step execution lifecycle via AsyncLocalStorage:
  • onBefore & onSkip: Pre-execution guards and fallback computations are governed by the step’s allowlist (violations tagged with phase: 'before').
  • action & reduce: The core step execution runs within the policy context (violations tagged with phase: 'action').
  • onAfter: Context enrichment and post-processing cannot bypass step network restrictions (violations tagged with phase: 'after').
  • onFail: Step-level retries and fallback error handlers adhere to the policy perimeter.
  • Global Plugins (executeBefore, executeAfter): Engine-level plugins execute outside this boundary to ensure system observability and metrics remain unaffected.
  • Compensations (step.compensate): Sagas rollback in an independent scope with their own execution perimeter.

step.allowNetwork(hosts)

Declares an allowlist of target hosts, wildcard subdomains, ports, or regular expressions permitted for network calls during this step.

Signatures

Parameters

  • hosts: (string | RegExp)[] — Array of hostnames ('api.stripe.com'), wildcard patterns ('*.stripe.com'), specific ports ('api.internal:8080'), or RegExps (/^api\.internal$/).

Example


step.allowUnixSockets(sockets)

Explicitly permits communication over specified local Unix domain sockets (IPC filesystem paths) during step execution.

Signature

Example


step.denyNetwork()

Shorthand for .allowNetwork([]). Strictly denies all external outbound network access from the step’s lifecycle hooks and action.

Signature

Example


step.networkPolicy(policy)

Configures the complete network egress policy object for the step.

Signature

Parameters

  • policy: NetworkPolicyConfig
    • allowedHosts: (string | RegExp)[] (optional) — Allowed target host patterns.
    • defaultPolicy: 'allow' | 'deny' (optional, default: 'deny') — Default fallback rule.
    • allowLocalhost: boolean (optional, default: true) — Loopback exemption.
    • allowUnixSockets: string[] (optional) — Allowed Unix domain socket paths.

Example


Execution and Inspection

step.run and step.execute

Runs the step directly as a standalone unit.

Graph and Export Methods

  • step.toGraph(): Returns a StepNode AST.
  • step.inspect(): Returns inspection metrics for this step.
  • step.toMermaid() / step.toDot() / step.toJSON(): Visual diagram and AST exports.

Static Methods and Configuration

The Step class exposes static utilities and orchestrator shortcuts:
  • Step.create(name, action): Primary factory method for step construction.
  • Step.flow(...steps) / Step.pipe(...steps): Shorthand alias to compose a sequential Flow.
  • Step.start(steps, param?, options?): Low-level executor entry point.
  • Step.config(props): Configures global runtime settings (logging, plugins, telemetry).
  • Step.useStorage(adapter): Registers the global StorageAdapter.
  • Step.checkpoint(stackId, options?): Captures an instantaneous checkpoint snapshot.
  • Step.restoreCheckpoint(data, options?): Restores stack state from a serialized snapshot.
  • Step.parallel(...), Step.all(...), Step.allSettled(...), Step.race(...): Combinator factories.
  • Step.when(...), Step.branch(...), Step.map(...): Branching and collection combinators.
  • Step.waitForEvent(...), Step.wait(...): Durable wait factories.