A routine chains product calls on the node itself, so the Markdown from the scrape reaches the model without a round trip through your code. The screenshot step has needs: [], so it starts at the same time as the scrape. Save this definition as page-brief.json:

json
{ "name": "page-brief", "inputs": { "type": "object", "required": ["url"], "properties": { "url": { "type": "string" } } }, "steps": [ { "id": "page", "uses": "vision/scrape@1", "with": { "url": "${{ inputs.url }}", "formats": ["markdown"] } }, { "id": "brief", "uses": "infer/chat@1", "needs": ["page"], "with": { "model": "b3os/qwen3.5-9b", "max_tokens": 120, "chat_template_kwargs": { "enable_thinking": false }, "messages": [ { "role": "system", "content": "In one plain sentence of at most 30 words, say what this web page is for." }, { "role": "user", "content": "${{ steps.page.outputs.markdown }}" } ] } }, { "id": "shot", "uses": "render/screenshot@1", "needs": [], "with": { "url": "${{ inputs.url }}", "style": { "background": "b3os-dark", "frame": "browser-dark" }, "format": "webp" } } ], "output": { "brief": "${{ steps.brief.outputs.choices[0].message.content }}", "screenshot": "${{ steps.shot.outputs.artifacts[0].url }}" }}
Check

Verified 2026-11-01: this recipe's last run passed against https://beta-api.b3os.org, label live-recorded (recorded from production), from commit 771a9508. The recipe harness runs it again, and a failed run takes this page out of the cookbook.

Run it

bash
curl -s -X PUT https://beta-api.b3os.org/v1/routines/page-brief \ -H "Authorization: Bearer $B3OS_API_KEY" \ -H "Content-Type: application/json" \ -d @page-brief.jsoncurl -s "https://beta-api.b3os.org/v1/routines/page-brief/runs?wait=60" \ -H "Authorization: Bearer $B3OS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"input": {"url": "https://beta.b3os.org/demo/billing/"}}' \ | jq '{status, result, steps: [.steps[] | {id, status, duration_ms}]}'

The recipe's run.mjs publishes this definition under a fresh name, with the screenshot's content type and size in output in place of its URL so its checks can read them, runs it once and deletes it. steps[].duration_ms is each step's time on the node.

Owner: Docs. Products: Docs, Routines, Vision, Infer, 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 771a9508 , label live-recorded (recorded from production). Case recipes/routine-page-brief .

Ask a question... ⌘I