在前面的十三篇文章中,我们从使用者的视角理解了 Codex 的方方面面------CLI、桌面应用、IDE 插件、SDK、插件、MCP、CI/CD、批量任务。但如果你想知道 Codex 的 Agent Loop 到底是怎么实现的、为什么它能高效处理复杂任务、它的状态持久化机制是怎样的,就需要深入源码。Codex 的官方仓库是一个用 Rust 构建的大型工程------137 个 crate 构成的智能体架构。 本文从整体架构讲起,逐层拆解七层架构的设计,深入剖析 Session/Turn/Step 三级模型的实现,帮你理解在 Rust 中构建 AI 智能体的工程方法论。
一、为什么用 Rust 构建 Codex CLI?
Codex CLI 用 Rust 实现,而非 Python 或 TypeScript。这个选择背后有明确的工程考量:
性能:CLI 需要快速启动(毫秒级),Rust 的零成本抽象和静态编译让启动时间远优于 Python。
内存安全:AI 智能体需要处理来自不可信来源的数据(模型输出、工具返回结果),Rust 的所有权系统在编译期消灭了内存安全问题。
并发安全:Codex 需要同时管理多个工具调用、多个会话状态,Rust 的 Send/Sync 在编译期保证了并发安全。
单二进制分发:Rust 编译为单个静态二进制文件,用户无需安装运行时依赖,npm install 即可使用。
二、七层架构全景
Codex 的源码架构可以拆解为七层,从上到下依次为:

