Codex 使用 DeepSeek:Responses 協議、CC Switch 路由與驗證方法

依據 Codex 設定參考、DeepSeek API 與 CC Switch 文件,說明 Responses 和 Chat Completions 的差異,並驗證本地路由與 OpenRouter Responses Beta。

想讓 Codex 使用 DeepSeek,第一反應通常是改 ~/.codex/config.toml

1
2
model = "deepseek-chat"
base_url = "https://api.deepseek.com"

這個思路在一些舊版本或普通 OpenAI SDK 場景裡確實成立,但放到當前 Codex CLI 上,很容易撞到一個底層問題:Codex 的自定義模型供應商走的是 OpenAI Responses 協議,而 DeepSeek 官方介面主要提供 OpenAI 相容的 Chat Completions 呼叫方式。

我本機當前是 codex-cli 0.111.0codex --help 裡可以看到它支援 --config--model--profile 這些配置入口;OpenAI 官方 Codex 設定參考也寫得很明確:model_providers.<id>.wire_api 目前只支援 responses,省略時也預設是 responses

DeepSeek 官方文件則給出的呼叫路徑是 https://api.deepseek.com/chat/completions,示例也是 client.chat.completions.create(...)。所以問題不在於 DeepSeek 不能被 OpenAI SDK 呼叫,而在於 Codex 發出去的請求語義和 DeepSeek 原生介面能理解的語義不完全是一套東西。

這就是為什麼直接把 base_url 改成 https://api.deepseek.com 後,可能出現下面這些現象:

  • 請求路徑不匹配,直接 404 或返回格式不對。
  • 多輪對話、工具呼叫、補丁生成時解析失敗。
  • tool_calls 順序、訊息結構、流式事件格式對不上。
  • 看起來模型能回一句話,但一到 Codex 真正幹活就開始報錯。

更穩的辦法,是在 Codex 和 DeepSeek 之間放一個“翻譯層”。常見有兩種路線。 方法一:使用 CC Switch 的 DeepSeek 本地路由

本地閘道器的作用不是簡單轉發,而是把 Codex 的 Responses 請求轉換成 DeepSeek 能處理的 Chat Completions,再把普通 JSON、SSE 流、推理內容和工具呼叫轉換回 Codex 能解析的 Responses 事件。

CC Switch 從 3.16 起提供這一條明確的官方專案路徑。操作順序是:

  1. 從官方 Releases 安裝當前版本 CC Switch。
  2. 切換到頂部的 Codex 頁面並新增 Provider。
  3. 選擇內建 DeepSeek 預設,填寫 DeepSeek API Key。
  4. 保留預設自動啟用的 Needs Local Routing
  5. 在設定的 Routing 頁面啟動本地路由,併為 Codex 開啟接管。
  6. 完全退出並重新啟動 Codex,使模型目錄重新載入。

路由啟用後,官方指南給出的 Codex 本地地址通常是:

1
http://127.0.0.1:15721/v1

不要把這個埠寫成固定真理;以 CC Switch 當前介面和生成的使用者級 ~/.codex/config.toml 為準。CC Switch 會管理模型目錄和鑑權欄位,手動複製舊教程中的 TOML 反而容易與當前版本衝突。

進入 Codex 後,先用 /model 檢查是否顯示 DeepSeek 預設,再發一個最小請求。隨後檢視 CC Switch Routing 頁面的請求數量或日誌;只有請求確實經過本地路由,才能證明不是誤用了其他 Provider。 實際環境記錄

本文複核時,本機執行結果為:

1
codex-cli 0.111.0

codex --help 同時顯示 --config--model--profile 可用。當前機器沒有安裝 CC Switch,也沒有配置 DeepSeek Key,因此本文不聲稱完成了端到端 DeepSeek 生成實測;上面的介面步驟來自 CC Switch 專案文件。讀者自己的驗收應儲存 Codex 版本、CC Switch 版本、請求日誌和工具呼叫結果。 方法二:用 OpenRouter BYOK 做線上橋接

如果不想執行本地轉換層,可以評估 OpenRouter 的 Responses API Beta 與 BYOK。BYOK 是把自己的上游供應商 Key 繫結到 OpenRouter,由 OpenRouter 負責路由;Codex 訪問時使用的仍是 OpenRouter API Key。

OpenRouter 當前把 Responses API 標為 Beta,並說明它是無狀態實現。介面能力和 Codex 所需事件仍可能變化,因此這條路線應先驗證,再決定是否用於長期工作。

這裡最容易寫錯的是環境變數。Codex 訪問的是 OpenRouter,所以 env_key 通常應該是 OPENROUTER_API_KEY,不是 DEEPSEEK_API_KEY。DeepSeek Key 要在 OpenRouter 的 BYOK 或 provider key 設定裡新增。

配置示例:

1
2
3
4
5
6
7
8
9
[profiles.deepseek-openrouter]
model = "deepseek/deepseek-chat"
model_provider = "openrouter"

[model_providers.openrouter]
name = "OpenRouter"
base_url = "https://openrouter.ai/api/v1"
env_key = "OPENROUTER_API_KEY"
wire_api = "responses"

啟動方式:

