DSPy
Give a DSPy program the live web. One function on SpecStream's Search API returns passages for a RAG module or a dspy.ReAct tool, a second reads pages with the Extract API, and the MCP server adds Deep Search lists.
What you need
- Python 3.10 or later, with DSPy 3.x.
- A SpecStream API key, made under Agents & API in your workspace (more on keys). New accounts get $10 of credit, no card.
- For the MCP step: Python 3.12 or later, for the
specstream-mcp-stdiobridge.
- 1
1. Install DSPy and set your key
The search function below sends the key as a Bearer token. Keep it in the environment, out of your code.
Shell - 2
2. Write the search function
DSPy has no built-in web search: its own tool example returns a placeholder where a search API call would go. This function is that call. It asks the Search API for
kresults withpassages=true, and each of the firstksources then carries anexcerpt: the text of its page closest to the query, up to about 3,500 characters. A page not read in time keeps itssnippet.It returns a
dspy.Predictionwithpassages, the shape DSPy's RAG tutorial reads from its retriever, and each passage starts with the page's title and URL so the model can name its source.specstream_search.py - 3
3. Use it in a RAG module
This is the module from DSPy's RAG tutorial, with the live web as the corpus:
forwardcallssearchand passes the passages ascontext. You can compile it with any DSPy optimizer, as you would with a local index.rag.py - 4
4. Give a ReAct agent search and page reading
dspy.ReActtakes plain functions as tools and reads their names, type hints and docstrings. Withweb_searchandread_page, the agent finds pages, then reads the ones it needs in full through the Extract API. A page that refuses a plain read is tried again as a browser, then from the site's feed, then from its newest public archive capture.agent.py - 5
5. Every SpecStream tool over MCP
Install the bridge with
pip install -U "dspy[mcp]" specstream-mcp-stdio.dspy.Tool.from_mcp_toolturns each tool the server lists into a DSPy tool:search_webandread_pages, and the Deep Search tools that return whole lists as structured rows. Keep the agent call inside the open session, and call it withacall.A Deep Search run starts only after a quote's maximum is approved. Give the key a spending limit under Agents & API, and the agent can never spend above it.
mcp_agent.py
What the search function reads
| Search API field | In each passage |
|---|---|
data.sources[].title | The first words of the passage |
data.sources[].url | In brackets after the title, so the model can cite it |
data.sources[].excerpt | The page's text closest to the query, with passages=true |
data.sources[].snippet | Used when a page was not read in time |
Programs that call dspy.Retrieve
Older programs call dspy.Retrieve(k=3) after dspy.configure(rm=...). dspy.Retrieve calls the rm with the query and k, and reads long_text from each item it gets back. Wrap the passages to fit: with from dspy.dsp.utils import dotdict, set dspy.configure(rm=lambda query, k=3, **kwargs: [dotdict(long_text=p) for p in search(query, k=k).passages]).
Searching less while you compile
An optimizer runs your program over the training set many times, and each run that calls search is a charged search. Decorate search with functools.lru_cache while you compile, so each training question is searched once per process.
More results, filters and answers
num takes 1 to 100 results, and page continues the same ranked list. Operators in q hold on every result: site:, -site:, "phrase", filetype: and after:/before:. The same reply also carries answer for a question with one answer, with the page it was read from. Every parameter is in the Search API reference.
If a call fails
raise_for_status raises the HTTP error. 401 means SpecStream got no valid key: check that SPECSTREAM_API_KEY is set where the program runs. A search the engines find nothing for returns 200 with empty sources, so search returns no passages.
Cost
A search is $5 per 1,000 searches of up to 10 results; add speed=fast to the parameters and it costs a fifth of that. A page read is $0.80 per 1,000 pages, with no charge for a page that has no text. Both come from your balance with no quote. New accounts start with $10 of credit, no card. See how billing works, and send questions to [email protected].
More
SpecStream for DSPy covers what it does in DSPy 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].