<WaitForEvent> durably suspends the workflow until a matching external event arrives (or the timeout expires). The event payload is written to the configured output.
Import
Props
| Prop | Type | Default | Description |
|---|---|---|---|
id | string | (required) | Unique node id within the workflow. |
event | string | (required) | Event name/type to wait for (e.g. "deploy.completed"). |
correlationId | string | undefined | Correlation key to match the right event instance. |
output | z.ZodObject | Table | string | (required) | Where to store the event payload. |
outputSchema | z.ZodObject | undefined | Zod schema for validating the event payload. |
timeoutMs | number | undefined | Max wait time in ms before timeout behavior triggers. |
onTimeout | "fail" | "skip" | "continue" | "fail" | What happens when the timeout expires. |
async | boolean | false | When true, unrelated downstream flow can continue while the event is still pending. Explicit dependencies still wait for the payload. |
skipIf | boolean | false | Skip this node entirely. |
dependsOn | string[] | undefined | Task IDs that must complete first. |
needs | Record<string, string> | undefined | Named deps. Keys become context keys, values are task IDs. |
label | string | wait:<event> | Display label override. |
meta | Record<string, unknown> | undefined | Extra metadata. |
Basic Usage
Timeout Behaviors
onTimeout | Effect |
|---|---|
"fail" | Node fails. Workflow stops (unless continueOnFail is set on a parent). |
"skip" | Node is skipped. Downstream nodes that depend on it see skipped status. |
"continue" | Node completes with a null/empty payload. Downstream nodes proceed. |
Correlated Events
UsecorrelationId to match specific event instances when multiple events of the same type may arrive:
Durable Deferred Resolution
Whenasync is true, the wait node becomes a durable deferred: the workflow records the subscription durably and allows unrelated downstream work to proceed immediately. The deferred resolves when the event arrives. Any task that explicitly depends on this node (via dependsOn or needs) still blocks until the payload is available.
This pattern is useful when you want to kick off a long-running external process and continue with independent work while waiting:
Behavior
- When the scheduler reaches this node, it enters
waiting-eventstatus. - The engine durably records the event subscription (event name + correlation ID).
- When a matching event arrives (via webhook, API call, or event bus), the node resumes and writes the payload to
output. - If
timeoutMselapses first, theonTimeoutbehavior applies. - With
async, later unrelated nodes can continue before the event arrives. Use explicitdependsOn/needswhen later work really requires the payload.
Rendering
<WaitForEvent> renders as a smithers:wait-for-event host element. The scheduler treats it like a task node that enters waiting-event status instead of in-progress.
Notes
- This is a push-based primitive. For poll-based external checks, use a
<Task>with a compute function. - The event payload is validated against
outputSchemawhen provided. - Combine with
<Sequence>to gate downstream work on external events. - Multiple
<WaitForEvent>nodes can wait for different events in a<Parallel>block. - Async event waits contribute to the Prometheus gauge
smithers_external_wait_async_pending{kind="event"}while unresolved.