Skip to content

系统提示词 (System Prompt)

源码版本rust-v0.145.0

codex 把"对模型说的话"拆成几段静态文本、模板和上下文片段拼装而成。prompts crate 提供常量与模板,core 在 session 启动时挑出对应模型的 base instructions,再叠加 AGENTS.mdpermissions instructions、personality 片段,组成最终的 system prompt。本页讲这套组装链路。

职责

  1. 维护各模型默认 base instructions 与 personality 模板,按模型 slug 选择填充:codex-rs/protocol/src/openai_models.rs:478-500
  2. 暴露工具/审批相关的常量提示(apply_patch、compaction、review、permissions、realtime):codex-rs/prompts/src/lib.rs:1-27
  3. AGENTS.md 与用户指令拼出项目级 developer instructions:codex-rs/core/src/agents_md.rs:53-80
  4. 把 sandbox/approval policy 渲染成模型可见的 permissions instructions:codex-rs/prompts/src/permissions_instructions.rs:62-117
  5. 在 session 启动与 turn 切换时落定 base_instructions,并供 client/compact 读取:codex-rs/core/src/session/mod.rs:615-631

设计动机

base instructions 不能写死在 core 里。不同模型(gpt-5.1、gpt-5.2-codex 等)有不同的默认人格与工具描述;同模型还可能切换 personality(friendly/pragmatic/none)。把模板放进 models-managercore/templates/,由 ModelMessages.instructions_template 在运行时替换 占位符,让新增模型只需要新增一份 markdown,core 不用动。

另一层动机是 provenance(来源可追溯)。AGENTS.md 可能来自用户级、项目根、子目录;多层叠加时 LoadedAgentsMd 保留每条 entry 的来源,必要时按 environment 加标签输出,让模型知道哪段指令来自哪个目录。permission instructions 同理——它不是普通字符串,而是带 <permissions instructions> marker 的 ContextualUserFragment,便于上下文管理器在压缩或回放时识别和剥离。

关键文件

base_instructions 三级 fallback——优先用户 config,其次从 conversation history 恢复,最后才用模型默认。

rust
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));

personality 模板替换:如果模型有 instructions_template,总是用模板替换 ;没有模板就退回 base_instructions

rust
pub fn get_model_instructions(&self, personality: Option<Personality>) -> String {
    if let Some(model_messages) = &self.model_messages
        && let Some(template) = &model_messages.instructions_template
    {
        let personality_message = model_messages
            .get_personality_message(personality)
            .unwrap_or_default();
        template.replace(PERSONALITY_PLACEHOLDER, personality_message.as_str())
    } else {
        // ...
        self.base_instructions.clone()
    }
}

permissions instructions 不是普通字符串,而是带 marker 的 ContextualUserFragment,便于上下文管理器在压缩或回放时识别和剥离。

rust
impl ContextualUserFragment for PermissionsInstructions {
    fn role(&self) -> &'static str { "developer" }
    fn markers(&self) -> (&'static str, &'static str) { Self::type_markers() }
    fn type_markers() -> (&'static str, &'static str) {
        ("<permissions instructions>", "</permissions instructions>")
    }
    fn body(&self) -> String { PermissionsInstructions::body(self) }
}

数据流

边界与失败

小结

系统提示词在 codex 里不是一段写死的字符串,而是 模型默认 → config 覆盖 → 历史快照 的三级 fallback 加上 AGENTS.mdpermissions instructionspersonality 等带 marker 的片段叠加。prompts crate 只放常量与模板,组装逻辑都在 core 里,调用方拿到的 BaseInstructions 已经是落定的字符串。理解这条链路对调试 Agent 主循环 里"模型为什么这么回答"和 压缩 (compaction) 里"哪些段被剥掉再重放"都很关键。