Skip to the page

DR Tulu

Run DR Tulu's web search and page reading on SpecStream by changing one address in each of two files. Your Serper and Jina keys become one SpecStream key, and the model, prompts and tool parser stay as they are.

SpecStream for DR TuluAgent frameworks & builders

What you need

  • DR Tulu's agent library installed from its repository with uv pip install -e ., as the README shows, so the files you edit are the ones Python runs. A copy installed from PyPI sits in site-packages and these steps do not change it.
  • A SpecStream key. Get your key on the Search API screen of your SpecStream workspace. New accounts start with $10 of credit, no card.
  1. 1. Point the Serper search at SpecStream

    DR Tulu has no setting for its search address. search_serper in agent/dr_agent/mcp_backend/apis/serper_apis.py posts every search to https://google.serper.dev/search. From the agent directory, change that address to SpecStream's Serper route. On macOS, write sed -i '' in place of sed -i.

    Shell, in dr-tulu/agent
    sed -i 's#https://google.serper.dev/search#https://api.specstream.ai/serper/search#' \
    dr_agent/mcp_backend/apis/serper_apis.py
  2. 2. Point the Jina Reader browsing at SpecStream

    fetch_webpage_content_jina in agent/dr_agent/mcp_backend/apis/jina_apis.py reads a page by calling https://r.jina.ai/ followed by the page's address. Change the prefix to SpecStream's Jina Reader route. The page's address stays on the end, as before.

    Shell, in dr-tulu/agent
    sed -i 's#https://r.jina.ai/#https://api.specstream.ai/jina/#' \
    dr_agent/mcp_backend/apis/jina_apis.py
    grep -n "api.specstream.ai" dr_agent/mcp_backend/apis/*.py
  3. 3. Put your SpecStream key in both variables

    In agent/.env, the file you copied from .env.example, set SERPER_API_KEY and JINA_API_KEY to your SpecStream key. DR Tulu sends the first in the X-API-KEY header and the second as a Bearer token, and those are the places SpecStream reads the key on each route. Keep .env out of anything you commit.

    Leave S2_API_KEY as it is. With the default search_tool_name of serper, both of the agent's search tools, snippet_search and google_search, go through Serper.

    agent/.env
    SERPER_API_KEY=YOUR_SPECSTREAM_KEY
    JINA_API_KEY=YOUR_SPECSTREAM_KEY
  4. 4. Restart the MCP backend without its cache

    The MCP backend reads both files when it starts, so stop a backend that is running and start it again. DR Tulu keeps API replies on disk for 10 days, so a question you asked before would come back from that cache. Start the backend with --no-cache while you check the change.

    Shell, in dr-tulu/agent
    python -m dr_agent.mcp_backend.main --port 8000 --no-cache
  5. 5. Ask DR Tulu

    Start the workflow as the README does. It finds the backend on port 8000 and uses it. Ask about something from this week, and the answer cites pages read through SpecStream. Each call is in your account's request log with its route as the endpoint.

    Shell, in dr-tulu/agent
    python workflows/auto_search_sft.py serve --port 8080 --config workflows/auto_search_sft.yaml
    # or a short evaluation run
    python workflows/auto_search_sft.py generate-dataset simpleqa \
    --num-examples 2 --config workflows/auto_search_sft.yaml --output results.jsonl

What changes and what stays

Each SpecStream route answers in the shape DR Tulu already parses. The Serper route returns organic[] with title, link, snippet and position, and SerperSearchTool reads title, link and snippet. The Jina Reader route, asked with Accept: application/json as DR Tulu asks, returns data.title, data.url and data.content, and JinaBrowseTool passes content to the model. DR Tulu still sends gl, hl and num, and SpecStream reads them.

Keep browse_tool_name: "jina", as the shipped auto_search_sft.yaml sets it. The serper browse tool calls https://scrape.serper.dev, and the Scholar tool calls https://google.serper.dev/scholar. The two sed lines leave both addresses as they were, and the default workflow calls neither.

Evaluation runs

The repository's evaluation scripts run workflows/auto_search_sft.py with search_tool_name=serper and browse_tool_name=jina in --config-overrides. They reach the same two functions, so a benchmark run searches and reads through SpecStream with no other change. If several machines share one checkout, apply the two lines once in that checkout, and set the key in the environment each backend starts from.

What each call costs

  • A search is one Search API call through a drop-in address: $1 per 1,000 searches of up to 10 results. The shipped config asks for 10 results (number_documents_to_search: 10), so each search stays at that price. A search that returns no results costs nothing.
  • A page read is one Extract API page at $0.80 per 1,000 pages. A page that gives no text is not charged.
  • The shipped config allows the agent 10 tool calls a question (search_agent_max_tool_calls: 10), so one question costs at most 10 searches or page reads.
  • Calls come out of your balance with no quote and no approval, and every call, charged or not, is in your request log.

Why run DR Tulu on SpecStream

DR Tulu's README sends you to two services for two keys, one for search and one for reading pages. On SpecStream one key and one balance pay for both, and the request log shows every search and every page a run made, which helps when you compare runs.

SpecStream's search API scores 97.9 F-score on all 1,000 SimpleQA Verified questions and 64.0 item F1 on all 200 WideSearch tasks. Scores and method are on the benchmarks page.

Limits and errors

  • When the account has used its calls for the minute, SpecStream answers 429 with Retry-After, and nothing is charged. DR Tulu does not retry: the tool fails with an error that starts with API request failed with status 429.
  • API request failed with status 401 means the key is missing or wrong. Check SERPER_API_KEY and JINA_API_KEY in the environment the backend starts from.
  • An old answer after the change means the backend served it from its cache. Restart it with --no-cache.

Go back

Run git checkout -- dr_agent/mcp_backend/apis/serper_apis.py dr_agent/mcp_backend/apis/jina_apis.py in the agent directory, put your Serper and Jina keys back in .env, and restart the backend. Questions: [email protected].

More

SpecStream for DR Tulu covers what it does in DR Tulu 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].