A wait step holds a run until someone answers it: here a routine reads a page with vision/scrape@1, waits for the approve signal, and takes a screenshot with render/screenshot@1 only when the payload says approved: true. The run costs nothing while it waits, and gives up after the step's ms (10 minutes here). The recipe publishes the routine, starts a run, sends the approval once the run waits for it, and deletes the routine. Owner: routines.

Info

Not verified yet: no docs-examples run has covered the runnable snippets on this page.

The routine

Save it as routine.json:

json
{ "name": "recipe-approve-then-screenshot", "inputs": { "type": "object", "properties": { "url": { "type": "string", "default": "https://example.com" } } }, "steps": [ { "id": "page", "uses": "vision/scrape@1", "with": { "url": "${{ inputs.url }}", "formats": ["markdown"] } }, { "id": "approval", "wait": { "signal": "approve", "ms": 600000 } }, { "id": "shot", "if": "${{ steps.approval.outputs.payload.approved == true }}", "uses": "render/screenshot@1", "with": { "url": "${{ inputs.url }}" } } ], "output": { "summary": "Approved by ${{ steps.approval.outputs.payload.by }}; screenshot taken", "screenshot": "${{ steps.shot.outputs.artifacts[0].url }}" }}

Run it

Publish it, start a run, and approve it once it waits:

bash
curl -s -X PUT https://beta-api.b3os.org/v1/routines/recipe-approve-then-screenshot \ -H "Authorization: Bearer $B3OS_API_KEY" -H "Content-Type: application/json" -d @routine.jsonRUN_ID=$(curl -s https://beta-api.b3os.org/v1/routines/recipe-approve-then-screenshot/runs \ -H "Authorization: Bearer $B3OS_API_KEY" -H "Content-Type: application/json" -d '{}' | jq -r .id)curl -s "https://beta-api.b3os.org/v1/routines/runs/$RUN_ID/signal" \ -H "Authorization: Bearer $B3OS_API_KEY" -H "Content-Type: application/json" \ -d '{"name": "approve", "payload": {"approved": true, "by": "ops"}}'

What it produced

bash
$ node run.mjs# exit 0

The outputs this recipe publishes (its recipe.json publish.outputs), with workspace identifiers redacted. The run's stdout, stderr and other outputs are not published.

Captured 2026-11-01 from commit an unknown commit, label live-recorded (recorded from production). Case recipes/approve-then-screenshot .

How it works

A signal sent before the step waits is buffered, so the approval can come at any time after the run starts. The waiting step completes with the payload as its outputs, and the shot step's if reads it: a payload without approved: true skips the screenshot. In the dashboard, the run page shows the waiting step with a payload box that sends the signal. A signal to a run that already finished answers 409 run_not_waiting.

Owner: Routines. Products: Routines, Vision, Render.

Output of the last green run

bash
$ node run.mjs# exit 0

The outputs this recipe publishes (its recipe.json publish.outputs), with workspace identifiers redacted. The run's stdout, stderr and other outputs are not published.

Captured 2026-11-01 from commit an unknown commit, label live-recorded (recorded from production). Case recipes/approve-then-screenshot .

Ask a question... ⌘I