Codex Prompt 工程与上下文管理精读
调研时间:2026-06-22 源码 commit:98845e4 本地 CLI:codex-cli 0.125.0
一句话定位
Codex 的 prompt 系统是一个多层注入架构:base instructions(模型模板 + 人格)作为 system prompt,AGENTS.md / Skills / Plugins / Context 作为 user-role 消息注入 conversation history,最终形成每次 API 调用的完整 Prompt 结构体。上下文管理通过 auto-compaction 机制自动维护,在达到 token 阈值时触发摘要压缩。
日常类比
把 Codex 的 prompt 组装想象成一个演出的后台准备:
- base instructions(剧本):定义角色身份和表演规范——”你是一个编程助手”
- AGENTS.md(导演备注):项目特定的行为指引——”这个场景要用 TypeScript”
- Skills(道具清单):临时加载的专业知识——”这场需要数据库知识”
- Config 层级(剧团规章):从公司规定到个人习惯,低优先级被高优先级覆盖
- Auto-compaction(场记摘要):演出太长时,场记写个”前情提要”让下一幕演员能接上
类比边界:真实演出中演员有自主判断,Codex 的 prompt 注入是确定性的——相同输入必然产生相同的 Prompt 结构。
Prompt 全景架构
flowchart TD
subgraph Config["配置层级(低→高优先级)"]
ADM[admin] --> SYS[system]
SYS --> CLOUD[cloud]
CLOUD --> USR[user]
USR --> PROF[profile]
PROF --> PROJ[project tree]
PROJ --> REPO[repo]
REPO --> CLI[runtime/CLI]
end
subgraph Assembly["Prompt 组装"]
BI[Base Instructions<br/>模板 + 人格]
AM[AGENTS.md<br/>项目指引]
SK[Skills<br/>按需注入]
PL[Plugins]
CTX[Context Updates<br/>env/permissions/realtime]
HIST[Conversation History]
TOOLS[Tool Specs]
end
Config -->|base_instructions<br/>developer_instructions| BI
Config -->|personality| BI
BI --> PROMPT[Prompt 结构体]
AM --> PROMPT
SK --> PROMPT
PL --> PROMPT
CTX --> PROMPT
HIST --> PROMPT
TOOLS --> PROMPT
PROMPT --> API[API 调用]
一、Base Instructions(系统指令)
模板与人格分离
Codex 将系统指令拆为两部分:
- 模板文件:
codex-rs/core/templates/model_instructions/gpt-5.2-codex_instructions_template.md - 人格文件:
codex-rs/core/templates/personalities/gpt-5.2-codex_friendly.md或gpt-5.2-codex_pragmatic.md
模板中包含一个占位符,运行时被人格内容替换:
// codex-rs/protocol/src/openai_models.rs:452
pub fn get_model_instructions(&self, personality: Option<Personality>) -> String {
if let Some(template) = &model_messages.instructions_template {
template.replace(PERSONALITY_PLACEHOLDER, personality_message)
} else {
self.base_instructions.clone() // fallback to legacy prompt
}
}
[源码] 旧版 fallback:codex-rs/core/gpt_5_codex_prompt.md 和 codex-rs/core/prompt_with_apply_patch_instructions.md
模板内容概要(gpt-5.2 版)
模板覆盖以下内容:
- 身份声明:”You are Codex, a coding agent based on GPT-5”
- 输出格式规则(Markdown 约定、无嵌套列表、标题用粗体而非 #)
- 行为约束(编辑规范、git 安全操作指南、plan tool 使用时机)
- 前端设计指南(CSS/UI 相关建议)
- 代码审查模式规则
- 人格占位符注入点
Session 初始化
// SessionConfiguration 确定最终 base_instructions
base_instructions: config.base_instructions
.clone()
.unwrap_or_else(|| model_info.get_model_instructions(config.personality)),
[源码] config 中的 base_instructions 字段可直接覆盖模板——完全旁路模型默认指令。
二、AGENTS.md 加载机制
发现逻辑
核心实现:codex-rs/core/src/agents_md.rs
project_root (由 .git 等标记确定)
├── AGENTS.override.md ← 最高优先级
├── AGENTS.md ← 标准
├── subdir/
│ ├── AGENTS.override.md
│ └── AGENTS.md
└── ... (遍历直到 cwd)
加载规则:
- 从 project root 到 cwd 逐级遍历
- 每级优先读 AGENTS.override.md,没有则读 AGENTS.md
- 受
project_doc_max_bytes预算限制,超出截断 - config 中可声明备选文件名
渲染为 Conversation History
// codex-rs/core/src/context/user_instructions.rs
impl ContextualUserFragment for UserInstructions {
fn type_markers() -> (&'static str, &'static str) {
("# AGENTS.md instructions", "</INSTRUCTIONS>")
}
fn body(&self) -> String {
format!("{directory}\n\n<INSTRUCTIONS>\n{}\n", self.text)
}
}
最终在 history 中表现为一条 user-role 消息:
# AGENTS.md instructions
[directory path]
<INSTRUCTIONS>
[AGENTS.md 文件内容]
</INSTRUCTIONS>
[源码] AGENTS.md 不进 system prompt——而是作为 user 消息注入 conversation history。这意味着模型将其视为”用户提供的项目指引”而非”系统级身份”。
三、Skills 注入
触发与加载
sequenceDiagram
participant U as User Input
participant T as turn.rs
participant SK as core-skills
participant H as History
U->>T: 消息包含 $skill-name
T->>T: collect_explicit_skill_mentions()
T->>SK: build_skill_injections()
SK->>SK: 读取 SKILL.md 文件内容
SK-->>T: Vec<SkillInjection>
T->>T: 转换为 SkillInstructions
T->>H: 作为 user-role 消息插入
渲染格式
// codex-rs/core-skills/src/skill_instructions.rs
impl ContextualUserFragment for SkillInstructions {
fn type_markers() -> (&'static str, &'static str) {
("<skill>", "</skill>")
}
fn body(&self) -> String {
format!("\n<name>{}</name>\n<path>{}</path>\n{}\n",
self.name, self.path, self.contents)
}
}
在 history 中的最终形态:
<skill>
<name>database</name>
<path>/project/.codex/skills/database/SKILL.md</path>
[SKILL.md 完整内容]
</skill>
[源码] Skills 按需注入:只有用户消息中显式提及 $skill-name 才加载对应 SKILL.md。不使用的 skill 不消耗 token。
四、Tools 注入
构建流程
// turn.rs:1211 → built_tools()
fn built_tools(&self) -> ToolRouter {
// 收集所有工具规格:
// - 内置工具:shell, apply_patch, plan
// - MCP tools:从 MCP server 连接获取
// - Dynamic tools:运行时注册的工具
let router = ToolRouter::new(...);
router
}
最终通过 router.model_visible_specs() 提取 Vec<ToolSpec> 放入 Prompt。
Tool 可见性控制
不是所有注册的工具都对模型可见——model_visible_specs() 过滤掉内部工具(如 escalation 相关的),只暴露模型应该调用的工具。
五、Config 层级体系
加载优先级(低到高)
admin → system → cloud → user → profile → project(tree) → repo → runtime/CLI
[源码] codex-rs/config/src/loader/mod.rs
安全门控
项目级 config 有信任级别门控机制:
- 不受信任的项目 config 无法覆盖敏感字段
PROJECT_LOCAL_CONFIG_DENYLIST阻止 repo config 设置特定键- 只有手动信任的项目才能从 config 注入
base_instructions
影响 Prompt 的关键 Config 字段
| 字段 | 作用 | 注入位置 |
|---|---|---|
| base_instructions | 完全覆盖模型模板 | system prompt |
| developer_instructions | 开发者附加指令 | developer role 消息 |
| personality | 选择 friendly/pragmatic 人格 | 模板占位符替换 |
| project_doc_max_bytes | AGENTS.md 最大读取字节数 | 影响 AGENTS.md 截断 |
| auto_compact_token_limit | 压缩触发阈值 | 影响 compaction 时机 |
六、Context Window 管理
Token 估计
// codex-rs/core/src/context_manager/history.rs
fn estimate_token_count_with_base_instructions() -> usize {
base_instructions_tokens + history_items.iter().map(|i| i.token_count()).sum()
}
Auto-Compaction 触发
两种评估 scope:
Total:全量 token 对比 auto_compact_token_limitBodyAfterPrefix:扣除 prefill 后的增量 token 对比限制
默认阈值:context_window 的 90%。
Compaction 时机
flowchart TD
PT[Pre-turn check] -->|token > 90%| COMPACT
MT[Mid-turn check<br/>sampling 返回后] -->|token_limit_reached<br/>+ needs_follow_up| COMPACT
DS[Model downshift] -->|切换到小 context 模型| COMPACT
COMPACT --> LOCAL[Local summarization]
COMPACT --> REMOTE[Remote compaction V1]
COMPACT --> REMOTEV2[Remote compaction V2]
Compaction Prompt
You are performing a CONTEXT CHECKPOINT COMPACTION. Create a handoff summary
for another LLM that will resume the task.
Include:
- Current progress and key decisions made
- Important context, constraints, or user preferences
- What remains to be done (clear next steps)
- Any critical data, examples, or references needed to continue
[源码] codex-rs/prompts/templates/compact/prompt.md
压缩后的 History 结构
compaction 完成后,原始 history 被替换为一条 compaction summary 消息 + 后续新消息。AGENTS.md 和 Skills 注入会在新 turn 重新加载(不依赖 compaction 保留)。
完整 Per-Turn 组装流程
Session Init
├── Config loading (admin→...→runtime)
├── Model info → get_model_instructions(personality) → base_instructions
├── AGENTS.md discovered → stored in SessionConfiguration
└── SessionConfiguration finalized
Per-Turn Execution (run_turn)
├── 1. Pre-sampling compaction (if token_limit reached)
├── 2. record_context_updates_and_set_reference_context_item()
│ └── Diffs: environment, permissions, personality, collab mode
├── 3. build_skills_and_plugins()
│ ├── Collect $skill mentions from user input
│ ├── Read SKILL.md → SkillInjection → SkillInstructions
│ ├── Read plugins → PluginInjection
│ └── Insert as user-role messages into history
├── 4. Sampling loop:
│ ├── Clone history → input items
│ ├── built_tools() → ToolRouter → model_visible_specs()
│ ├── get_base_instructions() → BaseInstructions
│ ├── build_prompt(input, tools, base_instructions) → Prompt
│ ├── Send to API
│ ├── Process response
│ └── If token_limit_reached && needs_follow_up → compact → loop
└── Turn complete: model returns assistant-only message
Prompt 结构体
pub struct Prompt {
pub input: Vec<ResponseItem>, // conversation history
pub tools: Vec<ToolSpec>, // 模型可见工具定义
pub parallel_tool_calls: bool,
pub base_instructions: BaseInstructions, // system prompt
pub output_schema: Option<Value>,
}
input 中消息的时序排列:
- AGENTS.md instructions(user role,
<INSTRUCTIONS>标签) - Environment context updates(user role)
- Permissions instructions(developer role)
- Skill injections(user role,
<skill>标签) - Plugin injections
- User messages + tool call/result pairs
- Compaction summary(如有压缩历史)
与 Claude Code 的差异(待 Agent A 核对)
| 维度 | Codex | Claude Code(推测) |
|---|---|---|
| 项目指引文件 | AGENTS.md / AGENTS.override.md | CLAUDE.md |
| 注入角色 | user role 消息 | 推测为 system prompt 或 user role |
| 层级遍历 | project root → cwd 逐级合并 | 推测有类似层级 |
| Skill 触发 | 显式 $skill-name 提及 | 推测基于自然语言匹配 |
| 人格系统 | 模板 + 可选人格文件(friendly/pragmatic) | 无公开人格切换机制 |
| 上下文压缩 | Auto-compaction(local/remote/V2),90% 阈值触发 | 推测有类似机制,细节未知 |
| Config 安全 | 项目级 config 有信任门控 + denylist | 推测无分级信任机制 |
| Tool 可见性 | model_visible_specs 过滤内部工具 | 推测类似(部分工具对用户不可见) |
| Override 机制 | AGENTS.override.md 最高优先级 | 无对应公开机制 |
关键差异洞察:
- Codex 将 AGENTS.md 注入为 user role 而非 system prompt——模型将其视为”用户指引”而非”身份定义”,理论上降低了 prompt injection 风险
- Codex 的人格系统(friendly vs pragmatic)是编译时模板替换,比运行时指令切换更可控
- Codex 的 config 信任分级(admin → runtime)是企业部署场景的设计——管理员可锁定策略,开发者无法从 repo config 越权
设计洞察
为什么 AGENTS.md 是 user role 而非 system role
- 安全性:system prompt 被模型视为最高权限;将项目指引降为 user role 减少了通过恶意 AGENTS.md 越狱的风险
- 可覆盖性:system prompt(base_instructions)由平台控制,项目级指引不应覆盖平台策略
- 清晰分层:system = 身份 + 能力,user = 上下文 + 指引
Skills 按需加载的优势
- Token 效率:未触发的 skill 零消耗
- 可预测性:用户显式控制注入内容
- 安全性:不会因为项目中存在 SKILL.md 就自动注入
Auto-Compaction 的 trade-off
- 优势:无限长对话不会 OOM;摘要保留关键上下文
- 劣势:压缩有信息损失;多次压缩后早期细节可能丢失
- 缓解:AGENTS.md 和 Skills 在每个 turn 重新注入,不依赖 compaction 保留
局限性
- 模板硬编码模型名:
gpt-5.2-codex模板与特定模型绑定,切换模型需新模板 [源码] - AGENTS.md 截断无提示:超过 project_doc_max_bytes 直接截断,用户无感知 [源码]
- Skill 触发依赖精确匹配:必须输入
$skill-name格式,自然语言描述不触发 [源码] - Compaction 质量不可控:摘要由模型生成,可能遗漏关键细节;无人工验证机制 [源码]
- Config 层级复杂度:8 层优先级在排查问题时增加认知负担 [源码]
- 无增量注入:每次 turn 都重新注入完整 AGENTS.md 和 Skills,对长文件是 token 浪费 [源码]
证据等级汇总
| 结论 | 来源 |
|---|---|
| AGENTS.md 作为 user role 注入,非 system prompt | [源码] core/src/context/user_instructions.rs |
| 模板 + 人格文件分离设计 | [源码] protocol/src/openai_models.rs:452 |
| Skills 通过 $skill-name 显式触发 | [源码] core-skills/src/injection.rs |
| Config 8 层优先级 admin→runtime | [源码] config/src/loader/mod.rs |
| Auto-compaction 90% 阈值 | [源码] core/src/context_manager/history.rs |
| Compaction prompt 使用 handoff summary 格式 | [源码] prompts/templates/compact/prompt.md |
| 项目 config 有信任门控 + denylist | [源码] config/src/loader/mod.rs |
| ToolRouter 过滤内部工具 | [源码] turn.rs:1211 built_tools() |