Anthropic 相容 API:/v1/messages 與 Claude Code 的關鍵契約
想讓 Claude Code 走本地閘道、但又不想改它的 Anthropic 協定用法,你只要把 Base URL 指向 Antigravity Tools,然後用 /v1/messages 跑通一次請求就行。
什麼是 Anthropic 相容 API?
Anthropic 相容 API 指 Antigravity Tools 對外提供的 Anthropic Messages 協定端點。它接收 /v1/messages 請求,在本地做報文清理、串流封裝與重試輪換後,再把請求轉發到上游提供真實模型能力。
學完你能做什麼
- 用 Antigravity Tools 的
/v1/messages介面跑通 Claude Code(或任何 Anthropic Messages 客戶端) - 分清楚 Base URL 和驗證 header 怎麼配,避免 401/404 盲試
- 需要串流就拿到標準 SSE;不需要串流也能拿到 JSON
- 知道代理在後台做了哪些「協定修補」(warmup 攔截、訊息清理、簽名兜底)
你現在的困境
你想用 Claude Code/Anthropic SDK,但網路、帳號、配額、限流這些問題讓對話很不穩定;你已經把 Antigravity Tools 當作本地閘道跑起來了,卻常卡在這幾類問題:
- Base URL 寫成了
.../v1或被客戶端「疊路徑」,結果直接 404 - 開了代理驗證但不知道客戶端到底用哪個 header 傳 key,結果 401
- Claude Code 的後台 warmup/摘要任務把配額悄悄吃掉
什麼時候用這一招
- 你要接入 Claude Code CLI,並希望它「按 Anthropic 協定」直連本地閘道
- 你手頭的客戶端只支援 Anthropic Messages API(
/v1/messages),不想改程式碼
🎒 開始前的準備
前置條件
本課預設你已經跑通了本地反代的基本閉環(能訪問 /healthz,知道代理連接埠與是否開啟驗證)。如果還沒跑通,先看 啟動本地反代並接入第一個客戶端。
你需要準備三樣東西:
- 代理位址(範例:
http://127.0.0.1:8045) - 是否開啟了代理驗證(以及對應的
proxy.api_key) - 一個能發 Anthropic Messages 請求的客戶端(Claude Code / curl 都行)
核心思路
Anthropic 相容 API 在 Antigravity Tools 裡對應一組固定路由:POST /v1/messages、POST /v1/messages/count_tokens、GET /v1/models/claude(見 src-tauri/src/proxy/server.rs 的 Router 定義)。
其中 /v1/messages 是「主線入口」,代理會在真正發上游請求前做一堆相容性處理:
- 清理歷史訊息裡不被協定接受的欄位(例如
cache_control) - 合併連續同角色訊息,避免「角色交替」驗證失敗
- 偵測 Claude Code 的 warmup 報文並直接回傳模擬回應,減少配額浪費
- 根據錯誤類型做重試與帳號輪換(最多 3 次嘗試),提升長會話穩定性
跟我做
第 1 步:確認 Base URL 只寫到連接埠
為什麼/v1/messages 是代理側固定路由,Base URL 寫成 .../v1 很容易被客戶端再拼一次 /v1/messages,最終變成 .../v1/v1/messages。
你可以先用 curl 直接探活:
#你應該看到:{"status":"ok"}
curl -sS "http://127.0.0.1:8045/healthz"第 2 步:如果你開啟了驗證,先記住這 3 種 header
為什麼 代理的驗證中介程式會從 Authorization、x-api-key、x-goog-api-key 裡取 key;開了驗證但 header 沒對上,就會穩定 401。
代理接受哪些驗證 header?
Authorization: Bearer <key>、x-api-key: <key>、x-goog-api-key: <key> 都能用(見 src-tauri/src/proxy/middleware/auth.rs)。
第 3 步:用 Claude Code CLI 直連本地閘道
為什麼 Claude Code 使用 Anthropic Messages 協定;把它的 Base URL 指向本地閘道,就能複用 /v1/messages 這套契約。
按 README 的範例設定環境變數:
export ANTHROPIC_API_KEY="sk-antigravity"
export ANTHROPIC_BASE_URL="http://127.0.0.1:8045"
claude你應該看到:Claude Code 能正常啟動,並在你發送訊息後收到回覆。
第 4 步:先列出可用模型(給 curl/SDK 用)
為什麼 不同客戶端會把 model 原樣傳過來;先把模型列表拿到手,排查問題會快很多。
curl -sS "http://127.0.0.1:8045/v1/models/claude" | jq你應該看到:回傳一個 object: "list" 的 JSON,其中 data[].id 就是可用的模型 ID。
第 5 步:用 curl 呼叫 /v1/messages(非串流)
為什麼 這是最小可重現鏈路:不用 Claude Code,也能確認「路由 + 驗證 + 請求體」到底哪裡出錯。
curl -i "http://127.0.0.1:8045/v1/messages" \
-H "Content-Type: application/json" \
-H "x-api-key: sk-antigravity" \
-d '{
"model": "<從 /v1/models/claude 裡選一個>",
"max_tokens": 128,
"messages": [
{"role": "user", "content": "你好,簡單介紹一下你自己"}
]
}'你應該看到:
- HTTP 200
- 回應標頭裡可能包含
X-Account-Email和X-Mapped-Model(用於排障) - 回應體是 Anthropic Messages 風格的 JSON(
type: "message")
第 6 步:需要串流時,打開 stream: true
為什麼 Claude Code 會用 SSE;你自己用 curl 也能把 SSE 跑通,確認中間沒有代理/緩衝問題。
curl -N "http://127.0.0.1:8045/v1/messages" \
-H "Content-Type: application/json" \
-H "x-api-key: sk-antigravity" \
-d '{
"model": "<從 /v1/models/claude 裡選一個>",
"max_tokens": 128,
"stream": true,
"messages": [
{"role": "user", "content": "用 3 句話解釋什麼是本地反代"}
]
}'你應該看到:一 行行的 SSE 事件(event: message_start、event: content_block_delta 等)。
檢查點 ✅
GET /healthz回傳{"status":"ok"}GET /v1/models/claude能拿到data[].idPOST /v1/messages能 200 回傳(非串流 JSON 或串流 SSE 二選一)
踩坑提醒
1) Base URL 不要寫成 .../v1
Claude Code 的範例是 ANTHROPIC_BASE_URL="http://127.0.0.1:8045",因為代理側路由本身就帶 /v1/messages。
2) 開了驗證但 proxy.api_key 為空,會直接拒絕
代理驗證開啟但 api_key 為空時,中介程式會直接回傳 401(見 src-tauri/src/proxy/middleware/auth.rs 的保護邏輯)。
3) /v1/messages/count_tokens 在預設路徑下是佔位實作
當 z.ai 轉發沒啟用時,這個端點會直接回傳 input_tokens: 0, output_tokens: 0(見 handle_count_tokens)。不要用它來判斷真實 token。
4) 你明明沒開串流,但看到伺服器在「內部走 SSE」
代理對 /v1/messages 有一個相容策略:當客戶端不要求串流時,伺服器可能會內部強制走串流再把結果收集成 JSON 回傳(見 handle_messages 裡 force_stream_internally 的邏輯)。
本課小結
- Claude Code/Anthropic 客戶端要跑通,本質是 3 件事:Base URL、驗證 header、
/v1/messages請求體 - 代理為了「協定能跑 + 長會話穩定」,會對歷史訊息做清理、對 warmup 做攔截、並在失敗時重試/輪換帳號
count_tokens目前不能當真實口徑(除非你啟用了對應的轉發路徑)
下一課預告
附錄:原始碼參考
點擊展開查看原始碼位置
更新時間:2026-01-23
| 功能 | 檔案路徑 | 行號 |
|---|---|---|
代理路由:/v1/messages / count_tokens / models/claude | src-tauri/src/proxy/server.rs | 120-193 |
Anthropic 主入口:handle_messages(含 warmup 攔截與重試迴圈) | src-tauri/src/proxy/handlers/claude.rs | 240-1140 |
模型列表:GET /v1/models/claude | src-tauri/src/proxy/handlers/claude.rs | 1163-1183 |
count_tokens(z.ai 未啟用時回傳 0) | src-tauri/src/proxy/handlers/claude.rs | 1186-1210 |
| Warmup 偵測與模擬回應 | src-tauri/src/proxy/handlers/claude.rs | 1375-1493 |
| --- | --- | --- |
請求清理:移除 cache_control | src-tauri/src/proxy/mappers/claude/request.rs | 68-148 |
| 請求清理:合併連續同角色訊息 | src-tauri/src/proxy/mappers/claude/request.rs | 253-296 |
| --- | --- | --- |
關鍵常數:
MAX_RETRY_ATTEMPTS = 3:/v1/messages的最大重試次數