本文记录一次完整的 OpenCodex 实践过程,目标是让 Codex 同时使用 OpenAI 和 DeepSeek,并让 DeepSeek V4-Flash 作为 Codex 的默认子代理。


1. 为什么需要 OpenCodex

如果只是想在 GPT 和 DeepSeek 之间切换,其实不需要 OpenCodex。

OpenCodex 更有价值的地方在于,它可以在本地启动一个代理,将不同 Provider 的模型统一接入 Codex。

最终形成类似:

1
2
3
4
5
6
7
                    ┌── GPT-5.6 Sol

Codex ── OpenCodex ─┼── GPT-5.6 Terra

├── DeepSeek V4-Flash

└── DeepSeek V4-Pro

进一步还可以配置:

1
2
3
4
5
主代理:GPT

├── 子代理 → DeepSeek V4-Flash

└── 子代理 → DeepSeek V4-Pro

这和单纯使用 CC Switch 进行供应商切换是不一样的。


2. 安装 OpenCodex

Windows PowerShell:

1
npm install -g open-codex

安装完成后理论上应该能够直接运行:

1
ocx --version

遇到的问题

第一次安装后执行:

1
ocx --version

出现:

1
ocx : 无法将“ocx”项识别为 cmdlet、函数、脚本文件或可运行程序

说明 npm 全局安装目录没有正确进入当前 PowerShell 的 PATH。

这个问题和 OpenCodex 本身无关,本质上是:

1
2
3
4
5
npm global package

npm bin 目录

没有进入 PATH

处理好 PATH 后即可继续。


3. 初始化 OpenCodex

执行:

1
ocx init

OpenCodex 会让我们选择默认 Provider。

这里选择:

1
1. OpenAI — ChatGPT login

而不是直接选择 DeepSeek。

原因是我们的目标是:

OpenAI 作为 Codex 主通道,同时后面再加入 DeepSeek。

因此选择:

1
Select default provider (number): 1

然后:

1
Proxy port [10100]:

直接使用默认:

1
10100

之后 OpenCodex 会保存配置:

1
~/.opencodex/config.json

并询问:

1
Inject into Codex config.toml? [Y/n]

选择:

1
Y

这样 OpenCodex 会自动修改 Codex 的 Provider 配置,让 Codex 的 OpenAI 请求经过本地代理。

最终核心关系变成:

1
2
3
4
5
6
7
Codex

http://127.0.0.1:10100/v1

OpenCodex

OpenAI / DeepSeek / 其他 Provider

4. 启动 OpenCodex

执行:

1
ocx start

成功后可以看到:

1
2
3
4
5
6
7
opencodex proxy running on http://localhost:10100

