摘要: OpenRouter 推出 agentic web tools,讓支援 tool calling 的模型在同一個 request 內自行決定呼叫 openrouter:web_search 和 openrouter:web_fetch 的次數與時機。工具在 OpenRouter server 端執行,提供一致的 tool 定義和回傳格式,client 不必為不同 provider 重寫串接程式。使用者仍要用 max_total_results、max_content_tokens 和網域過濾控制成本與 context,並注意 native engine 定價與帳單歸屬不同。
模型過去要取得網路資訊,選項只有兩個:接受某一家 provider 內建的搜尋工具,從此被它綁住;或者自己寫程式在 client 端串接搜尋與抓取服務,還得逐一應付各家不同的 schema。OpenRouter 推出的 agentic web tools 另闢一條路——openrouter:web_search 與 openrouter:web_fetch 這組 server tools,讓任何 model 在同一個 request 之內就能自行搜尋、開啟找到的頁面讀取內容,並且綜合出自己的答案。
這套設計的價值落在兩件事上。第一是執行位置:tools 全部在 OpenRouter 的 server 端執行完畢,結果直接送到 model 面前,client 完全不必寫任何程式。第二是輸出的一致性:tool 定義、呼叫介面、回傳格式,在每一個具備 tool calling 能力的 model 上都長得一樣——換掉 model,工具照用,一個以路由為業的平台本來就該把這個優勢做出來。
搜尋的主導權:從固定外掛轉向 agentic
OpenRouter 之前的 web search plugin 走的是固定行程:無論任務內容為何,每個 request 必定執行一次搜尋,幾時搜、下什麼 query,model 都插不上話。改用新的 server tools 之後,這些判斷回到 model 手上——單一 request 可以搜 0 次也可以搜 N 次,query 要下什麼、何時下,全由 model 面對任務自行拿捏。若任務是比較三家雲端 GPU 供應商的報價,model 會自己發出三次條件不同的查詢,再把結論整合起來。搜尋次數由寫死的常數變成模型的判斷,agentic 與否的分界就在這裡。
執行發生在 server,client 端不必動手
啟用工具只要宣告一次 {"type": "openrouter:web_search"}。以前每換一家 provider,tool 定義和結果 parser 都得跟著重寫,行為還未必對得上——例如某些原生工具裡根本沒有 blocked domains 的嚴格執行這回事。這層抽象如今把工具能力從各家差異中抽離出來:如果連行為都要完全相同,就把 Exa 或 Parallel 指定為 engine,request 不管最終落到哪個 model,model 收到的結果都不會變。
Web Search:engine 有四種,計價各不同
| Engine | 運作方式 | 計價 |
|---|---|---|
| Auto(預設) | provider 有支援就用 native,沒有則改走 Exa | 跟著實際用到的 engine 走 |
| Native | 使用 provider 自帶的搜尋 | 由 provider 定價 |
| Exa | 搜尋委託 Exa 執行,從 OpenRouter credits 扣款 | 每次請求 $0.005(最多 10 筆),每多一筆加 $0.001 |
| Parallel | 搜尋委託 Parallel 執行,同樣從 credits 扣款 | 每次請求 $0.005(最多 10 筆),每多一筆加 $0.001 |
四種 engine 各司其職:Auto 先看 provider 支不支援 native search,不支援就退回 Exa;需要行為跨 model 都一致、費用可以預期時,就直接點名 Exa 或 Parallel——兩者價格相同,差別只在執行的人是誰。search_context_size(控制結果 context 的規模)只有 Exa 和 Parallel 會理會,native engine 收到會直接忽略;網域過濾方面,多數 engine 都吃 allowed_domains 與 excluded_domains。文件裡的範例拿來就能用:max_results 設 5、allowed_domains 只留 arxiv.org 與 nature.com、search_context_size 開到 high,就組成一份只讀學術來源、高 context 的研究配置。
Web Fetch:engine 共五種,一個免費
Fetch 通常跟在搜尋後面跑:model 先靠 web_search 圈出候選頁面,接著用 web_fetch 把整份內容抓回來,整條研究流程就在同一個 request 之內由這兩個工具接力完成。
| Engine | 運作方式 | 計價 |
|---|---|---|
| Auto(預設) | provider 有支援就用 native,沒有則改走 Exa | 跟著實際用到的 engine 走 |
| Native | 使用 provider 自帶的抓取 | 由 provider 定價 |
| OpenRouter | 由 OpenRouter 直接發 HTTP 請求抓取 | Free |
| Exa | 做內容抽取,輸出乾淨的 markdown | 每次 $0.001 |
| Parallel | 走 Parallel 的 extract API 做抽取 | 每次 $0.001 |
fetch 這邊多了一個由 OpenRouter 自己提供的 engine:直接對目標發 HTTP 請求、定價 Free,成本敏感的場景就從這裡起步。Exa 與 Parallel 每次抓取 $0.001,會做內容抽取,並輸出乾淨易讀的 markdown。只要指名 Exa、Parallel 或 OpenRouter 其中之一,allowed_domains 與 blocked_domains 就能跨 model 一致地限制哪些 URL 可以抓——native fetch 能力本來就各家不一,希望參數被確實遵守,就從這三個裡挑。
成本與 context 用量的調節旋鈕
agentic loop 裡,真正要防的不是單一次的費用,而是「次數 × context」的乘積。有兩個參數建議直接納入預設:max_total_results 替單一 request 裡全部搜尋加總的結果數設下天花板,一旦碰到,model 收到的就是額度用盡的提示,而不是再跑一輪搜尋;max_content_tokens(文件範例給的是 50000)則框住餵給 model 的內容 token 總量,免得一個大頁面就把 context window 吃掉一半。用實際數字抓一下量級:拿三家 GPU 供應商來比較時,model 若對每家各搜一次、每次 max_results 是 5,累積結果就是 15 筆;把 max_total_results 定在 15,這個任務還會再花多少搜尋成本就被鎖死了。
從 plugin 搬過來:改一行,守一條紅線
"plugins": [{ "id": "web" }] → "tools": [{ "type": "openrouter:web_search" }]
整個遷移就是一個動作:request body 裡的 plugins 換名成 tools,OpenRouter 也備有完整的遷移指南。真正的紅線在 model 端:server tools 只能用在具備 tool calling 能力的 model;不支援的 model 就得留在舊 plugin 上——代價是退回那種每個 request 都固定搜一次的被動節奏。
已知限制與代價
既然是 server-side 工具,執行過程就不歸你管:自訂 JavaScript 跑不了,redirect 也無法在 client 端攔下處理。max_content_tokens 一旦把內容截斷,model 收到的就只有截斷後的版本,藏頁尾的關鍵資訊可能因此漏掉。費用面上,agentic loop 裡 model 說不定會一口氣連搜好幾輪,Exa 與 Parallel 單次不貴,但行為次數一多就得盯著;native engine 的價格由 provider 說了算,跨 provider 比較成本時要各自分開估。還有個實務細節是帳單歸屬:Exa 與 Parallel 的費用記在 OpenRouter credits,帳目集中一處;native engine 的花費則進到 provider 的帳單,成本能見度因此一分為二。
給 Builder 的起手建議
三個馬上能套用的起步做法:一、先用 OpenRouter 自家的 fetch engine(免費)把流程跑通,品質有更高要求時再換成 Exa 的 clean markdown;二、讓 max_total_results 和 max_content_tokens 成為預設配置,成本與 context 用量就變得可預測;三、用 allowed_domains 讓搜尋與抓取只落在可信網域,再用反向的 blocked_domains 排除內部網域——文件裡的範例擋的正是 internal.example.com——當你要把 agent 服務對外開放時,這同時是一道安全邊界。在 Chatroom 介面上點工具圖示,就能直接打開這兩個工具;走 API 的話就照上面表格的參數設。