1
2
export OPENROUTER_API_KEY="your-openrouter-key"
codex --profile deepseek-openrouter

PowerShell:

1
2
$env:OPENROUTER_API_KEY="your-openrouter-key"
codex --profile deepseek-openrouter

然後在 OpenRouter 後臺新增 DeepSeek provider key,並限制允許使用該 BYOK Key 的 OpenRouter API Key。模型 ID 必須以 OpenRouter 當前模型目錄為準,不能把 DeepSeek 官方模型名直接照搬後假定可用。

在啟動 Codex 前,先驗證 Responses 端點本身:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
$headers = @{
  Authorization = "Bearer $env:OPENROUTER_API_KEY"
  "Content-Type" = "application/json"
}

$body = @{
  model = "从 OpenRouter 模型目录复制的 DeepSeek ID"
  input = "只回复 READY"
  max_output_tokens = 16
} | ConvertTo-Json -Depth 6

Invoke-RestMethod `
  -Uri https://openrouter.ai/api/v1/responses `
  -Method Post `
  -Headers $headers `
  -Body $body

這個請求成功,只證明基礎 Responses 呼叫可用。還要在臨時倉庫中驗證檔案讀取、補丁、流式響應和工具呼叫,才能判斷它是否滿足 Codex 工作流。

這條路省掉本地閘道器維護,但會增加線上中間層,而且 Responses 仍處於 Beta。排障時要分別儲存 Codex、OpenRouter 和上游 DeepSeek 的錯誤資訊。 要不要繼續用 deepseek-chat 這個模型名?

DeepSeek 官方文件在 2026 年 5 月的說明裡,推薦模型名已經出現 deepseek-v4-flashdeepseek-v4-pro,並提示 deepseek-chatdeepseek-reasoner 相容別名會在 2026-07-24 之後廢棄。

所以新配置裡更建議優先測試:

1
model = "deepseek-v4-flash"

如果走 OpenRouter,則要按 OpenRouter 的模型命名來寫,例如:

1
model = "deepseek/deepseek-chat"

實際可用名稱以你所用閘道器或 OpenRouter 模型頁為準。模型名不對時,錯誤通常會表現為 model not found、404,或者 provider 找不到對應 endpoint。 直接改 DeepSeek 官方 base_url 為什麼不推薦

你當然可以試著寫:

1
2
3
4
5
6
7
8
[profiles.deepseek-direct]
model = "deepseek-v4-flash"
model_provider = "deepseek"

[model_providers.deepseek]
name = "DeepSeek"
base_url = "https://api.deepseek.com"
env_key = "DEEPSEEK_API_KEY"

但這更像排錯實驗,不適合作為穩定方案。因為 Codex 會按 Responses 協議去和自定義 provider 說話,而 DeepSeek 官方示例走的是 /chat/completions。如果 DeepSeek 或 Codex 未來補齊了相容層,這種直連才可能變得簡單;在此之前,橋接層更靠譜。 改完配置後還是走 OpenAI 怎麼辦

先確認配置檔案位置。全域性配置應該在:

1
~/.codex/config.toml

專案裡的 .codex/config.toml 不適合放 model_providermodel_providers 這類機器級 provider 配置。OpenAI 官方文件也提醒,專案級配置不會覆蓋這些本地 provider 和認證相關欄位。

不要把 codex logout 當成通用排錯第一步。官方登入態和第三方 Provider 配置是不同問題;貿然退出只會增加恢復成本。先檢查正在使用的 profile、model_provider、模型目錄和本地路由日誌。

還可以用臨時參數做一次快速驗證:

1
codex --profile deepseek-openrouter

或者:

1
codex -c model_provider=openrouter -c model="实际模型 ID"

如果這樣能生效,說明配置本身可讀;如果不生效,優先檢查 profile 名稱、TOML 語法、環境變數是否只在當前 shell 裡有效。 排障清單

  • 401:Key 不對,或者 env_key 指向了錯誤的環境變數。
  • 404base_url 或模型名不對,也可能是把 Responses 請求打到了只支援 Chat Completions 的地址。
  • tool_calls、patch、流式解析報錯:大機率是協議橋接不完整。
  • 仍顯示預設 OpenAI 模型:確認使用者級配置、profile 與 /model 結果,不要先刪除登入態。
  • PowerShell 設定環境變數後新開視窗失效:$env:... 只對當前會話生效,需要長期儲存就改使用者環境變數。

- OpenRouter BYOK 沒走自己的 DeepSeek Key:檢查 OpenRouter 後臺 provider key 是否繫結、是否允許當前 OpenRouter API Key 使用,以及是否開啟了 fallback。 結論

讓 Codex 使用 DeepSeek,不是不能改 config.toml,而是不能只改 base_url 就指望一切自動相容。

當前可以驗證的兩條路是:

  1. 用 CC Switch 本地路由做 Responses 與 Chat Completions 轉換。
  2. 用 OpenRouter Responses API Beta,再結合 BYOK 路由到自己的 DeepSeek Key。

兩種方法都不能只以“返回一句話”作為成功標準。至少要驗證模型選擇、流式輸出、檔案修改、工具呼叫、錯誤恢復和 Key 是否實際走向預期 Provider。

參考資料: