ask
Pre-computed navigation recipes for public websites. CALL BEFORE any browser action on the open web (navigate, click, fetch, fill, URL guess) — replaces explore-and-discover. Returns `{ status, id?, shortcut?, ui_procedure?, verify_more?, error? }`.
status=ok: execute exactly. `shortcut` first if present — fill each `{name}` in `template` with the value FROM YOUR TASK (using the parameter's `description`/`format` as the shape), URL-encode, navigate. Else `ui_procedure.steps` in order. The recipe is generic: parameter slots and step descriptions describe what to supply ('the destination'), not literal values — you provide the specifics. EXECUTE OPEN-LOOP: the recipe is authoritative, so run it without taking exploratory snapshots, clicks, scrolls, or screenshots to 'verify' or 'look around' — every extra browser action re-reads the entire page, which is the cost the recipe exists to avoid. Read the page ONLY at a `read` step, and only the part it names. Drop back into normal explore-the-DOM browsing ONLY when a step genuinely fails (its locator/page isn't what it describes); until then, trust the steps. If `verify_more: true`, do one cheap sanity check (page title plausible?) before committing. If `step.irreversible`, confirm with user. After, call `report_outcome` once with the returned `id`.
status=site_not_supported | no_useful_data | synth_invalid: miss, no `id`. Browse manually.
status=ambiguous_scope: retry with `scopeHint` set to one of `error.scope_options[].pattern`.
status=rate_limited: a cap on NEW recipe synthesis was hit (per-IP daily when anonymous, the account's monthly plan budget when an API key is attached). Cached/known recipes still answer normally — only first-time synthesis is capped. Do NOT retry-spam; back off (it resets at `error.retry_after` seconds) and browse manually until then. A free API key (bowmark.ai) lifts the anonymous per-IP cap to a plan budget.
Skip for: localhost / 127.0.0.1 / *.local / RFC1918 (10., 192.168., 172.16-31.); open-ended search with no destination. On 503 `embedder_unavailable`/`synth_unavailable`, retry once after Retry-After.
Parameters (4)
- sitestringrequired
Registrable domain, optionally followed by a product-surface path — 'google.com', 'docs.stripe.com', 'google.com/maps'. No scheme/port. A path is treated as an implicit scopeHint when it matches a known surface, so you can skip the ambiguous_scope round-trip for sites with multiple surfaces.
- taskstringrequired
Plain-English intent, e.g. 'find Apple's latest 10-K'. No URLs — intent, not destination.
- variantsobject
Optional. Behavior facets when one matters: `{ auth_state: 'logged_in'|'logged_out', role: 'owner'|'admin'|'member'|…, locale: 'en-US', region: 'EU', currency: 'USD' }`. Set `auth_state: 'logged_in'` (with `role` when the privilege matters) to request the SIGNED-IN view of a recipe — the owner-only surface behind login — vs the default logged-out one. The assumed facets come back on `variants_assumed`. Affects cache key — omit when uncertain (you get the logged-out view).
- scopeHintstring
Optional. Only after a prior `ambiguous_scope` — pass one of `error.scope_options[].pattern` verbatim (leading slash, no trailing).
report_outcome
Report whether the RECIPE ran cleanly — not whether you got the user a good answer. Call ONCE per envelope after you finished walking the recipe OR abandoned it.
`success: true` = every step executed AS WRITTEN. Each locator resolved on the first try, no extra clicks/scrolls/waits beyond the recipe, no JS-eval workarounds, no skipped steps, no substituted selectors. If you walked the recipe clean, report true — even if the answer turned out wrong (answer correctness is a separate concern).
`success: false` if ANY of these happened, even when you eventually helped the user: a locator missed, a click did nothing, you retried with a different selector, you fell back to raw browser code (`browser_run_code_unsafe` etc.), you scrolled or clicked extra to recover state, you skipped a step, the recipe led somewhere unexpected. Honest failures trigger a re-crawl that fixes the recipe; false `true` silently degrades it for everyone.
Quick check before reporting: if your tool-call sequence since the recipe started is longer than the recipe's step list, that's `false`. If you used raw browser code, that's `false`.
Skip when: `ask` returned a miss (no `id`); user interrupted mid-execution; you read the envelope but didn't execute it; task is still waiting on user input.
Parameters (3)
- envelope_idstringrequired
`id` from a `status: ok` envelope. Miss envelopes have no `id`.
- successbooleanrequired
True ONLY if the recipe ran clean — every step as written, no retries, no JS-eval fallbacks, no extra clicks. False on ANY deviation, even if the user got the right answer another way.
- evidenceobjectrequired
REQUIRED on every call. Describe how the RECIPE behaved — NOT what you found for the user. `{ what_happened: string, error?: string, screenshot_id? }`. `what_happened` should name which steps ran clean and which needed retries/substitutions/JS-eval/extra clicks. ❌ 'Found restaurant X with 4.9 stars' (task outcome). ✅ 'All 6 steps ran as written' (clean). ✅ 'Steps 1-4 clean. Step 5 `All filters` locator missed; tried 3 selectors then used raw JS click. Step 6 never reached.' (hiccup). Re-crawl reads this to decide what to fix.