Skip to the page

Browser Use research reports

Give a browser-use agent a research tool with @tools.action. The agent asks one question, SpecStream reads the live web and writes a report with numbered citations, and the agent keeps its browser for the pages that need a click, a form or a sign in.

SpecStream for Browser Use research reportsAgent frameworks & builders

What you need

  • Python 3.11 or newer and browser-use 1.0, with a model it can run: your Browser Use key or your own model's key.
  • A SpecStream account. New accounts start with $10 of credit, no card. Create one.
  1. 1. Install browser-use and httpx

    The browser-use README asks you to pin the exact version, because releases can change the API. httpx makes the calls to SpecStream.

    Terminal
    pip install 'browser-use==1.0.3' httpx
  2. 2. Create a SpecStream key

    Create a key under Agents & API in your SpecStream workspace and give it a spending limit. Keep it in an environment variable where the agent runs:

    Terminal
    export SPECSTREAM_API_KEY="YOUR_SPECSTREAM_API_KEY"
  3. 3. Register the research tool

    @tools.action turns a function into a tool the model can call next to its Python REPL. The parameters question and depth become the tool's arguments, and the description tells the model when to use it.

    The function starts a report with POST /v1/research, which answers at once with the report's id. It then reads GET /v1/research/{id} every 5 seconds until status is completed, and returns the text, the citations and the price to the model. Pass the Tools() object to the Agent as tools:

    agent.py
    import asyncio
    import os
    from typing import Literal
    import httpx
    from browser_use import Agent, Tools
    tools = Tools()
    SPECSTREAM = "https://api.specstream.ai/v1"
    HEADERS = {"Authorization": f"Bearer {os.environ['SPECSTREAM_API_KEY']}"}
    @tools.action(
    "Research a question on the live web. Returns a written report with [1] markers and the page behind each marker. "
    "Takes one to five minutes. Use it for a question that needs many pages, not for one fact."
    )
    async def specstream_research(question: str, depth: Literal["quick", "standard", "deep"] = "quick") -> dict:
    async with httpx.AsyncClient(timeout=60, headers=HEADERS) as client:
    r = await client.post(f"{SPECSTREAM}/research", json={"input": question, "depth": depth})
    r.raise_for_status()
    run = r.json()["data"]
    while run["status"] in ("queued", "running"):
    await asyncio.sleep(5)
    r = await client.get(f"{SPECSTREAM}/research/{run['id']}")
    r.raise_for_status()
    run = r.json()["data"]
    if run["status"] != "completed":
    raise RuntimeError(f"Report {run['id']} ended as {run['status']}")
    report = run["report"]
    return {
    "report": report["content"],
    "citations": [
    {"n": c["n"], "url": c["url"], "title": c["title"], "read_at": c["read_at"], "excerpt": c["excerpt"]}
    for c in report["citations"]
    ],
    "price_usd": run["usage"]["charged_usd"],
    }
    agent = Agent(
    "Which countries have a retail central bank digital currency, and when did each launch? "
    "Call specstream_research once, then open the central bank's page for the newest launch and confirm its date.",
    tools=tools,
    )
    print(agent.run_sync().final_result())
  4. 4. Run the agent

    Run python agent.py. The agent calls specstream_research, waits for the report, and then uses the browser only for the page the task tells it to check.

    A quick report takes about a minute, a standard report about four minutes and a deep report about five. The tool has no time limit of its own in browser-use. The wait counts toward the run's timeout, which is 1,700 seconds by default, so one report of any depth fits in a default run.

    Terminal
    python agent.py

What the agent gets back

report is the written answer in Markdown, with a [1] marker after each cited sentence. citations has one entry for each marker: its number n, the url and title of the page, read_at, the time SpecStream read that page in this run, and excerpt, the passage behind the sentence. price_usd is what the report cost.

The model sees the returned dict as JSON, so it can quote a sentence with its URL in the final result, or open a cited URL in the browser to check it.

FieldTypeWhat it holds
questionstr, inputThe question in plain words, up to 15,000 characters.
depthquick, standard or deep, inputHow far the report goes. The tool's default is quick.
reportstr, outputThe report in Markdown with [1] markers.
citationslist, outputn, url, title, read_at and excerpt for each cited sentence.
price_usdfloat, outputThe price taken for this report.

Cost

A report costs $0.10 at quick depth, $0.30 at standard and $1.00 at deep. The price is taken from your SpecStream balance once, when the report is delivered. A canceled report is not charged. If the balance does not hold the report's price, the POST answers 402, raise_for_status raises, and the model gets the error.

The model chooses depth, so it chooses the price. To fix the price of every report, remove the depth parameter from the function and send one depth in the json body. Your model and browser are billed as before. See pricing.

When a call fails

A tool that raises does not end a browser-use run. The model gets the error and can try again or go on with the browser. The function raises on any HTTP error and when a report ends as failed, cancelled or payment_required.

To retry a POST safely after a network error, send an Idempotency-Key header of at most 128 characters: the same key and body return the same report. 429 comes with Retry-After when the account used its calls for the minute.

Limit the sites, or get JSON

Add fields to the json body of the POST. include_domains and exclude_domains choose the sites the report reads. length is short, standard or long. For a JSON object in place of text, send "output": {"type": "json", "schema": {...}} with your JSON Schema and return report["structured"] from the tool. Every field is in the research report docs.

A report, a search or the browser

Use the research tool when the answer is spread over many pages and the reader wants it written with its sources. The agent spends one tool call on it, and the model's conversation receives one report with its citations.

Use a search tool for one fact or a list of results: the Browser Use search guide registers specstream_search the same way, at $5 per 1,000 searches, and a page reader at $0.80 per 1,000 pages. The three functions can share one Tools() object.

Keep the browser for what only a browser does: a sign in, a form, a click, a page that changes as you use it.

Remove

Delete the @tools.action function, or create the Agent without tools. To stop the key working everywhere, revoke it in Agents & API in your workspace. Questions go to [email protected].

More

SpecStream for Browser Use research reports covers what it does in Browser Use research reports on one page. Every other tool has its guide in Connect your tools. You see the most a request can cost before it starts, and the matches are paid from your balance. Billing has the details. For help, email [email protected].