Skip to main content

Web Search

Include real-time information in answers (market data, news, weather, fact-checking). The Turing Platform offers two paths suited to different scenarios:

PathTypical useWhat you write
Path A: Model built-in searchA single LLM call that returns a final answer with search results already integratedAdd tools or enable_search to a /chat/completions, /messages, or /responses request
Path B: Standalone search endpointYou control the pipeline: search first, then feed results to any LLM / RAG systemCall /proxy/<provider>/search directly and compose the prompt yourself

Not sure which to use? Choose A when you need the model to decide when to search and automatically inject citations into the answer. Choose B when search results need to go through embedding / retrieval / or integration with your own systems.


Qwen / Gemini / Claude use the standard /v1/chat/completions endpoint, with provider differences expressed in tools / extra_body; ByteDance Volcano (Ark) is the only exception — its built-in search is only available on /v1/responses. For the full request body schema see /api/create-chat-completion; for the Claude native protocol see Messages API; for the Responses protocol see Responses API.

Supported Models

The full list of supported models is determined by the provider sections in the model list and the Web Search / built-in tool markers:

Qwen

from openai import OpenAI

client = OpenAI(
api_key="your-api-key",
base_url="https://live-turing.cn.llm.tcljd.com/api/v1"
)

response = client.chat.completions.create(
model="qwen-plus-latest",
messages=[
{"role": "user", "content": "What will the weather be like in Hangzhou tomorrow?"}
],
# enable_search is not a standard OpenAI parameter; pass it via extra_body in the Python SDK
extra_body={
"enable_search": True
}
)

print(response.choices[0].message.content)
curl $TURING_BASE_URL/chat/completions \
-H "Authorization: Bearer $TURING_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen-plus-latest",
"messages": [
{"role": "user", "content": "What will the weather be like in Hangzhou tomorrow?"}
],
"enable_search": true
}'

Gemini

The Gemini family configures Google Search via the tools parameter. Two search modes are available:

  • googleSearch: Standard Google Search
  • enterpriseWebSearch: Enterprise-grade search providing safer, more compliant results
from openai import OpenAI

client = OpenAI(
api_key="your-api-key",
base_url="https://live-turing.cn.llm.tcljd.com/api/v1"
)

response = client.chat.completions.create(
model="turing/gemini-3-pro-latest",
messages=[
{"role": "user", "content": "What is the weather like in Shanghai today?"}
],
extra_body={
"tools": [{"googleSearch": {}}]
}
)

print(response.choices[0].message.content)

To switch to enterprise mode, simply replace googleSearch with enterpriseWebSearch:

extra_body={
"tools": [{"enterpriseWebSearch": {}}]
}

Claude

The Claude family accepts Anthropic's native web_search_20250305 tool type via the tools parameter. The model automatically decides when to search and integrates search results with citations into its response.

Official documentation: Web search tool (Anthropic)

Optional fields:

  • max_uses: Maximum number of search calls allowed per conversation turn
  • allowed_domains / blocked_domains: Domain allowlist / blocklist (mutually exclusive)
  • user_location: Geographic context to guide the model's retrieval
from openai import OpenAI

client = OpenAI(
api_key="your-api-key",
base_url="https://live-turing.cn.llm.tcljd.com/api/v1"
)

response = client.chat.completions.create(
model="turing/claude-sonnet-5",
max_tokens=4096,
messages=[
{"role": "user", "content": "What was the closing price of the Shanghai Composite Index today?"}
],
extra_body={
"tools": [
{
"type": "web_search_20250305",
"name": "web_search",
"max_uses": 3
}
]
}
)

print(response.choices[0].message.content)

Claude Response Structure

The Claude response includes search call counts and citation metadata; the exact field locations depend on which API you use. Regardless of the API, usage.server_tool_use.web_search_requests always returns the number of searches actually triggered by the request, which you can use for billing reconciliation.

Via /v1/messages (Anthropic native API) — the content array contains the following blocks in order:

  1. server_tool_use — the search request issued by the model (includes input.query)
  2. web_search_tool_result — list of search results (title / url / encrypted_content / page_age)
  3. text — the final answer; citations are inserted as separate text blocks, each carrying a citations[] array pointing to the corresponding web_search_result_location

Example (excerpt):

{
"model": "claude-sonnet-5",
"content": [
{
"type": "server_tool_use",
"id": "srvtoolu_vrtx_01FZ...",
"name": "web_search",
"input": { "query": "Shanghai Composite Index closing price today" }
},
{
"type": "web_search_tool_result",
"tool_use_id": "srvtoolu_vrtx_01FZ...",
"content": [
{
"type": "web_search_result",
"title": "Shanghai Composite (SSEC) Real-Time Quote…",
"url": "https://cn.investing.com/indices/shanghai-composite",
"page_age": "5 days ago"
}
]
},
{
"type": "text",
"text": "The Shanghai Composite Index latest quote is 4,051.43 points",
"citations": [
{
"type": "web_search_result_location",
"cited_text": "Shanghai Composite (SSEC) latest index quote is 4,051.43…",
"url": "https://cn.investing.com/indices/shanghai-composite",
"title": "Shanghai Composite (SSEC) Real-Time Quote…"
}
]
}
],
"usage": {
"input_tokens": 11505,
"output_tokens": 235,
"server_tool_use": {
"web_search_requests": 1
}
}
}

Via /chat/completions (OpenAI-compatible API) — the response shape is closer to OpenAI:

  • choices[0].message.content — the model's final text response
  • choices[0].message.tool_calls — each web_search call actually made by the model
  • choices[0].message.provider_specific_fields.citations — citation array containing cited_text / url / title / supported_text
  • usage.server_tool_use.web_search_requests — number of searches triggered in this request
tip

The encrypted_content / encrypted_index fields are opaque data used by Anthropic for multi-turn conversation signature verification. Pass them through to the next request as-is; do not modify them.

ByteDance Volcano Ark

ByteDance Volcano's web search is executed server-side by Ark and is enabled via tools: [{"type": "web_search"}]. The model decides when to search and writes citations back into the response.

Only available on /v1/responses

This is the key difference from the other three providers. Passing the same tools to /chat/completions will be rejected outright by Ark:

{"error": {"message": "VolcengineException - The request failed because it is missing `tools.function` parameter", "code": "400"}}

tools on /chat/completions only accepts type: function. Use /v1/responses for web search.

Official documentation: Web Content Plugin (Volcano Ark) ↗

Supported models are indicated by the built-in tool markers in Model List → ByteDance Volcano.

from openai import OpenAI

client = OpenAI(
api_key="your-api-key",
base_url="https://live-turing.cn.llm.tcljd.com/api/v1"
)

response = client.responses.create(
model="bytedance/deepseek-v4-flash",
input="Use web search to check today's weather in Shenzhen and provide source links",
tools=[{"type": "web_search"}],
)

print(response.output_text)
curl $TURING_BASE_URL/responses \
-H "Authorization: Bearer $TURING_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "bytedance/deepseek-v4-flash",
"input": "Use web search to check today'\''s weather in Shenzhen and provide source links",
"tools": [{"type": "web_search"}]
}'

Ark Response Structure

In addition to reasoning and message, the output array includes web_search_call items that record each retrieval actually initiated by the model:

{
"output": [
{ "type": "reasoning", "summary": [], "status": "completed" },
{
"type": "web_search_call",
"id": "ws_0217858...",
"status": "completed",
"action": {
"type": "search",
"query": "Shenzhen weather August 4, 2026; Shenzhen today's weather"
}
},
{
"type": "message",
"role": "assistant",
"content": [{ "type": "output_text", "text": "..." }]
}
]
}

Citations are annotated as url_citation attached to output_text. In streaming mode (stream: true), three additional events are emitted — response.web_search_call.in_progress / .searching / .completed — and citations are delivered incrementally via response.output_text.annotation.added.

The usage field includes the actual number of searches performed. The field names differ from Claude / Gemini: tool_usage is the total count and tool_usage_details breaks it down by content source.

"usage": {
"input_tokens": 3996,
"output_tokens": 1050,
"tool_usage": { "web_search": 3 },
"tool_usage_details": { "web_search": { "search_engine": 3 } }
}

The schema is consistent between streaming and non-streaming; tool_usage is returned with the final response.completed event.


Path B: Standalone Search Endpoints

The platform proxies multiple third-party search engines, suitable for custom RAG pipelines: retrieve results first, then perform embedding / reranking / feeding to any LLM.

Baidu (China region only)

curl $TURING_BASE_URL/proxy/baidu/search \
-H "Authorization: Bearer $TURING_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "Search for today'\''s CSI 50 performance",
"count": 10
}'

Response excerpt:

