OpenAI Codex
OpenAI Codex 完整架构分析与实现指南
OpenAI Codex 完整架构分析与实现指南
📋 目录
项目概述
什么是 Codex CLI?
OpenAI Codex CLI 是一个开源的终端编码代理,它能在本地运行,读取、修改和执行代码。它是 OpenAI 为开发者提供的 AI 编程助手,可以:
- ✅ 自动编写和重构代码
- ✅ 执行 shell 命令
- ✅ 运行测试和调试
- ✅ 生成 Pull Request
- ✅ 代码审查和分析
- ✅ 支持多模态输入(文本+图像)
核心特点
- 开源 - Apache 2.0 许可证
- 本地运行 - 代码不上传云端
- 用 Rust 重写 - 从 TypeScript/Node.js 迁移到 Rust,获得更高性能和安全性
- 沙箱隔离 - 多层安全机制保护系统
- MCP 支持 - 可作为 MCP 客户端或服务器
核心架构设计
整体架构
Codex CLI 采用分层架构,将用户界面、核心引擎和工具执行分离:
┌─────────────────────────────────────────────────────────┐
│ 用户界面层 │
│ ┌──────────┐ ┌──────────┐ ┌─────────────────┐ │
│ │ TUI │ │ Exec │ │ MCP Server │ │
│ │ (终端UI) │ │ (无头模式) │ │ (协议服务器) │ │
│ └──────────┘ └──────────┘ └─────────────────┘ │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 提交/事件协议层 │
│ Submission Queue / Event Queue │
│ (异步双向通信,解耦请求和处理) │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 核心引擎层 │
│ ┌──────────────────────────────────────────────┐ │
│ │ codex-core (Rust Workspace) │ │
│ │ │ │
│ │ • Session 管理(会话状态) │ │
│ │ • TurnContext(单轮上下文) │ │
│ │ • Agent Loop(主循环逻辑) │ │
│ │ • Model Integration(模型交互) │ │
│ │ • Tool Execution(工具执行) │ │
│ └──────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 工具与服务层 │
│ ┌────────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ Sandbox │ │ MCP │ │ File Ops │ │
│ │ (沙箱) │ │ (协议) │ │ (文件操作) │ │
│ └────────────┘ └──────────┘ └──────────────┘ │
│ │
│ ┌────────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ Auth │ │ Config │ │ Responses │ │
│ │ (认证) │ │ (配置) │ │ API │ │
│ └────────────┘ └──────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────┘
Rust Workspace 结构
Codex CLI 使用 Cargo Workspace 组织多个 crate:
codex-rs/
├── cli/ # CLI 入口和命令分发
├── core/ # 核心引擎(Session, Agent Loop)
├── tui/ # 终端 UI (使用 Ratatui)
├── exec/ # 无头执行模式
├── mcp-server/ # MCP 服务器实现
├── protocol/ # 通信协议定义
├── login/ # 认证系统
├── sandbox/ # 沙箱抽象层
├── macos-seatbelt/ # macOS 沙箱实现
├── linux-sandbox/ # Linux Landlock + seccomp
├── responses-api-proxy/ # API 代理服务器
├── process-hardening/ # 进程加固
└── config/ # 配置管理
技术栈与实现
为什么从 TypeScript 迁移到 Rust?
OpenAI 团队列出了以下原因:
- 零依赖安装 - 不再需要 Node.js v22+
- 原生安全绑定 - Rust 可直接使用 OS 级沙箱 API
- 优化性能 - 无 GC,内存占用更低
- 可扩展协议 - 支持其他语言扩展(TypeScript, Python)
核心技术
| 组件 | 技术选型 |
|---|---|
| CLI 框架 | clap (命令行解析) |
| 异步运行时 | tokio (异步 I/O) |
| 终端 UI | ratatui (原 tui-rs) |
| HTTP 客户端 | reqwest |
| 序列化 | serde + serde_json |
| 配置管理 | toml |
| macOS 沙箱 | Apple Seatbelt (sandbox-exec) |
| Linux 沙箱 | Landlock + seccomp |
| MCP 实现 | 自定义 stdio 协议 |
Agent 设计模式
核心理念 ReAct 模式
Codex 采用单线程 Agent Loop,避免多 Agent 并发的复杂性:
┌─────────────────────────────────────────────────────────┐
│ Agent Loop (单循环) │
│ │
│ 1. 接收用户输入 │
│ 2. 构建上下文(System Prompt + 历史 + 用户消息) │
│ 3. 调用 Responses API (流式响应) │
│ 4. 处理模型输出: │
│ ├─ reasoning (推理过程) │
│ ├─ message (文本消息) │
│ └─ function_call (工具调用) │
│ 5. 执行工具 → 获取结果 → 追加到历史 │
│ 6. 回到步骤 2,继续循环 │
│ 7. 直到任务完成或用户中断 │
└─────────────────────────────────────────────────────────┘
System Prompt 设计
Codex 的 System Prompt 非常关键,它定义了 Agent 的"操作系统":
You are Codex, based on GPT-5. You are running as a coding agent in the Codex CLI on a user's computer. ## General - The arguments to `shell` will be passed to execvp() - Most terminal commands should be prefixed with ["bash", "-lc"] - Always set the `workdir` param when using the shell function - When searching, prefer `rg` over `grep` (faster) ## Tools 1. **shell** - Execute shell commands 2. **apply_patch** - Apply unified diffs to files ## Coding Guidelines - Minimal, surgical diffs (avoid full file rewrites) - Run tests to verify changes - Use project's existing patterns - Check linter/formatter output ## Workflow 1. Read files to understand context (cat, rg, find) 2. Make minimal changes (apply_patch) 3. Verify changes (run tests, linters) 4. Iterate until success
关键点:
- ✅ 简洁明了 - GPT-5-Codex 提示词比 GPT-5 少 60% token
- ✅ 工具优先 - 教会模型"shell-first"思维
- ✅ 安全默认 - 明确沙箱和网络限制
- ✅ 验证驱动 - 强调测试和验证
工具系统
主要工具
Codex 暴露给模型的工具非常简洁:
1. shell 工具
// 工具定义 { "name": "shell", "description": "Execute shell command in sandbox", "parameters": { "cmd": ["string"], // 命令数组 "workdir": "string", // 工作目录 "env": {"key": "value"} // 环境变量(可选) } }
执行流程:
- 模型生成 function_call:
{"name": "shell", "arguments": {"cmd": ["ls", "-la"]}} - CLI 拦截调用 → 检查审批策略
- 根据策略决定是否需要用户确认
- 在沙箱中执行命令
- 返回 stdout/stderr 给模型
2. apply_patch 工具
// 特殊格式的补丁 *** Begin Patch *** Update File: src/main.rs @@ -fn main() { - println!("Hello"); +fn main() { + println!("Hello, World!"); } *** End Patch
处理逻辑:
- 解析补丁格式
- 生成彩色 diff 展示给用户
- 根据审批策略决定是否应用
- 使用
fs操作直接修改文件
审批策略
Codex 提供 3 种审批模式:
| 模式 | 读文件 | 写文件 | 执行命令 | 用例 |
|---|---|---|---|---|
| Suggest (建议模式) | ✅ 自动 | ❌ 需确认 | ❌ 需确认 | 最安全,适合学习 |
| Auto-Edit (自动编辑) | ✅ 自动 | ✅ 自动 | ❌ 需确认 | 快速重构 |
| Full-Auto (全自动) | ✅ 自动 | ✅ 自动 | ✅ 自动 | CI/CD 管道 |
工具分类逻辑
fn can_auto_approve(cmd: &[String], policy: ApprovalMode) -> bool { match policy { ApprovalMode::Suggest => { // 只允许读操作 is_read_only_command(cmd) } ApprovalMode::AutoEdit => { // 允许读操作 + 文件写入 is_read_only_command(cmd) || is_file_write(cmd) } ApprovalMode::FullAuto => { // 允许所有操作(在沙箱内) true } } } fn is_read_only_command(cmd: &[String]) -> bool { matches!(cmd[0].as_str(), "cat" | "ls" | "head" | "tail" | "rg" | "find") }
安全沙箱机制
多层防护
Codex 实现了纵深防御:
┌──────────────────────────────────────────────────┐
│ Layer 1: 审批策略 (Application-Level Controls) │
│ • 命令分类(读/写/执行) │
│ • 用户确认流程 │
│ • 命令黑名单 │
└──────────────────────────────────────────────────┘
↓
┌──────────────────────────────────────────────────┐
│ Layer 2: OS 级沙箱 (OS-Level Sandboxing) │
│ macOS: Apple Seatbelt (sandbox-exec) │
│ Linux: Landlock + seccomp-bpf │
└──────────────────────────────────────────────────┘
↓
┌──────────────────────────────────────────────────┐
│ Layer 3: 网络隔离 (Network Isolation) │
│ • 默认禁用网络 │
│ • 白名单:仅允许 OpenAI API │
│ • iptables/ipset 防火墙规则 │
└──────────────────────────────────────────────────┘
↓
┌──────────────────────────────────────────────────┐
│ Layer 4: 文件系统限制 (Filesystem Restrictions) │
│ • 只读:系统目录 │
│ • 读写:$PWD (项目目录) │
│ • 读写:$TMPDIR (临时目录) │
└──────────────────────────────────────────────────┘
macOS 实现
// 使用 Apple Seatbelt fn create_sandbox_profile() -> String { r#" (version 1) (deny default) (allow file-read*) (allow file-write* (subpath (param "PWD")) (subpath (param "TMPDIR"))) (deny network*) (allow network-outbound (remote ip "api.openai.com:443")) "# } fn run_in_sandbox(cmd: &[String]) -> Result<Output> { Command::new("sandbox-exec") .arg("-p") .arg(create_sandbox_profile()) .args(cmd) .output() }
Linux 实现
// 使用 Landlock (Linux 5.13+) use landlock::*; fn create_landlock_ruleset() -> Result<Ruleset> { Ruleset::default() .handle_access(AccessFs::from_all(ABI::V2))? .add_rule(PathBeneath::new(&pwd, AccessFs::from_all(ABI::V2)))? .add_rule(PathBeneath::new("/tmp", AccessFs::from_all(ABI::V2)))? .restrict_self()? } // seccomp-bpf 限制系统调用 fn apply_seccomp_filter() { let filter = SeccompFilter::new() .allow_syscall("read") .allow_syscall("write") // ... 白名单其他必要系统调用 .deny_default(); filter.load().unwrap(); }
执行流程详解
完整的用户请求流程
让我们跟踪一个完整的请求:codex "Add error handling to main.rs"
┌─────────────────────────────────────────────────────────┐
│ Step 1: CLI 入口 │
│ • 解析命令行参数 │
│ • 加载配置文件 (~/.codex/config.toml) │
│ • 检查认证状态 │
│ • 初始化 TUI 或 Exec 模式 │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ Step 2: 上下文构建 │
│ • 读取项目文档 (AGENTS.md, codex.md) │
│ • 读取全局指令 (~/.codex/instructions.md) │
│ • 检查 Git 状态 │
│ • 组装 System Prompt │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ Step 3: 提交到核心引擎 │
│ • 创建 Submission: Op::StartTurn { prompt, ... } │
│ • 发送到 Submission Queue │
│ • 核心引擎接收并处理 │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ Step 4: Agent Loop 执行 │
│ ┌─────────────────────────────────────────────┐ │
│ │ 4.1 调用 Responses API │ │
│ │ POST /v1/responses │ │
│ │ { │ │
│ │ "model": "gpt-5-codex", │ │
│ │ "messages": [...], │ │
│ │ "tools": [{"name": "shell"}, ...], │ │
│ │ "stream": true │ │
│ │ } │ │
│ └─────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────┐ │
│ │ 4.2 处理流式响应 │ │
│ │ • response.reasoning (内部推理) │ │
│ │ • response.message (文本输出) │ │
│ │ • response.function_call (工具调用) │ │
│ └─────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────┐ │
│ │ 4.3 执行工具调用 │ │
│ │ 假设模型输出: │ │
│ │ { │ │
│ │ "name": "shell", │ │
│ │ "arguments": { │ │
│ │ "cmd": ["cat", "src/main.rs"] │ │
│ │ } │ │
│ │ } │ │
│ │ │ │
│ │ → 检查审批策略 │ │
│ │ → 在沙箱中执行 cat src/main.rs │ │
│ │ → 返回文件内容给模型 │ │
│ └─────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────┐ │
│ │ 4.4 模型生成补丁 │ │
│ │ { │ │
│ │ "name": "shell", │ │
│ │ "arguments": { │ │
│ │ "cmd": ["apply_patch", "*** ..."] │ │
│ │ } │ │
│ │ } │ │
│ │ │ │
│ │ → 解析补丁 │ │
│ │ → 显示彩色 diff │ │
│ │ → 请求用户确认(如果不是 Full-Auto) │ │
│ │ → 应用补丁到文件 │ │
│ └─────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────┐ │
│ │ 4.5 验证更改 │ │
│ │ 模型可能执行: │ │
│ │ • cargo check (语法检查) │ │
│ │ • cargo test (运行测试) │ │
│ │ • git diff (查看更改) │ │
│ └─────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────┐ │
│ │ 4.6 完成或继续迭代 │ │
│ │ • 如果测试通过 → 输出完成消息 │ │
│ │ • 如果测试失败 → 继续循环修复 │ │
│ └─────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ Step 5: 事件返回 │
│ • 通过 Event Queue 发送事件给 UI │
│ • EventMsg::Reasoning - 显示推理过程 │
│ • EventMsg::Message - 显示文本输出 │
│ • EventMsg::ToolCall - 显示工具调用和结果 │
│ • EventMsg::TurnComplete - 任务完成 │
└─────────────────────────────────────────────────────────┘
Submission/Event 协议
Codex 使用自定义的异步协议解耦请求和响应:
// 提交类型 enum Op { StartTurn { prompt: String, images: Vec<PathBuf>, context: TurnContext, }, Cancel { submission_id: u64, }, // ... } // 事件类型 enum EventMsg { Reasoning { text: String, }, Message { content: String, }, ToolCall { tool: String, args: serde_json::Value, }, ToolResult { output: String, }, TurnComplete, Error { message: String, }, } // 核心循环 async fn submission_loop( mut rx: mpsc::Receiver<Op>, tx: mpsc::UnboundedSender<EventMsg>, ) { while let Some(op) = rx.recv().await { match op { Op::StartTurn { prompt, context, .. } => { // 调用 Agent Loop execute_turn(&prompt, &context, &tx).await; } Op::Cancel { .. } => { // 取消执行 break; } } } }
配置系统
五层优先级
Codex 的配置系统支持 5 个优先级层:
1. 命令行参数 (最高优先级)
codex -c model=gpt-5-codex -c approval_mode=full-auto
2. 环境变量
export CODEX_MODEL=gpt-5-codex
3. 项目配置 (.codex/config.toml)
[default]
model = "gpt-5-codex"
approval_mode = "auto-edit"
4. 用户全局配置 (~/.codex/config.toml)
[default]
model = "gpt-5"
5. 内置默认值 (最低优先级)
配置文件示例
# ~/.codex/config.toml [default] model = "gpt-5-codex" model_provider = "openai" approval_mode = "auto-edit" sandbox = "workspace-write" max_turns = 50 [profiles.strict] approval_mode = "suggest" sandbox = "read-only" [profiles.ci] approval_mode = "full-auto" quiet = true [mcp_servers.filesystem] command = "mcp-server-filesystem" args = ["--allowed-dirs", "/home/user/projects"] [mcp_servers.github] command = "mcp-server-github" env = { GITHUB_TOKEN = "ghp_xxx" }
MCP 集成
什么是 MCP?
Model Context Protocol (MCP) 是 OpenAI 定义的标准协议,用于 AI Agent 之间的通信。
Codex 的双重角色
1. 作为 MCP 客户端
Codex 可以连接到其他 MCP 服务器,扩展其能力:
# 配置 MCP 服务器 codex mcp add filesystem --command mcp-server-filesystem codex mcp add github --command mcp-server-github
流程:
Codex CLI → [MCP Protocol] → MCP Server (filesystem)
↓
读取文件/目录
2. 作为 MCP 服务器
其他 Agent 可以调用 Codex:
# 启动 MCP 服务器模式 codex mcp # 或者通过 npx npx codex mcp
在 Agents SDK 中使用:
from agents import Agent from agents.mcp import MCPServerStdio async with MCPServerStdio( name="Codex CLI", params={ "command": "npx", "args": ["-y", "codex", "mcp"] }, client_session_timeout_seconds=360000 ) as codex_mcp_server: agent = Agent( name="Developer", instructions="You are a coding assistant", mcp_servers=[codex_mcp_server] ) # Agent 现在可以调用 Codex 的能力 result = await agent.run("Refactor this code")
MCP 工具定义
Codex 暴露的 MCP 工具:
{ "tools": [ { "name": "codex_execute", "description": "Execute a coding task in Codex CLI", "inputSchema": { "type": "object", "properties": { "prompt": { "type": "string", "description": "Task description" }, "approval-policy": { "type": "string", "enum": ["suggest", "auto-edit", "full-auto", "never"] }, "sandbox": { "type": "string", "enum": ["read-only", "workspace-write", "danger-full-access"] } }, "required": ["prompt"] } } ] }
如何实现类似的 Agent
第一步
| 组件 | 推荐选项 |
|---|---|
| 语言 | Rust (性能) 或 Python (快速开发) |
| 异步运行时 | Rust: tokio / Python: asyncio |
| CLI 框架 | Rust: clap / Python: click |
| 终端 UI | Rust: ratatui / Python: rich + textual |
| LLM SDK | OpenAI SDK / Anthropic SDK |
第二步
# Python 示例 import openai import asyncio from typing import List, Dict class CodingAgent: def __init__(self, model="gpt-4"): self.model = model self.history: List[Dict] = [] self.system_prompt = """ You are a coding assistant. You can: 1. Execute shell commands using the 'shell' tool 2. Apply patches to files using the 'apply_patch' tool Always verify your changes by running tests. """ async def run(self, user_prompt: str): # 添加用户消息 self.history.append({ "role": "user", "content": user_prompt }) # 主循环 while True: # 调用 LLM response = await openai.chat.completions.create( model=self.model, messages=[ {"role": "system", "content": self.system_prompt}, *self.history ], tools=[ { "type": "function", "function": { "name": "shell", "description": "Execute shell command", "parameters": { "type": "object", "properties": { "cmd": { "type": "array", "items": {"type": "string"} } }, "required": ["cmd"] } } }, # ... 其他工具 ] ) message = response.choices[0].message # 处理工具调用 if message.tool_calls: for tool_call in message.tool_calls: result = await self.execute_tool(tool_call) # 添加工具结果到历史 self.history.append({ "role": "tool", "tool_call_id": tool_call.id, "content": result }) # 继续循环 continue else: # 没有工具调用,任务完成 print(message.content) break async def execute_tool(self, tool_call): tool_name = tool_call.function.name args = json.loads(tool_call.function.arguments) if tool_name == "shell": return await self.run_shell(args["cmd"]) elif tool_name == "apply_patch": return await self.apply_patch(args["patch"]) async def run_shell(self, cmd: List[str]): # 实现沙箱执行 import subprocess result = subprocess.run( cmd, capture_output=True, text=True, timeout=30 ) return f"stdout: {result.stdout}\nstderr: {result.stderr}"
第三步
# 简单的 Linux 沙箱示例 import subprocess import tempfile import os class Sandbox: def __init__(self, work_dir: str): self.work_dir = work_dir def run_command(self, cmd: List[str]) -> str: # 使用 firejail 作为简单沙箱 sandbox_cmd = [ "firejail", "--quiet", "--private=" + self.work_dir, "--net=none", # 禁用网络 "--", *cmd ] result = subprocess.run( sandbox_cmd, capture_output=True, text=True, timeout=30 ) return result.stdout + result.stderr
第四步
class ApprovalPolicy: SUGGEST = "suggest" AUTO_EDIT = "auto_edit" FULL_AUTO = "full_auto" def __init__(self, mode: str): self.mode = mode def should_approve(self, tool: str, args: dict) -> bool: if self.mode == self.FULL_AUTO: return True if self.mode == self.AUTO_EDIT: # 自动批准读操作和写文件 if tool == "shell": cmd = args["cmd"][0] return cmd in ["cat", "ls", "find", "grep"] elif tool == "apply_patch": return True # Suggest 模式:都需要确认 return False def request_approval(self, tool: str, args: dict) -> bool: print(f"\n🔔 Approval needed:") print(f"Tool: {tool}") print(f"Args: {args}") response = input("Approve? (y/n): ") return response.lower() == 'y'
第五步 MCP
from mcp import Server, Tool class CodexMCPServer: def __init__(self): self.server = Server() self.agent = CodingAgent() @self.server.tool() async def codex_execute( prompt: str, approval_policy: str = "suggest" ) -> str: """Execute a coding task""" self.agent.approval_mode = approval_policy result = await self.agent.run(prompt) return result async def run(self): await self.server.run(transport="stdio") # 启动 MCP 服务器 if __name__ == "__main__": server = CodexMCPServer() asyncio.run(server.run())
完整的最小实现框架
my-coding-agent/
├── src/
│ ├── main.py # CLI 入口
│ ├── agent.py # Agent Loop
│ ├── tools.py # 工具实现
│ ├── sandbox.py # 沙箱封装
│ ├── approval.py # 审批系统
│ ├── config.py # 配置管理
│ └── mcp_server.py # MCP 服务器
├── prompts/
│ └── system_prompt.txt # System Prompt
├── config.toml # 默认配置
├── requirements.txt
└── README.md
关键实现要点
-
System Prompt 设计
- 简洁明了,定义 Agent 的"操作系统"
- 明确工具使用规范
- 包含安全约束和验证要求
-
工具系统
- 保持工具数量少(5 个)
- 使用 shell 作为通用工具
- 实现专门的文件编辑工具(diff-based)
-
安全机制
- 多层防护 + 沙箱 + 网络隔离
- 默认拒绝,白名单允许
- 用户可控的安全级别
-
用户体验
- 流式输出,实时反馈
- 彩色 diff 显示
- 清晰的审批界面
-
可扩展性
- 支持 MCP 协议
- 插件化工具系统
- 配置驱动的行为
架构图
系统架构图
┌────────────────────────────────────────────────────────────────┐
│ 用户层 │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ 开发者 │ │ CI/CD │ │ 其他 Agent │ │
│ └────┬─────┘ └────┬─────┘ └──────┬───────┘ │
│ │ │ │ │
│ ↓ ↓ ↓ │
└────────────────────────────────────────────────────────────────┘
│ │ │
↓ ↓ ↓
┌────────────────────────────────────────────────────────────────┐
│ 接口层 │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ TUI │ │ Exec │ │ MCP Server │ │
│ │(终端界面) │ │(无头模式) │ │ (stdio协议) │ │
│ └────┬─────┘ └────┬─────┘ └──────┬───────┘ │
│ │ │ │ │
│ └─────────────────┼────────────────────┘ │
│ ↓ │
└────────────────────────────────────────────────────────────────┘
│
↓
┌────────────────────────────────────────────────────────────────┐
│ 异步通信层 (SQ/EQ) │
│ │
│ ┌───────────────────────────────────────────────────┐ │
│ │ Submission Queue ←→ Event Queue │ │
│ │ (提交队列) (事件队列) │ │
│ └───────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────┘
│
↓
┌────────────────────────────────────────────────────────────────┐
│ 核心引擎 (codex-core) │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Agent Loop (主循环) │ │
│ │ │ │
│ │ while not done: │ │
│ │ 1. 调用 Responses API │ │
│ │ 2. 处理 reasoning/message/function_call │ │
│ │ 3. 执行工具 │ │
│ │ 4. 追加结果到历史 │ │
│ │ 5. 检查完成条件 │ │
│ └─────────────────────────────────────────────────┘ │
│ │ │
│ ┌──────────────────────┴─────────────────────────┐ │
│ │ │ │
│ ↓ ↓ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Session │ │ TurnContext │ │
│ │ (会话管理) │ │ (单轮上下文) │ │
│ └─────────────┘ └─────────────┘ │
└────────────────────────────────────────────────────────────────┘
│
↓
┌────────────────────────────────────────────────────────────────┐
│ 工具执行层 │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ Shell │ │ Patch │ │ MCP 客户端 │ │
│ │ 执行器 │ │ 应用器 │ │ (外部工具) │ │
│ └────┬─────┘ └────┬─────┘ └──────┬───────┘ │
│ │ │ │ │
│ └───────────────┼──────────────────┘ │
│ ↓ │
└────────────────────────────────────────────────────────────────┘
│
↓
┌────────────────────────────────────────────────────────────────┐
│ 安全沙箱层 │
│ │
│ ┌─────────────────────────────────────────────┐ │
│ │ 审批策略检查 │ │
│ │ • Suggest: 所有写操作需确认 │ │
│ │ • Auto-Edit: 自动应用文件更改 │ │
│ │ • Full-Auto: 完全自动化 │ │
│ └─────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────┐ │
│ │ OS 级沙箱 (Seatbelt/Landlock) │ │
│ │ • 文件系统限制: 仅 $PWD + $TMPDIR 可写 │ │
│ │ • 网络隔离: 仅允许 api.openai.com │ │
│ │ • 系统调用过滤 (Linux seccomp) │ │
│ └─────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────┘
│
↓
┌────────────────────────────────────────────────────────────────┐
│ 外部服务层 │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────┐ │
│ │ OpenAI API │ │ 文件系统 │ │ Git │ │
│ │ (Responses) │ │ (读/写) │ │ (版本控制)│ │
│ └──────────────┘ └──────────────┘ └──────────┘ │
└────────────────────────────────────────────────────────────────┘
Agent Loop 流程图
┌──────────────────────┐
│ 用户输入提示 │
│ "Add error handling" │
└──────────┬───────────┘
↓
┌──────────────────────┐
│ 构建上下文 │
│ • System Prompt │
│ • 历史消息 │
│ • 项目文档(AGENTS.md) │
└──────────┬───────────┘
↓
┌──────────────────────┐
│ 调用 Responses API │
│ (流式响应) │
└──────────┬───────────┘
↓
┌──────────────────────┐
│ 解析响应类型 │
└──────────┬───────────┘
↓
┌─────────┴─────────┐
↓ ↓
┌────────────────┐ ┌──────────────┐
│ Reasoning │ │ Message │
│ (推理过程) │ │ (文本输出) │
└────────────────┘ └──────────────┘
↓ ↓
(显示推理) (显示消息)
↓ ↓
└─────────┬─────────┘
↓
┌──────────────────────┐
│ Function Call? │
│ (工具调用) │
└──────────┬───────────┘
↓
┌────┴────┐
│ 是否? │
└────┬────┘
↓
┌──────┴──────┐
↓ ↓
【是】 【否】
↓ ↓
┌──────────────────┐ ┌──────────────┐
│ 解析工具调用 │ │ 任务完成 │
│ • shell │ │ 输出结果 │
│ • apply_patch │ └──────────────┘
└─────────┬────────┘
↓
┌──────────────────┐
│ 检查审批策略 │
│ • 需要确认? │
│ • 自动批准? │
└─────────┬────────┘
↓
┌─────┴─────┐
↓ ↓
【需确认】 【自动批准】
↓ ↓
┌─────────┐ │
│ 显示 UI │ │
│ 等待确认│ │
└────┬────┘ │
↓ ↓
┌──┴────────┴──┐
│ 在沙箱中执行 │
│ 获取输出 │
└──────┬────────┘
↓
┌──────────────┐
│ 追加到历史 │
│ • Tool Call │
│ • Tool Result│
└──────┬───────┘
↓
┌──────────────┐
│ 继续循环 │
│ (回到 API) │
└──────────────┘
↓
(返回顶部)
工具执行流程
┌─────────────────────────────────────────────────┐
│ 模型生成工具调用 │
│ { │
│ "name": "shell", │
│ "arguments": {"cmd": ["cat", "main.rs"]} │
│ } │
└────────────────────┬────────────────────────────┘
↓
┌─────────────────────────────────────────────────┐
│ 工具分发器 (Tool Dispatcher) │
│ • 识别工具类型 │
│ • 解析参数 │
└────────────────────┬────────────────────────────┘
↓
┌──────┴──────┐
│ 工具类型? │
└──────┬──────┘
↓
┌────────────┴────────────┐
↓ ↓
┌──────────┐ ┌──────────────┐
│ shell │ │ apply_patch │
└────┬─────┘ └──────┬───────┘
↓ ↓
┌──────────────┐ ┌──────────────┐
│ 分类命令类型 │ │ 解析补丁 │
│ • 读操作 │ │ 格式 │
│ • 写操作 │ └──────┬───────┘
│ • 危险操作 │ ↓
└──────┬───────┘ ┌──────────────┐
↓ │ 生成 diff │
┌──────────────┐ │ 预览 │
│ 审批策略检查 │ └──────┬───────┘
│ │ ↓
│ Suggest: │ ┌──────────────┐
│ 所有需确认 │ │ 审批检查 │
│ │ └──────┬───────┘
│ Auto-Edit: │ ↓
│ 读自动批准 │ ┌──────┴───────┐
│ 写需确认 │ ↓ ↓
│ │ 【需确认】 【自动】
│ Full-Auto: │ ↓ ↓
│ 全自动 │ ┌──────────┐ │
└──────┬───────┘ │ 显示 UI │ │
↓ │ 等待输入 │ │
┌───┴───┐ └────┬─────┘ │
↓ ↓ ↓ ↓
【需确认】【自动】 ┌─────────────────┴──┐
↓ ↓ │ 应用文件更改 │
│ │ │ (fs 操作) │
│ │ └─────────┬──────────┘
↓ ↓ ↓
┌──┴───────┴──┐ ┌──────────────┐
│ 显示确认 UI │ │ 返回结果 │
│ • 命令内容 │ │ 给模型 │
│ • 风险评估 │ └──────────────┘
└──────┬──────┘
↓
┌────┴────┐
│ 用户决定 │
└────┬────┘
↓
┌───┴───┐
↓ ↓
【批准】 【拒绝】
↓ ↓
│ ┌──────┐
│ │返回错误│
│ └──────┘
↓
┌──────────────────┐
│ 在沙箱中执行 │
│ │
│ macOS: │
│ sandbox-exec │
│ │
│ Linux: │
│ Landlock │
│ + seccomp │
└────────┬─────────┘
↓
┌──────────────────┐
│ 捕获输出 │
│ • stdout │
│ • stderr │
│ • exit code │
└────────┬─────────┘
↓
┌──────────────────┐
│ 格式化结果 │
│ 返回给 Agent │
└──────────────────┘
总结
Codex 的核心设计原则
-
简洁性 - 少即是多
- 最小化工具数量
- 简化 System Prompt
- Shell-first 设计哲学
-
安全性 - 纵深防御
- 应用级审批策略
- OS 级沙箱隔离
- 网络访问控制
- 文件系统限制
-
可观测性 - 透明执行
- 流式输出推理过程
- 彩色 diff 预览
- 详细的工具调用日志
-
可扩展性 - 模块化设计
- MCP 协议支持
- 配置驱动行为
- 插件化工具系统
实现建议
如果你想构建类似的 Coding Agent,关键步骤是:
-
从最小 MVP 开始
- 实现基本的 Agent Loop
- 支持 1-2 个核心工具
- 添加简单的沙箱
-
迭代改进
- 优化 System Prompt
- 增强安全机制
- 改善用户体验
-
集成生态
- 支持 MCP 协议
- 连接 IDE/CI/CD
- 构建工具库
-
持续学习
- 研究开源项目(Codex CLI, Claude Code)
- 参考最佳实践
- 收集用户反馈
参考资源
- 官方文档: https://developers.openai.com/codex
- GitHub 仓库: https://github.com/openai/codex
- OpenAI Cookbook: https://cookbook.openai.com
- MCP 协议: https://modelcontextprotocol.io
附录
A. Responses API 详解
Codex 使用 OpenAI 的 Responses API(而非标准的 Chat Completions API):
# Responses API 请求 POST /v1/responses { "model": "gpt-5-codex", "messages": [...], "tools": [...], "stream": true, "previous_response_id": "resp_abc123" # 用于续传 } # 流式响应事件 event: response.output_item.done data: { "type": "reasoning", "content": "I need to read the file first..." } event: response.output_item.done data: { "type": "function_call", "name": "shell", "arguments": "{\"cmd\": [\"cat\", \"main.rs\"]}" }
B. Rust Crate 依赖关系
codex-rs/cli
├── codex-rs/core
│ ├── codex-rs/protocol
│ ├── codex-rs/login
│ ├── codex-rs/config
│ └── codex-rs/sandbox
│ ├── codex-rs/macos-seatbelt
│ └── codex-rs/linux-sandbox
├── codex-rs/tui
└── codex-rs/exec
C. 性能优化点
- 静态链接 - 无运行时依赖
- 零拷贝 - 使用
bytescrate - 异步 I/O - tokio 运行时
- 流式处理 - 增量解析 JSON
- 缓存策略 - 缓存模型列表和配置
文档版本: 1.0
最后更新: 2025-11-12
作者: Claude (基于 OpenAI Codex 公开资料整理)