1. 为什么 Codex 多代理一换 provider 就乱套
如果你正在用 Codex 做多代理协作,大概率踩过这个坑:项目里.codex/config.toml写得满满当当,模型名、网关地址、并发数、子代理定义全塞在一起。平时跑得好好的,一旦用 CCSwitch 切到另一个 provider,模型 ID 对不上了、子代理找不到、凭证还串了,最后连"到底是哪一层配置生效"都说不清。
这个问题的本质不是 CCSwitch 不好用,而是配置没有分层。Codex 的多代理工作流里,有三类东西天然属于不同生命周期:角色定义(Sol 规划、Luna 执行)应该跟着人走,跨项目复用;多代理开关和并发策略属于公共偏好,切 provider 不该动;而 base_url、API Key、协议类型这些是 provider 私有的,切一次就该整体换一次。把这三类混在一个文件里,切换时必然互相覆盖。
我试过把 Sol 和 Luna 的角色规则直接写进 provider profile,结果每次换网关都要重新粘贴一遍 agent 定义,漏一行就报Unknown model。后来改成三层结构——全局角色层、CCSwitch 公共配置层、provider 层——切换才真正变成"只换通道,不换分工"。
这篇就按这个思路,给你一套可复制的config.toml骨架和 CCSwitch 切换验证步骤,并用 TaoToken 统一 Key/API 通道接入,让 Sol 规划、Luna 执行的双角色工作流在任意 profile 下都保持一致。适合已经在用 Codex CLI、想上多代理但被配置漂移折磨的开发者。
2. 三层配置模型:角色、公共、provider 各管一段
先把职责边界划清楚,后面所有配置都围绕这三层展开。
角色层放在 Codex 全局目录%USERPROFILE%\.codex\agents\,定义 Sol 和 Luna 各自能干什么、用什么模型、什么权限。这一层不含任何 Key,跟着你的账号走,所有项目共享。
公共配置层由 CCSwitch 维护,不同版本可能叫"公共配置""通用配置"或common_config_codex。这里放所有 profile 都该一致的设置:多代理开关、默认子代理模型、并发线程数。切 provider 时这一层不动。
provider 层是 CCSwitch 的 profile,只负责请求发到哪个base_url、用哪个账号或 Key、支持哪些模型、走什么协议。它不该决定谁是 Sol 谁是 Luna。
一句话理解:Sol 是技术负责人,Luna 是执行团队。需求进来,Sol 拆解定边界,Luna 的 scout 探索、worker 并行改代码、critic 审查、tester 跑验证,最后 Sol 整合验收提交。重点不是多开几个模型,而是最终决策权始终留在主会话。
为什么要这么分?全交给强模型,读仓库、跑重复测试也烧高价 token,主会话上下文混入大量探索细节后架构判断会变钝;全交给普通模型,边界不清时容易顺手重构旁边模块、忽略安全风险。分层后各司其职,切换 provider 时供应商可以变,角色分工不变。
3. 可复制的 config.toml 与全局 agent 骨架
3.1 全局 agent 文件
在%USERPROFILE%\.codex\agents\下放四个文件。Windows 下%USERPROFILE%不一定和项目同盘符,先用 PowerShell 确认:
$env:USERPROFILEluna_scout.toml(只读探索):
name = "luna_scout" description = "Read-only codebase explorer for mapping files, dependencies, and docs." model = "gpt-5.6-luna" model_reasoning_effort = "max" sandbox_mode = "read-only" developer_instructions = """ You are luna_scout, a scoped read-only explorer. Map the requested code, dependencies, and documentation. Cite paths and symbols. Never edit files or expand the assigned scope. Escalate to the Sol leader when the task is ambiguous, out of scope, or low-confidence. """luna-worker.toml(受限执行):
name = "luna-worker" description = "Execution-focused worker for clearly bounded delegated tasks." model = "gpt-5.6-luna" model_reasoning_effort = "max" sandbox_mode = "workspace-write" developer_instructions = """ You are a scoped execution worker. Only change the files and modules explicitly assigned by the Sol leader. Do not commit, open a PR, deploy, or broaden the task. Return changed files, verification commands, results, and residual risks. Escalate when the boundary or expected result is unclear. """luna_critic.toml(对抗式审查)和luna_tester.toml(按计划验证)同理,前者sandbox_mode = "read-only",后者workspace-write但只跑指定测试计划。模型 ID 只是示例,替换成你当前 profile 实际提供的名字。
3.2 CCSwitch 公共配置
在 CCSwitch 的公共 Codex 配置里写跨 profile 一致的部分:
[features] multi_agent = true multi_agent_v2 = false [agents] max_concurrent_threads_per_session = 4 default_subagent_model = "gpt-5.6-luna" default_subagent_reasoning_effort = "max"multi_agent_v2 = false是针对部分模型目录兼容问题的保守设置。如果你的 Codex 版本和模型目录已全部使用 v2,以当前版本文档为准,别机械复制这一行。
3.3 provider 层与 TaoToken 接入
provider profile 只写通道信息。用 OpenAI-compatible 网关时,配置里只写环境变量名,真正的密钥放环境变量或 CCSwitch 安全存储:
[model_providers.taotoken] name = "TaoToken Gateway" base_url = "https://taotoken.net/api" env_key = "TAOTOKEN_API_KEY" wire_api = "responses"TaoToken 在这里的角色是统一 Key/API 通道:你只需要在它那边维护一份凭证,Codex 侧通过base_url指向https://taotoken.net/api,用env_key引用环境变量即可。这样切换 profile 时,认证信息跟着通道走,角色定义留在全局层,互不干扰。Key 在控制台生成,接入细节看官方文档,别把密钥写进config.toml、AGENTS.md或 Git。
4. 切换验证:从单模型冒烟到多代理闭环
配置写完不算数,得逐层验证。先确认 CLI 本身可用:
codex --version再分别验证两个模型能否响应:
codex exec --sandbox read-only -c 'model="gpt-5.6-sol"' "Reply with exactly: SOL_SMOKE_OK" codex exec --sandbox read-only -c 'model="gpt-5.6-luna"' "Reply with exactly: LUNA_SMOKE_OK"两个都返回对应字符串,说明 provider 层通道通了。但两个模型能分别聊天,不代表 Sol 已经能把任务交给 Luna,必须验证真正的多代理路径:
codex exec --sandbox read-only "按全局规则 spawn luna_scout,只读说明当前仓库结构,输出以 SCOUT_DONE 开头。"看到SCOUT_DONE开头的仓库结构说明,才算多代理配置真正可用。切换 CCSwitch profile 后,建议关闭旧主会话、新开终端、重新跑一遍这三步冒烟。已经启动的进程通常保留启动时的环境和认证状态,别在一个正在执行的多代理任务中途切 profile。
5. 本篇常见错排查
Unknown model gpt-5.6-luna:多半是模型目录或多代理版本过滤问题,不是提示词问题。检查当前 profile 是否真的提供 Luna、模型目录是否包含它、是否需要生成 v1 catalog、multi_agent_v2是否该关闭。如果 skill 仓库提供prepare-luna-catalog.sh,优先用脚本生成,别手工编 JSON,生成的大文件放进.gitignore。
CCSwitch 切换后配置消失:别把[features]和[agents]写在某个 provider profile 的config.toml里,跨 profile 的内容放公共配置,provider profile 只留网关和认证。
Key 能用但请求失败:检查 Key 和base_url是否属于同一 provider。直连 Key、网关 Key、Anthropic Key 不能随意混用。
普通模型改了不该改的文件:缩小 worker 的文件范围、降低并发,让 critic 只读审查。别用更长的提示词掩盖没有边界的问题。
CLI 启动报找不到 codex.js:这是 CLI 安装不完整,不是 Sol/Luna 配置错误。用当前 Node/npm 环境重装后重跑冒烟:
npm install -g @openai/codex codex --version别删%USERPROFILE%\.codex,那里存着认证、会话和配置数据。
6. 把通道统一起来,让切换只换供应商
落到实操,最小路径是这样:先在 CCSwitch 公共 Codex 配置里打开多代理、把默认子代理设为普通模型;在%USERPROFILE%\.codex\agents放好 scout、worker、critic、tester 四个角色;确认所有 CCSwitch profile 都同时提供强模型和普通模型——只支持强模型的 profile 无法完成 Sol 到 Luna 的委派;先只用 scout + worker + tester 跑通闭环,再加复杂并行策略。
通道侧用 TaoToken 统一 Key/API,Codex 侧只认https://taotoken.net/api这一个base_url,凭证走环境变量。这样每次切 profile,你换的只是供应商,Sol 的规划权、Luna 的执行边界、并发策略全都不动。需要生成和管理 Key 就去控制台,接入参数对照文档,长期跑编码和 Agent 任务的话可以看 Coding Plan 的额度方案,想先验证模型响应直接开模型对话试一句冒烟指令即可。最终目标不是模型越多越好,而是每个模型都在适合自己的范围内运行,把架构判断、风险承担和最终验收留给 Sol。