agentgateway 1.6.0 的變更清單裡有一筆 PR #3363,標題是「fix(llm): carry thinking blocks between Messages and Chat Completions」,讓 thinking 區塊在 Anthropic Messages 跟 Chat Completions 之間轉換時能帶過去。同一份 release notes 的第一條 breaking change 卻寫著:從這版開始,Anthropic Messages 請求預設不走 Chat Completions 了,改走 OpenAI Responses。而 Responses 那條轉換,原文是這樣寫的:

The Responses conversion drops extended-thinking history, while the Chat Completions conversion preserves it.

一條路剛修好,預設就換到另一條會漏東西的路上。

會被這件事打到的處境很具體:你的 client 講的是 Anthropic Messages 格式,中間放了一台 gateway,後面接的卻是別家的模型。release notes 自己點名了這種 client,同一版的新功能裡有一句「Provider context-overflow errors are translated so Claude Code can compact and retry」,也就是後端模型回 context 爆掉的錯誤時,gateway 會翻譯成 Claude Code 看得懂、能自己壓縮重試的樣子。開發團隊顯然知道有人把 Claude Code 接在它後面。

先交代手上有什麼:README、官方文件、v1.6.0 的 release notes、GitHub API 查到的 repo 資訊。agentgateway 我沒裝,一個請求都沒送過,所以下面講的行為全是文件的說法;哪幾句是我自己推的,寫到時會講。

1.6 為什麼會出現這種互相打架的改動,要從頭講起。

2025 年 3 月:一個 Rust 寫的 proxy

repo 是 2025 年 3 月 18 日建的,主要語言 Rust,Apache-2.0 授權。GitHub 上的簡介只有一行:「Next Generation Agentic Proxy for AI Agents and MCP servers」。到 2026 年 10 月 6 日我用 GitHub API 查的時候,它有 5,194 顆星,最近一次 push 是當天早上(UTC)。

它要擋在什麼東西前面,README 列得很清楚:LLM 請求(統一成 OpenAI 相容的 API,加上預算控管和負載平衡)、MCP server、A2A agent,再加上自架模型的推論路由。認證、RBAC、限流、TLS、guardrail 這些傳統 gateway 該有的也都在。README 同時自承「currently in active development」,功能還會變。

五個月後的 2025 年 8 月 25 日,Linux Foundation 發新聞稿宣布接下這個專案,寫明是 Solo.io 創建後捐出來的,列出的貢獻公司有 AWS、Cisco、Huawei、IBM、Microsoft、Red Hat、Shell、Zayo。新聞稿講的問題只有一句:現有的 gateway 大多設計在 AI agent 出現之前,不大改架構就很難支援這些新協定。Solo.io 執行長 Idit Levine 在新聞稿裡講得更直接:

Existing API gateways weren’t designed for the rapidly evolving networking demands of AI and agentic architectures, and they can’t adapt fast enough.

前半句像行銷詞。一年後回頭看,該記住的是後半句「can’t adapt fast enough」:協定會一直變,gateway 得跟著變,還得變得夠快。

2026 年 7 月:協定自己把 session 拆掉

2026 年 7 月 6 日,diginomica 報導 agentgateway 移到 Agentic AI Foundation(AAIF)底下,跟 Anthropic 的 MCP、Block 的 goose、AGENTS.md 放在同一個傘下。三個禮拜後,MCP 發了 2026-07-28 修訂版,把整個握手拆掉了。

舊的 MCP 像打電話給總機轉分機。你先 initialize 打通,拿到一個 Mcp-Session-Id,之後整通電話都要接在同一條線上,總機得記住你接的是哪支分機。新的 MCP 比較像寄信,每封信自己在 _meta 裡寫清楚寄件人是誰、講哪一版、要什麼,誰收到都看得懂,不必記得上一封。client 想知道對面能做什麼,就送一個 server/discover 去問。這版規格 client 端要怎麼判斷對面是新是舊,我在〈握手拆掉之後,你的 MCP client 怎麼判斷對面是新是舊〉寫過,這裡只看中間那一層。

