Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
32a12c0
feat(chat): add native web search support with cost tracking
steebchen Jan 2, 2026
2daa0e0
chore(autofix): apply diff
steebchen Jan 2, 2026
f0ff651
feat(web-search): add native web search tool support and documentation
steebchen Jan 2, 2026
85a898b
feat(models,docs): add GPT-5 series web search support and update docs
steebchen Jan 2, 2026
dbf8a51
feat(ui): add web search capability filter and column in all models
steebchen Jan 2, 2026
71ee641
feat(ui): display web search cost in LogCard and model pricing
steebchen Jan 2, 2026
b31b685
refactor(models): enhance model lookup by supporting provider modelNa…
steebchen Jan 3, 2026
6591892
feat(chat): add filtering for providers supporting web search tool
steebchen Jan 3, 2026
91780a8
feat(docs, ui): rename and update web search feature to native web se…
steebchen Jan 3, 2026
b7a2efc
chore: migrations
steebchen Jan 3, 2026
cfac491
chore: migrations
steebchen Jan 3, 2026
ee2ff99
Merge remote-tracking branch 'origin/terragon/add-native-websearch-su…
steebchen Jan 3, 2026
43d299b
feat(web-search): improve billing and display for web search usage
steebchen Jan 3, 2026
3656a9e
fix(models): correct webSearchPrice for non-reasoning models
steebchen Jan 3, 2026
26c2c52
feat(chat): validate model supports web_search tool usage
steebchen Jan 3, 2026
489b687
fix: docs
steebchen Jan 3, 2026
6ec5efd
Merge remote-tracking branch 'origin/main' into terragon/add-native-w…
steebchen Jan 4, 2026
da22350
fix: add Responses API handler to mock server for tests
steebchen Jan 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions apps/admin/src/lib/api/v1.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,7 @@ export interface paths {
presencePenalty: number | null;
reasoningEffort: string | null;
responseFormat?: unknown;
tools: {
tools: ({
/** @enum {string} */
type: "function";
function: {
Expand All @@ -612,7 +612,19 @@ export interface paths {
[key: string]: unknown;
};
};
}[] | null;
} | {
/** @enum {string} */
type: "web_search";
user_location?: {
city?: string;
region?: string;
country?: string;
timezone?: string;
};
/** @enum {string} */
search_context_size?: "low" | "medium" | "high";
max_uses?: number;
})[] | null;
toolChoice: "none" | "auto" | "required" | {
/** @enum {string} */
type: "function";
Expand Down
348 changes: 348 additions & 0 deletions apps/docs/content/features/web-search.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,348 @@
---
title: Native Web Search
description: Enable real-time web search capabilities to get up-to-date information from the internet.
icon: Globe
---

import { Callout } from "fumadocs-ui/components/callout";

# Native Web Search

LLM Gateway supports native web search capabilities that allow models to access real-time information from the internet. This feature is useful for answering questions about current events, recent news, live data, and other time-sensitive information that may not be in the model's training data.

## How It Works

When you include the `web_search` tool in your request, the model can search the web to gather relevant information before generating a response:

1. You send a request with the `web_search` tool enabled
2. The model determines if web search is needed based on the query
3. If needed, the model performs web searches to gather current information
4. The model synthesizes the search results and generates a response
5. Citations are included in the response to show information sources

## Supported Providers

Native web search is available on select models. See all models with native web search support on our [models page](https://llmgateway.io/models?filters=1&webSearch=true).

## Basic Usage

To enable web search, add the `web_search` tool to your request:

```bash
curl -X POST "https://api.llmgateway.io/v1/chat/completions" \
-H "Authorization: Bearer $LLM_GATEWAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-5.2",
"messages": [
{
"role": "user",
"content": "What is the current weather in San Francisco?"
}
],
"tools": [
{
"type": "web_search"
}
]
}'
```

### Example Response

```json
{
"id": "chatcmpl-abc123",
"object": "chat.completion",
"created": 1234567890,
"model": "openai/gpt-5.2",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "The current weather in San Francisco is 57°F (14°C) with mostly cloudy skies...",
"annotations": [
{
"type": "url_citation",
"url": "https://weather.com/...",
"title": "San Francisco Weather"
}
]
Comment on lines +65 to +71

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Documentation example shows incorrect annotation structure.

The example response shows a flat annotation format, but the actual UrlCitationAnnotation type (in types.ts) uses a nested structure with url_citation object:

 "annotations": [
   {
     "type": "url_citation",
-    "url": "https://weather.com/...",
-    "title": "San Francisco Weather"
+    "url_citation": {
+      "url": "https://weather.com/...",
+      "title": "San Francisco Weather"
+    }
   }
 ]

The same inconsistency appears in the Citations section (lines 210-221). Please update the examples to match the actual API response structure.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"annotations": [
{
"type": "url_citation",
"url": "https://weather.com/...",
"title": "San Francisco Weather"
}
]
"annotations": [
{
"type": "url_citation",
"url_citation": {
"url": "https://weather.com/...",
"title": "San Francisco Weather"
}
}
]
🤖 Prompt for AI Agents
In apps/docs/content/features/web-search.mdx around lines 78-84 and 210-221, the
example JSON shows annotations as a flat object with keys like "type":
"url_citation" and top-level "url"/"title", but the actual UrlCitationAnnotation
type uses a nested structure where the annotation has "type": "url_citation" and
a nested "url_citation" object containing the fields (e.g., url, title). Update
both examples to wrap the url/title inside a "url_citation" object under the
annotation entry to match the API response shape.

},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 15,
"completion_tokens": 150,
"total_tokens": 165,
"cost_usd_total": 0.0315
}
}
```

## Web Search Options

The `web_search` tool accepts optional configuration parameters:

### User Location

Provide location context to get more relevant local search results:

```json
{
"type": "web_search",
"user_location": {
"city": "San Francisco",
"region": "California",
"country": "US",
"timezone": "America/Los_Angeles"
}
}
```

### Search Context Size

Control the amount of web content retrieved (OpenAI only):

```json
{
"type": "web_search",
"search_context_size": "medium"
}
```

Available values:

- `low` - Minimal search context, faster responses
- `medium` - Balanced context (default)
- `high` - Maximum search context, more comprehensive

### Max Uses

Limit the number of searches per request (provider-dependent):

```json
{
"type": "web_search",
"max_uses": 3
}
```

## Using with SDKs

### OpenAI SDK (Python)

```python
from openai import OpenAI

client = OpenAI(
base_url="https://api.llmgateway.io/v1",
api_key="your-api-key"
)

response = client.chat.completions.create(
model="openai/gpt-5.2",
messages=[
{"role": "user", "content": "What are the latest news headlines today?"}
],
tools=[{"type": "web_search"}]
)

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

### OpenAI SDK (TypeScript)

```typescript
import OpenAI from "openai";

const client = new OpenAI({
baseURL: "https://api.llmgateway.io/v1",
apiKey: "your-api-key",
});

const response = await client.chat.completions.create({
model: "openai/gpt-5.2",
messages: [{ role: "user", content: "What are the latest tech news?" }],
tools: [{ type: "web_search" }],
});

console.log(response.choices[0].message.content);
```

## Streaming

Web search works with streaming responses. Citations are included in the final chunks:

```bash
curl -X POST "https://api.llmgateway.io/v1/chat/completions" \
-H "Authorization: Bearer $LLM_GATEWAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-5.2",
"messages": [
{"role": "user", "content": "What is the current stock price of Apple?"}
],
"tools": [{"type": "web_search"}],
"stream": true
}'
```

## Citations and Sources

Web search responses include citations to show where information was sourced from. These appear in the `annotations` field of the message:

```json
{
"annotations": [
{
"type": "url_citation",
"url": "https://example.com/article",
"title": "Article Title",
"start_index": 0,
"end_index": 50
}
]
}
```

<Callout type="info">
Citation format may vary slightly between providers, but LLM Gateway
normalizes them into a consistent structure.
</Callout>

## Cost Tracking

Web search costs are tracked separately from token costs in the usage object:

```json
{
"usage": {
"prompt_tokens": 15,
"completion_tokens": 150,
"total_tokens": 165,
"cost_usd_total": 0.0125,
"cost_usd_input": 0.0015,
"cost_usd_output": 0.01,
"cost_usd_web_search": 0.01
}
}
```

The `cost_usd_web_search` field shows the cost incurred specifically for web search queries. Web search is billed at $0.01 per search call for reasoning models (GPT-5, o-series) and $0.025 per call for non-reasoning models.

## Combining with Function Tools

You can use web search alongside regular function tools:

```json
{
"tools": [
{ "type": "web_search" },
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get weather for a location",
"parameters": {
"type": "object",
"properties": {
"location": { "type": "string" }
}
}
}
}
]
}
```

<Callout type="warning">
Some dedicated search models only support web search and do not support
additional function tools. Use `gpt-5.2` or other GPT-5 series models if you
need both web search and function tools.
</Callout>

## Use Cases

### Current Events and News

```json
{
"messages": [
{ "role": "user", "content": "What are the major news stories today?" }
],
"tools": [{ "type": "web_search" }]
}
```

### Real-Time Data

```json
{
"messages": [
{ "role": "user", "content": "What is the current price of Bitcoin?" }
],
"tools": [{ "type": "web_search" }]
}
```

### Research and Fact-Checking

```json
{
"messages": [
{
"role": "user",
"content": "What are the latest findings on climate change?"
}
],
"tools": [{ "type": "web_search" }]
}
```

### Local Information

```json
{
"messages": [
{
"role": "user",
"content": "What restaurants are open near me right now?"
}
],
"tools": [
{
"type": "web_search",
"user_location": {
"city": "New York",
"country": "US"
}
}
]
}
```

## Best Practices

1. **Use GPT-5.2**: For the best web search experience with full tool support, use `openai/gpt-5.2`
2. **Provide location context**: When queries are location-dependent, include `user_location` for more relevant results
3. **Monitor costs**: Web search incurs per-query costs in addition to token costs
4. **Check citations**: Always review the citations in responses to verify information sources
5. **Use streaming**: For user-facing applications, enable streaming to show responses as they're generated

## Error Handling

If you try to use web search with a model that doesn't support it:

```json
{
"error": {
"message": "Model gpt-4o does not support native web search. Remove the web_search tool or use a model that supports it. See https://llmgateway.io/models?features=webSearch for supported models.",
"type": "invalid_request_error"
}
}
```

To avoid this error, only use the `web_search` tool with [native web search enabled models](https://llmgateway.io/models?filters=1&webSearch=true).
Loading
Loading