Let the model retrieve live information from the web during a Responses API request.
The web search helper lets the model issue search queries and read the results in the middle of its answer. No client-side code is needed — OpenDunes runs the search on the model's behalf, inside the one request.
Add the opendunes:web_search helper to your tools array:
curl https://opendunes.com/v1/responses \
-H "Authorization: Bearer $OPENDUNES_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-5.1",
"input": "What is the latest release of PHP?",
"tools": [
{ "type": "opendunes:web_search", "parameters": { "max_results": 3 } }
]
}'The model decides when to search. It may search several times in one request, reads the results, then answers with citations.
The helper takes optional parameters:
| Parameter | Description |
|---|---|
max_results | The most results per search (default 5) |
max_uses | The most searches the model may make in this request |
max_total_results | The most results across every search in this request |
allowed_domains · excluded_domains | Keep results to, or away from, these domains |
search_context_size | How much of each page to read: low, medium or high |
A request runs at most 30 helper steps in all; max_tool_calls on the request lowers that number.
The answer cites its sources as url_citation annotations on the text:
{
"output": [
{
"type": "message",
"role": "assistant",
"status": "completed",
"content": [
{
"type": "output_text",
"text": "The latest PHP release is …",
"annotations": [
{
"type": "url_citation",
"url": "https://www.php.net/releases/",
"start_index": 0,
"end_index": 28
}
]
}
]
}
],
"usage": {
"input_tokens": 105,
"output_tokens": 250,
"server_tool_use": { "web_search_requests": 1 },
"cost": 1.92
}
}usage.server_tool_use.web_search_requests counts the searches the model made. Any item the helper adds to output is named opendunes:web_search.
The helper sits in the same tools array as your own functions. The model chooses which to call; your functions come back to you as function_call items, the searches are run for you. See Tool Calling.
Each search is billed in DA per search, on top of the model's tokens — the search results the model reads are input tokens. usage.cost is the whole charge in DA, the searches included.
Search results are added to the model's context. Across many searches they consume context budget; max_results and max_total_results keep that in check.