Harness Engineering¶
这里的 harness 指 Codex 给模型动作套上的执行外壳。模型可以提出“运行命令、改文件、调用 MCP、请求权限、生成图片、spawn agent”等动作,但每个动作都必须穿过同一套工程边界。
工具注册:ToolRegistry¶
ToolRegistry 位于 codex-rs/core/src/tools/registry.rs。它负责:
- 按
ToolName保存CoreToolRuntime。 - 检查工具是否支持并发。
- 创建 streamed argument diff consumer。
- 执行 pre-tool-use hook。
- 调用真正的 handler。
- 执行 post-tool-use hook。
- 发送 tool start/finish lifecycle。
- 记录工具遥测和 dispatch trace。
CoreToolRuntime 继承 ToolExecutor<ToolInvocation>,但又补充了 Codex 核心需要的能力:hook payload、telemetry tags、argument diff、取消等待策略等。
工具规划:ToolRouter¶
ToolRouter 把模型输出的 ResponseItem 转成内部 ToolCall,并把 tool call 分发给 registry。它还持有本次 turn 的 model_visible_specs。
源码入口:
codex-rs/core/src/tools/router.rscodex-rs/core/src/tools/spec_plan.rs
spec_plan.rs 很关键:它不是简单列出所有工具,而是根据 turn context、MCP 工具、deferred MCP 工具、extension tools、dynamic tools、code mode、multi-agent 版本等条件构建“本轮可见工具集”。
执行编排:ToolOrchestrator¶
ToolOrchestrator 位于 codex-rs/core/src/tools/orchestrator.rs,文件注释已经把流程概括成:
- approval
- select sandbox
- attempt
- retry with escalated sandbox strategy on denial
它统一处理:
AskForApproval策略。- Guardian 自动 review。
- PermissionRequest hook。
- 文件系统 sandbox policy。
- network sandbox policy。
- managed network approval。
- sandbox denied 后是否可升级重试。
- sandbox outcome 遥测。
这个设计的好处是工具 handler 不需要各自实现审批和沙箱语义,减少安全策略分叉。
并发与取消:ToolCallRuntime¶
codex-rs/core/src/tools/parallel.rs 负责工具并发:
- 支持并发的工具走读锁。
- 不支持并发的工具走写锁。
- 用户取消时根据工具声明决定是否等待 runtime 清理。
- 取消后生成模型可见的 aborted tool output。
- 避免 tool finish 和 abort finish 重复上报。
这让“多个工具并行”和“用户中断”同时可控,而不是散落在每个工具实现里。
Hook 的位置¶
工具执行路径里有三类 hook 特别重要:
PreToolUse:可阻止工具执行,或改写 tool input。PostToolUse:可阻止工具结果返回模型,或替换模型可见反馈。PermissionRequest:可自动允许或拒绝审批请求。
hook 不是 UI 装饰,而是执行 harness 的一部分。
可学习的设计¶
Codex 的 harness engineering 值得学习的地方在于,它承认模型输出是不可信的执行计划,因此把每个计划都放进一个可审计管道:
- 模型只提出动作。
- registry 校验工具名和 payload。
- hook 可以检查或改写。
- orchestrator 决定审批和沙箱。
- runtime 处理并发、取消和结果。
- event/telemetry 记录全过程。