2.1 入口层:codex-cli
codex-cli 是用户交互的入口,负责:
解析命令行参数(codex、codex exec、codex mcp 等子命令)。
加载配置文件(config.toml、AGENTS.md)。
初始化认证(ChatGPT OAuth 或 API Key)。
启动会话核心。
rust
// 简化的入口逻辑
fn main() {
let args = Cli::parse();
match args.command {
Command::Interactive => run_interactive(args),
Command::Exec { prompt, sandbox } => run_exec(prompt, sandbox),
Command::Mcp { action } => run_mcp(action),
}
}
2.2 会话核心层:codex-core
codex-core 是 Codex 的"大脑",实现了 Agent Loop、Turn 管理和状态机。
核心结构:
rust
pub struct Session {
id: SessionId,
turns: Vec<Turn>,
state: SessionState,
config: SessionConfig,
}
pub struct Turn {
id: TurnId,
steps: Vec<Step>,
status: TurnStatus,
}
pub struct Step {
id: StepId,
tool_call: Option<ToolCall>,
model_response: Option<ModelResponse>,
}
Agent Loop 的实现:
rust
impl Session {
pub async fn run_turn(&mut self, user_input: String) -> Result<TurnResult> {
let mut turn = Turn::new();
let mut prompt = self.build_prompt(&user_input);
loop {
// 1. 查询模型
let response = self.client.query(&prompt).await?;
// 2. 判断是否有工具调用
match response.tool_call {
Some(tool_call) => {
// 3. 执行工具
let tool_result = self.execute_tool(tool_call).await?;
// 4. 将工具输出追加到提示词
prompt = self.append_tool_result(prompt, tool_result);
turn.add_step(Step::tool_call(tool_call, tool_result));
}
None => {
// 5. 没有工具调用,返回最终响应
turn.complete(response.text);
break;
}
}
}
self.turns.push(turn);
Ok(turn.into_result())
}
}
2.3 协议层:codex-protocol
codex-protocol 定义了 Codex 与模型、工具之间的通信协议。
核心 trait:
rust
#[async_trait]
pub trait Tool {
fn name(&self) -> &str;
fn description(&self) -> &str;
fn schema(&self) -> serde_json::Value;
async fn execute(&self, input: serde_json::Value) -> Result<ToolOutput>;
}
工具路由:
rust
pub struct ToolRouter {
registry: ToolRegistry,
parallel_tools: HashSet<String>,
}
impl ToolRouter {
pub async fn route(&self, call: ToolCall) -> Result<ToolOutput> {
let tool = self.registry.get(&call.name)?;
tool.execute(call.input).await
}
}
2.4 客户端层:codex-client
codex-client 负责与 OpenAI API(或自定义 Provider)通信。
rust
pub struct Client {
base_url: String,
auth: Auth,
http: reqwest::Client,
}
impl Client {
pub async fn query(&self, prompt: &Prompt) -> Result<ModelResponse> {
let request = self.build_request(prompt);
let response = self.http.post(&self.base_url)
.bearer_auth(self.auth.token())
.json(&request)
.send()
.await?;
self.parse_response(response).await
}
}
2.5 沙盒执行层:codex-sandbox
codex-sandbox 负责安全执行命令和文件操作。它使用平台特定的隔离技术:
rust
pub trait Sandbox {
fn execute(&self, command: &Command) -> Result<CommandOutput>;
fn read_file(&self, path: &Path) -> Result<String>;
fn write_file(&self, path: &Path, content: &str) -> Result<()>;
}
// Linux 实现:Landlock + seccomp
pub struct LinuxSandbox { /* ... */ }
// macOS 实现:Seatbelt
pub struct MacOSSandbox { /* ... */ }
// Windows 实现:受限令牌
pub struct WindowsSandbox { /* ... */ }
2.6 状态持久化层:codex-state
codex-state 负责会话状态的保存和恢复。Codex 使用 Rollout 机制持久化会话:
rust
pub struct Rollout {
session_id: SessionId,
turns: Vec<TurnRecord>,
metadata: RolloutMetadata,
}
impl Rollout {
pub fn save(&self, path: &Path) -> Result<()> { /* ... */ }
pub fn load(path: &Path) -> Result<Self> { /* ... */ }
}
Rollout 的价值:当你中断一个会话后重新打开,Codex 可以从 Rollout 恢复完整的对话历史,继续之前的任务。
2.7 基础设施层:codex-common
codex-common 提供日志、遥测和配置管理:
rust
pub struct Telemetry {
session_id: SessionId,
turn_id: TurnId,
events: Vec<TelemetryEvent>,
}
impl Telemetry {
pub fn record_turn_start(&mut self, turn: &Turn) { /* ... */ }
pub fn record_tool_call(&mut self, call: &ToolCall) { /* ... */ }
pub fn record_turn_end(&mut self, turn: &Turn) { /* ... */ }
}
三、Session / Turn / Step 三级模型的源码实现
三级交互模型是 Codex 状态管理的核心。
3.1 Session:完整会话
rust
pub struct Session {
id: SessionId,
turns: Vec<Turn>,
status: SessionStatus,
config: SessionConfig,
rollout: Option<Rollout>,
}
impl Session {
pub fn new(config: SessionConfig) -> Self { /* ... */ }
pub async fn run_turn(&mut self, input: String) -> Result<TurnResult> { /* ... */ }
pub fn save_rollout(&self) -> Result<()> { /* ... */ }
}
3.2 Turn:用户视角的一轮交互
rust
pub struct Turn {
id: TurnId,
user_input: String,
steps: Vec<Step>,
status: TurnStatus,
started_at: Instant,
completed_at: Option<Instant>,
}
pub enum TurnStatus {
Running,
Completed,
Failed(String),
Aborted,
}
3.3 Step:系统内部的一次推理-工具循环
rust
pub struct Step {
id: StepId,
model_input: Prompt,
model_output: ModelResponse,
tool_call: Option<ToolCall>,
tool_output: Option<ToolOutput>,
}
pub enum StepResult {
ToolCall(ToolCall),
FinalResponse(String),
}
四、从源码中学到的设计模式
4.1 命令模式:工具调用的统一抽象
Codex 将所有工具调用统一为 ToolCall 结构:
rust
pub struct ToolCall {
pub id: String,
pub name: String,
pub input: serde_json::Value,
}
无论是 Shell 命令、文件读写还是 MCP 工具,都通过相同的 ToolCall 结构表达。这让 Agent Loop 无需关心具体工具的实现细节。
4.2 状态机模式:Turn 的生命周期
Turn 的状态转换是一个明确的状态机:
text
Pending → Running → Completed
↓
Failed / Aborted
每个状态转换都有明确的条件和副作用,避免了状态混乱。
4.3 观察者模式:事件流
Codex 通过事件流将执行进度实时推送给客户端:
rust
pub enum Event {
TurnStarted { turn_id: TurnId },
ToolCallStarted { call: ToolCall },
ToolCallCompleted { call: ToolCall, output: ToolOutput },
TurnCompleted { turn_id: TurnId, result: TurnResult },
}
SDK 的 runStreamed() 就是通过订阅这个事件流实现的。
五、七层架构的协作流程
将以上各层串联起来,一次完整的 Codex 任务执行流程如下:
text
-
入口层:用户执行
codex "修复 bug" -
入口层:解析参数,加载配置,初始化认证
-
会话核心层:创建 Session,开始 Turn
-
会话核心层:构建提示词(系统指令 + 上下文 + 用户输入)
-
客户端层:发送请求到 OpenAI API
-
会话核心层:接收模型响应,发现工具调用请求
-
协议层:将工具调用路由到对应工具
-
沙盒执行层:在沙盒中执行工具(读取文件、运行命令)
-
会话核心层:将工具输出追加到提示词
-
客户端层:重新查询模型
-
重复 6-10 直到模型返回最终响应
-
状态持久化层:保存 Rollout
-
基础设施层:记录遥测事件
-
入口层:返回结果给用户
六、对构建 AI 智能体的启示
从 Codex 的源码中,我们可以提炼出构建 AI 智能体的通用设计原则:
-
分层解耦:将 Agent Loop、工具执行、状态管理、通信协议分离,每层只关心自己的职责。
-
统一抽象:用 ToolCall 统一所有工具调用,用 Event 统一所有进度通知。
-
状态持久化:Rollout 机制让会话可以中断和恢复,这对于长时间运行的任务至关重要。
-
安全隔离:沙盒层是独立的一层,不是散落在各处的安全检查。
-
可观测性:遥测事件贯穿整个执行流程,便于调试和优化。
-
类型安全:用 Rust 的类型系统表达状态转换,编译期消灭状态错误。
七、小结
为什么用 Rust:性能、内存安全、并发安全、单二进制分发。
七层架构:入口层 → 会话核心层 → 协议层 → 客户端层 → 沙盒执行层 → 状态持久化层 → 基础设施层。
Session / Turn / Step:三级交互模型的源码实现。
设计模式:命令模式(ToolCall)、状态机模式(Turn 生命周期)、观察者模式(事件流)。
协作流程:从用户输入到最终响应的完整链路。
通用原则:分层解耦、统一抽象、状态持久化、安全隔离、可观测性、类型安全。