Examples
Canonical install plus advanced runtime override examples for specialized sites.
The generated production install is the single script tag. Inline rover('boot') snippets below are advanced/legacy overrides for teams that intentionally manage config in code. Rover v2 task boundaries are strict: normal sends always start a fresh task boundary. Only ask_user answers continue the current boundary.
Canonical Setup
Default production install. Runtime policy, Activity, discovery, and billing config come from the Rover site record.
<script
src="https://rover.rtrvr.ai/embed.js?v=your_site_key_id"
async
data-site-id="my-site"
data-public-key="pk_site_your_public_key"
data-site-key-id="your_site_key_id"></script>Journeys + Async Identify
Blend workspace journeys with runtime overrides and personalize greeting after login.
<script>
(function(){ var r = window.rover = window.rover || function(){ (r.q = r.q || []).push(arguments); }; r.l = +new Date(); })();
rover('boot', {
siteId: 'my-app',
publicKey: 'pk_site_your_public_key',
siteKeyId: 'your-site-key-id',
allowedDomains: ['app.example.com'],
// Workspace journeys are fetched by default via /v2/rover/session/open.
// Optional override in boot config:
ui: {
shortcuts: [
{ id: 'onboard', label: 'Onboard me', prompt: 'Guide me through onboarding', routing: 'planner', enabled: true }
],
greeting: { text: 'Hey {name}! Need setup help?', delay: 2000, duration: 8000 }
},
});
// Later, when auth completes:
rover('identify', { name: 'Alex', email: 'alex@example.com' });
</script>
<script
src="https://rover.rtrvr.ai/embed.js?v=your_site_key_id"
async
data-site-id="your_site_id"
data-public-key="pk_site_your_public_key"
data-site-key-id="your_site_key_id"></script>Voice Dictation
Enable browser dictation so visitors can speak requests, edit the transcript, and manually send.
<script>
(function(){ var r = window.rover = window.rover || function(){ (r.q = r.q || []).push(arguments); }; r.l = +new Date(); })();
rover('boot', {
siteId: 'my-app',
publicKey: 'pk_site_your_public_key',
allowedDomains: ['app.example.com'],
ui: {
voice: {
enabled: true,
language: 'en-US',
autoStopMs: 2600
}
}
});
</script>
<script
src="https://rover.rtrvr.ai/embed.js?v=your_site_key_id"
async
data-site-id="your_site_id"
data-public-key="pk_site_your_public_key"
data-site-key-id="your_site_key_id"></script>Onboarding Flow
Auto-routing setup with planner fallback only when ACT has no usable outcome.
<script>
(function(){ var r = window.rover = window.rover || function(){ (r.q = r.q || []).push(arguments); }; r.l = +new Date(); })();
const isNewUser = !localStorage.getItem('onboarded');
rover('boot', {
siteId: 'my-app',
publicKey: 'pk_site_your_public_key',
allowedDomains: ['app.example.com'],
openOnInit: isNewUser,
taskRouting: {
mode: 'auto',
plannerOnActError: true, // Planner fallback runs only if ACT has no usable result
actHeuristicThreshold: 5
},
checkpointing: { enabled: true, autoVisitorId: true },
});
</script>
<script
src="https://rover.rtrvr.ai/embed.js?v=your_site_key_id"
async
data-site-id="your_site_id"
data-public-key="pk_site_your_public_key"
data-site-key-id="your_site_key_id"></script>Checkout Assistant
Help users complete checkout by filling addresses, applying promos, and handling payment flows.
<script>
(function(){ var r = window.rover = window.rover || function(){ (r.q = r.q || []).push(arguments); }; r.l = +new Date(); })();
rover('boot', {
siteId: 'my-store',
publicKey: 'pk_site_your_public_key',
allowedDomains: ['shop.example.com', 'checkout.example.com'],
domainScopeMode: 'registrable_domain',
allowActions: true,
taskRouting: { mode: 'auto', plannerOnActError: true },
});
</script>
<script
src="https://rover.rtrvr.ai/embed.js?v=your_site_key_id"
async
data-site-id="your_site_id"
data-public-key="pk_site_your_public_key"
data-site-key-id="your_site_key_id"></script>Form Assistance
Guide users through complex multi-step forms with validation and auto-fill.
<script>
(function(){ var r = window.rover = window.rover || function(){ (r.q = r.q || []).push(arguments); }; r.l = +new Date(); })();
rover('boot', {
siteId: 'my-portal',
publicKey: 'pk_site_your_public_key',
allowedDomains: ['portal.example.com'],
sessionScope: 'tab',
taskRouting: { mode: 'planner' },
checkpointing: { enabled: true, autoVisitorId: true },
});
</script>
<script
src="https://rover.rtrvr.ai/embed.js?v=your_site_key_id"
async
data-site-id="your_site_id"
data-public-key="pk_site_your_public_key"
data-site-key-id="your_site_key_id"></script>Read-Only Support Agent
Rover helps users find information and navigate, but doesn't take actions.
<script>
(function(){ var r = window.rover = window.rover || function(){ (r.q = r.q || []).push(arguments); }; r.l = +new Date(); })();
rover('boot', {
siteId: 'my-help',
publicKey: 'pk_site_your_public_key',
allowedDomains: ['help.example.com'],
allowActions: false,
});
</script>
<script
src="https://rover.rtrvr.ai/embed.js?v=your_site_key_id"
async
data-site-id="your_site_id"
data-public-key="pk_site_your_public_key"
data-site-key-id="your_site_key_id"></script>Strict Host Scope
Host-only install example for tightly controlled sites. Navigation behavior stays managed by Rover runtime.
<script>
(function(){ var r = window.rover = window.rover || function(){ (r.q = r.q || []).push(arguments); }; r.l = +new Date(); })();
rover('boot', {
siteId: 'secure-app',
publicKey: 'pk_site_your_public_key',
allowedDomains: ['app.example.com'],
domainScopeMode: 'host_only',
sessionScope: 'tab',
});
</script>
<script
src="https://rover.rtrvr.ai/embed.js?v=your_site_key_id"
async
data-site-id="your_site_id"
data-public-key="pk_site_your_public_key"
data-site-key-id="your_site_key_id"></script>A2W Run Examples
Use POST https://agent.rtrvr.ai/v1/a2w/runs when you can send JSON. Use GET with execution=cloud and format=markdown for URL-fetch chatbots. Deep links like ?rover=... stay browser-first convenience unless paired with rover_exec.
Browser-first query param
Fastest way to make Rover run in the page UI on first-party rtrvr.ai. Other Rover installs expose `?rover=` when AI launch is enabled for the site.
https://www.rtrvr.ai/?rover=get%20me%20the%20latest%20blog%20postCreate an A2W run
Machine path for any AI, CLI, or agent that needs progress and a final result back.
curl -X POST 'https://agent.rtrvr.ai/v1/a2w/runs' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
"url": "https://www.rtrvr.ai",
"prompt": "get me the latest blog post"
}'Guaranteed browserless execution
Use cloud execution explicitly when the caller cannot open a real browser. The create call can return 202 before the run is finished; follow the returned links until terminal or input_required.
curl -X POST 'https://agent.rtrvr.ai/v1/a2w/runs' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Prefer: execution=cloud, wait=10' \
-d '{
"url": "https://www.rtrvr.ai",
"prompt": "get me the latest blog post"
}'Chatbot GET execution
Use this when the caller can only fetch a URL. Rover opens the target in the hosted cloud browser and returns markdown with a self-contained poll link.
https://agent.rtrvr.ai/v1/a2w/runs?url=https%3A%2F%2Fwww.rtrvr.ai&prompt=get%20me%20the%20latest%20blog%20post&execution=cloud&wait=25&format=markdownResolve a Rover deep link
Use from-url when a page URL contains rover or rover_shortcut but no rover_exec parameter.
https://agent.rtrvr.ai/v1/a2w/from-url?url=https%3A%2F%2Fexample.com%2F%3Frover_shortcut%3Dcheckout_flow&execution=cloud&wait=25&format=markdownStream or continue the run
Use the canonical run URL for SSE, NDJSON, polling, continuation, and cancel.
# SSE
curl -N 'https://agent.rtrvr.ai/v1/a2w/runs/a2w_run_123?access=a2w_access_...' \
-H 'Accept: text/event-stream'
# Continue input_required
curl -X POST 'https://agent.rtrvr.ai/v1/a2w/runs/a2w_run_123?access=a2w_access_...' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{ "input": "Use the newest post from the blog index page." }'
# Cancel
curl -X DELETE 'https://agent.rtrvr.ai/v1/a2w/runs/a2w_run_123?access=a2w_access_...' \
-H 'Accept: application/json'Cross-site handoff
Delegate a child task to another Rover-enabled site and keep one shared workflow lineage.
# Create the root run first
curl -X POST 'https://agent.rtrvr.ai/v1/a2w/runs' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
"url": "https://x.com",
"prompt": "Start checkout and hand off shipping selection when needed"
}'
# Later, delegate from the parent run
curl -X POST 'https://agent.rtrvr.ai/v1/a2w/runs/a2w_run_parent/handoffs?access=a2w_access_parent' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
"url": "https://y.com",
"instruction": "Continue the checkout flow and return the shipping options.",
"contextSummary": "User already selected product and entered address on x.com.",
"expectedOutput": "Return the cheapest valid shipping option and ETA."
}'
# Read the shared workflow
curl 'https://agent.rtrvr.ai/v1/a2w/workflows/a2w_wf_456?access=a2w_access_...' \
-H 'Accept: application/json'Node fetch
Self-contained browserless example for agents running in Node 18+.
const createResponse = await fetch('https://agent.rtrvr.ai/v1/a2w/runs', {
method: 'POST',
headers: {
'content-type': 'application/json',
'accept': 'application/json',
'prefer': 'execution=cloud, wait=10',
},
body: JSON.stringify({
url: 'https://www.rtrvr.ai',
prompt: 'get me the latest blog post',
}),
});
const created = await createResponse.json();
const runUrl = created.run;
let run = created;
while (!['completed', 'failed', 'cancelled', 'expired'].includes(run.status)) {
if (run.status === 'input_required') {
throw new Error(`A2W run needs input: ${JSON.stringify(run.input ?? {})}`);
}
const runResponse = await fetch(runUrl, {
headers: { accept: 'application/json', prefer: 'wait=10' },
});
run = await runResponse.json();
console.log(run.status, run.result?.text ?? '');
}
if (run.status !== 'completed') {
throw new Error(run.result?.error || `A2W run ended with ${run.status}`);
}Python
Simple requests-based cloud execution loop that long-polls the returned run URL.
import requests
create = requests.post(
"https://agent.rtrvr.ai/v1/a2w/runs",
headers={
"Content-Type": "application/json",
"Accept": "application/json",
"Prefer": "execution=cloud, wait=10",
},
json={
"url": "https://www.rtrvr.ai",
"prompt": "get me the latest blog post",
},
)
create.raise_for_status()
created = create.json()
run_url = created["run"]
payload = created
while payload["status"] not in {"completed", "failed", "cancelled", "expired"}:
if payload["status"] == "input_required":
raise RuntimeError(f"A2W run needs input: {payload.get('input')}")
current = requests.get(
run_url,
headers={"Accept": "application/json", "Prefer": "wait=10"},
timeout=30,
)
current.raise_for_status()
payload = current.json()
print(payload["status"], payload.get("result", {}).get("text", ""))
if payload["status"] != "completed":
raise RuntimeError(payload.get("result", {}).get("error") or f"A2W run ended with {payload['status']}")Shell helper
Create a cloud A2W run and stream NDJSON events. Requires jq.
rover_run() {
local url="$1"
local prompt="$2"
local created run_url
created="$(curl -sS -X POST 'https://agent.rtrvr.ai/v1/a2w/runs' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Prefer: execution=cloud, wait=10' \
-d "$(jq -nc --arg url "$url" --arg prompt "$prompt" '{url:$url,prompt:$prompt}')")" || return 1
run_url="$(printf '%s' "$created" | jq -r '.run')"
curl -sS "$run_url" -H 'Accept: application/x-ndjson'
}
rover_run "https://www.rtrvr.ai" "get me the latest blog post"Need a pattern not listed here? Check the Configuration Reference for all available options, or reach out on Discord.