Claude Code 与 Codex 式 Coding Agent 运行时详解:一次真实任务如何被推进

作者:Codex 整理时间:2026-04-23 03:20:00 CST 来源:基于 AI Agent 架构形态详解:从单 Agent 到 Claude Code 与 Codex 式系统 进一步扩展 主题:以“修复一个仓库里失败的测试并准备提交补丁”为具体例子,讲清 Claude Code / Codex 式 Coding Agent 如何在权限、沙箱、项目规则、工具层、子代理、验证闭环与日志审计约束下推进任务。 说明:本文讨论的是“Codex 式 coding agent 的合理运行时抽象”,不是对任何产品私有内部实现的披露。

关联文章:

从一句请求开始:Coding Agent 不是直接写代码,而是在运行时里推进任务

假设用户给出一句很常见的请求:

这个仓库测试挂了,帮我修一下并提交补丁。

如果把 Coding Agent 理解成“一个会写代码的模型”,你可能会以为它下一步就是直接改文件。 但真正可靠的 Coding Agent 不应该这么做。

它首先要建立任务边界:

  • 当前工作目录是什么
  • 项目有什么规则
  • 是否已有用户改动
  • 是否允许写文件
  • 是否允许运行命令
  • 是否允许联网查资料
  • 是否需要提交 commit
  • 哪些动作需要用户确认

也就是说,Coding Agent 的核心不是“马上写代码”,而是:

在一个受约束运行时中,持续感知、计划、行动、验证、修正,并最终交付可审计结果。

一、运行时抽象总览:模型、工具与工作区之间如何分工

在这个抽象里,可以把 Coding Agent 分成四个大区:

  • 模型 / 推理核心:理解任务、形成计划、解释错误、决定下一步
  • 工具层:读文件、搜索代码、运行测试、调用 Git、访问浏览器或 MCP 服务
  • 工作区状态:源码、测试、配置、日志、git diff、依赖环境
  • 治理层:权限、沙箱、审批、项目规则、审计日志

其中最容易被低估的是工作区。 对 Coding Agent 来说,工作区不是普通文件夹,而是任务推进的状态载体。

例如它会通过下面这些观察来判断现实:

  • git status 显示哪些文件已有改动
  • 测试日志告诉它哪里失败
  • package.jsonpyproject.toml 告诉它该如何运行测试
  • AGENTS.md 或项目规则告诉它哪些动作不能做
  • git diff 告诉它最终补丁是否干净

模型提供推理,工具连接现实,工作区承载状态,治理层限制风险。 四者合在一起,才像一个真正可用的 Coding Agent 运行时。

二、权限、沙箱与审批:Agent 能做什么,不能做什么

Coding Agent 的第一层边界是权限。

权限不是“麻烦的限制”,而是让 Agent 能进入真实工程环境的前提。 如果一个 Agent 能随意删文件、联网、安装依赖、推送代码,那么它越强,风险越大。

常见权限边界包括:

  • 文件系统权限:只读、工作区写入、指定目录可写、全盘访问
  • 命令权限:普通命令自动执行,高风险命令需要确认,危险命令直接禁止
  • 网络权限:是否允许查官方文档、拉依赖、访问外部 API
  • Git 权限:是否允许 commit、push、改分支、改历史
  • 外部系统权限:是否允许访问 GitHub、CI、数据库、工单系统

这些边界会直接改变 Agent 的行为。

例如:

  • 如果不能联网,它就会优先读本地文档和源码
  • 如果不能安装依赖,它就会报告缺失依赖,而不是偷偷安装
  • 如果推送需要确认,它最多准备好 commit,不会自动 push
  • 如果检测到危险命令,它应该停下来说明风险

所以权限与沙箱不是附加功能,而是运行时架构的一部分。 它们决定 Agent 的行动空间,也决定事故能否被控制在可恢复范围内。

三、项目规则与记忆:AGENTS.md、用户偏好和仓库惯例如何影响执行

进入一个仓库后,Agent 不应该只看代码。 它还要看规则。