{
"trace_id": "trace_32bHCrZm1GIXbYNyP6duD",
"code": 0,
"message": "Success",
"data": {
"requestId": "51ec6302-1aa0-4c09-b32a-d7e18c4676fc",
"references": [
{
"id": 1,
"title": "CSI A50 (930050) Stock Price, Quote, Chart…",
"url": "https://emwap.eastmoney.com/quote/stock/2.930050.html",
"website": "East Money",
"content": "Open High …",
"date": "2026-02-27 00:00:00",
"type": "web"
}
]
}
}

Tavily (Global, LLM-optimized)

The request body and response structure are passed through transparently to the official Tavily protocol. For full parameter documentation (search_depth, topic, time_range, include_domains, include_answer, include_raw_content, etc.) see the Tavily Search API Reference.

  • Endpoint: POST /proxy/tavily/search
  • Required parameter: query
  • Common parameters: max_results, search_depth (basic / advanced), topic (general / news / finance), time_range, include_answer, include_raw_content, include_domains, exclude_domains
curl $TURING_BASE_URL/proxy/tavily/search \
-H "Authorization: Bearer $TURING_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "latest AI developments 2024",
"max_results": 5
}'

Response excerpt:

{
"query": "latest AI developments 2024",
"results": [
{
"title": "2024 Global Trends in AI - WEKA",
"url": "https://www.weka.io/resources/analyst-report/2024-global-trends-in-ai/",
"content": "Discover key AI trends in 2024…",
"score": 0.7498395
}
],
"responseTime": 0.86,
"requestId": "bb84e696-88cd-4b0f-b832-0aba925d312e"
}

Tavily Extract (Web Page Content Extraction)

Extracts clean body text from a set of known URLs. Useful when you already have a list of links (crawled candidates, user-pasted URLs) and need to feed them into embedding / RAG.

  • Endpoint: POST /proxy/tavily/extract
  • Required parameter: urls (a single URL string or an array of URLs)
  • Common parameters: query (focuses extraction on content relevant to this query), extract_depth (basic / advanced; advanced doubles the cost), format (markdown / text), chunks_per_source, include_images, include_favicon, timeout
curl $TURING_BASE_URL/proxy/tavily/extract \
-H "Authorization: Bearer $TURING_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"urls": ["https://example.com/pricing"],
"extract_depth": "advanced",
"format": "markdown"
}'

Response excerpt:

{
"results": [
{
"url": "https://example.com/pricing",
"raw_content": "# Pricing\n..."
}
],
"failed_results": []
}
tip

You are only billed for successfully returned URLs; links appearing in failed_results are not charged. Billing formula: (successful URL count / 5) × (1 for basic or 2 for advanced) × $0.008.

Tavily Crawl (Site Crawling)

Starting from a seed URL, follows links outward and extracts the body text of each page encountered. Useful when you don't have an existing URL list and only have an entry page — the crawler automatically discovers and fetches relevant subpages.

  • Endpoint: POST /proxy/tavily/crawl
  • Required parameter: url (seed URL)
  • Common parameters: instructions (natural-language description of which pages to find, e.g. "find pricing pages"), max_depth (link-following depth), max_breadth (maximum links to follow per page), limit (total page crawl limit), select_paths / select_domains (regex allowlists), exclude_paths / exclude_domains (regex blocklists), allow_external (whether to follow off-site links), extract_depth (applies to each crawled page; same semantics as Extract)
curl $TURING_BASE_URL/proxy/tavily/crawl \
-H "Authorization: Bearer $TURING_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"instructions": "find pricing pages",
"max_depth": 2,
"limit": 20
}'

Response excerpt:

{
"base_url": "https://example.com",
"results": [
{ "url": "https://example.com/pricing", "raw_content": "..." },
{ "url": "https://example.com/plans", "raw_content": "..." }
]
}
tip

Billing = Map cost + Extract cost, both calculated from the same set of successfully crawled pages: map_cost(page count) + extract_cost(page count, extract_depth). For example, 20 successful pages with extract_depth: "basic" gives (20/10 × $0.008) + (20/5 × $0.008) = $0.048.

Tavily Map (Site Structure Discovery)

Discovers a site's URL structure without extracting body content. Useful when you just want to know "what pages exist on this site" and then selectively call Extract on the pages you need.

  • Endpoint: POST /proxy/tavily/map
  • Required parameter: url (seed URL)
  • Common parameters: instructions (natural-language description of which pages to include; setting this doubles the cost), max_depth, max_breadth, limit (same semantics as Crawl), select_paths / select_domains (regex allowlists), exclude_paths / exclude_domains (regex blocklists), allow_external
curl $TURING_BASE_URL/proxy/tavily/map \
-H "Authorization: Bearer $TURING_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"max_depth": 3,
"select_paths": ["/docs/.*"]
}'

