深入剖析 OpenAI Codex:下一代 AI 编程助手的架构与原理
本文将带你深入了解 OpenAI Codex 的内部架构、设计思路和实现原理。无论你是初学者还是有经验的开发者,都能从中获得对 AI 编程助手的深刻理解。
目录
- 什么是 Codex?
- 整体架构概览
- 核心特性详解
- 底层协议与通信机制
- 记忆系统:如何记住对话
- 上下文工程:智能管理有限的"脑容量"
- 工具系统:让 AI 能够"动手"
- 安全沙箱:给 AI 一个安全的"游乐场"
- MCP 协议:连接外部世界的桥梁
- 执行策略:智能的权限管理
- 如何使用 Codex
- 总结
什么是 Codex?
想象一下,你有一个超级聪明的编程助手,它不仅能理解你的需求,还能直接帮你写代码、运行命令、修改文件。这就是 Codex —— OpenAI 推出的本地 AI 编程代理。
用大白话解释
如果把编程比作做菜:
- 普通的 AI 助手(如 ChatGPT)就像一本菜谱,告诉你怎么做,但你需要自己动手
- Codex 就像一个真正的厨师,不仅告诉你怎么做,还能直接帮你把菜做出来
核心能力
- Codex 能做什么?
- 理解代码:阅读和分析你的项目代码
- 编写代码:自动编写新功能或修复 bug
- 执行命令:运行测试、构建项目、git 操作等
- 修改文件:直接编辑、创建、删除文件
- 搜索信息:在代码库中搜索,甚至进行网络搜索
- 调用外部工具:通过 MCP 协议连接各种外部服务
整体架构概览
Codex 采用了 Monorepo(单一代码仓库) 的组织方式,主要由 Rust 和 TypeScript 两种语言构建。
为什么选择 Rust?
| 特性 | 说明 |
|---|---|
| 性能 | Rust 编译成机器码,运行速度极快 |
| 安全 | 内存安全保证,避免常见的安全漏洞 |
| 并发 | 优秀的异步编程支持,可同时处理多个任务 |
| 跨平台 | 一套代码可编译到 macOS、Linux、Windows |
项目结构图
codex/
├── codex-rs/ # Rust 核心代码(45+ 个模块)
│ ├── core/ # 核心引擎 - AI 的"大脑"
│ ├── tui/ # 终端界面 - 用户交互
│ ├── cli/ # 命令行入口
│ ├── exec/ # 非交互式执行
│ ├── mcp-server/ # MCP 服务器
│ └── ... # 其他支持模块
│
├── sdk/typescript/ # TypeScript SDK(给开发者用的库)
├── shell-tool-mcp/ # Shell 工具 MCP 实现
└── docs/ # 文档
架构分层图
graph TB
subgraph UserInterface["用户接口层"]
CLI["CLI 命令行"]
TUI["TUI 终端界面"]
SDK["TypeScript SDK"]
end
subgraph CoreEngine["核心引擎层"]
Codex["Codex 核心引擎"]
ModelClient["模型客户端"]
ContextMgr["上下文管理器"]
ToolRouter["工具路由器"]
end
subgraph ExecutionLayer["执行层"]
ShellExec["Shell 执行器"]
FileOps["文件操作"]
MCPClient["MCP 客户端"]
WebSearch["网络搜索"]
end
subgraph SecurityLayer["安全层"]
Sandbox["沙箱隔离"]
ExecPolicy["执行策略"]
Approval["审批系统"]
end
CLI --> Codex
TUI --> Codex
SDK --> Codex
Codex --> ModelClient
Codex --> ContextMgr
Codex --> ToolRouter
ToolRouter --> ShellExec
ToolRouter --> FileOps
ToolRouter --> MCPClient
ToolRouter --> WebSearch
ShellExec --> Sandbox
ShellExec --> ExecPolicy
FileOps --> Sandbox
FileOps --> Approval
MCPClient --> Approval
style UserInterface fill:#E3F2FD,stroke:#1976D2
style CoreEngine fill:#E8F5E9,stroke:#388E3C
style ExecutionLayer fill:#FFF3E0,stroke:#F57C00
style SecurityLayer fill:#FCE4EC,stroke:#C2185B
Codex 的架构可以分为四层:
- 用户接口层:你与 Codex 交互的入口(CLI、TUI、SDK)
- 核心引擎层:处理 AI 推理、工具调用、上下文管理
- 执行层:实际执行命令、修改文件、调用外部服务
- 安全层:沙箱隔离、权限控制、执行策略
核心特性详解
1. 多模式交互
Codex 支持三种使用模式:
| 交互式 TUI | 非交互式 Exec | SDK 集成 |
|---|---|---|
| 实时对话界面 | 自动化脚本执行 | 嵌入到你的应用 |
| 适合日常开发 | 适合 CI/CD | 适合构建产品 |
2. 会话管理
每次与 Codex 的对话都是一个"会话"(Session)。Codex 会:
- 记住你们的对话历史
- 保存执行过的命令和结果
- 支持暂停和恢复对话
3. 智能审批
Codex 不会盲目执行所有命令。对于危险操作,它会:
你: 帮我删除所有日志文件
Codex: 我需要执行 `rm -rf ./logs/*`,这会删除所有日志。
[允许执行] [拒绝] [白名单此命令]
底层协议与通信机制
提交队列/事件队列(SQ/EQ)模式
Codex 内部使用了一种高效的异步通信模式:
sequenceDiagram
participant User as 用户/TUI
participant SQ as 提交队列 (SQ)
participant Engine as Codex 核心引擎
participant LLM as 大语言模型
participant Tools as 工具系统
participant EQ as 事件队列 (EQ)
User->>SQ: 提交用户输入
Note over SQ: Op::UserTurn
SQ->>Engine: 异步接收提交
Engine->>LLM: 调用模型 API
LLM-->>Engine: 流式响应
Engine->>EQ: 发送 AgentMessage 事件
EQ-->>User: 实时显示 AI 回复
LLM-->>Engine: 工具调用请求
Engine->>Tools: 执行工具
Engine->>EQ: 发送 ExecApprovalRequest
EQ-->>User: 请求用户批准
User->>SQ: 提交批准决定
SQ->>Engine: 接收批准
Tools-->>Engine: 工具执行结果
Engine->>EQ: 发送 ExecCommandOutput
EQ-->>User: 显示执行结果
Engine->>LLM: 继续推理
LLM-->>Engine: 最终响应
Engine->>EQ: 发送 TurnCompleted
EQ-->>User: 显示完成状态
用大白话解释:
想象一家餐厅:
- 提交队列(SQ) 就像顾客下单的窗口
- Codex 核心引擎 就像厨房
- 事件队列(EQ) 就像出餐窗口
顾客下单后不需要等在窗口,可以去座位上等。厨房做好菜后,通过出餐窗口通知顾客取餐。
核心代码结构
// 简化版的 Codex 核心结构
pub struct Codex {
// 提交队列:接收用户输入
tx_sub: Sender<Submission>,
// 事件队列:发送处理结果
rx_event: Receiver<Event>,
}
事件类型
Codex 定义了丰富的事件类型来描述各种操作:
| 事件类型 | 说明 | 示例 |
|---|---|---|
AgentMessage | AI 的回复 | "我来帮你修复这个 bug" |
ExecCommandOutput | 命令执行结果 | 测试运行的输出 |
PatchApprovalRequest | 请求批准文件修改 | 修改 config.js |
TokenCount | Token 使用统计 | 输入 1000,输出 500 |
记忆系统:如何记住对话
问题:AI 的"健忘症"
大语言模型本身是"无状态"的,每次调用都是全新的开始。就像一个失忆的人,每天早上醒来都不记得昨天发生了什么。
解决方案:持久化历史
Codex 通过多层记忆系统解决这个问题:
graph TB
subgraph ShortTerm["短期记忆 - 上下文管理器"]
CM["ContextManager"]
Items["对话项目列表"]
TokenInfo["Token 统计"]
CM --> Items
CM --> TokenInfo
end
subgraph MediumTerm["中期记忆 - 消息历史"]
History["history.jsonl"]
Entry1["session_id + timestamp + text"]
Entry2["session_id + timestamp + text"]
Entry3["..."]
History --> Entry1
History --> Entry2
History --> Entry3
end
subgraph LongTerm["长期记忆 - 会话持久化"]
Sessions["~/.codex/sessions/"]
Session1["session_abc.json"]
Session2["session_xyz.json"]
Sessions --> Session1
Sessions --> Session2
end
subgraph ProjectMemory["项目记忆 - AGENTS.md"]
AgentsMD["AGENTS.md"]
Rules["项目规范"]
Constraints["约束条件"]
AgentsMD --> Rules
AgentsMD --> Constraints
end
User["用户"] --> CM
CM -->|"保存到"| History
CM -->|"持久化"| Sessions
AgentsMD -->|"加载到"| CM
style ShortTerm fill:#E3F2FD,stroke:#1976D2
style MediumTerm fill:#E8F5E9,stroke:#388E3C
style LongTerm fill:#FFF3E0,stroke:#F57C00
style ProjectMemory fill:#F3E5F5,stroke:#7B1FA2
三层记忆架构
1. 短期记忆:上下文管理器(ContextManager)
pub struct ContextManager {
// 当前对话的所有项目(从旧到新排序)
items: Vec<ResponseItem>,
// Token 使用信息
token_info: Option<TokenUsageInfo>,
}
作用:管理当前对话中的所有消息、工具调用和结果。
2. 中期记忆:消息历史(Message History)
存储位置:~/.codex/history.jsonl
{"session_id": "abc123", "ts": 1699123456, "text": "帮我写一个排序函数"}
{"session_id": "abc123", "ts": 1699123460, "text": "好的,这是冒泡排序的实现..."}
特点:
- 使用 JSONL 格式(每行一个 JSON)
- 原子写入(不会出现写一半的情况)
- 自动管理大小(超过限制会清理旧记录)
3. 长期记忆:会话持久化
存储位置:~/.codex/sessions/
每个会话保存为独立的 JSON 文件,包含完整的对话状态,支持随时恢复。
项目文档记忆:AGENTS.md
Codex 还会读取项目中的 AGENTS.md 文件,了解项目的特殊规则:
# AGENTS.md
## 项目规范
- 使用 TypeScript 编写
- 所有函数必须有注释
- 测试覆盖率要求 80% 以上
## 禁止操作
- 不要修改 .env 文件
- 不要删除 migrations 文件夹
上下文工程:智能管理有限的"脑容量"
问题:上下文窗口的限制
大语言模型有一个"上下文窗口"限制,就像人的工作记忆一样有限。如果对话太长,模型就会"记不住"前面的内容。
┌────────────────────────────────────────────────────────────┐
│ 上下文窗口示意图 │
├────────────────────────────────────────────────────────────┤
│ [系统提示] [用户1] [AI1] [用户2] [AI2] ... [用户N] [AI N] │
│ ←─────────────── 有限的容量 ──────────────────→ │
│ │
│ 超出容量时:旧的内容会被"遗忘" │
└────────────────────────────────────────────────────────────┘
解决方案:智能上下文管理
Codex 采用多种策略来最大化利用有限的上下文:
flowchart TD
Start["开始新的对话轮次"] --> Check{"检查上下文大小"}
Check -->|"< 80% 窗口"| Normal["正常添加内容"]
Check -->|">= 80% 窗口"| Strategy["应用优化策略"]
Strategy --> S1["策略1: Token 估算"]
Strategy --> S2["策略2: 智能截断"]
Strategy --> S3["策略3: 对话压缩"]
Strategy --> S4["策略4: 环境差异"]
S1 --> |"每4字节≈1 token"| Estimate["快速估算大小"]
S2 --> |"保留头尾"| Truncate["删除中间内容"]
S3 --> |"AI 生成摘要"| Compact["压缩历史对话"]
S4 --> |"只发送变化"| Diff["差异化更新"]
Estimate --> Optimize["优化后的上下文"]
Truncate --> Optimize
Compact --> Optimize
Diff --> Optimize
Normal --> Send["发送给模型"]
Optimize --> Send
Send --> Response["获取模型响应"]
Response --> Update["更新 Token 统计"]
Update --> End["完成"]
style Start fill:#4CAF50,color:#fff
style End fill:#4CAF50,color:#fff
style Strategy fill:#FF9800,color:#fff
style Check fill:#2196F3,color:#fff
策略 1:Token 估算
不使用精确的 tokenizer(太慢),而是用简单的启发式算法:
const APPROX_BYTES_PER_TOKEN: usize = 4;
// 估算 token 数量:每 4 个字节约等于 1 个 token
fn approx_token_count(text: &str) -> usize {
(text.len() + 3) / 4 // 向上取整
}
策略 2:智能截断
对于过长的输出,保留头尾,删除中间:
原始输出(10000 字符):
┌─────────────────────────────────────────────────────────────┐
│ [头部 1000 字符] [...中间内容...] [尾部 1000 字符] │
└─────────────────────────────────────────────────────────────┘
截断后(2500 字符):
┌─────────────────────────────────────────────────────────────┐
│ [头部 1000 字符] ... [省略 7500 字符] ... [尾部 1000 字符] │
└─────────────────────────────────────────────────────────────┘
策略 3:对话压缩(Compaction)
当上下文接近满时,Codex 会请求 AI 对之前的对话进行"摘要":
压缩前:
用户: 帮我看看为什么测试失败
AI: 好的,让我运行测试... 测试结果是... 问题在于...
用户: 修复它
AI: 我修改了文件... 现在测试通过了
用户: 还有其他问题吗?
...(很多轮对话)
压缩后:
[摘要] 用户请求修复测试失败问题,经过分析发现是类型错误,
已修改 src/utils.ts 第 42 行,测试现已通过。
策略 4:环境上下文差异
只发送变化的部分,而不是每次都发送完整的环境信息:
<!-- 首次发送完整上下文 -->
<environment_context>
<cwd>/path/to/project</cwd>
<sandbox_mode>workspace-write</sandbox_mode>
<shell>bash</shell>
</environment_context>
<!-- 之后只发送变化 -->
<environment_context_diff>
<cwd>/path/to/project/src</cwd> <!-- 只有工作目录变了 -->
</environment_context_diff>
工具系统:让 AI 能够"动手"
为什么需要工具?
大语言模型本身只能"说",不能"做"。工具系统就是给 AI 装上"手",让它能够:
- 执行 shell 命令
- 读写文件
- 搜索代码
- 调用外部服务
工具架构
graph LR
subgraph AI["AI 模型"]
LLM["大语言模型"]
Decision["决策: 需要使用工具"]
end
subgraph Router["工具路由器"]
Registry["工具注册表"]
Dispatch["分发器"]
end
subgraph Tools["内置工具"]
Shell["Shell 执行器"]
ReadFile["文件读取"]
ApplyPatch["补丁应用"]
GrepFiles["文件搜索"]
ListDir["目录列表"]
ViewImage["图片查看"]
end
subgraph External["外部工具"]
MCP["MCP 工具"]
WebSearch["网络搜索"]
end
subgraph Security["安全检查"]
Policy["执行策略"]
Sandbox["沙箱隔离"]
Approval["用户审批"]
end
LLM --> Decision
Decision --> Registry
Registry --> Dispatch
Dispatch --> Shell
Dispatch --> ReadFile
Dispatch --> ApplyPatch
Dispatch --> GrepFiles
Dispatch --> ListDir
Dispatch --> ViewImage
Dispatch --> MCP
Dispatch --> WebSearch
Shell --> Policy
ApplyPatch --> Approval
MCP --> Approval
Policy --> Sandbox
Approval --> Sandbox
Sandbox --> Result["执行结果"]
Result --> LLM
style AI fill:#E3F2FD,stroke:#1976D2
style Router fill:#E8F5E9,stroke:#388E3C
style Tools fill:#FFF3E0,stroke:#F57C00
style External fill:#F3E5F5,stroke:#7B1FA2
style Security fill:#FCE4EC,stroke:#C2185B
内置工具列表
| 工具名称 | 功能 | 示例 |
|---|---|---|
shell | 执行命令 | npm test, git status |
read_file | 读取文件 | 查看 config.json |
list_dir | 列出目录 | 浏览项目结构 |
apply_patch | 修改文件 | 修复代码 bug |
grep_files | 搜索文件 | 查找函数定义 |
view_image | 查看图片 | 分析截图 |
web_search | 网络搜索 | 查找文档 |
mcp_tool | 调用 MCP 工具 | 使用外部服务 |
工具调用流程
1. AI 决定使用工具
└── "我需要运行测试来验证修复"
2. 生成工具调用
└── { tool: "shell", command: "npm test" }
3. 权限检查
└── 检查执行策略和沙箱规则
4. 执行工具
└── 在沙箱中运行命令
5. 返回结果
└── 将输出返回给 AI
6. AI 继续推理
└── "测试通过了,修复成功!"
工具注册机制
Codex 使用统一的工具注册表来管理所有工具:
pub struct ToolRegistry {
handlers: HashMap<ToolType, Box<dyn ToolHandler>>,
}
pub trait ToolHandler: Send + Sync {
async fn handle(
&self,
invocation: ToolInvocation
) -> Result<ToolOutput, ToolError>;
}
安全沙箱:给 AI 一个安全的"游乐场"
为什么需要沙箱?
让 AI 执行命令是危险的。想象一下:
用户: 帮我清理项目
AI: 好的,我来执行 rm -rf / # 危险!会删除整个系统!
沙箱就是为了防止这种灾难性的操作。
沙箱原理
graph TB
subgraph Request["命令请求"]
Cmd["执行命令: npm test"]
end
subgraph PolicyCheck["策略检查"]
EP["执行策略引擎"]
Decision{"决策"}
end
subgraph SandboxSelect["沙箱选择"]
Platform{"操作系统?"}
MacOS["macOS: Seatbelt"]
Linux["Linux: Landlock + Seccomp"]
Windows["Windows: RestrictedToken"]
end
subgraph Permissions["权限控制"]
FS["文件系统访问"]
Net["网络访问"]
Proc["进程权限"]
end
subgraph Execution["执行环境"]
Isolated["隔离进程"]
Result["执行结果"]
end
Cmd --> EP
EP --> Decision
Decision -->|"allow"| Platform
Decision -->|"prompt"| UserApproval["用户审批"]
Decision -->|"forbidden"| Blocked["拒绝执行"]
UserApproval -->|"批准"| Platform
UserApproval -->|"拒绝"| Blocked
Platform -->|"darwin"| MacOS
Platform -->|"linux"| Linux
Platform -->|"win32"| Windows
MacOS --> FS
Linux --> FS
Windows --> FS
FS --> Net
Net --> Proc
Proc --> Isolated
Isolated --> Result
style Request fill:#E3F2FD,stroke:#1976D2
style PolicyCheck fill:#FFF3E0,stroke:#F57C00
style SandboxSelect fill:#E8F5E9,stroke:#388E3C
style Permissions fill:#FCE4EC,stroke:#C2185B
style Execution fill:#F3E5F5,stroke:#7B1FA2
style Blocked fill:#FFCDD2,stroke:#D32F2F
三种沙箱策略
| 策略 | 文件权限 | 网络权限 | 适用场景 |
|---|---|---|---|
read-only | 只读 | 禁止 | 代码审查 |
workspace-write | 工作区可写 | 可配置 | 日常开发 |
danger-full-access | 完全访问 | 允许 | 特殊场景 |
跨平台沙箱实现
Codex 针对不同操作系统使用不同的沙箱技术:
macOS: Seatbelt
// 生成 SBPL(Seatbelt Profile Language)策略
let profile = format!(r#"
(version 1)
(deny default)
(allow file-read* (subpath "{writable_root}"))
(allow file-write* (subpath "{writable_root}"))
(deny network*)
"#);
Linux: Landlock + Seccomp
// Landlock:限制文件系统访问
let ruleset = Ruleset::new()
.handle_access(AccessFs::ReadFile)?
.create()?;
// Seccomp:阻止危险的系统调用
seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM),
SCMP_SYS(connect), 0)?; // 禁止网络连接
Windows: RestrictedToken
使用 Windows 的受限令牌和 ACL(访问控制列表)来限制权限。
沙箱绕过机制
有时候确实需要执行受限的操作,Codex 提供了安全的升级路径:
1. AI 请求执行需要额外权限的命令
2. 向用户显示权限提升请求
3. 用户确认后,在沙箱外执行
4. 记录操作日志
MCP 协议:连接外部世界的桥梁
什么是 MCP?
MCP(Model Context Protocol) 是一个开放协议,让 AI 助手能够与外部工具和服务交互。可以把它想象成 AI 世界的"USB 接口"。
graph LR
subgraph CodexCore["Codex 核心"]
MCPManager["MCP 连接管理器"]
ToolRouter["工具路由器"]
end
subgraph MCPClients["MCP 客户端连接"]
Client1["RmcpClient #1"]
Client2["RmcpClient #2"]
Client3["RmcpClient #3"]
end
subgraph Transport["传输层"]
Stdio["Stdio 传输"]
HTTP["HTTP 传输"]
OAuth["OAuth 认证"]
end
subgraph MCPServers["MCP 服务器"]
GitHub["GitHub 服务器"]
Slack["Slack 服务器"]
Custom["自定义服务器"]
end
subgraph Protocol["协议层"]
Init["1. 初始化握手"]
ListTools["2. 获取工具列表"]
CallTool["3. 调用工具"]
Result["4. 返回结果"]
end
ToolRouter --> MCPManager
MCPManager --> Client1
MCPManager --> Client2
MCPManager --> Client3
Client1 --> Stdio
Client2 --> HTTP
Client3 --> OAuth
Stdio --> GitHub
HTTP --> Custom
OAuth --> Slack
GitHub --> Init
Init --> ListTools
ListTools --> CallTool
CallTool --> Result
style CodexCore fill:#E3F2FD,stroke:#1976D2
style MCPClients fill:#E8F5E9,stroke:#388E3C
style Transport fill:#FFF3E0,stroke:#F57C00
style MCPServers fill:#F3E5F5,stroke:#7B1FA2
style Protocol fill:#E0F7FA,stroke:#00838F
MCP 的角色
Codex 可以同时作为:
- MCP 客户端:调用其他 MCP 服务器提供的工具
- MCP 服务器:让其他应用调用 Codex 的能力
连接外部服务示例
# ~/.codex/config.toml
[mcp_servers.github]
enabled = true
[mcp_servers.github.transport]
type = "stdio"
command = "npx"
args = ["@modelcontextprotocol/server-github"]
配置后,Codex 就能使用 GitHub 的功能:
用户: 帮我创建一个 issue 报告这个 bug
Codex: 好的,我来调用 GitHub MCP 服务器创建 issue...
[调用 mcp__github__create_issue 工具]
Issue 已创建:https://github.com/xxx/xxx/issues/123
MCP 通信流程
┌─────────────┐ JSON-RPC ┌─────────────┐
│ Codex │ ◄──────────────► │ MCP 服务器 │
│ (客户端) │ over stdio │ (GitHub) │
└─────────────┘ └─────────────┘
1. 初始化握手:交换能力声明
2. 工具列表:获取可用工具
3. 工具调用:执行具体操作
4. 返回结果:获取执行结果
支持的传输方式
| 传输方式 | 适用场景 | 示例 |
|---|---|---|
| stdio | 本地进程 | npx 启动的工具 |
| HTTP | 远程服务 | 云端 API |
| HTTP + OAuth | 需要认证的服务 | GitHub, Slack |
执行策略:智能的权限管理
问题:如何判断命令是否安全?
不是所有命令都同样危险:
ls完全安全npm test通常安全rm -rf /绝对危险git push需要确认
解决方案:执行策略引擎
Codex 使用基于规则的执行策略系统:
flowchart TD
Start["命令: git push origin main"] --> Parse["解析命令 tokens"]
Parse --> Lookup["查找匹配规则"]
subgraph Rules["规则库"]
R1["prefix_rule(['ls'], 'allow')"]
R2["prefix_rule(['git', 'push'], 'prompt')"]
R3["prefix_rule(['rm', '-rf'], 'forbidden')"]
end
Lookup --> R1
Lookup --> R2
Lookup --> R3
R1 --> Match{"匹配检查"}
R2 --> Match
R3 --> Match
Match -->|"匹配 R2"| Collect["收集匹配结果"]
Match -->|"无匹配"| Heuristics["启发式检查"]
Heuristics -->|"安全命令"| AllowH["Decision: Allow"]
Heuristics -->|"危险命令"| PromptH["Decision: Prompt"]
Collect --> MaxDecision["选择最严格决策"]
MaxDecision --> FinalAllow["Allow: 直接执行"]
MaxDecision --> FinalPrompt["Prompt: 请求用户批准"]
MaxDecision --> FinalForbid["Forbidden: 拒绝执行"]
AllowH --> FinalAllow
PromptH --> FinalPrompt
FinalPrompt --> UserChoice{"用户选择"}
UserChoice -->|"批准"| Execute["执行命令"]
UserChoice -->|"白名单"| Whitelist["添加 allow 规则"]
UserChoice -->|"拒绝"| Reject["取消执行"]
Whitelist --> Execute
style Start fill:#2196F3,color:#fff
style FinalAllow fill:#4CAF50,color:#fff
style FinalPrompt fill:#FF9800,color:#fff
style FinalForbid fill:#F44336,color:#fff
style Rules fill:#E8F5E9,stroke:#388E3C
策略文件格式
策略文件使用类 Python 的 Starlark 语言:
# ~/.codex/policy/default.codexpolicy
# 允许常见的安全命令
prefix_rule(
pattern = ["ls"],
decision = "allow",
)
prefix_rule(
pattern = ["cat"],
decision = "allow",
)
# 需要确认的命令
prefix_rule(
pattern = ["git", ["push", "pull", "fetch"]],
decision = "prompt",
)
# 禁止危险命令
prefix_rule(
pattern = ["rm", "-rf"],
decision = "forbidden",
)
决策优先级
当多个规则匹配时,采用最严格的决策:
forbidden(禁止) > prompt(提示) > allow(允许)
内置安全检测
除了显式规则,Codex 还有内置的启发式安全检测:
// 已知的安全命令(27个)
const SAFE_COMMANDS: &[&str] = &[
"cat", "echo", "ls", "pwd", "grep", "head", "tail",
"wc", "sort", "uniq", "diff", "file", "which", "date",
"env", "printenv", "hostname", "uname", "whoami",
// ...
];
// 危险命令检测
fn is_dangerous_command(cmd: &[String]) -> bool {
matches!(cmd,
["rm", "-rf", ..] |
["git", "reset", "--hard", ..] |
["sudo", ..] |
// ...
)
}
动态白名单
当你批准一个命令后,可以选择"白名单此命令",Codex 会自动更新策略文件:
# 自动添加的规则
prefix_rule(pattern=["npm", "test"], decision="allow")
如何使用 Codex
安装方式
# 方式 1:通过 npm 安装
npm install -g @openai/codex
# 方式 2:通过 Homebrew 安装(macOS)
brew install --cask codex
登录认证
# 使用 ChatGPT 账户登录(推荐)
codex login
# 或者使用 API Key
export CODEX_API_KEY=sk-xxx
基本使用
# 启动交互式界面
codex
# 直接执行任务(非交互式)
codex exec "帮我写一个快速排序函数"
# 在特定目录工作
codex --cd /path/to/project
TypeScript SDK 使用
import { Codex } from "@openai/codex-sdk";
const codex = new Codex();
const thread = codex.startThread({
model: "gpt-4",
sandboxMode: "workspace-write",
workingDirectory: "./my-project"
});
// 同步模式:等待完成
const turn = await thread.run("帮我修复所有的 TypeScript 错误");
console.log(turn.finalResponse);
// 流式模式:实时获取事件
const { events } = await thread.runStreamed("运行测试");
for await (const event of events) {
if (event.type === "item.completed") {
console.log("完成:", event.item);
}
}
配置文件
# ~/.codex/config.toml
# 默认模型
model = "gpt-4-turbo"
# 沙箱策略
sandbox_policy = "workspace-write"
# 审批策略
approval_policy = "on-request"
# MCP 服务器配置
[mcp_servers.github]
enabled = true
[mcp_servers.github.transport]
type = "stdio"
command = "npx"
args = ["@modelcontextprotocol/server-github"]
总结
Codex 的设计哲学
- 安全第一:多层沙箱、执行策略、用户审批
- 可扩展性:工具系统、MCP 协议、插件架构
- 智能管理:上下文压缩、记忆持久化、Token 优化
- 用户体验:交互式界面、流式输出、断点续传
技术亮点
| 特性 | 技术实现 | 优势 |
|---|---|---|
| 性能 | Rust 核心 | 接近原生速度 |
| 安全 | 多平台沙箱 | 系统级隔离 |
| 扩展 | MCP 协议 | 开放生态 |
| 智能 | 上下文工程 | 高效利用模型能力 |
| 体验 | SQ/EQ 异步模式 | 流畅的交互 |
未来展望
Codex 代表了 AI 编程助手的一个重要方向:从"建议"走向"执行",从"对话"走向"协作"。随着 AI 能力的提升和工具生态的完善,我们可以期待更加智能、安全、高效的编程助手。
附录:关键文件路径速查
| 组件 | 路径 |
|---|---|
| 核心引擎 | codex-rs/core/src/codex.rs |
| TUI 界面 | codex-rs/tui/src/app.rs |
| 工具系统 | codex-rs/core/src/tools/ |
| 沙箱实现 | codex-rs/core/src/sandboxing/ |
| 执行策略 | codex-rs/execpolicy/src/ |
| MCP 客户端 | codex-rs/rmcp-client/src/ |
| 上下文管理 | codex-rs/core/src/context_manager/ |
| 记忆系统 | codex-rs/core/src/message_history.rs |
| TypeScript SDK | sdk/typescript/src/ |
- 作者【前端领秀】一个喜欢探索前端领域AI赋能的开发者,喜欢我的可以关注我,私信我邀请进入技术群,我会时刻分享最新前沿AI技术;