常见规则来源包括:

  • AGENTS.md
  • README.md
  • CONTRIBUTING.md
  • 测试说明
  • package scripts
  • 用户在当前对话里给出的限制
  • 长期偏好或项目记忆

这些规则会影响很多细节:

  • 搜索时优先用什么工具
  • 能不能改生成文件
  • 测试命令是什么
  • 是否必须运行格式化
  • 提交信息怎么写
  • 是否不能覆盖用户已有改动

例如一个项目规则可能写着:

搜索代码时优先使用 rg。
不要修改 dist/ 下的生成文件。
提交前至少运行 npm test。
如果发现 unrelated changes,不要回滚。

这些看起来像小事,但对 Coding Agent 很重要。 因为没有规则,Agent 会把所有仓库当成同一个仓库;有了规则,它才开始像一个真正进入项目的工程师。

四、MCP 与工具层:从推理到可执行动作

模型本身不能直接改变现实。 它要通过工具层把“我应该做什么”变成“我实际做了什么”。

工具可以包括:

  • shell
  • 文件读取
  • 代码搜索
  • 代码编辑
  • Git
  • 测试运行器
  • 浏览器
  • GitHub / CI
  • 日志系统
  • 数据库
  • MCP 服务

MCP 可以理解为一种外部能力适配层。 它把文档、服务、工具、资源、企业系统暴露成 Agent 可调用的接口。

这件事的价值不只是“工具更多”,而是:

工具让 Agent 能通过现实反馈校正自己的判断。

例如,Agent 猜测某个函数导致测试失败,这只是一个假设。 它必须读源码、运行测试、看错误栈、检查 diff,才能把假设变成证据。

没有工具层,Agent 只能像顾问一样给建议。 有了工具层和验证闭环,它才开始像工程师一样推进任务。

五、一个具体任务怎么跑:修复失败测试的完整执行链

下面用一个具体任务串起来:

修复一个仓库里失败的测试,并准备提交补丁。

1. 接收请求并建立边界

Agent 首先不会直接改代码,而是确认:

  • 当前仓库在哪里
  • 工作区是否干净
  • 用户是否要求 commit
  • 是否允许运行测试
  • 是否允许联网或安装依赖

这一步的关键是避免一上来就破坏用户现场。

2. 读取项目规则与测试入口

接着它会找:

  • AGENTS.md
  • README.md
  • package.json
  • pyproject.toml
  • pytest.ini
  • Makefile
  • 测试目录

目标是确定项目语言、测试框架、约定命令和禁止操作。

3. 运行基线测试

Agent 会运行最小合理测试命令,例如:

npm test
pytest
make test

如果全量测试太慢,它可能先运行失败用例或相关测试文件。 这一步的产物不是“通过或失败”四个字,而是错误栈、失败断言、文件路径和复现条件。

4. 读取相关源码与测试

根据错误栈,Agent 读取:

  • 失败测试文件
  • 被测模块
  • fixture
  • mock 数据
  • 相关配置
  • 最近相关变更

它会搜索函数名、错误消息、断言文本和调用路径,逐步缩小问题范围。

5. 制定小计划

一个合理计划可能是:

1. 修复 parser 对空 metadata 字段的处理。
2. 保持现有接口返回结构不变。
3. 运行失败测试文件。
4. 如果通过,再运行相关包测试。
5. 检查 git diff,确认没有无关改动。

计划不需要很宏大,但必须可执行、可验证、可回滚。

6. 应用最小补丁

Agent 应该优先修改业务代码,而不是简单删除测试或放宽断言。 除非能证明测试期望已经过时,否则“让测试不报错”不等于“修复问题”。

7. 局部验证与失败重试

第一次修改后,Agent 运行局部测试。 如果仍然失败,它会读取新错误。

例如:

  • 第一次错误是 TypeError
  • 修改后变成断言不匹配

这说明第一个问题已经解决,但输出格式仍不符合预期。 于是 Agent 更新假设,继续读格式化逻辑,做第二次小修改。

8. 全量验证与 diff 检查

