Skip to main content
A run can wait for the outside world for as long as its TTL allows: minutes, days, weeks. Nothing runs and nothing is held in memory meanwhile. Rewind gives three ways to wait.

Signals

In the script
In your harness, when the manager decides
Each run has one mailbox per signal name, first in, first out:
  • If the script already waits on signal("manager_review"), the signal resolves it.
  • If not yet, the signal is kept. The next signal("manager_review") returns it at once: nothing is lost if the manager decides before the script reaches that line.
  • Two signals with the same name are returned by two successive signal() calls, in arrival order.
  • With { timeout }, signal() returns undefined if nothing arrived in time. Without one, the run’s TTL bounds the wait.
Send signals with an idempotency key: the same key sent twice delivers one signal. Without one, a retried request leaves a second signal in the mailbox. Signal names starting with rewind: are reserved. A run that has ended refuses signals (run-ended). The model sends signals too, with the agent tool signal_run, and so do other scripts, to runs of workflows.

Webhook URLs for external systems

External systems do not know run ids. A script asks for a URL bound to itself and a signal name; everything posted to it becomes that signal.
In the script
When the sender gives a delivery id, it is used as the signal’s idempotency key. The server needs a public URL (--public-url on a server of your own) to hand out webhook URLs.

Approve a tool call

A tool with the approval policy waits for your harness before each call is sent. The run is suspended, and its state says which call waits, with its arguments, so the person who decides sees exactly what will happen.
In the toolset
In your harness
You learn that a run waits from the run’s state (run.waitingFor), from the agent tools’ results (result.run), or from the webhook run.suspended.
The same calls handle a tool call parked because the tool’s schema changed during the run (approval.reason is "schema_changed"): approve it to continue against the new schema, or reject it. A call parked because credentials expired is not an approval: renew the credentials instead.

A complete example

examples/human-approval runs a refund that waits for a manager’s signal, then for your harness to approve the payment call:
In the dashboard, Observability → Waiting lists every run waiting for the outside world, grouped by what it waits for, with the line it is paused on.