They are partners: search finds the pages, fetch reads them. The calls never
appear in the message you receive — they are the router’s, not the model’s — but
they are reported alongside it on streamed responses as
tool activity chunks.
When they are on
Both are injected by default when your request brings notools of its own.
If you send your own tool definitions, the router assumes you are running your
own loop and injects nothing.
Override either way explicitly:
What it costs
Two separate costs, and the second is the one that surprises people: The search itself costs about $0.00875 per call, capped at 3 per request. The tokens are the larger bill. Each tool round sends the conversation, the tool definitions, and every result so far back upstream as input. A single production search turn metered 41,759 input tokens. At 0.04 in tokens against $0.009 in search fees.Why it is billed after the fact
Nothing knows whether a request will search until it does. Quoting up front for three searches that almost never happen would have charged every caller roughly thirty times what an ordinary chat turn costs. So tool spend is metered as it runs and billed at settlement instead — and a turn that lands above its quote books the difference as credit debt, collected on that payer’s next request. This is the one case where your bill can exceed what you were quoted. See How billing works.Turning it off
If you are running on a tight balance, or you want costs that track the quote more closely:Controls and limits
- 3 searches per request, maximum. A turn that wants a fourth is answered with what it has.
- 5 tool rounds per request, after which the model is asked to answer with what it has gathered.
- 15-second timeout on each search and each fetch.
- 400 KB raw / 80,000 characters per fetched page, truncated past that.
- 5 redirects, each one re-validated.
web_fetch validates the target address inside the connection’s own DNS
lookup, so the address vetted is by construction the address connected to.
Private, loopback, and link-local addresses are refused — a model cannot be
talked into fetching your internal network.
Checking availability
web_search requires a search provider to be configured on the router. The live
answer is in GET /v1/models:
available is false, the tool is not injected at all — passing
"web_search": true will not enable it.