局部测试通过后,还要做更大范围验证:

  • 相关测试
  • 全量单元测试
  • 类型检查
  • lint
  • 构建

然后检查:

git diff
git status

确认没有带入日志、缓存、构建产物、用户无关改动。

9. 准备提交与最终交付

如果用户要求提交,Agent 可以准备 commit message,例如:

fix parser handling for empty metadata fields

最终交付应该包括:

  • 改了什么
  • 为什么这样改
  • 运行了哪些验证
  • 是否已提交
  • 还有哪些风险或未验证项

没有这些交代,任务就不算完整闭环。

六、子代理与并行探索:把不确定性拆成多条路径

复杂任务里,最耗时间的往往不是修改,而是定位。 这时可以把不确定性拆成几条并行探索路径。

例如主 Agent 可以并行派出:

  • 子代理 A:分析失败日志和错误栈
  • 子代理 B:搜索相关源码路径
  • 子代理 C:查看最近变更或提交差异
  • 子代理 D:检查文档和项目规则

但关键原则是:

  • 子代理优先只读
  • 主代理负责合并结论
  • 避免多个子代理同时写同一批文件
  • 并行结果必须带证据
  • 有冲突时由主代理仲裁

Multi-Agent 的价值不是“人多势众”,而是把不确定性隔离成多个低风险探索任务。

七、验证闭环:读、改、测、失败、再改

Coding Agent 的可靠性来自验证闭环。 没有验证的补丁,只能算“生成了一段代码”,不能算“完成了工程任务”。

一个健康闭环通常是:

建立假设
  -> 最小修改
  -> 局部测试
  -> 读取失败
  -> 修正假设
  -> 再次修改
  -> 更大范围验证
  -> 检查 diff
  -> 交付

失败不是异常,而是正常推进机制。 真正危险的不是测试失败,而是测试失败后 Agent 仍然假装已经完成。

所以成熟的 Coding Agent 应该区分:

  • 快速局部验证
  • 相关范围验证
  • 最终全量验证
  • 未能验证的残留风险

如果某些测试因为依赖缺失、环境限制或权限不足无法运行,最终交付时必须明确说明。

八、日志审计与最终交付:为什么过程也很重要

工程任务不是只看最后一段代码。 过程同样重要。

至少应该留下这些可审计痕迹:

  • 读取过哪些关键文件
  • 运行过哪些命令
  • 哪些测试失败过
  • 做过哪些修改
  • 验证结果是什么
  • 是否跳过了某些检查
  • 是否需要人工确认

最终交付也应该结构化:

  • 变更摘要
  • 修改文件
  • 验证命令与结果
  • commit 信息
  • 残留风险
  • 未做事项

如果需要提交补丁,还要特别检查:

  • 是否包含无关改动
  • 是否覆盖用户未提交修改
  • 是否把生成文件、日志、缓存带进去了
  • commit message 是否清楚

这也是 Coding Agent 与普通代码生成器的差别:

它不是替代工程纪律,而是把工程纪律自动化、显性化、可追踪化。

总结:Coding Agent 的价值在于把工程闭环变成运行时能力

用这一个“修复失败测试”的例子回看,Coding Agent 真正做的事情不是单点写代码,而是持续推进一个工程闭环:

  • 理解目标
  • 建立上下文
  • 遵守项目规则
  • 在权限与沙箱中行动
  • 调用工具观察现实
  • 做最小修改
  • 用测试验证
  • 根据失败修正
  • 检查 diff
  • 结构化交付

这就是 Claude Code / Codex 式系统最值得学习的地方: 它们把模型能力放进了一个可执行、可验证、可治理的运行时里。

所以,如果要判断一个 Coding Agent 是否真正成熟,不要只问“它会不会写代码”。 更应该问:

  • 它是否理解项目规则
  • 它是否尊重权限边界
  • 它是否能利用工具验证现实
  • 它是否能从失败中修正
  • 它是否能交付可审计过程

一个真正可靠的 Coding Agent,本质上不是“更会补全代码的模型”,而是能把工程任务从模糊目标推进到可验证补丁的代理运行时系统