Skip to main content
Reports validate asynchronously by default. Use a wait when a backend operation or agent tool must pass a check before continuing.

Before the action

waitFor checks role, prerequisites, thread state, and transitions, then atomically claims an invocation. Do not execute if it rejects or times out. The next report for that step on the same thread instance carries the invocation ID automatically. Permission does not imply success or validate future content.

After reporting the outcome

Also supported: .failed('Reason', { waitFor: true }). The response waits for that event’s worker validation without polling. It cannot undo an action. If a report was accepted but the validation wait timed out, the error carries stepId. Resume the wait without recording a duplicate:

Fresh approval for every attempt

Use this complete repeatable workflow when each refund attempt needs its own approval:
A grant consumes that approval, including when execution fails or the grant is abandoned. Concurrent callers cannot use the same approval for two invocations. A repeatable action must not be terminal; finish with a separate step.

Recovery

Cancel a grant you will not use with await grant.cancel(). Cancellation does not restore its consumed approval. If a permission response is lost, recover using its invocationId rather than claiming another invocation:
Persist an invocation ID before requesting permission when crash recovery matters. Outstanding claims do not expire automatically. Preserve live Valkey state; Threadify does not use a potentially stale PostgreSQL archive to grant permission. Use your operation’s own idempotency mechanism for external side effects.

Go and Python

Go uses thread.WaitFor(ctx, name, &threadify.WaitOptions{Timeout: 10 * time.Second}) and threadify.ReportOptions{WaitFor: true}. Python uses await thread.wait_for(name, WaitOptions(timeout=10)) and success(wait_for=True). JavaScript timeouts are milliseconds; Go uses durations and Python uses seconds. See the Go and Python examples.

Existing OpenTelemetry instrumentation

After obtaining permission, set threadify.thread_id, threadify.step_name, and threadify.invocation_id on the individual operation span. Its exporter can report the outcome instead of duplicating it with an SDK step report. Use the same identity that obtained the grant. Passive OTLP export alone cannot gate execution. Protocol details and failure behavior