Codex 的一点探索

2026/08/19 codex , ai

Codex 模型适配与原生 Plan Mode 信息图

最近开始研究 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。优先级是:

  1. 用户自己配置的 base_instructions
  2. 恢复任务时保存下来的 Instructions;
  3. 模型目录中的专属模板。

所以,模型切换并不是“同一个 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 的完整工作方式。

例如,模型还需要正确理解:

  • commentaryfinal Channel;
  • 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 决定了这些能力能不能稳定地发挥出来。