Codex 的一点探索
最近开始研究 Codex 的源码,主要是想解决两个一直困扰我的问题。
第一个问题是,Codex 明明可以接入其他模型,为什么换完模型以后,经常感觉模型“降智”了?一个模型在自己的原生工具里面表现不错,放进 Codex 以后却不一定有相同的效果。
第二个问题是,我之前研究过 Superpowers。它通过“探索、澄清、计划、执行、测试”把 AI 编程变成一套相对完整的软件开发流程。后来使用 Codex 的 Plan Mode 时,我发现两者很像。那么,Codex 是不是已经把 Superpowers 内置进去了?
为了回答这两个问题,我看了一遍 Codex 的模型管理、Session、Plan Mode 和工具实现。下面的分析基于 Codex commit 343074d420,后续实现可能发生变化。
Codex 不只是给模型套了一层壳
我之前对 Codex 的理解比较简单:它是一个 Agent Harness,底层模型可以替换,上层负责提供 Shell、文件编辑、Plan Mode 和权限控制等能力。
这个理解不能说错,但漏掉了一个很重要的部分:Codex 并不是用同一套配置去调用所有模型。
它的实际效果至少由下面几部分共同决定:
模型本身
+ 模型专属 Instructions
+ 模型能力 Metadata
+ 工具协议
+ 上下文与压缩策略
+ Codex Harness
= 最终编码效果
所以,更换模型并不是只改一个模型名称。换掉模型以后,整套联合适配都有可能发生变化。
Codex 为不同模型维护了专属 Metadata
Codex 内置了一份 models.json,里面不只是模型名称,还包含每个模型的能力描述。
以其中一个模型为例,配置大致如下:
{
"slug": "gpt-5.6-sol",
"tool_mode": "code_mode_only",
"use_responses_lite": true,
"context_window": 272000,
"max_context_window": 872000,
"comp_hash": "3000",
"truncation_policy": {
"mode": "tokens",
"limit": 10000
},
"model_messages": {
"instructions_template": "..."
}
}
完整的数据结构定义在 ModelInfo 中。这些字段会影响很多事情:
- 给模型发送什么工具,以及使用哪一种工具模式;
- 是否使用 Responses Lite;
- 支持哪些 Reasoning 参数;
- 工具输出截断多少;
- 什么时候压缩上下文;
- 模型切换前是否需要先压缩;
- 注入哪一套 Developer Instructions。
这就不是简单的 model=gpt-5.6-sol 了,而是一整套模型运行时配置。
不同模型收到的基础 Prompt 也不同
模型配置中还有一个 ModelMessages 结构,其中包括:
pub struct ModelMessages {
pub instructions_template: Option<String>,
pub instructions_variables: Option<ModelInstructionsVariables>,
pub approvals: Option<ApprovalMessages>,
pub collaboration_modes: Option<CollaborationModeMessages>,
pub auto_review: Option<AutoReviewMessages>,
pub permissions: Option<PermissionMessages>,
pub multi_agent: Option<MultiAgentMessages>,
pub token_budget: Option<ModelTokenBudgetConfig>,
pub guardian_v2: Option<GuardianV2ModelConfig>,
}
也就是说,Codex 会针对不同模型准备不同的 Instructions、权限消息、协作模式和 Multi-Agent 配置。模型收到的不只是用户输入,还会收到一份很长的工作说明,告诉它如何与用户沟通、如何调用工具、如何编辑文件、如何处理破坏性操作,以及如何使用 Skills。
创建 Session 时,Codex 会按照下面的顺序选择基础 Instructions:
let base_instructions = config
.base_instructions
.clone()
.or_else(|| conversation_history.get_base_instructions().map(|s| s.text))
.unwrap_or_else(|| model_info.get_model_instructions(config.personality));
源码位于 session/mod.rs。优先级是:
- 用户自己配置的
base_instructions; - 恢复任务时保存下来的 Instructions;
- 模型目录中的专属模板。
所以,模型切换并不是“同一个 Prompt 换一个模型跑”。即使两个模型本身能力接近,收到的工作说明也可能不一样。
第三方模型为什么容易“降智”
Codex 查找模型配置时,会进行最长前缀匹配,也支持去掉一层 Provider Namespace 后再次匹配。完整逻辑在 manager.rs 中。
例如:
| 用户指定的模型 | 匹配结果 |
|---|---|
gpt-5.6-sol | 使用对应的专属 Metadata |
gpt-5.6-sol-2026-08 | 通过最长前缀继承对应 Metadata |
openrouter/gpt-5.6-sol | 去掉 Namespace 后再次匹配 |
anthropic/claude-sonnet-4.6 | 找不到匹配,进入 Fallback |
问题就出在 Fallback 上。
对于未知模型,Codex 会通过 model_info_from_slug 生成一份通用配置。其中包含很多默认假设:
- Context Window 按 272K 处理;
- 工具输出按照 10,000 Bytes 截断;
- 没有模型专属的 Reasoning Effort 列表;
- 没有 Code Mode;
- 没有 Multi-Agent 版本;
- 没有 Compaction Compatibility Hash;
- 没有模型专属的 Approval 和 Permission 消息。
Codex 自己也会给出警告:找不到模型 Metadata 时将使用 Fallback,这可能降低性能并带来问题。
未知模型并不是完全“裸奔”。它仍然会收到 prompt.md 中的通用 Codex Prompt,也仍然可以使用 Codex 的工具和上下文管理。
但这时实际运行的是:
第三方模型
+ 通用 Codex Prompt
+ 通用能力 Metadata
+ Codex 工具协议
+ Codex 上下文管理
而不是:
第三方模型
+ 针对该模型优化的 Prompt
+ 该模型熟悉的工具协议
+ 该模型对应的上下文策略
API 兼容不代表 Harness 兼容
第三方模型可能支持 OpenAI-compatible Function Calling,但这只能说明 API 形状兼容,并不代表它熟悉 Codex 的完整工作方式。
例如,模型还需要正确理解:
commentary和finalChannel;- Codex 的工具名称与 JSON Schema;
- Plan Mode 的
<proposed_plan>; request_user_input的交互方式;- 工具调用后的连续执行;
- Compaction Summary;
AGENTS.md的作用域与优先级;- Sandbox Approval;
- 清空上下文后的 Plan Handoff。
这些能力不是接通 API 就自动拥有的。如果模型没有针对这套协议做过适配,它在原生 Agent 中很聪明,进入 Codex 后也可能手忙脚乱。
上下文压缩也有区别
普通自定义 Provider 默认不支持 Codex 的 Remote Compaction:
let remote_compaction =
if self.info.is_openai()
|| is_azure_responses_provider(...) {
RemoteCompactionSupport::V2
} else {
RemoteCompactionSupport::Unsupported
};
源码位于 provider.rs。不支持时,Codex 会回退到本地摘要压缩。
这时压缩质量取决于第三方模型能否正确理解 Codex 的 Summarization Prompt。如果一个长任务经历多次压缩,每次都丢一点信息,最后就可能完全偏离原始目标。
这也解释了为什么有些模型刚开始表现还行,任务越长却越容易乱。问题不一定只在 Context Window 大小,也可能出在压缩协议和信息交接上。
Codex 是否内置了 Superpowers?
第二个问题的答案需要分成两层:
Codex 没有把 Superpowers 的具体 Skill 实现直接写进 Core,但已经把它代表的主要软件开发流程做成了原生能力。
我在当前源码中没有找到 Superpowers 的实际 SKILL.md 实现。仓库里出现的 superpowers 名称,主要位于 TUI 的测试夹具中。例如 skills_toggle_view.rs 中有一个模拟 Skill,hooks_browser_view.rs 中也有一个模拟 Plugin Hook。
这些代码只能说明 Codex 的 Plugin 和 Skill UI 能够展示 Superpowers 一类插件,不能证明它被编译进了 Codex Core。
但如果不看文件名,只看工作流程,就会发现 Codex Plan Mode 与 Superpowers 高度重叠:
只读探索仓库
→ 澄清用户意图
→ 形成完整实现方案
→ 用户确认
→ 进入 Default Mode
→ 编码、测试与验证
Plan Mode 如何把开发流程原生化
Codex 的 Plan Mode 不是简单提醒模型“先列个计划”,而是由 Prompt、工具和 TUI 共同组成的一套状态机。
第一阶段:先探索,再提问
Plan Mode 的模板明确要求 explore first, ask second:
- 先阅读和搜索仓库;
- 能从代码中找到的答案,不要反过来问用户;
- 先理解当前实现,再澄清真正缺失的信息;
- Plan Mode 中不允许修改仓库文件。
对应规则位于 plan.md。这和 Superpowers 的 Brainstorming 很像,核心都是拒绝一上来就写代码。
第二阶段:澄清真正的需求
探索完仓库以后,Plan Mode 才会补齐用户意图,包括目标、成功标准、范围、限制条件、当前状态和关键取舍。
Codex 还为此提供了结构化的 request_user_input 工具。它并不是普通的聊天提问,而是会生成 1~3 个问题,每个问题提供互斥选项,并在 Plan Mode 中阻塞等待用户回答。
这意味着“需求澄清”不再只是一句 Prompt 建议,而是 Agent Runtime 里的原生交互能力。
第三阶段:形成 Decision-complete 的计划
Plan Mode 要求最终方案不仅写“修改登录功能”“补充测试”这样的 TODO,还要包含技术方案、API、Schema、数据流、边界情况、失败模式、测试、迁移和监控等信息。
模板中用了一个很准确的词:decision complete。也就是说,计划应该完整到执行者拿到以后不需要临场做关键决策。
最终计划会放在 <proposed_plan> 中。TUI 会把它识别成独立的 Plan Item 并保存,而不是把它当作普通聊天文字。实现位于 streaming.rs。
Codex 默认也不会像部分 Superpowers 工作流那样,把计划写进仓库里的 Markdown 文件。计划属于当前任务,不会污染工作树。
第四阶段:确认如何执行
计划完成后,Codex 会提供三个选项:
Yes, implement this plan
Yes, clear context and implement
No, stay in Plan mode
源码位于 plan_implementation.rs。
其中最有意思的是“清空上下文后执行”。需求探索可能已经消耗了大量上下文,还混杂着被否决的方案和讨论过程。Codex 可以清掉这些内容,只把最终 Plan 作为 Handoff 交给新的执行上下文。
这刚好回应了我之前在《上下文之战》里担心的问题:上下文不是越多越好。把决策过程全部留给执行阶段,有时反而会让模型受到旧方案干扰。
Plan Mode 和 update_plan 不是一回事
这两个名字很像,但用途完全不同:
| 能力 | 作用 |
|---|---|
| Plan Mode | 探索需求、澄清问题、形成最终设计 |
update_plan | 在执行阶段追踪 TODO 和进度 |
Plan Mode 甚至明确禁止调用 update_plan:
if turn.mode == ModeKind::Plan {
return Err(FunctionCallError::RespondToModel(
"update_plan is a TODO/checklist tool \
and is not allowed in Plan mode"
));
}
对应实现位于 plan.rs。
简单来说:
Plan Mode = 设计规格
update_plan = 执行看板
这也是我之前容易混淆的地方。列出三条 TODO 并不代表真正完成了需求分析,更不代表方案已经可以交给另一个 Agent 执行。
回到最开始的两个问题
为什么替换模型以后会感觉“降智”?
因为 Codex 的能力不只来自模型,而是来自模型、专属 Instructions、能力 Metadata、工具协议和上下文策略的联合适配。第三方模型即使可以通过兼容 API 运行,也经常只能使用通用 Fallback。能调用,不等于被正确适配。
Codex 是否内置了 Superpowers?
它没有内置 Superpowers 的具体 Skill 文件,但已经把“探索、澄清、完整计划、用户确认、执行、验证”这条主流程做进了 Plan Mode 和 Agent Runtime。对于 Codex 来说,Superpowers 不再是走完整开发流程的必要条件,更像是一组可以继续叠加的增强能力,例如系统化调试、TDD 和完成前验证。
看完源码以后,我对 Harness 的理解也更具体了一点。Harness 不是简单地给模型几把工具,更不是把模型名称做成一个下拉框。它需要知道模型会什么、如何与模型交流、什么时候压缩上下文,以及如何把需求澄清、计划和执行连接起来。
模型决定了能力上限,Harness 决定了这些能力能不能稳定地发挥出来。