OpenRouter Server Tools 网页搜索工具:为任意模型提供实时搜索能力

openrouter:web_search 是 OpenRouter 的 Server Tool(Beta),让任何 LLM 模型都能在推理过程中执行实时网络搜索。只需在 tools 数组中添加该工具,模型即可根据请求内容自主决定是否搜索、搜索几次,并将结果融入回复。支持五种搜索引擎:auto(默认)、native(provider 原生)、exa、firecrawl(BYOK)、parallel。可配置 max_results(单次搜索结果数)、max_total_results(整个请求的总结果上限)、search_context_size(每条结果的内容详细程度)和域名过滤。用量记录在响应 usage.server_tool_use.web_search_requests 中。本文还提供从旧版 Web Search Plugin(plugins 数组方式)迁移到新版的完整对照示例。

openrouter:web_search Server Tool(目前为 Beta)让任何 OpenRouter 模型都能获取实时网络信息。模型判断需要当前数据时,调用该工具执行搜索;OpenRouter 返回结果,模型据此生成有据可查的回复。

Beta 提醒:Server Tools 目前处于 Beta 阶段,API 和行为可能会有变更。

工作原理

  1. tools 数组中包含 { "type": "openrouter:web_search" }
  2. 模型根据用户请求决定是否需要搜索,并生成搜索词
  3. OpenRouter 使用配置的引擎执行搜索(默认 auto,优先 provider 原生,回退到 Exa)
  4. 搜索结果(URL、标题、摘要)返回给模型
  5. 模型综合结果生成回复,必要时可在一次请求中多次搜索

快速开始

const response = await fetch('https://openrouter.ai/api/v1/chat/completions', {
  method: 'POST',
  headers: {
    Authorization: 'Bearer <OPENROUTER_API_KEY>',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    model: 'openai/gpt-4o',
    messages: [
      {
        role: 'user',
        content: '本周 AI 领域有哪些重大进展?'
      }
    ],
    tools: [
      { type: 'openrouter:web_search' }
    ]
  }),
});

const data = await response.json();
console.log(data.choices[0].message.content);

参数配置

{
  "type": "openrouter:web_search",
  "parameters": {
    "engine": "exa",
    "max_results": 5,
    "max_total_results": 20,
    "search_context_size": "medium",
    "allowed_domains": ["example.com"],
    "excluded_domains": ["reddit.com"]
  }
}
参数 类型 默认值 说明
engine string auto 搜索引擎:autonativeexafirecrawlparallel
max_results integer 5 单次搜索最多返回结果数(1–25),对 Exa、Firecrawl、Parallel 有效;native 忽略
max_total_results integer 整个请求所有搜索的总结果上限,控制费用和 context 占用
search_context_size string medium 每条结果的内容量:lowmediumhigh;Exa 控制单条字符数,Parallel 控制所有结果总字符数
user_location object 用户大致位置,用于地理偏向搜索(目前仅 native 支持)
allowed_domains string[] 只返回这些域名的结果
excluded_domains string[] 排除这些域名的结果

用户位置

{
  "type": "openrouter:web_search",
  "parameters": {
    "user_location": {
      "type": "approximate",
      "city": "Beijing",
      "region": "Beijing",
      "country": "CN",
      "timezone": "Asia/Shanghai"
    }
  }
}

所有字段均为可选。

引擎选择

引擎 说明
auto(默认) 优先使用 provider 原生搜索,不支持时回退到 Exa
native 强制使用 provider 内置搜索
exa 使用 Exa 的搜索 API(关键词 + 语义混合)
firecrawl 使用 Firecrawl 搜索 API(BYOK,需自备密钥)
parallel 使用 Parallel 搜索 API

引擎能力对比

功能 Exa Firecrawl Parallel Native
域名过滤 视 provider
内容量控制 ✓(单条限制) ✓(总量限制)
API Key 服务端 BYOK 服务端 Provider 处理

域名过滤

{
  "type": "openrouter:web_search",
  "parameters": {
    "allowed_domains": ["arxiv.org", "nature.com"],
    "excluded_domains": ["reddit.com"]
  }
}

各引擎域名过滤支持情况:

引擎 allowed_domains excluded_domains 备注
Exa 可同时使用
Parallel 互斥,二选一
Firecrawl 设置后返回错误
Native (Anthropic) 互斥,二选一
Native (OpenAI) excluded 被忽略
Native (xAI) 互斥,二选一
Native (Perplexity) 不支持

控制总结果数

在 Agent 循环中控制费用和 context 用量:

{
  "type": "openrouter:web_search",
  "parameters": {
    "max_results": 5,
    "max_total_results": 15
  }
}

达到上限后,后续搜索调用会返回"已达到限制"提示,不再执行真实搜索。

Responses API 支持

const response = await fetch('https://openrouter.ai/api/v1/responses', {
  method: 'POST',
  headers: {
    Authorization: 'Bearer <OPENROUTER_API_KEY>',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    model: 'openai/gpt-4o',
    input: '今天比特币价格是多少?',
    tools: [
      { type: 'openrouter:web_search', parameters: { max_results: 3 } }
    ]
  }),
});

用量追踪

搜索用量记录在响应 usage 对象中:

{
  "usage": {
    "input_tokens": 105,
    "output_tokens": 250,
    "server_tool_use": {
      "web_search_requests": 2
    }
  }
}

web_search_requests 记录模型在这次请求中发起的搜索次数。

费用

引擎 费用
Exa 每 1000 条结果 $4(默认 5 条 = 最多 $0.02/次搜索)
Parallel 每 1000 条结果 $4(与 Exa 相同)
Firecrawl 直接使用你的 Firecrawl credits,OpenRouter 不收费
Native 由 provider 收费(OpenAI、Anthropic、Perplexity、xAI 各有定价)

费用均叠加在处理请求和响应的标准 LLM token 费用之上。

从旧版 Web Search Plugin 迁移

旧版 plugins 数组方式已弃用,请迁移到新版 tools 数组方式。

主要差异:

对比项 Web Search Plugin(已弃用) Web Search Server Tool
启用方式 plugins: [{ id: "web" }] tools: [{ type: "openrouter:web_search" }]
搜索决策 每次请求固定搜索一次 模型自主决定是否/何时搜索
调用次数 1 次 0 到多次
总结果上限 有(max_total_results

迁移示例:

// 旧版(已弃用)
{
  "model": "openai/gpt-4o",
  "messages": [...],
  "plugins": [{ "id": "web", "max_results": 3 }]
}

// 新版
{
  "model": "openai/gpt-4o",
  "messages": [...],
  "tools": [
    { "type": "openrouter:web_search", "parameters": { "max_results": 3 } }
  ]
}
// 旧版(:online 变体)
{ "model": "openai/gpt-4o:online" }

// 新版
{
  "model": "openai/gpt-4o",
  "tools": [{ "type": "openrouter:web_search" }]
}

常见问题

Q: 模型一定会搜索吗?

A: 不一定。模型自主判断是否需要搜索。用户问"今天 XX 新闻"时大概率触发;问历史知识时可能直接回答。如需确保触发,可在系统提示中明确说明"当用户问到时效性问题时,必须使用搜索工具"。

Q: 如何控制搜索费用?

A: 使用 max_total_results 限制整个请求中所有搜索的总结果数。例如设置为 10,模型最多获取 10 条结果后就不能再搜索了。对于 Agent 循环场景,这是控制费用最有效的参数。

Q: Exa 和 Parallel 引擎的区别是什么?

A: 两者费用相同(每 1000 条 $4),都支持域名过滤。主要差异在内容量控制:Exa 的 search_context_size 控制每条结果的字符数;Parallel 的 search_context_size 控制所有结果的总字符数。如果需要精确控制每条结果的信息量,选 Exa;需要控制总 token 消耗,选 Parallel。