Response excerpt:

{
"base_url": "https://example.com",
"results": [
"https://example.com/docs/quickstart",
"https://example.com/docs/api-reference"
]
}
tip

Billed by successfully discovered page count. No content extraction makes this the cheapest of the three: (successful page count / 10) × (1 without instructions or 2 with instructions) × $0.008.

Rate Limits and Errors

Extract / Crawl / Map share the same per-key / per-team rate-limiting strategy as /proxy/tavily/search — requests that exceed quota or RPM limits are rejected before consuming any Tavily quota. Errors returned by Tavily are mapped directly to the corresponding HTTP status codes (400/422 for parameter errors, 401 for invalid credentials, 408/504 for timeouts, 429 for rate limiting, 5xx for upstream failures) and are not wrapped uniformly as 500.

Cloudsway (Search, China Region)

An alternative search channel for the China region. Retrieve web results first, then summarize, RAG, rerank, or feed them to another model as needed.

  • Endpoint: GET /proxy/cloudsway/search
  • Required parameter: q
  • Common parameters: count, freshness, offset, enableContent, contentType, contentTimeout, mainText, sites, blockWebsites
  • Headers: Usually only Authorization is required; headers such as Pragma and Accept can be included at the caller's discretion
curl --location "$TURING_BASE_URL/proxy/cloudsway/search?q=%E6%97%A5%E6%9C%AC" \
-H "Authorization: Bearer $TURING_API_KEY" \
-H "Accept: */*"

Parameter descriptions:

  • q: Search query string; must not be empty.
  • count: Number of results to return; default 10, maximum 50, valid range 1–50.
  • freshness: Filter results by time; options: Day / Week / Month.
  • offset: Pagination offset; default 0. Setting this too high may return empty results.
  • enableContent: Whether to fetch a long summary of the web page; true returns a long summary, false does not; default false.
  • contentType: Format of the long summary; only applies when enableContent=true; options: HTML / MARKDOWN / TEXT; defaults to TEXT.
  • contentTimeout: Timeout in seconds for fetching the long summary; default 0, maximum 10; only applies when enableContent=true.
  • mainText: Whether to return the body excerpt most relevant to the query; only applies when enableContent=true.
  • sites: Restrict results to specified sites; provide the host only, e.g. baijiahao.baidu.com.
  • blockWebsites: Exclude results from specified sites; provide the host only, e.g. baijiahao.baidu.com.

Response fields are largely consistent with the Legacy Bing Proxy. Common fields include:

  • queryContext.originalQuery: The original query string.
  • webPages.value[]: Array of search results.
  • webPages.value[].name / url / snippet: Title, link, and short summary.
  • webPages.value[].datePublished: Publication date of the page; included for some results.
  • webPages.value[].mainText: Body excerpt most relevant to the query.
  • webPages.value[].siteName: Site name; included for some results.
  • webPages.value[].contentCrawled: Whether the long summary was successfully fetched.
  • webPages.value[].content: Long summary body text.
  • webPages.value[].logo / imageList / score: Site icon, image list, and content relevance score.
tip

If you only need standard search results, passing just q and count is usually sufficient. Only enable enableContent / mainText when you need to build enriched summaries or RAG context.

note

Both sites and blockWebsites require the host only — do not include the protocol. For example, use www.tiktok.com, not https://www.tiktok.com.

Legacy Bing Proxy (Auto-routes to Baidu/Google)

Legacy endpoint. Automatically routes to Baidu domestically and Google internationally. New projects should call the dedicated endpoints above directly for a more stable response structure.

  • Endpoint: POST /proxy/bing/v7.0/search
  • Parameters: q (required, query string), count (optional, default 10, maximum 25)
curl $TURING_BASE_URL/proxy/bing/v7.0/search \
-H "Authorization: Bearer $TURING_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"q": "Ming Imperial Palace",
"count": "10"
}'

Response fields: queryContext.originalQuery, webPages.value[] (including id / name / url / snippet / displayUrl / datePublished, etc.), _type: "SearchResponse".

Notes
  • Keep your API key secure; do not expose it in client-side code.
  • The availability and accuracy of search results depend on the search engine provider.
  • Some search results contain third-party content; please be mindful of copyright when using them.

See also

  • Billing & Usage — Billing dimensions for web_search_requests and vertex_ai_grounding_metadata lift logic
  • Chat Completions API — How to use web search on the OpenAI-compatible API
  • Messages APIweb_search_tool_result block structure on the Claude native API