Documentation Index
Fetch the complete documentation index at: https://docs.arouter.ai/llms.txt
Use this file to discover all available pages before exploring further.
The web_search Server Tool enables models to search the web during inference. The model decides when a search is needed, ARouter performs it, and the results are injected back into the model’s context automatically.
This is the recommended replacement for the deprecated web plugin and :online model suffix. See Migration Guide below.
Quick Start
{
"model": "openai/gpt-5.4",
"messages": [
{"role": "user", "content": "What happened in AI research this week?"}
],
"tools": [
{"type": "arouter", "arouter": {"id": "web_search"}}
]
}
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.arouter.ai/v1",
apiKey: "lr_live_xxxx",
});
const response = await client.chat.completions.create({
model: "openai/gpt-5.4",
messages: [
{ role: "user", content: "What happened in AI research this week?" }
],
tools: [
{ type: "arouter", arouter: { id: "web_search" } } as any,
],
});
console.log(response.choices[0].message.content);
from openai import OpenAI
client = OpenAI(
base_url="https://api.arouter.ai/v1",
api_key="lr_live_xxxx",
)
response = client.chat.completions.create(
model="openai/gpt-5.4",
messages=[
{"role": "user", "content": "What happened in AI research this week?"}
],
tools=[
{"type": "arouter", "arouter": {"id": "web_search"}}
],
)
print(response.choices[0].message.content)
curl https://api.arouter.ai/v1/chat/completions \
-H "Authorization: Bearer lr_live_xxxx" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-5.4",
"messages": [
{"role": "user", "content": "What happened in AI research this week?"}
],
"tools": [
{"type": "arouter", "arouter": {"id": "web_search"}}
]
}'
Configuration
Pass configuration options inside the arouter object:
{
"tools": [
{
"type": "arouter",
"arouter": {
"id": "web_search",
"max_results": 5,
"engine": "exa",
"include_domains": ["arxiv.org", "nature.com"],
"exclude_domains": ["reddit.com"]
}
}
]
}
| Parameter | Type | Default | Description |
|---|
id | string | — | Must be "web_search" |
max_results | integer | 5 | Maximum number of search results to return |
engine | string | auto | Search engine: "native", "exa", "parallel", or "firecrawl" |
include_domains | string[] | — | Restrict results to these domains (supports wildcards) |
exclude_domains | string[] | — | Exclude results from these domains (supports wildcards) |
max_total_results | integer | — | Cap total results across multiple searches in one request |
Engine Selection
| Engine | Description | Best For |
|---|
| (unset) | Use native if provider supports it, else Exa | General use |
"native" | Provider’s built-in search (OpenAI, Anthropic, xAI) | Best citation quality |
"exa" | Exa’s neural+keyword hybrid search | Research, niche topics |
"parallel" | Parallel’s search API | Fast broad queries |
"firecrawl" | Firecrawl deep crawl (BYOK) | Full page content |
Engine Compatibility
| Engine | include_domains | exclude_domains |
|---|
| Exa | Yes | Yes |
| Parallel | Yes | Yes (mutually exclusive with include) |
| Native (Anthropic) | Yes | Yes (mutually exclusive) |
| Native (OpenAI) | Yes | Ignored |
| Native (xAI) | Yes | Yes (mutually exclusive, max 5 each) |
Domain Filtering
Restrict or exclude domains with optional wildcards:
{
"tools": [
{
"type": "arouter",
"arouter": {
"id": "web_search",
"include_domains": ["*.edu", "arxiv.org", "openai.com/blog"],
"exclude_domains": ["reddit.com", "quora.com"]
}
}
]
}
Parsing Citations
Web search results are returned in annotations on the assistant message:
{
"choices": [
{
"message": {
"role": "assistant",
"content": "According to recent research, [arxiv.org](https://arxiv.org/abs/...) ...",
"annotations": [
{
"type": "url_citation",
"url_citation": {
"url": "https://arxiv.org/abs/2501.12345",
"title": "Scaling Laws for LLMs",
"content": "We study the relationship between...",
"start_index": 32,
"end_index": 96
}
}
]
}
}
]
}
Usage Tracking
Each web search invocation is tracked:
{
"usage": {
"prompt_tokens": 320,
"completion_tokens": 180,
"total_tokens": 500,
"cost": 0.0045,
"server_tool_calls": {
"web_search": 1
}
}
}
Pricing
| Engine | Cost |
|---|
| Exa | $4.00 per 1,000 results |
| Parallel | $4.00 per 1,000 results |
| Native (OpenAI, Anthropic, xAI) | Pass-through at provider rate |
| Firecrawl | BYOK — your Firecrawl API key |
With the default max_results: 5, an Exa search costs $0.02 per invocation. Search costs are charged in addition to normal LLM token costs.
Migrating from Web Plugin
If you previously used the web plugin or :online suffix, migration is straightforward:
Before (deprecated):
{
"model": "openai/gpt-5.4:online",
"messages": [{"role": "user", "content": "Latest AI news"}]
}
{
"model": "openai/gpt-5.4",
"plugins": [{"id": "web", "max_results": 3}],
"messages": [{"role": "user", "content": "Latest AI news"}]
}
After (recommended):
{
"model": "openai/gpt-5.4",
"tools": [
{"type": "arouter", "arouter": {"id": "web_search", "max_results": 3}}
],
"messages": [{"role": "user", "content": "Latest AI news"}]
}
The key behavioral difference: the plugin always runs web search on every request, while the Server Tool lets the model decide whether a search is warranted for the given query.
Next Steps