← All docs

Guides

Web Search

The model runs web searches — Google bills per search query; Z.AI bills per search-enabled request.

Updated

When the model decides it needs to, it runs a web search itself and answers from the results. Your client does not have to execute any tool — just add a single web_search entry to tools.

json
{
  "model": "everyais/gemini-3-6-flash",
  "messages": [{"role": "user", "content": "What's the weather in Seoul today?"}],
  "tools": [{"type": "web_search"}]
}
python
resp = client.chat.completions.create(
    model="everyais/gemini-3-6-flash",
    messages=[{"role": "user", "content": "What's the weather in Seoul today?"}],
    tools=[{"type": "web_search"}],
)

Supported models

Check capabilities.web_search in GET /v1/models — that list is the only source of truth. Support varies by model within both Gemini and Z.AI families. Check the current catalog. Check this field for the example model too, and replace the ID if the supported models change.

bash
curl https://api.everyais.com/v1/models \
  -H "Authorization: Bearer $EVERYAIS_API_KEY" \
  | jq '.data[] | select(.capabilities.web_search) | .id'

If you send web_search to a model that does not support it, you get 400 web_search_unsupported_model before the provider is called (no billing).

  • You can put at most 1 web_search entry in the tools array (2 or more returns 400).
  • You can use it alongside function tools. tool_choice: "none" disables both functions and search. Requiring a tool or naming a function when only search is present returns 400.
  • It is /v1/chat/completions only — /v1/messages and /v1/responses do not support it yet.

Search billing by provider

Google Gemini bills per executed search query. Two queries within one request are billed as two searches. If the model does not search, search billing is zero.

Z.AI bills one search for each successful request with web search enabled, even when there are no results or the model does not search: billed_queries = 1. This search charge also applies to models whose tokens are free.

  • Search cost = billed_queries × search price, and it is summed separately from token billing.
  • pricing.is_free covers only input, output, and cache tokens; it does not waive search charges.
  • Content fetched by Google search is not billed as input tokens.
  • Check the number of queries actually billed in x_everyais.web_search.billed_queries in the response. On non-streaming responses, the x-everyais-cost-usd header carries the total including search cost.

There is no parameter that forcibly caps the query count (the provider does not offer one). To control spend, use the monthly/daily spend limit on the API key.

Reading citations from the response

json
{
  "choices": [{
    "index": 0,
    "message": {
      "role": "assistant",
      "content": "Seoul is clear today with a high of 28 degrees.",
      "annotations": [
        {
          "type": "url_citation",
          "url_citation": {
            "url": "https://...",
            "title": "Seoul weather",
            "start_index": 0,
            "end_index": 47
          }
        }
      ]
    },
    "finish_reason": "stop"
  }],
  "x_everyais": {
    "web_search": {
      "queries": ["Seoul weather today"],
      "search_entry_point_html": "<div>...</div>",
      "billed_queries": 1
    }
  }
}
FieldDescription
message.annotations[]OpenAI url_citation-compatible citations. start_index/end_index are character indexes into content, so slicing with them directly gives you the cited span
x_everyais.web_search.queriesThe search terms the model actually ran
x_everyais.web_search.billed_queriesSearch billing units: executed queries for Google; 1 per successful search-enabled Z.AI request
x_everyais.web_search.search_entry_point_htmlSearch suggestion HTML provided by Google

⚠️ search_entry_point_html is HTML that Google requires you to display. If your service shows search results on screen, render it as-is. It is untrusted external HTML, so isolate it — for example with <iframe sandbox srcdoc="...">.

Streaming

With stream: true, the citations and search info follow after the body.

  1. The body delta.content chunks
  2. One delta.annotations chunk (just before finish)
  3. The finish_reason chunk
  4. The usage chunk (choices: []) — this is where x_everyais.web_search rides

Citation indexes can only be fixed once the whole body has arrived, so they come exactly once, at the end. The search query count is also only in the final usage chunk, so read the stream to the end to reconcile cost.