Research: Codex Plan mode behavior and prompt architecture
Open 💬 1 comment Opened Aug 13, 2026 by microtears
💡 Likely answer: A maintainer (github-actions[bot], contributor)
responded on this thread — see the highlighted reply below.
调研范围
基于 openai/codex 提交 363427b5e3fe1b6d7499e6bc47651f62a5a3b1d2(2026-08-13)进行源码审阅,聚焦 Plan 模式的状态、提示词、工具约束、流式协议和实施切换流程。
结论
Plan 模式是独立的协作模式,不是 update_plan 待办工具。它主要依赖 developer 提示词约束模型行为,并结合少量运行时硬约束、<proposed_plan> 协议及 TUI 的“批准后实施”交互实现闭环。
运行链路
- 用户在 TUI 选择/切换到
Plan。内置预设默认设置Medium推理强度,且可由plan_mode_reasoning_effort覆盖。 - 每轮 world state 将 Plan 提示词包装在
<collaboration_mode>developer 消息中并注入模型上下文,状态随会话持久化。 - 模型先进行只读探索、澄清意图、补齐实施决策,然后以独占行的
<proposed_plan>...</proposed_plan>输出完整计划。 - 运行时把该块从普通 assistant 文本中剥离,流式发送
PlanDelta,最终生成TurnItem::Plan。 - TUI 收到 PlanItem 后提供三项操作:保留上下文切换 Default 并实施、新开上下文携带计划实施、或继续 Plan 模式。
Plan 提示词要点
完整原文:plan.md
- 严格分为环境事实探索、意图澄清、实施细节澄清三阶段。
- 用户的“直接实现”不能结束 Plan 模式,只能理解成“规划如何实施”;仅 developer 指令能切换模式。
- 允许阅读、搜索、静态分析、无副作用命令和只写缓存的构建/测试。
- 禁止编辑仓库、应用补丁、迁移、改写型 formatter/codegen,以及所有实际执行计划的副作用操作。
- 优先使用
request_user_input询问无法从环境发现、且会实质影响方案的偏好或取舍。 - 只有当方案“实现者不需要再做决策”时才能生成最终计划;每轮至多一个
<proposed_plan>。 - 最终计划默认应简洁,并包含标题、摘要、公共接口变化、测试和明确的默认假设。
硬约束与软约束
| 行为 | 实现方式 |
|---|---|
| 不因用户命令退出 Plan | developer 提示词 |
| Plan 中不修改仓库 | developer 提示词 |
| update_plan | 运行时明确拒绝 |
| request_user_input | Plan 中可用且阻塞等待;Default 默认不可用,需 feature 开启 |
| 空闲自动唤醒 | Plan 模式下禁止启动 |
| <proposed_plan> | 运行时解析为独立流式事件和 PlanItem |
重要边界:Core 中对 Plan 的通用工具执行没有发现针对 exec、apply_patch 等变更工具的统一后端拒绝。因此“不得写入”主要是高优先级提示词约束,而非完整的强制沙箱隔离;update_plan 是已确认的特例硬拦截。
关键实现位置
- 模式与 mask 定义
- 内置 Plan / Default 预设
- world-state developer 提示注入
- Plan 流式分流与 PlanItem 生命周期
<proposed_plan>解析器update_plan在 Plan 中的拒绝- 实施确认弹窗与上下文转交
额外注意
实际运行的提示词可能不同于仓库模板:若模型目录返回 collaboration_mode_messages.plan,该内容会优先覆盖本地预设;若 include_collaboration_mode_instructions = false,则不会注入该 developer 提示块。
1 Comment
English translation:
Research Scope
A source code review was conducted based on commit
363427b5e3fe1b6d7499e6bc47651f62a5a3b1d2(2026-08-13) ofopenai/codex, focusing on Plan mode's state, prompts, tool constraints, streaming protocol, and implementation transition flow.Conclusions
Plan mode is a distinct collaboration mode, not the
update_plantask-list tool. It primarily relies on developer prompts to constrain model behavior, combined with a small number of hard runtime constraints, the<proposed_plan>protocol, and the TUI's “implement after approval” interaction to complete the workflow.Execution Flow
Planin the TUI. The built-in preset usesMediumreasoning effort by default, which can be overridden byplan_mode_reasoning_effort.<collaboration_mode>developer message and injects it into the model context. The state persists throughout the session.<proposed_plan>...</proposed_plan>on dedicated lines.PlanDelta, and ultimately generates aTurnItem::Plan.Key Points of the Plan Prompt
Full original text: plan.md
request_user_inputto ask about preferences or tradeoffs that cannot be discovered from the environment and would materially affect the approach.<proposed_plan>.Hard and Soft Constraints
| Behavior | Implementation |
|---|---|
| Do not exit Plan because of a user command | Developer prompt |
| Do not modify the repository in Plan | Developer prompt |
|
update_plan| Explicitly rejected at runtime ||
request_user_input| Available in Plan and blocks while awaiting input; unavailable by default in Default unless enabled by a feature || Automatic wake-up while idle | Prevented from starting in Plan mode |
|
<proposed_plan>| Parsed at runtime into a separate streaming event and PlanItem |Important boundary: No uniform backend rejection specific to Plan was found in Core for general tool execution involving mutation tools such as
execandapply_patch. Therefore, “must not write” is primarily enforced through high-priority prompt constraints rather than complete mandatory sandbox isolation;update_planis a confirmed special case with hard blocking.Key Implementation Locations
<proposed_plan>parserupdate_planin PlanAdditional Notes
The prompt used at runtime may differ from the repository template: if the model catalog returns
collaboration_mode_messages.plan, its content takes precedence over the local preset; ifinclude_collaboration_mode_instructions = false, the developer prompt block is not injected.<!-- codex-issue-translator -->