Durable Waits and External Signals

A durable wait pauses a run without keeping a script worker alive. WOML records the wait and can resume the same run after a runtime restart. Choose a timer for time-based work or an external signal for a callback from another system.

Choose a wait

NeedFlow item
Pause for a duration<wait id="pause" duration="10m" />
Resume at an instant<wait-until id="window" at="..." />
Wait for a matching callback<wait-for id="result" signal="..." correlation="..." />

Each item belongs inside <steps> and publishes its result under context.steps.<id>.

Wait for a callback

An earlier step can supply a correlation value:

WOML
<step id="dispatchBuild">
  <script>return { buildId: crypto.randomUUID() };</script>
</step>

<wait-for
  id="buildResult"
  signal="ci.build.succeeded"
  correlation="{{context.steps.dispatchBuild.buildId}}"
  timeout="1h"
  on-timeout="fail"
>
  <schema>{ "type": "object", "required": ["commit"], "properties": { "commit": { "type": "string" } }, "additionalProperties": false }</schema>
</wait-for>

The callback must match the exact run, wait, signal, correlation, schema, and a unique idempotency key. This prevents a callback for one build from waking another. Do not use a JavaScript promise or sleep loop for a long wait.

Deliver and inspect a signal

External HTTP signal ingress requires a dedicated token and a protected endpoint. For local operator delivery, use the owner-authenticated CLI:

Terminal
woml get <run-id>
woml signal ci.build.succeeded --run <run-id> --wait buildResult --correlation <build-id> --id ci-run-123 --payload ./result.json

Validate signal payloads before delivery and use TLS plus an authenticating reverse proxy when exposing callback ingress beyond a trusted host. Timeouts, cancellation, duplicate delivery, and restart recovery are settled by the durable runtime.