Web search
Let a chat model look things up by giving it a web_search tool that the gateway runs against a registered search tool.
4 min readUpdated for v2.4.0Edit on GitHub
tool_loopTurn it on
- 1
Register a search tool
Add a model of type Web search (SearXNG) (
search) whose API base is a SearXNG instance with JSON output on. See Register a search tool. - 2
Turn Web search on
Open Settings › Boons, switch Web search on and Open its row. Pick the Search tool, then set Results per search, Searches per request and Search timeout under Limits. Save with the save bar. Until a search tool is picked, Settings › Needs you says so.
- 3
Grant it to a chat model
On the chat model's page, turn on Function calling under Native, then switch Web search on under Boons and save. The model calls the tool itself, so the switch can't be turned on while Function calling is off, and turning Function calling off turns it off.
Or through the Management API:
curl -X PUT http://localhost:9180/api/v1/settings/boons \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"web_search_enabled": true,
"web_search_tool": "web",
"web_search_max_results": 5,
"web_search_max_searches_per_request": 3,
"web_search_timeout_ms": 15000
}'
Then add web_search to the model's boons, with supports_function_calling: true. The Tool loop switch doesn't need to be on; web search works without it.
Ask something current
curl http://localhost/v1/chat/completions \
-H "Authorization: Bearer $OBLETH_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "my-chat-model",
"messages": [{"role": "user", "content": "What changed in the latest PostgreSQL minor release?"}]
}'
The model calls web_search, the gateway runs the search and hands back the results, and the model answers citing the URLs it used. The response carries x-obleth-boons: web_search and holds the final answer only, never the tool call.
On a streaming request, each search shows as a one-line marker on the reasoning channel (reasoning_content) naming the tool and the query, so a client sees the work while the stream waits for the results.
What the model sees
- A
web_searchtool withquery, a short search-engine query, and optionaldomains, a list of sites to keep results to (at most 10). It is described by the Tool description, which says when to search and when to answer directly. - For a client that sent no tools and has no tool-loop nudge, a short system note: the tool exists, call it for current or external facts and cite the URLs, and don't offer searching otherwise.
- After each search, a numbered list of results: title, URL, publication date when known, and a snippet cut to 400 characters, ending with a request to cite the URLs it relies on.
- When nothing was found, or the search could not run, a sentence saying so and telling the model to answer from what it knows. The request never fails because of the boon.
Settings
| Settings label | Field | Default |
|---|---|---|
| Web search on | web_search_enabled | false |
| Search tool | web_search_tool | none; must be a search model. "" clears it, which turns the boon off |
| Results per search | web_search_max_results | 5, at most 10 |
| Searches per request | web_search_max_searches_per_request | 3, at most 8 |
| Search timeout | web_search_timeout_ms | 15000 ms, per search |
| Tool description | web_search_tool_description | built-in text; "" puts the default back |
A 0 for any number keeps the stored value.
When it applies
The tool is added when Web search is on in Settings with a search tool picked, the model has web_search in its boons list, and the model is flagged supports_function_calling. Without function calling the model gets no tool and the gateway logs a warning; the model's page marks the boon as doing nothing, and Settings › Needs you lists the model.
If the client already defines a tool named web_search, or a granted MCP server exposes one, that tool wins and the boon is inactive for the request.
A model can hold this boon with image generation and speculation. When the speculation classifier can't place a request in a category, speculation abstains so the model can search.
Limits and failures
- Searches run inside the gateway's tool loop, so the Tool loop's Turns and Request deadline apply, even with its switch off. A search's timeout is cut to whatever remains of the deadline.
- Searches per request counts every search that was sent, including failed ones, so a failing search tool isn't retried past the limit. A call past it gets a result saying the request has used its searches.
- The tenant's input guardrails scan each query before it leaves: a redacted query is searched as redacted, and a blocked one is not searched.
- A missing or disabled search tool, an upstream error and a timeout each become a failure result the model answers around.
- The search itself is the same upstream call as
POST /v1/search, with the same failover between the search tool's endpoints and the same domain filter.
Usage
Each search is a usage row under the search tool's name, with admission = boon, request_type = web_search_boon, no tokens and no cost. Its parent_request_id is the chat request's id, so the request's panel in Request logs lists each search under Helper calls as "web search", failed ones included: the row records 200, 502 for an upstream failure or 504 for a timeout, and how long the search took. The chat model's follow-up turns are billed like the tool loop's.
