The idea
A task is the unit of work: you submit a natural-language prompt, we spin up a browser and an LLM-driven agent, the agent runs until it completes or fails, and we return a result.Lifecycle
Every task moves through these states on our side:pending— enqueued on SQS, waiting for a worker.running— a worker picked it up, the browser is spinning up.completed— the agent finished and reported a result.failed— hard error (worker crash, unhandled exception, hit theTASK_TIMEOUT_MShard cap).task.errorexplains what happened.
tasks.run(...) polls this cycle for you and returns only when terminal (completed or failed). Use tasks.submit(...) + tasks.get(...) directly if you want to drive the loop yourself.
What a task record contains
Every task record accumulates rich observability data you can read back anytime:Task type for typed field access.
Task options
The natural-language prompt.
Pass a previous task’s
sessionId to continue a conversation. Omit to start a new one.If you know the specific URL the agent should start from, pass it. Skips the agent’s initial URL-discovery step.
If set, the agent returns structured data conforming to the schema on
task.structured_content. The result field still contains a natural-language summary.Hard cap on agent steps before the task is forced to finalize. Server-side clamped to
≤ 25.If true, the last page’s HTML is returned on
task.html_dump. Useful for downstream parsing; adds to response size.Latency you can expect
Rough ranges based on how tricky the task is:| Task shape | Typical latency |
|---|---|
| Factual lookup on a popular site (HN top story, Wikipedia article, Amazon product, Airbnb search) | 1-4 seconds |
| Authenticated social-media query (your Twitter feed, TikTok trending, YouTube subscriptions) | 5-30 seconds |
| Open-ended research on a site we don’t pre-optimize | 10-60 seconds |
Failures
A task ends instatus: "failed" when:
- The worker hit an unhandled exception (rare — we’ve instrumented most paths)
- The task exceeded
TASK_TIMEOUT_MS(3 minutes by default) - A required credential was missing AND the agent couldn’t fall back to a public path
task.error for the specific message. If you’re in a session, the next turn you submit will include this failure in previousError so the agent knows not to retry the same approach.
What stablebrowse doesn’t do
- Persist browser state between tasks. Each task is a fresh Chrome instance. Session continuity flows via
previousContext, not a live browser. - Chain tasks automatically. You can’t say “run task A then task B.” Submit them separately.
- Provide realtime streaming of agent steps. Polling
GET /v1/tasks/{id}returns the lateststepSummaries[]as they accumulate, but there’s no WebSocket/SSE stream in v1.