POST /v1/responses → provider translation
POST /v1/chat/completions → OpenAI-compatible clients
GET /healthz → health check
GET /api/* → management API
GET / → GUI dashboard

同时可以看到:

1
2
Codex model catalog:
C:\Users\86182\.codex\opencodex-catalog.json

这个文件非常重要。

它实际上就是:

OpenCodex 给 Codex 提供的模型目录。


5. OpenCodex 最重要的几个文件

Windows 下主要关注:

1
C:\Users\86182\.opencodex\

其中:

1
config.json

保存 OpenCodex 自己的配置。

而:

1
C:\Users\86182\.codex\opencodex-catalog.json

是 OpenCodex 提供给 Codex 的模型目录。

另外:

1
C:\Users\86182\.codex\config.toml

是 Codex 自己的配置。

所以可以简单理解为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
OpenCodex 配置

~/.opencodex/config.json

↓ sync

模型目录

~/.codex/opencodex-catalog.json



Codex

~/.codex/config.toml

6. 配置 DeepSeek

在 OpenCodex 中添加 DeepSeek Provider。

配置完成后,OpenCodex 可以同时维护:

1
2
OpenAI
DeepSeek

模型目录也可以同时出现:

1
2
3
4
gpt-5.6-sol
gpt-5.6-terra
deepseek/deepseek-v4-flash
deepseek/deepseek-v4-pro

此时需要注意一个非常重要的区别:

模型出现在 Codex 菜单里 ≠ 模型已经成为子代理。

例如:

1
2
3
4
5
6
Codex 模型菜单:

GPT-5.6 Sol
GPT-5.6 Terra
DeepSeek V4-Flash
DeepSeek V4-Pro

只能证明:

1
Codex 能够选择这些模型

并不能证明:

1
2
3
spawn_agent

DeepSeek V4-Flash

所以还需要进行第二层配置。


7. 第一层:配置 OpenCodex 子代理 roster

OpenCodex 提供:

1
ocx agent subagents set

我们配置:

1
2
& $ocx agent subagents set `
"gpt-5.6-sol,gpt-5.6-terra,gpt-5.6-luna,deepseek/deepseek-v4-flash,deepseek/deepseek-v4-pro"

然后检查:

1
& $ocx agent subagents status --json

这里的作用是:

告诉 OpenCodex:哪些模型允许被作为子代理候选。

例如:

1
2
3
4
5
1. gpt-5.6-sol
2. gpt-5.6-terra
3. gpt-5.6-luna
4. deepseek/deepseek-v4-flash
5. deepseek/deepseek-v4-pro

这相当于建立一个:

1
Subagent Roster

8. 第二层:配置 Codex 默认子代理

接下来编辑:

1
C:\Users\86182\.codex\config.toml

加入:

1
2
3
[agents]
default_subagent_model = "deepseek/deepseek-v4-flash"
default_subagent_reasoning_effort = "high"

这样 Codex 在没有显式指定模型的情况下派生子代理时,默认选择:

1
DeepSeek V4-Flash

最终:

1
2
3
4
5
Codex 主代理

│ spawn_agent

DeepSeek V4-Flash

9. 这里踩到的最大坑:配置顺序

这是这次实践中最值得记下来的地方。

不能:

1
2
3
修改模型目录

马上修改 [agents]

因为正在运行的 Codex 进程可能还没有加载新的模型目录

正确顺序应该是:

1
2
3
4
5
6
7
8
9
10
11
12
13
① ocx sync

② 完全退出 Codex

③ 重新启动 Codex

④ 确认模型菜单已经出现 DeepSeek

⑤ 再修改 ~/.codex/config.toml 的 [agents]

⑥ 再次重启 Codex

⑦ 新建任务测试

10. 实际遇到的报错

我们最开始配置完成后,Codex 仍然报:

1
2
3
4
5
Unknown model deepseek/deepseek-v4-flash for spawn_agent.

Available models:
gpt-5.6-sol,
gpt-5.6-terra

即使:

1
2
[agents]
default_subagent_model = "deepseek/deepseek-v4-flash"

已经写进去了,仍然失败。

这说明:

config.toml 里写了 DeepSeek,不代表当前运行中的 Codex 模型注册表里真的存在 DeepSeek。


11. 最关键的排查方法:直接检查模型目录

我们没有继续猜配置,而是直接检查:

1
2
3
4
5
6
7
8
9
10
11
12
13
$catalogPath = "$env:USERPROFILE\.codex\opencodex-catalog.json"

$catalog = Get-Content $catalogPath -Raw | ConvertFrom-Json

$catalog.models |
Where-Object {
$_.slug -in @(
"gpt-5.6-sol",
"deepseek/deepseek-v4-flash"
)
} |
Select-Object slug, multi_agent_version, priority, visibility |
Format-Table -AutoSize

最终得到:

1
2
3
4
slug                       multi_agent_version priority visibility
---- ------------------- -------- ----------
gpt-5.6-sol v1 0 list
deepseek/deepseek-v4-flash v1 3 list

这一步非常关键。

因为它证明:

1
2
3
4
5
6
7
DeepSeek V4-Flash

已经进入 OpenCodex catalog

visibility = list

multi_agent_version = v1

也就是说,模型目录本身已经正常了

重新启动 Codex 后,子代理最终成功使用 DeepSeek。


12. 最终的配置结构

最终形成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
                     OpenCodex

┌──────────────┴──────────────┐
│ │
OpenAI DeepSeek
│ │
┌──────┴──────┐ ┌───────┴────────┐
│ │ │ │
GPT-5.6 Sol GPT-5.6 Terra V4-Flash V4-Pro
│ │ │
└─────────────┴──────────────┘

Codex

主代理 GPT

spawn_agent

DeepSeek V4-Flash

13. Windows 开机常驻

OpenCodex 还可以注册 Windows Task Scheduler,让代理开机自动启动。

执行:

1
ocx service install

第一次遇到了:

1
WINDOWS_SCHTASKS_CREATE_ACCESS_DENIED

原因不是 OpenCodex 配置错误,而是:

当前 PowerShell 没有管理员权限,无法向 Windows Task Scheduler 创建任务。

因此需要:

1
2
3
4
5
右键 PowerShell

以管理员身份运行

ocx service install

安装成功后检查:

1
ocx service status

如果成功,会显示:

1
service installed

之后可以让 OpenCodex 在 Windows 启动时自动运行。


14. 一个很容易混淆的问题:OpenCodex、Codex App、VS Code

OpenCodex 本质上是在本地提供代理:

1
localhost:10100

然后修改 Codex 的 Provider 配置。

所以它不是单独替代 Codex,而是在 Codex 和模型 Provider 之间增加了一层:

1
2
3
4
5
6
7
8
9
10
11
Codex App

VS Code Codex

Codex CLI


OpenCodex

├── OpenAI
└── DeepSeek

因此具体哪些客户端会跟着生效,要看它们是否使用同一个 Codex 配置和运行链路,而不能简单理解为“装了 OpenCodex 所有软件都会自动变”。


15. 关于 Luna 视觉 Sidecar

这部分我们也进行了配置尝试。

配置:

1
2
3
4
"visionSidecar": {
"model": "gpt-5.6-luna",
"backend": "openai"
}

同时 DeepSeek Provider 中:

1
2
3
4
5
6
"noVisionModels": [
"deepseek-chat",
"deepseek-reasoner",
"deepseek-v4-pro",
"deepseek-v4-flash"
]

检查:

1
2
3
4
5
6
7
8
$config = Get-Content "$env:USERPROFILE\.opencodex\config.json" -Raw |
ConvertFrom-Json

$config.visionSidecar | ConvertTo-Json

$config.providers.deepseek |
Select-Object adapter, baseUrl, authMode, noVisionModels |
ConvertTo-Json -Depth 10

得到:

1
2
3
4
{
"model": "gpt-5.6-luna",
"backend": "openai"
}

以及:

1
2
3
4
5
6
7
8
9
10
11
{
"adapter": "openai-chat",
"baseUrl": "https://api.deepseek.com",
"authMode": "key",
"noVisionModels": [
"deepseek-chat",
"deepseek-reasoner",
"deepseek-v4-pro",
"deepseek-v4-flash"
]
}

Sidecar 状态也显示:

1
ocx agent sidecar status --json
1
2
3
4
5
6
7
8
9
{
"webSearch": {
"model": "gpt-5.6-luna"
},
"vision": {
"model": "gpt-5.6-luna",
"backend": "openai"
}
}

同时:

1
codex login status

显示:

1
Logged in using ChatGPT

说明:

1
2
3
4
5
Luna 配置存在
+
OpenAI 登录存在
+
Vision Sidecar 状态存在

但是实际测试时:

DeepSeek 请求图片后,没有观察到 Luna 被实际调用,也没有成功让 DeepSeek 获得图片内容。

因此目前不能把这部分描述为“已经实现”。


16. 这次实践最值得记住的几个知识点

① 模型目录 ≠ 子代理

1
模型出现在 Codex 菜单

只代表:

Codex 可以选择它。

而:

1
spawn_agent → DeepSeek

还需要配置:

1
2
3
OpenCodex subagent roster
+
Codex [agents]

② 配置文件 ≠ 运行时状态

即使:

1
default_subagent_model = "deepseek/deepseek-v4-flash"

写对了,如果当前 Codex 进程的模型目录里没有这个模型,仍然会:

1
Unknown model

所以排查 Agent 问题时,不能只看 config.toml


ocx sync 很重要

它承担的是:

1
2
3
4
5
6
7
Provider 配置

OpenCodex 模型发现

opencodex-catalog.json

Codex 模型目录

所以新增模型后,一个非常重要的动作就是:

1
ocx sync

④ 修改模型后一定重启 Codex

尤其是:

1
2
3
4
模型目录
Provider
Subagent
Agents

这些配置发生变化后,最好:

1
2
3
4
sync
→ 完全退出 Codex
→ 重启
→ 新建任务

不要拿旧会话验证新模型。


⑤ 最可靠的验证方式不是问模型“你是谁”

例如:

“你是不是 DeepSeek?”

并不能证明实际路由。

更可靠的是:

1
2
3
4
5
OpenCodex 日志
+
模型 catalog
+
spawn_agent 实际路由

也就是:

1
配置 → catalog → runtime → 日志

这条链路才是真正的验证方法。


17. 最终成果

这次实践最终完成了:

1
2
3
4
5
6
7
                    ┌── GPT-5.6 Sol

Codex → OpenCodex ──┼── GPT-5.6 Terra

├── DeepSeek V4-Flash

└── DeepSeek V4-Pro

并成功实现:

1
2
3
4
5
Codex 主代理

spawn_agent

DeepSeek V4-Flash

同时掌握了完整的排查思路:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Provider

模型目录

ocx sync

Codex 重启

Subagent roster

[agents]

spawn_agent

日志验证

Luna 视觉 Sidecar 目前仅完成配置层面的尝试,实际图片中转链路尚未验证成功,因此暂不算完成。