gateway 就是那間收發室。協定一改,收發室最尷尬:外面同時有人打電話、有人寄信,後面的分機也是新舊混著。

agentgateway 的 MCP 規格相容頁對這件事的立場寫得很明確:

The sessionless protocol is the recommended direction for MCP going forward, and agentgateway supports it by default.

舊版的 client 跟 server 照樣支援,文件說新舊可以在同一台 gateway 後面共存。舊 client 走 initialize 進來,gateway 繼續接;新 client 打到舊 server 被拒,client 退回舊流程,文件說這個退回由 gateway 透明處理。不過同一頁對舊版本的保證只到「typically work, but are not guaranteed」,也就是通常會動,但不保證。

真正讓我停下來的是「交集」

讀到這裡都還在預期內。讓我意外的是 Virtual MCP。

Virtual MCP 是把好幾個 MCP server 縫成一個給 client 看。文件的定義是「Multiplexing combines multiple MCP servers (targets) within a single backend into one unified MCP server」。client 只看到一台 server,背後其實是一整排。

一整排 server 的協定版本不會整齊。相容頁講到這種聯合(federating)的情況,用的詞是 intersection:gateway 拿所有 target 都支援的版本交集去協商,讓 client 只會談成每個 target 都服務得了的版本。

照這句話推,後果是這樣(這是我的推論,文件沒有這樣舉例):你把九台已經支援 2026-07-28 的 server 跟一台只會舊握手的 server 縫在一起,交集裡就沒有新版,整個 virtual server 對 client 來說會被那一台拉回舊版。木桶的高度看最短那片板子,協定版本也一樣。

所以我的建議是:用 Virtual MCP 縫 server 之前,先盤點每個 target 講哪一版,把還沒升級的那幾台拆到另一個 backend,不要跟新的縫在一起。 會讓我改變想法的條件有兩個。一是你的 client 本來就只會舊握手,那交集掉回舊版對你沒有損失。二是你只縫一兩台、而且它們同時升級,那盤點的成本大於收益。

Virtual MCP 還有一個小到容易漏看的規則。多個 target 時,tool 名稱預設會加上 target 名當前綴,文件給的例子是 time_get_current_time、everything_echo。緊接著有一句:「the target names cannot include underscores (_)」。

文件沒解釋為什麼。看例子就懂了:前綴和原本的 tool 名之間用的就是底線,而 tool 名自己也常帶底線(get_current_time)。gateway 收到 time_get_current_time,要知道該轉給哪個 target,只能從第一個底線切開。target 名如果叫 my_time,my_time_get_current_time 就不知道該在哪裡切了。所以底線被保留給分隔符用,target 名不准碰。這段同樣是我從範例推出來的理由。

如果你嫌前綴醜,把前綴模式設成 never,那所有 target 的 tool 名就必須彼此不撞,文件寫「agentgateway fails to start if two targets expose the same tool name in this mode」,撞名直接起不來。還有一個邊角:target 可以掛條件,條件全部算出 false 時,client 看到的是一台空的 virtual MCP server,不是錯誤。空的跟壞的在 client 那頭長得很像,排查時記得先看條件。

2026 年 8 月到 10 月:36 天裡的轉換帳

agentgateway 走到 1.6 的路

2025-03-18

GitHub repo 建立,Rust 寫成。

2025-08-25

Linux Foundation 宣布接手,Solo.io 捐出。

2026-07-06

diginomica 報導移入 AAIF。

2026-07-28

MCP 新修訂拆掉 session 握手;agentgateway 文件寫明預設支援 sessionless。

2026-08-27

v1.5.0。Anthropic Messages 轉換偏好 Chat Completions。

2026-09-14 ~ 10-01

v1.6.0 的 alpha.1、alpha.2、rc.1 三個預發布版。

2026-10-02

v1.6.0 正式版,預設轉換改走 OpenAI Responses。

v1.5.0 在 2026 年 8 月 27 日發,v1.6.0 在 10 月 2 日發,中間隔 36 天。rc.1 是 UTC 10 月 1 日 22:35 發的,正式版是 10 月 2 日 16:26,不到 18 小時。

