openinterpreter 中 Codex CLI 的 Default 协作模式提示词模板:模板结构、渲染与注入机制详解
本篇技术指南聚焦仓库内 codex-rs/collaboration-mode-templates/templates/default.md 这一协作模式(Collaboration Mode)提示词模板。读完后,你将理解 Default 模式指令模板的完整文本语义、{{KNOWN_MODE_NAMES}} 占位符的运行时渲染方式、模板如何被编译进 Rust crate 并经预设系统注入为 developer 指令,以及模式切换(<collaboration_mode> 块)与 request_user_input 工具可用性之间的门控关系。
模板文件在项目中的定位
codex-rs 工作区中的 collaboration-mode-templates 是一个独立的轻量 crate(包名 codex-collaboration-mode-templates,见 Cargo.toml),它的整个 src/lib.rs 只有两行,核心手法是 include_str! 把 Markdown 模板在编译期固化进二进制:
pub const PLAN: &str = include_str!("../templates/plan.md");
pub const DEFAULT: &str = include_str!("../templates/default.md");
(见 src/lib.rs。)这意味着 templates/default.md 与 templates/plan.md 不是运行时读取的资源文件,而是构建产物的静态字符串常量,运行时零 IO 开销,且内容变更必然触发重新编译——这对提示词模板是一种强约束的工程实践。
该 crate 的下游消费者是 models-manager 的协作模式预设模块 collaboration_mode_presets.rs,它同时引用了 PLAN 与 DEFAULT 两个常量。
Default 模式模板全文与逐句语义
下面是 templates/default.md 的完整内容(渲染后,{{KNOWN_MODE_NAMES}} 占位符会被替换,见下文):
You are now in Default mode. Any previous instructions for other modes (e.g. Plan mode) are no longer active.
Your active mode changes only when new developer instructions with a different
<collaboration_mode>...</collaboration_mode>change it; user requests or tool descriptions do not change mode by themselves. Known mode names are {{KNOWN_MODE_NAMES}}.request_user_input availability
Use the
request_user_inputtool only when it is listed in the available tools for this turn.In Default mode, strongly prefer making reasonable assumptions and executing the user's request rather than stopping to ask questions. If you absolutely must ask a question because the answer cannot be discovered from local context and a reasonable assumption would be risky, ask the user directly with a concise plain-text question. Never write a multiple choice question as a textual assistant message.
这段模板由四条规则构成,逐句拆解如下:
-
模式声明与失效声明(第 3 行):开场即声明“当前处于 Default 模式,此前其他模式(如 Plan 模式)的指令不再生效”。这是提示词工程中典型的“状态覆盖”写法,避免旧模式的 developer 指令在历史上下文中残留并继续约束模型行为。
-
模式切换的单一入口(第 5 行):明确规定只有新的 developer 指令携带不同的
<collaboration_mode>...</collaboration_mode>块时,模式才会改变;用户口头请求或工具描述本身都不能切换模式。同时通过占位符注入系统当前已知的全部模式名(渲染后为 "Default and Plan",见下文渲染机制),使模型知道“还有哪些模式存在”。 -
request_user_input的可用性门控(第 9 行):只有当该工具“列在本轮可用工具中”时才允许使用。这与源码中的门控逻辑呼应:config_types.rs 中ModeKind::allows_request_user_input仅对Plan返回true:pub const fn allows_request_user_input(self) -> bool { matches!(self, Self::Plan) }即 Default 模式下该工具通常不会出现在工具列表中,模板文本是在提示词层面对同一约束的二次强调(防御性冗余)。
-
Default 模式的行为准则(第 11 行):强烈偏好“做出合理假设并直接执行”,而不是停下来提问;只有当答案无法从本地上下文发现、且合理假设有风险时,才允许提问——且必须用“简洁的纯文本提问”直接问用户,绝不允许把选择题写成普通助手消息。这与 Plan 模式(templates/plan.md 中“强烈倾向用
request_user_input工具提问、提供 2–4 个互斥选项”)形成鲜明对照:两种模式在“是否提问、如何提问”上是完全互补的策略设计。
模板渲染机制:KNOWN_MODE_NAMES 占位符
DEFAULT 常量并非直接注入,而是经过一次模板渲染。collaboration_mode_presets.rs 的实现链条如下:
const KNOWN_MODE_NAMES_TEMPLATE_KEY: &str = "KNOWN_MODE_NAMES";
static COLLABORATION_MODE_DEFAULT_TEMPLATE: LazyLock<Template> = LazyLock::new(|| {
Template::parse(COLLABORATION_MODE_DEFAULT)
.unwrap_or_else(|err| panic!("collaboration mode default template must parse: {err}"))
});
fn default_mode_instructions() -> String {
let known_mode_names = format_mode_names(&TUI_VISIBLE_COLLABORATION_MODES);
COLLABORATION_MODE_DEFAULT_TEMPLATE
.render([(KNOWN_MODE_NAMES_TEMPLATE_KEY, known_mode_names.as_str())])
.unwrap_or_else(|err| panic!("collaboration mode default template must render: {err}"))
}
关键事实:
- 模板解析与渲染失败时直接
panic!——模板是编译期常量,解析失败属于构建/启动期缺陷,宁可崩溃也不允许带着未渲染的占位符运行; - 模式名列表来自
TUI_VISIBLE_COLLABORATION_MODES(定义于 config_types.rs),当前值为[ModeKind::Default, ModeKind::Plan]; format_mode_names按数量做自然语言格式化:0 个输出 "none",1 个输出单名,2 个输出 "Default and Plan",多个用逗号连接。当前配置下渲染结果为 "Default and Plan",因此模板第 5 行最终呈现为Known mode names are Default and Plan.;- 渲染使用
codex_utils_template::Template,即工作区内的通用模板工具 crate(utils/template)。
预设装配与 developer 指令注入
渲染完成的模板文本最终进入 CollaborationModeMask 结构,作为该模式的 developer_instructions:
fn default_preset() -> CollaborationModeMask {
CollaborationModeMask {
name: ModeKind::Default.display_name().to_string(),
mode: Some(ModeKind::Default),
model: None,
reasoning_effort: None,
developer_instructions: Some(Some(default_mode_instructions())),
}
}
对比 plan_preset():Plan 模式的 developer_instructions 直接使用未渲染的 COLLABORATION_MODE_PLAN 原文,且额外固定了 reasoning_effort: Some(Some(ReasoningEffort::Medium));Default 模式则不覆盖推理强度(reasoning_effort: None)。两个预设均由 builtin_collaboration_mode_presets() 统一产出,返回 [plan, default] 顺序的向量。
在配置层,<collaboration_mode> 开发者块是否有独立注入由配置项 include_collaboration_mode_instructions 控制,其定义见 config_toml.rs:
/// Whether to inject the `<collaboration_mode>` developer block.
pub include_collaboration_mode_instructions: Option<bool>,
该字段同样出现在核心配置模式文件中(config.schema.json 中有相同描述)。从源码结构看,模板全文经由预设的 developer_instructions 通道下发,而 <collaboration_mode> 块是另一条可开关注入的 developer 消息通道;会话历史的快照测试中可见该块的真实形态,例如 快照文件 里的 <collaboration_mode>make a plan</collaboration_mode>。此外,harness 层代码(如 swe_agent.rs)会显式识别以 <collaboration_mode> 开头的行,说明这类 developer 消息在运行时是被当作特殊结构处理的,而非普通文本。
模式模型:ModeKind 与 Default 的兼容别名
模板中的 “Default mode” 对应 config_types.rs 中的 ModeKind 枚举:
/// Initial collaboration mode to use when the TUI starts.
pub enum ModeKind {
Plan,
#[default]
#[serde(
alias = "code",
alias = "pair_programming",
alias = "execute",
alias = "custom"
)]
Default,
}
几个值得注意的实现细节:
Default是#[default]值,即未指定模式时的兜底协作模式,与模板“你是 Default 模式”的语义一致;- serde 别名
code/pair_programming/execute/custom提供了向后兼容:用户配置文件中写这些旧名字时会被反序列化为Default; display_name()返回 "Default" / "Plan",这正是format_mode_names渲染进模板的原始素材;- 会话层面的
CollaborationMode结构(mode+settings)支持with_updates增量更新模型、推理强度与 developer 指令,且保留当前 mode(见 config_types.rs)。
测试如何锁定模板行为
模板内容并非“写了就算”,而是被单测逐字锁定。collaboration_mode_presets_tests.rs 中的 default_mode_instructions_replace_mode_names_placeholder 测试断言了三件事:
- 渲染后的指令中不得残留
{{KNOWN_MODE_NAMES}}占位符; - 必须包含
Known mode names are {渲染结果}.这一片段(与TUI_VISIBLE_COLLABORATION_MODES动态一致,未来新增 TUI 可见模式时测试自动跟随); - 必须包含两条行为准则原文:
Use the request_user_input tool only when it is listed in the available tools与ask the user directly with a concise plain-text question。
另一个测试 preset_names_use_mode_display_names 则锁定了预设的元数据:Plan 预设的 reasoning_effort 固定为 Medium,Default 预设为 None,两者 model 均为 None。这些测试与模板文本构成“文档即代码、代码即契约”的闭环——修改模板措辞若越过关键断言就会被 CI 拦截。
设计小结:Default 模板的工程意图
把以上证据串起来,可以归纳出 Default 模式模板的设计意图:
- 状态隔离:开头两行解决多模式指令在长会话历史中的“串扰”问题;
- 切换确定性:把模式切换收敛到 developer 指令这一单一权威通道,防止模型把用户随口一句“帮我规划一下”误判为进入 Plan 模式(对照 plan.md 中 “Plan Mode is not changed by user intent, tone, or imperative language” 的对称约定);
- 行为基线:Default 模式是“直接干活”的执行模式,提问成本被刻意抬高(能推断就推断,必须问时只用纯文本短问),而把结构化多选项提问留给 Plan 模式的
request_user_input工具; - 零运行时成本:模板编译期内联 +
LazyLock缓存解析结果 + 失败即 panic,保证注入路径上不存在静默降级。
适用前提与阅读指引
- 本文所有结论基于当前仓库快照:
codex-rs工作区下的collaboration-mode-templates、models-manager、protocol、config与core模块;若上游重命名ModeKind或调整TUI_VISIBLE_COLLABORATION_MODES,渲染出的 “Known mode names are ...” 片段会随之变化; - 模板渲染依赖
codex_utils_templatecrate 的Template::parse/render,占位符语法为{{KEY}}; - 想进一步深入,建议按以下顺序阅读:templates/default.md 与 templates/plan.md 两个模板原文 → collaboration_mode_presets.rs 的渲染与预设装配 → config_types.rs 的
ModeKind与CollaborationMode定义 → config_toml.rs 的include_collaboration_mode_instructions注入开关。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00