Responses API Web Search
Use OpenAI-compatible web_search tools inside the attested TrustedRouter gateway with citations, source controls, streaming events, and explicit privacy limits.
Search the live web through the Responses API.
Add an OpenAI-compatible web_search tool. TrustedRouter asks the selected model for bounded search queries, calls Exa from inside the attested gateway, and returns cited source material without sending the original request body through the control plane.
web_searchandweb_search_preview- Non-streaming and Responses SSE lifecycle events
- URL citation annotations and optional full source lists
- At most three search calls per response
from openai import OpenAI
client = OpenAI(
api_key="sk-tr-v1-...",
base_url="https://api-azure.trustedrouter.com/v1"
)
response = client.responses.create(
model="anthropic/claude-sonnet-5",
input="What changed in Python this week? Cite sources.",
tools=[{
"type": "web_search",
"search_context_size": "medium"
}],
tool_choice="required",
include=["web_search_call.action.sources"],
store=False
)
print(response.output_text)
The same search engine for Chat.
/v1/chat/completions also accepts web_search and web_search_preview. These TrustedRouter compatibility aliases use the same Exa execution and controls as Responses, with at most three search calls. Set max_tool_calls to a value from 1 to 3.
The OpenRouter-style openrouter:web_search tool remains supported with a parameters object and a max_uses budget of up to 30. Use one hosted search tool per request.
Chat results include citations, search_results, and URL annotations. Streaming uses Chat completion chunks; set stream_options.include_usage to receive final usage and search cost.
Function tools remain caller-executed. Hosted tools such as file_search, code_interpreter, and mcp, plus free-form custom tools, are not implemented and return explicit errors.
{
"model": "anthropic/claude-sonnet-5",
"messages": [{
"role": "user",
"content": "What changed in Python this week? Cite sources."
}],
"tools": [{"type": "web_search"}],
"tool_choice": {"type": "web_search"},
"max_tool_calls": 1,
"stream": true,
"stream_options": {"include_usage": true}
}
Search controls
Bound the evidence.
Set search_context_size to low, medium, or high. Larger contexts return more source material and can increase latency and model input cost.
Constrain sources.
Use filters.allowed_domains or filters.blocked_domains. A request may use one list, not both.
Localize results.
Pass user_location with a two-letter country code. Precise city, region, and timezone controls are rejected until implemented.
Observe the search lifecycle.
Streaming responses emit response.web_search_call.in_progress, response.web_search_call.searching, and response.web_search_call.completed before normal output text events and response.completed.
{
"type": "web_search",
"search_context_size": "low",
"filters": {
"allowed_domains": ["python.org", "github.com"]
},
"user_location": {
"type": "approximate",
"country": "US"
}
}
Search is an explicit external disclosure.
The model can derive search queries from your prompt. Exa receives those queries plus configured filters and returns results to the enclave. Exa does not receive the original request body directly, but generated queries can contain prompt-derived information.
TrustedRouter therefore rejects hosted web search on trustedrouter/zdr, trustedrouter/e2e, trustedrouter/confidential, and trustedrouter/eu routes until Exa has an approved compatible posture. Do not attach web_search to sensitive requests unless this disclosure is acceptable.