回到開頭那件事。Anthropic Messages 進來、要送去別家模型時,gateway 得把它翻成對方懂的格式。這像把一份帶眉批的稿子交給翻譯社:A 社連眉批一起翻,B 社只翻正文。1.5 預設交給 A 社(Chat Completions),1.6 改交給 B 社(Responses),而 extended thinking 的歷史就是那些眉批。

受影響的範圍 release notes 列得很細:OpenAI、Ollama、Groq、Hugging Face、xAI 這幾個 provider,Azure 上非 Claude 的模型,還有同時宣告支援 Responses 和 Chat Completions 的自訂 provider。名單裡沒有 Anthropic 自己。照這份名單看,Claude 格式進、Claude 模型出的流量不在這條改動的範圍內。

1.6 動到的不只這一條。下面這張表只放 release notes 寫出前後差異的項目,都是升級時會默默改變行為的:

項目 1.5 1.6
Anthropic Messages 轉成 OpenAI 格式 偏好 Chat Completions,保留 extended-thinking 歷史 偏好 Responses,丟掉 extended-thinking 歷史
設定了 base URL 但沒帶路徑(如 https://api.openai.com) 自訂與 Ollama provider 會補 /v1;OpenAI 等內建 provider 轉送 client 的路徑 一律用 /,要自己改成 https://api.openai.com/v1
常見公開模型的計價 要另外設定 catalog 內建 catalog 給預設單價,USD 預算與用到 llm.cost 的政策升級後可能開始作用
檢查串流回應或 realtime 連線時,guard provider 本身出錯 等同把 failureMode 設成 failOpen 拒絕內容
取得 provider 憑證失敗 回 500 回 502
standalone YAML 裡沒加引號的 no 變成 boolean 維持字串
LLM 請求 buffer 預設上限 2 MiB 32 MiB

計價那一列最容易出事。你的 USD 預算原本對某些模型沒有作用,是因為 gateway 不知道它們多少錢;升級後它知道了,這些模型的花費就開始算進預算和 llm.cost 的判斷裡。你一行設定都沒改,行為卻變了。

專案自己留的那條死路

release notes 給了一個逃生口:設環境變數 AGENTGATEWAY_MESSAGES_PREFER_COMPLETIONS=true,就能退回 1.5 的 Chat Completions 偏好。但它附了兩個條件。一是這個變數的用途寫的是「a temporary workaround for a Responses conversion bug」,Responses 轉換有個 bug,原文沒說是哪個。二是「planned for removal in 1.7」。

這條死路是專案的,不是我的,我沒跑過。但讀完之後我會直接跳過那個環境變數。release notes 在同一節給了比較長命的做法:OpenAI provider 只拿來接 OpenAI 自家的 API;其他 OpenAI 相容的 server 改設成自訂 provider,只宣告它真的支援的格式,如果那台 server 沒實作 /v1/responses,或你的 client 需要 extended-thinking 歷史,就只宣告 Chat Completions。

靠環境變數續命,等於把同一個問題延到 1.7 再處理一次。照格式宣告的方式設好,1.7 拿掉那個變數時你不會有感覺。

如果你的 Anthropic 格式流量全部送到 Anthropic 自己,這整條改動跟你無關。如果只是 client 沒開 extended thinking,丟歷史這件事碰不到你,但 Responses 轉換那個沒寫明的 bug 會影響誰,原文沒說。

1.7 要回答的事

1.6 那兩件看似打架的事,我的讀法是這樣(從兩件事的時間點推的,release notes 沒有說明動機):PR #3363 把 Chat Completions 這條路補完整,讓它成為可靠的「明確選擇」;預設改走 Responses,是押注 Responses 才是之後的主路。前者留給知道自己要什麼的人,後者給不設定的人。

押注有沒有押對,要看 1.7。逃生口預計在 1.7 拿掉,那時候 Responses 那個沒寫明的轉換 bug 修好了沒有、Responses 轉換會不會學會帶上 thinking 歷史,release notes 都還沒講。MCP 那邊也一樣,2026-07-28 之後舊握手還能在 gateway 後面「typically work」多久,相容頁沒有給日期。

參考來源