如果你第一次打开codex-main这个源码目录,很容易被它的规模吓住:顶层有 npm 包、Rust workspace、SDK、app-server、MCP、插件、技能、沙箱、TUI、云任务、线程存储、模型提供商、登录认证等大量模块。它不像一个传统命令行工具,也不像一个简单的 ChatGPT 包装器。更准确地说,Codex CLI 是一个“本地运行的智能软件工程袋里”:它能理解用户目标,读取项目上下文,调用模型推理,决定是否执行命令或修改文件,把工具结果回传给模型,再持续推进任务直到给出最终结果。

本文基于当前工作区的codex-main源码目录进行分析,目标是让初学者也能看懂 Codex 的基本原理,同时给有工程背景的读者足够的架构细节。文章会围绕四个问题展开:
第一,Codex 到底是什么?它和普通命令行工具、普通聊天机器人有什么区别?
第二,Codex 的源码是如何组织的?哪些 crate 或目录承担核心职责?
第三,Codex 的核心执行原理是什么?从用户输入一条需求,到模型调用 shell、修改文件、读取 MCP 资源、输出最终答案,中间经过了哪些关键步骤?
第四,从工程实践角度看,我们可以怎样使用 Codex、扩展 Codex,或者从它的架构中学习如何设计自己的 AI Agent?
先给出一句通俗但准确的定义:
Codex 是一个以 Rust 为核心实现的本地软件工程 Agent 运行时,它通过协议层连接 UI、CLI、App Server 和无交互执行入口,通过 core 会话循环连接模型和工具,通过沙箱、审批、配置、MCP、技能、插件等机制把“模型会想”变成“系统能安全地做事”。
从源码看,Codex 并不是把用户问题直接发给模型,然后打印模型回答这么简单。它更像一个小型操作系统,里面有输入队列、事件队列、会话状态、权限系统、工具注册表、上下文管理器、模型客户端、执行沙箱、插件系统和持久化存储。模型只是决策核心之一,真正把 Agent 做成产品的是围绕模型的一整套工程系统。
为了帮助初学者建立直觉,我们先用一个简化流程表示 Codex 的工作方式:
普通回复
工具调用
用户输入任务
CLI/TUI/App Server 接收请求
加载配置、权限、AGENTS.md、技能和插件
构建模型可见上下文
向模型发起 Responses API 请求
模型输出什么
记录消息并展示给用户
ToolRouter 匹配工具
审批与沙箱检查
执行 shell、apply_patch、MCP、web、子袋里等工具
工具结果写回会话历史
结束当前 turn
这个循环是理解 Codex 的关键。传统 CLI 往往是“一条命令 -> 一个结果”,聊天机器人往往是“一段上下文 -> 一段文本”。Codex 则是“一段目标 -> 多轮推理 -> 多次工具调用 -> 状态更新 -> 最终交付”。它的源码复杂度主要来自三个方面:
exec、IDE/桌面 App、MCP Server、Cloud 任务等,所以需要稳定协议和分层架构。接下来进入源码层面的系统拆解。
简要介绍:codex-main是一个多语言单仓库,外层 npm 包负责分发和启动,核心能力集中在codex-rsRust workspace。最重要的主线是:codex-cli/bin/codex.js找到对应平台的原生二进制,Rustcli解析命令,tui或exec或app-server建立会话,core运行 Agent 主循环,protocol定义客户端与 Agent 之间的操作和事件,tools负责把模型输出映射成真实工具调用,sandboxing和权限系统负责限制风险。
很多初学者第一次理解 AI 编程工具时,会把它想成:
用户:帮我修 bug
程序:把问题发给模型
模型:返回一段代码
程序:显示代码
这只是最早期的代码助手形态。Codex 源码展示的是更成熟的 Agent 形态:
用户:帮我修 bug
Codex:读取项目规则
搜索相关文件
运行测试
分析失败
修改代码
再运行测试
汇总结论
这个过程中,模型需要不断“看见”外部世界。它不能只凭训练记忆回答,因为当前项目的代码、测试失败、用户本地环境、未提交变更、配置文件和工具输出都在实时变化。Codex 的核心价值就在于把这些外部信息纳入一个受控循环。
在codex-rs/core/src/session/turn.rs中,源码对run_turn的注释已经把核心机制讲得很清楚:每一次 sampling request,模型可能返回函数调用,也可能返回助手消息。如果返回工具调用,Codex 执行工具并把工具输出作为下一次请求的输入;如果返回普通助手消息,就记录进历史并认为当前 turn 完成。
也就是说,Codex 的“智能”不只是模型能力,还包括它周围的运行时能力:
ResponseInputItem。如果我们把 Codex 当成一个系统来观察,可以把它拆成五层:
用户入口层:CLI / TUI / exec / App Server / MCP Server
协议层:Op / Event / Thread / Turn
核心层:Session / Turn / Context / ModelClient
工具层:ToolRouter / ToolRegistry / ToolRuntime
执行与安全层:sandbox / approval / permission profile
模型与外部服务:OpenAI Responses API / WebSocket / HTTP / MCP
其中最重要的源码目录如下:
codex-main/├── README.md # 项目入口说明,介绍安装方式和产品形态├── codex-cli/│ └── bin/codex.js# npm 包入口,定位并启动平台原生二进制├── codex-rs/│ ├── Cargo.toml# Rust workspace,列出大量内部 crate│ ├── cli/# 顶层命令行解析与子命令分发│ ├── tui/# 交互式终端 UI│ ├── exec/ # 非交互执行入口,适合脚本和 CI│ ├── core/ # Agent 核心:会话、turn、工具、上下文、模型调用│ ├── protocol/ # 核心协议类型:Op、Event、SandboxPolicy 等│ ├── app-server/ # App/IDE 等宿主形态可复用的服务端│ ├── app-server-protocol/# App Server v1/v2 JSON-RPC 协议│ ├── codex-api/# OpenAI API / Responses API 访问层│ ├── codex-client/ # HTTP/SSE/WebSocket 客户端基础能力│ ├── model-provider/ # 模型提供商抽象│ ├── mcp-server/、codex-mcp/ # MCP 相关能力│ ├── core-skills/、skills/ # 技能加载与注入│ ├── core-plugins/、plugin/# 插件 manifest、市场和本地插件│ ├── sandboxing/ # 跨平台沙箱抽象│ ├── linux-sandbox/# Linux Landlock / bubblewrap 支持│ ├── windows-sandbox-rs/ # Windows 受限 token、ACL、WFP 等│ ├── thread-store/ # 线程持久化抽象│ ├── rollout/、rollout-trace/# 会话记录、回放和调试│ └── tools/# 工具规范和共享工具定义└── sdk/├── python/ # Python SDK└── typescript/ # TypeScript SDK
从这个目录可以看出,Codex 的核心不是某一个巨大文件,而是一组职责明确的 crate。core是大脑和调度中心,但它并不直接承担所有事情:协议在protocol,UI 在tui,无交互运行在exec,App 集成在app-server,沙箱在sandboxing,插件和技能也拆成独立模块。
这正是大型 Agent 工程的第一条经验:不要把“模型调用、工具实现、UI 展示、权限控制、配置读取、状态存储”塞进一个文件。它们变化频率不同,风险边界不同,测试方式也不同。
Codex 可以通过npm install -g @openai/codex、Homebrew 或安装脚本安装。源码中的codex-cli/package.json定义了 npm 包名和可执行入口:
{"name": "@openai/codex","bin": {"codex": "bin/codex.js"},"type": "module"}
但codex.js并不实现 Agent 本身。它做的是平台适配:根据process.platform和process.arch判断目标三元组,例如 macOS arm64 对应aarch64-apple-darwin,Linux x64 对应x86_64-unknown-linux-musl,Windows x64 对应x86_64-pc-windows-msvc。然后它到对应平台包的vendor/<target>/bin/codex下寻找真正的原生二进制,最后用spawn把参数原样转发过去。
简化版代码可以这样理解:
// 简化示例:根据平台选择原生 Codex 二进制const targetMap = {"darwin-arm64": "aarch64-apple-darwin","darwin-x64": "x86_64-apple-darwin","linux-x64": "x86_64-unknown-linux-musl","win32-x64": "x86_64-pc-windows-msvc",};const key = `${process.platform}-${process.arch}`;const targetTriple = targetMap[key];// 真实源码会处理更多平台、包管理器提示和信号转发const binaryPath = `vendor/${targetTriple}/bin/codex`;// 关键逻辑:Node 只负责启动,Agent 主体在 Rust 二进制里spawn(binaryPath, process.argv.slice(2), {stdio: "inherit",env: process.env,});
这个设计有几个好处:
初学者可以把codex-cli/bin/codex.js理解为“门卫”,它不负责推理,只负责把你带到真正的入口。
进入 Rust 之后,codex-rs/cli/src/main.rs使用clap定义了顶层命令。源码里的Subcommand很能说明 Codex 的产品边界:
Exec:非交互运行 Codex。Review:无交互代码审查。Login/Logout:认证管理。Mcp:管理外部 MCP server。Plugin:管理 Codex 插件。McpServer:把 Codex 作为 MCP server 运行。AppServer:运行 app server 或相关工具。App:启动桌面 App。Doctor:诊断本地安装、配置、认证和运行环境。Sandbox:在 Codex 提供的沙箱里运行命令。Resume/Fork/Archive/Delete/Unarchive:会话管理。Cloud:浏览 Codex Cloud 任务并应用变更。这说明 Codex CLI 不是单一命令,而是一个多入口工具箱。默认不带子命令时进入交互式 TUI;带exec时进入无交互模式;带mcp-server时变成 MCP 服务;带app-server时面向桌面或 IDE 宿主。
codex-rs/Cargo.toml是理解源码组织的关键。它的 workspace members 非常多,包括core、protocol、tui、exec、app-server、codex-api、codex-mcp、sandboxing、thread-store、core-skills、core-plugins、model-provider等。
初学者可能会问:为什么不用一个 crate?原因很实际。
第一,Codex 是多宿主系统。TUI、exec、App Server 和 MCP Server 都需要复用同一个核心 Agent,但它们的输入输出完全不同。把协议、核心、UI、无交互处理拆开,才能让同一个 core 服务多种入口。
第二,Codex 是安全敏感系统。执行 shell、修改文件、联网、读取本地资源都需要被严格约束。沙箱和权限逻辑必须独立、可测试、可复用,不能和 UI 代码混在一起。
第三,Codex 是可扩展系统。MCP、插件、技能、动态工具、子袋里都属于扩展点。扩展点如果散落在主循环里,会让系统越来越难维护。
第四,Codex 需要跨平台。macOS 有 Seatbelt,Linux 有 Landlock/bubblewrap,Windows 有受限 token、ACL、WFP 等机制。跨平台安全抽象需要独立模块承载。
源码中的AGENTS.md也明确提醒贡献者:“resist adding code to codex-core”。这句话很重要。codex-core已经很大,团队希望新功能优先放到更合适的 crate,而不是继续膨胀核心 crate。这是大型 Rust 项目常见的工程约束:核心越大,编译越慢,依赖越乱,测试越难,评审风险越高。
我们可以把核心 crate 职责概括如下:
入口层:cli/ 解析命令,分发到 TUI、exec、登录、插件、MCP 等功能tui/ 交互式终端体验exec/非交互模式,保证 stdout/stderr 语义清晰app-server/给桌面、IDE、远程控制等提供服务端能力协议层:protocol/Codex 内部 Op/Event/权限/配置/用户输入等类型app-server-protocol/ App Server JSON-RPC 协议和 v2 API核心层:core/Session、Turn、上下文、工具调度、模型请求、审批thread-store/会话持久化抽象rollout/ 本地记录和恢复工具与扩展层:tools/ 工具名称、规范和共享结构core-skills/ 技能发现、加载、渲染、注入core-plugins/插件 manifest、市场和安装状态codex-mcp/ MCP server 配置、工具暴露和连接执行与安全层:sandboxing/跨平台沙箱选择和命令转换linux-sandbox/ Linux 沙箱实现windows-sandbox-rs/ Windows 沙箱实现shell-command/ shell 命令解析与安全判断execpolicy/执行策略检查模型与服务层:codex-api/ Responses API、SSE、WebSocket、Realtime 等端点封装codex-client/HTTP 传输、重试、错误等基础客户端model-provider/模型提供商抽象login/ ChatGPT/API key/令牌等认证
如果你想快速入门源码,不建议从core/src/session/turn.rs第一行开始硬啃。更好的阅读顺序是:
README.md,理解产品形态。codex-cli/bin/codex.js,理解 npm 入口只负责启动原生二进制。codex-rs/cli/src/main.rs,理解顶层子命令。codex-rs/protocol/src/protocol.rs,理解Op和EventMsg。codex-rs/core/src/session/turn.rs的run_turn注释和主循环。codex-rs/core/src/tools/spec_plan.rs和router.rs,理解工具如何注册与分发。codex-rs/core/src/exec.rs、safety.rs、sandboxing/src/lib.rs,理解执行安全。codex-rs/protocol/src/protocol.rs的文件注释写明:它定义了 Codex session 中客户端与 Agent 之间的协议,采用 Submission Queue / Event Queue 模式进行异步通信。
这个设计非常关键。Codex 不是同步函数调用:
answer = codex.ask(prompt)
而是更接近:
客户端提交 Op
Agent 异步处理
Agent 不断发出 Event
客户端根据 Event 更新 UI
Submission结构包含:
id:用于关联提交和事件。op:实际操作,例如用户输入、取消、配置更新等。client_user_message_id:客户端侧用户消息 id。trace:W3C trace 上下文,用于跨异步任务追踪。Op是“客户端要 Agent 做什么”,EventMsg是“Agent 告诉客户端发生了什么”。这种设计有两个直接好处:
第一,UI 可以实时展示状态。模型推理、工具执行、shell 输出、补丁应用、审批请求、错误信息都可以变成事件流,而不是等所有事情结束才一次性返回。
第二,多入口可以复用同一套事件。TUI 可以把事件渲染成终端界面;exec --json可以输出 JSONL;App Server 可以把事件转成 JSON-RPC 通知;测试可以捕获事件做断言。
可以用下面的简化类型帮助理解:
// 简化示例:真实源码里的类型更丰富enum Op {UserTurn { input: Vec<UserInput> },Interrupt,ConfigureSession,}enum EventMsg {SessionConfigured,TurnStarted,AgentMessageDelta,ExecCommandBegin,ExecCommandOutputDelta,ApplyPatchApprovalRequest,TurnCompleted,Error,}
对于初学者来说,只要记住一点:Codex 的 UI 不直接驱动模型细节,它通过协议提交请求并消费事件。协议层是 Codex 多端复用的基础。
Codex 源码中逐渐用Thread替代早期的Conversation命名。一个 thread 可以理解为一次长期任务会话,里面包含多个 turn;每个 turn 是一次用户输入或自动推进触发的模型执行周期。
在codex-rs/core/src/codex_thread.rs中,CodexThread是对底层Codexsession 的封装。它提供了:
submit:提交Op。shutdown_and_wait:关闭会话。steer_input:向运行中的 turn 注入用户输入。inject_if_running:向当前活跃 turn 注入模型可见项目。try_start_turn_if_idle:在线程空闲时启动自动 turn。set_thread_memory_mode:设置线程是否适合后续记忆生成。ThreadConfigSnapshot则保存当前线程配置快照,包括:
这说明 Codex 的 thread 不是“聊天记录”这么简单,它携带运行时配置、权限、工作目录、模型选择、协作模式和来源信息。这样的设计让 resume、fork、App Server、多袋里协作成为可能。
再看codex-rs/core/src/session/session.rs,Session保存当前 Agent 运行上下文:
thread_id:线程 id。tx_event:向客户端发送事件。agent_status:Agent 状态。conversation:实时会话管理。active_turn:当前活跃 turn。input_queue:用户输入队列。guardian_review_session:审查/审批相关会话。services:模型客户端、MCP、插件、analytics、扩展等服务集合。SessionConfiguration则保存运行配置,例如 provider、collaboration mode、developer instructions、加载到的 AGENTS.md、base instructions、approval policy、permission profile、workspace roots、codex home、session source、dynamic tools 等。
从这些结构可以看出 Codex 的状态模型:
Thread 长期会话
Session 运行上下文
Turn 1
Turn 2
Turn N
历史与 rollout
配置快照
模型/MCP/插件/技能/状态服务
这种分层能解决一个实际问题:用户可能在一个任务里连续输入多次,也可能中断、恢复、fork,甚至让子袋里执行子任务。如果没有清晰的 Thread/Session/Turn 边界,状态很快会乱。
run_turn:Codex 的核心循环codex-rs/core/src/session/turn.rs是整套系统最核心的文件之一。它的run_turn做了很多事情,但可以拆成以下阶段:
第一阶段,准备模型客户端 session。ModelClientSession是 turn 级别的对象,用于缓存 WebSocket 连接、sticky routing token 和前一次请求信息。源码注释强调:每个 turn 都要创建新的ModelClientSession,不能跨 turn 复用,否则会把上一个 turn 的 sticky routing token 带到下一个 turn。
第二阶段,必要时执行 pre-sampling compact。上下文窗口有限,如果历史太长,Codex 会在采样前进行压缩,避免请求超过模型上下文限制。
第三阶段,记录上下文更新。Codex 会把当前工作目录、AGENTS.md、技能、插件、工具说明、用户输入等组织成模型可见内容。
第四阶段,构建技能和插件注入。build_skills_and_plugins会根据用户显式提及、配置、可用技能、插件和连接器,决定哪些内容注入模型上下文。
第五阶段,运行 hooks 并记录输入。Codex 支持生命周期 hooks,例如 session start、pre tool use、post tool use、turn stop 等。这些 hook 可以为企业治理、日志、审批和上下文增强提供入口。
第六阶段,进入 loop。每轮循环会:
run_sampling_request。把这个主循环写成伪代码,大概是:
// 简化示例:用中文注释解释 Codex turn 的核心思想async fn run_turn(input: Vec<TurnInput>) -> Result<Option<String>> {// 1. 为当前 turn 创建模型会话,缓存本 turn 内的连接和路由状态let mut client_session = model_client.new_session();// 2. 如果上下文太长,先压缩历史,避免超过上下文窗口run_pre_sampling_compact_if_needed().await?;// 3. 注入 AGENTS.md、技能、插件、环境信息和用户输入record_context_and_inputs(input).await?;loop {// 4. 把会话历史转换成模型请求let request_input = history.for_prompt();// 5. 向模型发请求,模型可能返回文本,也可能返回工具调用let output = run_sampling_request(&mut client_session, request_input).await?;// 6. 如果模型请求工具,执行工具并把结果写回历史if output.needs_tool_follow_up {execute_tools_and_record_outputs(output.tool_calls).await?;continue;}// 7. 如果期间用户又输入了内容,继续循环处理if has_pending_input().await {continue;}// 8. 没有后续工作,当前 turn 结束return Ok(output.last_agent_message);}}
这个循环体现了 Agent 与普通 LLM 应用的根本差异:模型不是一次性给答案,而是在“模型 -> 工具 -> 模型 -> 工具”的闭环里逐步完成任务。
需要
不需要
模型推理
需要工具吗
调用工具
工具返回结果
输出最终回复
codex-rs/core/src/client.rs是 Codex 与模型提供商通信的重要封装。文件开头的注释非常有价值,它说明了几个设计点:
ModelClient是 session 级别对象,保存稳定配置和状态,例如认证、provider 选择、conversation id、传输 fallback 状态。ModelClientSession是 turn 级别对象,用于在一个 turn 内复用 Responses WebSocket 连接。源码里能看到一系列请求头和端点常量,例如:
X_CODEX_INSTALLATION_ID_HEADERX_CODEX_TURN_STATE_HEADERX_CODEX_TURN_METADATA_HEADERX_CODEX_PARENT_THREAD_ID_HEADERRESPONSES_ENDPOINT = "/responses"RESPONSES_COMPACT_ENDPOINT = "/responses/compact"这说明 Codex 不是简单地把 prompt 发给模型。它还维护安装 id、turn metadata、窗口 id、父线程 id、sticky routing 状态等工程信息。这些信息用于服务端路由、调试、指标、压缩、子袋里关联和稳定性保障。
对初学者来说,可以这样理解:
Responses APIModelClientSessioncodex-coreResponses APIModelClientSessioncodex-core创建 turn 级会话可选 WebSocket prewarmstream(request_input, tools, metadata)/responses 或 WebSocket 请求SSE/WebSocket 事件流ResponseEvent解析文本、推理、工具调用
这种设计让 Codex 可以在交互式体验中边生成边展示,也可以在无交互模式中输出结构化 JSONL。
Agent 的关键能力不是会聊天,而是能安全地调用工具。Codex 的工具系统主要由几个文件构成:
codex-rs/core/src/tools/spec_plan.rs:决定当前 turn 暴露哪些工具。codex-rs/core/src/tools/router.rs:把模型输出转换成ToolCall并分发。codex-rs/core/src/tools/registry.rs:工具运行时接口、hook、telemetry 和输出转换。codex-rs/core/src/tools/parallel.rs:控制工具并行执行、取消和失败响应。codex-rs/core/src/tools/handlers/:内置工具 handler。handlers目录列出了 Codex 的很多内置工具能力:
shell/unified_exec:执行 shell 命令。apply_patch:应用补丁。mcp:调用 MCP 工具。mcp_resource:列出和读取 MCP 资源。plan:更新计划。request_permissions:请求权限。request_user_input:请求用户输入。tool_search:搜索延迟加载工具。view_image:查看本地图像。current_time:读取当前时间。multi_agents/agent_jobs:多袋里协作。new_context_window:开启新上下文窗口。list_available_plugins_to_install/request_plugin_install:插件发现与安装请求。ToolRouter::build_tool_call会把模型输出中的ResponseItem转成内部ToolCall。它处理三类主要工具调用:
FunctionCall:普通函数工具。ToolSearchCall:工具搜索。CustomToolCall:自定义工具调用。简化后可以理解为:
// 简化示例:把模型输出转换为 Codex 内部工具调用fn build_tool_call(item: ResponseItem) -> Option<ToolCall> {match item {// 模型请求函数工具ResponseItem::FunctionCall { name, arguments, call_id, .. } => {Some(ToolCall {tool_name: ToolName::plain(name),call_id,payload: ToolPayload::Function { arguments },})}// 模型请求自定义工具ResponseItem::CustomToolCall { name, input, call_id, .. } => {Some(ToolCall {tool_name: ToolName::plain(name),call_id,payload: ToolPayload::Custom { input },})}// 普通消息不是工具调用_ => None,}}
工具注册表ToolRegistry则保存工具名到 handler 的映射。每个 handler 实现统一接口,提供:
这让 Codex 可以做到“同一套工具协议,不同工具实现”。shell、patch、MCP、插件工具、动态工具都能通过统一的路由和执行框架运行。
codex-rs/core/src/tools/parallel.rs处理工具并行执行。这里有一个工程细节值得学习:不是所有工具都能安全并行。比如两个只读查询工具可以并行,但两个写文件工具如果同时跑,可能互相覆盖。源码中的ToolCallRuntime会询问 router:这个工具是否支持并行。
它使用一个RwLock:
这样多个并行安全工具可以同时运行,而互斥工具会串行执行。
伪代码如下:
// 简化示例:用读写锁控制工具并行async fn dispatch_tool(call: ToolCall) {let supports_parallel = router.tool_supports_parallel(&call);if supports_parallel {// 中文注释:并行安全工具共享读锁,可以同时执行let _guard = parallel_execution.read().await;router.dispatch(call).await;} else {// 中文注释:有副作用或不安全工具拿写锁,避免并发冲突let _guard = parallel_execution.write().await;router.dispatch(call).await;}}
同时,工具执行还需要支持取消。用户可能中断 turn,shell 命令可能超时,后台进程可能需要清理。ToolCallRuntime使用CancellationToken和AbortOnDropHandle处理取消。如果工具被取消,它会返回一个模型可见的 aborted response,而不是让整个系统状态不明。
这也是 Agent 工程很容易被忽视的地方:工具调用不是函数调用那么纯粹。真实命令可能卡住、超时、输出巨大、产生子进程、修改文件、要求审批。Codex 在工具层做了大量工程防护。
Codex 有多个入口,但核心都汇聚到同一套 session/thread 机制。
交互式 TUI 在codex-rs/tui/。tui/src/lib.rs中可以看到大量 UI 模块:app、bottom_pane、chatwidget、history_cell、markdown_render、slash_command、status、token_usage、resume_picker等。TUI 的职责是把协议事件渲染成用户能理解的终端界面,同时收集用户输入并发送到 App Server/Core。
无交互模式在codex-rs/exec/。exec/src/lib.rs文件顶部明确要求:
--json模式下,stdout 必须是 JSONL,每行一个事件。这个要求非常工程化。因为codex exec很可能用于脚本、CI 或管道,如果 stdout 混入日志,就会破坏调用者解析。
App Server 在codex-rs/app-server/,协议在app-server-protocol/。v2 协议里有ThreadStartParams、ThreadStartResponse、ThreadSettingsUpdateParams等结构,说明它面向更复杂的宿主,例如桌面 App、IDE、远程控制和其他客户端。App Server 把 Codex 的能力封装成 JSON-RPC 风格接口,让前端或宿主不用直接链接core内部实现。
三者关系可以这样理解:
cli/src/main.rs
tui: 交互式终端
exec: 无交互任务
app-server: 宿主服务
core: Agent 主循环
protocol: Op/Event/Model/Permission 类型
这里有一个有趣细节:TUI 和 exec 都越来越多地复用 app-server client/in-process app server。这说明 Codex 正在把“运行一个 Agent thread”从具体 UI 中抽离出来,让不同客户端都通过稳定服务接口访问核心能力。
Codex 有两类重要协议:
第一类是codex-rs/protocol,它是 core 内部会话协议,定义Op、EventMsg、SandboxPolicy、AskForApproval、UserInput、ResponseItem等核心类型。
第二类是codex-rs/app-server-protocol,它面向 App Server 客户端,提供 v1/v2 JSON-RPC API,包含 thread、turn、permission、model、plugin、mcp、config、environment 等接口。
为什么要分两层?因为 core 内部协议更贴近 Agent 运行时,而 App Server 协议更贴近产品宿主。内部可以演进得更快,外部协议需要更稳定、更容易导出 schema、TypeScript 类型和实验字段控制。
在app-server-protocol/src/protocol/v2/thread.rs中,ThreadStartParams包含很多宿主可传的配置:
modelmodel_providerservice_tiercwdruntime_workspace_rootsapproval_policyapprovals_reviewersandboxpermissionsconfigbase_instructionsdeveloper_instructionspersonalitymulti_agent_modeephemeralenvironmentsdynamic_toolsselected_capability_roots这说明 Codex 的外部 API 不是“传 prompt”那么简单,而是允许宿主完整控制运行环境、权限、模型和工具。
对于想设计自己 Agent 系统的人,这里有一个启发:如果你希望同一个 Agent 核心能服务 CLI、Web、IDE、桌面端和自动化任务,就应该尽早抽象协议边界,不要把 UI 操作直接写进核心逻辑。
codex-rs/core/src/config/mod.rs是一个很大的文件,涉及配置加载、权限 profile、模型 provider、MCP server、插件、特性开关、Windows 沙箱、网络袋里、认证存储、project doc 限制等。
Codex 的配置不是“读取一个 config.toml 然后用默认值补齐”。它需要合并多个配置层:
-c覆盖。它还需要做约束检查。例如企业管理员可能限制某些权限或 hook,配置层必须知道某个值来自哪里,是否允许被更高优先级覆盖。
源码中可以看到ConfigLayerStack、ConfigRequirements、Constrained、RequirementSource等概念。这些都是为了把“配置”升级成“可追踪、可约束、可解释”的运行时输入。
一个简化的config.toml可能像这样:
# 示例:Codex 配置片段,真实字段以当前版本文档和源码为准model = "gpt-5.2-codex"approval_policy = "on-request"sandbox_mode = "workspace-write"[permissions]# 中文注释:限制 Codex 默认只能写工作区,避免误改系统文件default = "workspace-write"[mcp_servers.docs]# 中文注释:注册一个 MCP server,让 Codex 能读取外部文档资源command = "node"args = ["./mcp-docs-server.js"]
配置层的关键不是字段多少,而是“配置影响运行时行为”。比如:
approval_policy会影响 shell 和 patch 是否需要用户确认。sandbox_mode会影响文件系统和网络访问。model会影响请求的模型和 reasoning 参数。codex-rs/core/src/agents_md.rs专门处理 AGENTS.md 发现和用户指令拼装。文件注释说明了规则:
.git。AGENTS.md。AGENTS.override.md。project_doc_max_bytes限制,默认来自DEFAULT_PROJECT_DOC_MAX_BYTES。这个机制很重要,因为代码库里的约定通常比通用模型知识更可靠。比如:
just test,不要直接cargo test。Codex 会把这些规则作为模型可见上下文注入,让模型在当前项目里“守规矩”。
一个典型AGENTS.md可以这样写:
# 项目协作规则- 始终使用中文回复用户。- 修改 Rust 代码后运行 `just fmt`。- 涉及 `core` 行为变更时优先添加集成测试。- 不要直接修改生成文件,先修改生成源。- 代码注释保持简短,只解释关键逻辑。
从 Agent 设计角度看,AGENTS.md 是一种“仓库级长期提示词”,但它不是随便拼 prompt,而是有明确发现顺序、大小限制和来源记录。这比把所有规则硬编码在系统提示词里更灵活。
Codex 支持 skills 和 plugins。源码中相关模块包括:
codex-rs/core/src/skills.rscodex-rs/core-skills/codex-rs/skills/codex-rs/core-plugins/codex-rs/plugin/技能可以理解为可复用工作流。例如“创建 Word 文档”“处理电子表格”“控制浏览器”“生成图片”等。技能通常包含SKILL.md,里面描述什么时候使用、如何使用、需要读取哪些参考文件、有哪些脚本或模板。
插件则更像一个可安装包,可以包含:
core-plugins/src/manifest.rs会解析插件 manifest。源码里能看到 manifest 支持字段:
nameversiondescriptionkeywordsskillsmcpServersappshooksinterface一个简化插件 manifest 可以这样理解:
{"name": "docs-helper","version": "0.1.0","description": "为项目文档提供检索和生成能力","skills": "./skills","mcpServers": "./mcp.json","hooks": "./hooks.toml","interface": {"displayName": "Docs Helper","shortDescription": "项目文档助手"}}
技能与插件的区别可以这样记:
Codex 在每个 turn 里会根据用户提及、配置和可用技能,决定是否注入技能说明。maybe_emit_implicit_skill_invocation还会根据命令和工作目录识别隐式技能调用,并上报 analytics。这个设计让技能不是“永远塞进上下文”,而是按需注入,减少 token 浪费。
MCP 是 Model Context Protocol 的缩写。Codex 源码中codex-rs/core/src/mcp.rs的McpManager负责把配置、插件和扩展贡献的 MCP server 合成运行时配置。
它支持几类来源:
McpManager::runtime_config会应用内置兼容、插件注册和 runtime overlay,最终得到当前 session/thread 可用的 MCP 配置。effective_servers还会结合认证状态做 gating。
MCP 对 Codex 很重要,因为它把 Agent 从“只能访问本地 shell 和文件”扩展到“可以访问外部授权数据和工具”。例如:
在工具层,Codex 有mcphandler 和mcp_resourcehandler,用于调用 MCP 工具、列出 MCP 资源、读取 MCP 资源模板等。模型看到的是统一工具接口,Codex 负责把调用转发到对应 MCP server。
一个简化 MCP server 配置可以这样写:
[mcp_servers.local_docs]command = "node"args = ["./tools/mcp-local-docs.js"]# 中文注释:Codex 启动时会根据配置拉起该 server,并把可用工具暴露给模型
一旦 Agent 具备执行命令、修改文件、访问网络或调用外部工具的能力,它就不再只是“生成文本”的系统,而是在真实开发环境里产生副作用的执行主体。Codex 的安全机制不是单点实现,而是由配置、审批、权限 profile、沙箱和工具安全检查共同组成。
codex-rs/protocol/src/protocol.rs定义了AskForApproval、SandboxPolicy等核心类型。SessionConfiguration中保存approval_policy、approvals_reviewer和permission_profile_state。工具执行前会根据当前策略决定:
codex-rs/core/src/safety.rs的assess_patch_safety是一个很好的例子。它会判断 apply_patch 是否为空、审批策略是什么、补丁目标是否被限制在可写路径内、当前平台是否有可用沙箱、是否需要询问用户。如果补丁试图写出项目外,且策略不允许审批升级,就会拒绝。
简化逻辑如下:
// 简化示例:补丁安全判断fn assess_patch_safety(action: Patch, policy: ApprovalPolicy, sandbox: SandboxPolicy) -> Decision {if action.is_empty() {return Decision::Reject("空补丁不能执行");}if action.only_writes_allowed_paths(&sandbox) {// 中文注释:补丁只写允许路径,可以在沙箱中自动执行return Decision::AutoApprove;}if policy.allows_user_approval() {// 中文注释:风险较高但允许用户审批,交给用户决定return Decision::AskUser;}// 中文注释:既不安全,也不能升级审批,直接拒绝Decision::Reject("写入路径不被允许")}
这个机制体现了一个重要原则:Agent 的默认能力应该受限,只有在策略允许时才扩大权限。尤其是写文件、联网、执行命令这些操作,不能完全交给模型自觉。
codex-rs/sandboxing/src/lib.rs是跨平台沙箱抽象入口。它会根据平台导出不同实现:
sandboxing模块提供:
SandboxManagerSandboxCommandSandboxExecRequestSandboxTypecompatibility_sandbox_policy_for_permission_profileget_platform_sandbox真正执行 shell 时,codex-rs/core/src/exec.rs会先构建ExecParams,再通过build_exec_request转成可执行请求,最终走sandboxing::execute_env。ExecParams包含命令、cwd、timeout/cancellation、环境变量、网络袋里、sandbox permissions、Windows sandbox level、justification 等信息。
一个 shell 调用不是简单的:
Command::new("bash").arg("-lc").arg(cmd).output()
而是类似:
是
否
模型请求 shell
Codex 解析命令
检查审批策略
选择沙箱类型
准备网络策略和文件系统权限
启动子进程
流式采集 stdout/stderr
是否超时或取消
清理进程组
等待命令正常结束
截断过大输出
把结构化结果回传模型
core/src/exec.rs里还有很多细节:
DEFAULT_EXEC_COMMAND_TIMEOUT_MS为 10 秒。这说明 Codex 对真实命令执行的复杂性有充分处理。很多自制 Agent demo 只调用subprocess.run,一旦命令卡住、输出巨大或产生后台进程,就会出现不稳定行为。Codex 的实现更接近生产系统。
Codex 对不同工具采用不同安全策略。
对于apply_patch,安全重点是路径约束:补丁是否只修改允许写入的路径?是否会写出项目外?当前平台能否 enforce sandbox?
对于 shell,安全重点更复杂:命令可能删除文件、联网、启动服务、写系统目录、泄露环境变量、执行无限循环。Codex 通过 shell command 解析、安全命令判断、审批策略、沙箱和输出限制共同控制风险。
对于 MCP,安全重点是外部授权和工具后果。某些 MCP 工具可能是只读资源查询,某些可能修改外部系统。Codex 需要根据工具暴露、审批模板和配置决定是否允许模型直接调用。
对于插件和 hooks,安全重点是来源和启用策略。企业环境可能只允许 managed hooks,避免用户或项目任意 hook 影响执行。
这也是为什么 Codex 源码中有大量“看起来不是 AI”的代码:权限、沙箱、配置、认证、持久化、事件、日志、测试。这些代码不是附属品,而是 Agent 产品可用的前提。
Codex 每次请求模型时,不是只发送用户输入。它会构建一个模型可见上下文,可能包含:
这些内容由core/src/context/、context_manager/、session/turn.rs、skills.rs、plugins/等模块共同完成。
源码中的AGENTS.md贡献规则也体现了上下文预算思想:项目文档有最大字节数,超过会截断。AGENTS.md不是越多越好,因为模型上下文窗口有限,太多规则会挤占真正任务内容。
Codex 的AGENTS.md中也强调模型可见上下文的工程要求:
这些规则非常适合所有 Agent 工程学习。上下文不是字符串拼接,而是有生命周期、预算、来源和结构的运行时数据。
Agent 执行复杂任务时,历史会越来越长。Codex 通过 compact 机制处理上下文窗口压力。
在run_turn中可以看到:
这类机制解决的是长期任务问题。比如用户让 Codex 分析一个大型代码库并修复多个测试,过程中可能产生几十次工具调用。如果每次都把完整历史塞给模型,很快超出上下文窗口;如果随意丢历史,模型又会忘记任务目标和已做决策。
压缩的目标不是“把历史变短”这么简单,而是保留决策相关信息:
可以把 compact 看成 Agent 的“工作记忆整理”。它决定长期任务能否可靠继续。
源码和项目规则都强调避免频繁改变模型可见上下文,因为这会影响 prompt cache。对于长上下文任务,缓存命中能显著降低延迟和成本。Codex 因此倾向于:
这对初学者可能有点抽象。可以类比浏览器缓存:如果网页静态资源 URL 每次都变,浏览器就没法缓存;如果 prompt 前缀每次都变,模型侧缓存也难命中。
因此,一个高质量 Agent 不只是“prompt 写得好”,还要“prompt 结构稳定”。
codex exec做无交互代码审查codex exec适合脚本和 CI 场景。它的关键特点是输出可控:默认 stdout 只输出最终消息,--json输出 JSONL 事件流。
示例命令:
# 中文注释:让 Codex 无交互审查当前工作区改动codex exec "请审查当前 git diff,找出可能的 bug、风险和缺失测试"
如果希望机器读取事件,可以使用 JSON 模式:
# 中文注释:JSONL 模式适合 CI 或上层系统解析codex exec --json "运行测试并修复失败,如果需要修改文件请直接修改"
从源码角度看,这会走codex-rs/exec/src/lib.rs。它会加载配置、解析 CLI 参数、创建 in-process app server/client,启动 thread/turn,并用不同 event processor 处理事件:
你可以把codex exec当成“可脚本化的 Codex Agent”。它和交互式 TUI 共享核心能力,但更适合自动化。
假设你的项目是 Rust 服务,要求所有修改必须格式化并运行特定测试。可以在仓库根目录创建:
# AGENTS.md## 开发规则- 始终使用中文回复。- 修改 Rust 代码后运行 `just fmt`。- 不要直接运行全量测试,除非用户要求;优先运行相关 crate 的测试。- 修改 `core` 或协议类型时,必须说明兼容性影响。- 生成代码要添加简短中文注释解释关键逻辑。## 验证命令- 格式化:`just fmt`- core 测试:`just test -p codex-core`- TUI 测试:`just test -p codex-tui`
Codex 会从项目根到当前目录收集 AGENTS.md。若子目录有更具体规则,它也会按路径顺序追加。比如:
repo/├── AGENTS.md└── crates/└── api/└── AGENTS.md
当 Codex 在crates/api下工作时,会看到根目录规则和crates/api/AGENTS.md的规则。这样不同子项目可以有局部约束。
如果你想让 Codex 访问一个本地知识库,可以写一个 MCP server。下面不是完整生产实现,只展示思想:
// mcp-local-notes.js// 中文注释:这是极简示意,真实 MCP server 需要按 SDK 协议实现const notes = {"release-process": "发布前需要运行测试、更新 changelog、创建 tag。","deploy": "部署由 CI 自动完成,不要手动登录服务器修改文件。",};async function searchNotes(query) {// 中文注释:根据关键词返回相关笔记return Object.entries(notes).filter(([key, value]) => key.includes(query) || value.includes(query)).map(([key, value]) => ({ key, value }));}// 中文注释:真实实现中,这里需要把 searchNotes 暴露为 MCP tool
在 Codex 配置中注册:
[mcp_servers.local_notes]command = "node"args = ["./mcp-local-notes.js"]
当 MCP server 正确实现协议后,Codex 可以在工具列表中看到它,并在需要时调用。这样你就能把企业内部知识库、项目文档、数据库查询、工单系统等接入 Codex。
Codex 的工具 handler 实际接口比较复杂,因为要支持 schema、暴露模式、hooks、telemetry、并行、取消等。我们用一个简化 Rust 示例表达核心思想:
// 中文注释:这是教学示例,不是 Codex 源码的完整接口trait ToolRuntime {fn name(&self) -> &'static str;fn schema(&self) -> JsonSchema;fn supports_parallel(&self) -> bool;async fn handle(&self, input: serde_json::Value) -> ToolResult;}struct CurrentTimeTool;impl ToolRuntime for CurrentTimeTool {fn name(&self) -> &'static str {"current_time"}fn schema(&self) -> JsonSchema {// 中文注释:告诉模型这个工具需要什么参数JsonSchema::object()}fn supports_parallel(&self) -> bool {true}async fn handle(&self, _input: serde_json::Value) -> ToolResult {// 中文注释:执行真实逻辑,并把结果转换成模型可读输出ToolResult::text(chrono::Utc::now().to_rfc3339())}}
真实 Codex 的CoreToolRuntime做得更完整,还支持:
pre_tool_use_payloadpost_tool_use_payloadwith_updated_hook_inputtelemetry_tagscreate_diff_consumerwaits_for_runtime_cancellation这些能力让工具不只是“执行函数”,还可以被 hook 检查、被监控、被取消、被增量展示。
如果你想自己实现一个非常简化的 Codex-like Agent,可以从这个伪代码开始:
// 中文注释:教学版迷你 Agent,只保留核心循环async fn mini_agent_loop(user_goal: String, tools: ToolRegistry) -> anyhow::Result<String> {let mut history = Vec::new();// 中文注释:记录用户目标history.push(Message::user(user_goal));loop {// 中文注释:把历史和工具 schema 发给模型let response = call_model(&history, tools.schemas()).await?;match response {ModelResponse::FinalText(text) => {// 中文注释:模型给出最终答案,任务结束history.push(Message::assistant(text.clone()));return Ok(text);}ModelResponse::ToolCall(call) => {// 中文注释:模型请求工具,先检查权限if !is_allowed(&call) {history.push(Message::tool_error(call.id, "权限不足"));continue;}// 中文注释:执行工具,并把结果写回历史let output = tools.dispatch(call).await;history.push(Message::tool_output(output));}}}}
这个示例缺少大量生产能力:沙箱、审批、上下文压缩、并行控制、取消、事件流、持久化、MCP、插件、技能、认证、错误恢复。但它已经体现 Codex 的核心范式:模型负责决策,宿主负责执行和约束,结果再回到模型。
Codex 最直接的用途是本地开发助手。它能:
与传统代码补全相比,Codex 更适合跨文件、跨步骤任务。比如:
请分析这个项目的认证流程,找出 access token 过期后的刷新路径,并补充缺失测试。
这个任务需要阅读多个文件、理解调用链、修改测试、运行验证。它不是单行补全能解决的。
codex exec让 Codex 可以进入脚本化场景:
因为 exec 模式严格区分 stdout/stderr,适合上层系统集成。
Codex 的 review 子命令和 guardian/review 相关模块说明它也面向审查场景。它可以帮助识别:
当然,AI 审查不能替代人工评审,尤其是安全、金融、隐私、生产事故相关变更。但它可以做第一轮扫描,让人工评审更聚焦。
源码中出现了multi_agents、agent_jobs、agent-graph-store、external-agent-sessions等模块,说明 Codex 正在支持更复杂的多袋里协作。
多袋里的典型价值是并行探索。例如一个大任务可以拆成:
这能减少等待时间,也能让不同上下文分开管理。但多袋里也带来新问题:如何传递上下文、如何防止重复修改、如何合并结论、如何限制并发、如何避免子袋里无限扩散。Codex 源码中有最大深度、最大并发、等待超时等配置,正是在处理这些工程风险。
通过 MCP、插件、skills 和 hooks,Codex 可以接入企业内部系统:
相比把所有数据复制进 prompt,MCP 让 Agent 按需访问资源;相比把所有逻辑写进核心,插件让能力可以独立发布和启用;相比把规则写在口头约定里,hooks 可以做机械化治理。
Codex 的 SQ/EQ 模式让 Agent 运行过程变成事件流。这对用户体验和调试都很重要。用户可以看到:
对开发者来说,事件流也利于测试。测试可以等待某个事件,而不是 sleep 固定时间。
源码中对输出 cap、I/O drain timeout、token budget、上下文大小、AGENTS.md 最大字节数都有明确限制。大型 Agent 最怕“无界”:
Codex 的实现处处体现“给每个入口加上边界”。
TUI、exec、App Server、MCP Server 都建立在相同 core 能力上。这避免了不同入口行为不一致。例如同样的审批策略、沙箱规则、工具执行、AGENTS.md 加载应该在所有入口一致生效。
Codex 不假设模型永远正确,也不假设用户希望 Agent 拥有无限权限。它通过 permission profile、sandbox、approval policy 和 tool hooks 让权限可控。
这对 AI 编程工具尤其重要。因为模型可能误判命令后果,例如执行rm -rf、覆盖配置、安装未知依赖、访问网络等。安全系统的目标不是让 Agent 什么都不能做,而是让它在“可解释、可审批、可约束”的框架内做事。
MCP、插件、技能、hooks 都让 Codex 变得可扩展。但源码也显示,扩展不是无边界的。比如:
这说明成熟 Agent 平台必须同时提供“扩展能力”和“治理能力”。
过去的代码助手主要解决“写一段代码”。Codex 这类 Agent 更进一步,解决“完成一个工程任务”。工程任务通常包括:
未来的软件工程 Agent 会越来越像一个初级到中级工程师的工作台,而不是一个补全插件。
Codex 源码和 README 都显示它有本地 CLI、IDE、桌面 App 和 Codex Web/Cloud 等形态。未来很可能形成混合模式:
这对开发者意味着:AI 工具不会只存在于编辑器侧边栏,而会贯穿本地终端、CI、代码托管平台、知识库和云端执行环境。
当 Agent 能改代码、跑命令、访问内部系统后,企业一定会关注:
Codex 源码中的 telemetry、approval、permission profile、hooks、thread store、rollout trace 都是在为这些问题打基础。未来 Agent 平台的竞争,不只在模型能力,也在安全、审计、治理和可观测性。
单个 Agent 的上下文和时间有限。复杂任务天然适合拆分。多袋里能带来并行收益,但也需要更好的协调机制。Codex 里已经有多袋里工具、agent job、spawn/wait/send message 等能力。未来可能会看到:
今天我们写一个 Agent demo 很容易,但写一个可用的 Agent 产品很难。Codex 源码展示了平台化方向:
未来开发者可能不会从零写 Agent,而是在类似 Codex 的平台上写技能、插件、MCP server 和策略。
先不要急着读所有代码。建议按下面顺序:
README.mdcodex-cli/bin/codex.jscodex-rs/Cargo.tomlcodex-rs/cli/src/main.rscodex-rs/protocol/src/protocol.rs
目标是回答:
重点读:
codex-rs/core/src/session/turn.rscodex-rs/core/src/session/session.rscodex-rs/core/src/codex_thread.rscodex-rs/core/src/client.rs
目标是回答:
run_turn做了哪些阶段?重点读:
codex-rs/core/src/tools/spec_plan.rscodex-rs/core/src/tools/router.rscodex-rs/core/src/tools/registry.rscodex-rs/core/src/tools/parallel.rscodex-rs/core/src/tools/handlers/
目标是回答:
重点读:
codex-rs/core/src/config/mod.rscodex-rs/core/src/safety.rscodex-rs/core/src/exec.rscodex-rs/sandboxing/src/lib.rscodex-rs/linux-sandbox/src/codex-rs/windows-sandbox-rs/src/
目标是回答:
重点读:
codex-rs/core/src/agents_md.rscodex-rs/core/src/skills.rscodex-rs/core-skills/codex-rs/core-plugins/src/manifest.rscodex-rs/core/src/mcp.rscodex-rs/codex-mcp/
目标是回答:
shell 是重要工具,但 Codex 还有 apply_patch、MCP、技能、插件、计划、权限请求、用户输入请求、图像查看、多袋里等能力。shell 只是工具生态的一部分。
模型可以请求工具,但宿主会检查权限、沙箱、审批、工具暴露、并行策略和取消状态。真正执行权在 Codex runtime,不在模型文本本身。
AGENTS.md 是模型可见的项目规则文件。它会进入 Codex 上下文,影响模型行为。README 面向人类,AGENTS.md 面向 Agent 协作规范。
MCP 是连接外部工具和资源的协议。插件是可安装能力包,可能包含 MCP 配置、skills、hooks、apps 和界面元数据。二者可以组合使用。
上下文太多会浪费 token、降低关注重点、影响缓存命中,甚至触发压缩。高质量 Agent 需要精准注入上下文,而不是把所有东西都塞给模型。
Codex 源码最值得学习的地方,不是某一个神奇 prompt,也不是某一个复杂算法,而是它把“AI 编程助手”工程化成了一个完整 Agent 平台。
从codex-main可以看到一个清晰分层:
codex-cli负责 npm 入口和平台二进制启动。cli负责顶层命令分发。tui、exec、app-server提供不同使用形态。protocol定义核心操作和事件。core负责 session、turn、上下文、模型请求和工具调度。tools体系让模型能安全调用 shell、patch、MCP、计划、多袋里等能力。sandboxing、safety、permissions、approval确保 Agent 能做事但不乱做事。AGENTS.md、skills、plugins、MCP 让 Codex 适配不同项目和组织环境。thread-store、rollout、rollout-trace支持持久化、恢复和调试。如果用一句话概括 Codex 的架构思想:
模型负责推理和决策,Codex runtime 负责上下文、工具、安全、状态和产品化体验。
这也是未来软件工程 Agent 的核心方向。真正可用的 Agent 不会只是一个大模型接口,而是一套把模型接入真实工程世界的运行时系统。它需要会读项目规则,会管理上下文,会安全执行命令,会请求审批,会连接外部工具,会记录历史,会恢复任务,会在不同入口提供一致能力。
对于初学者,建议不要一开始就陷入所有细节。先抓住主线:
否
是
用户输入
协议提交
会话配置
上下文构建
模型请求
工具调用
安全执行
结果回灌
是否完成
结束任务
理解了这条主线,再看core/src/session/turn.rs、tools/router.rs、tools/spec_plan.rs、core/src/client.rs、core/src/exec.rs、core/src/safety.rs,很多看似复杂的源码都会变得有章可循。