Skip to content

English Version →

本篇代码示例:code/ 实战练习:Project 06. 搭建一套完整的 agent 工作环境

第十二讲. 每次会话结束前都做好交接

这节课要解决什么问题

你的 agent 跑了一下午,改了 20 个文件,提交了代码,会话结束。下一个 agent 会话开始,一上来就发现:构建失败了、测试红了、临时调试文件到处都是、功能清单没更新、进度完全不清楚。新会话的前 30 分钟全花在"搞清楚上一个会话到底干了什么"上。

OpenAI 和 Anthropic 都明确指出:长期可靠性取决于操作纪律,不仅是单次运行的成功。 每个会话结束时的状态质量,直接决定下一个会话的效率。这就像 Git 的最佳实践——每次提交应该是一个原子性的、可编译的变更,而不是一堆半成品代码的堆砌。

核心概念

  • 清洁状态:会话结束时系统满足五个条件——构建通过、测试通过、进度已记录、无过时工件、启动路径可用。缺一个都不算"做完"。
  • 会话完整性:类比数据库事务——要么全部提交并留下清洁状态,要么回滚到上一致状态。没有中间地带。
  • 质量文档:对每个模块的质量等级做持续记录的活跃工件。不是一次性评估,而是跟踪代码库是变强了还是变弱了。
  • 清理循环:定期的维护会话,目标是系统性减少代码库中的熵。不是紧急修复,而是常规运维。
  • harness 简化:随着模型能力提升,定期移除不再必要的 harness 组件。今天必要的约束,三个月后可能是多余的开销。
  • 幂等清理:清理操作无论执行多少次都产生相同结果。确保清理在失败重试场景中仍然安全。

为什么会这样

熵增是默认状态

Lehman 的软件演化定律告诉我们:持续变更的系统,除非主动管理,否则复杂性必然增加。这对 AI 编码 agent 尤其成立——agent 每次会话都会引入变更,如果不在退出时清理,技术债务会指数级累积。

agent 会复制仓库中已有的模式——即使那些模式是不均匀的或次优的。 这是 OpenAI 在 5 个月的 Codex 实验中观察到的一个核心现象。随着时间的推移,这种复制必然导致漂移。

OpenAI 团队最初花每周五(20% 的工作时间)手动清理 "AI slop"。不出所料,这种方式不可扩展。他们的解决方案是:

  1. 把"黄金原则"编码进仓库:比如"优先使用共享工具包而非手写的 ad-hoc 辅助函数"(保持不变量集中)、"不要 YOLO 式地猜数据结构"(验证边界或依赖类型化 SDK)。这些原则是具体的、机械的、可自动检查的。
  2. 建立周期性的清理流程:一组后台 Codex 任务定期扫描偏差,更新质量评分,开针对性的重构 PR。大多数可以在一分钟内审查并自动合并。
  3. 人类品味捕获一次,持续执行:审查意见、重构 PR、用户侧 bug 都被转化为文档更新或直接编码到工具中。当文档不够用时,把规则提升为代码。

这个机制就像垃圾回收——技术债是高息贷款,持续小额还清几乎总是比攒到一次性爆发好得多。

来源:OpenAI: Harness engineering: leveraging Codex in an agent-first world一个使用 agent 持续开发 12 周的项目,没有清洁策略的情况下:

  • 第 1 周:构建通过率 100%,测试通过率 100%,新会话启动 5 分钟
  • 第 4 周:构建 95%,测试 92%,启动 15 分钟
  • 第 8 周:构建 82%,测试 78%,启动 35 分钟
  • 第 12 周:构建 68%,测试 61%,启动 60+ 分钟

同样的项目,有清洁策略的情况下:

  • 第 1 周:100%,100%,5 分钟
  • 第 12 周:97%,95%,9 分钟

12 周后,构建通过率差 29 个百分点,新会话启动时间差 85%。这不是理论推导,是实际可观测到的差异。

五个维度的清洁状态

清洁状态不是单一的"代码能编译",而是五个维度的综合:

构建维度:代码能无错构建?这是最基本的——下一个会话不应该先修构建错误。

测试维度:所有测试通过?包括会话之前就存在的测试——会话有责任不破坏已有功能。而且要在 CI 环境验证,不是"在我机器上通过"。

进度维度:当前进度已记录在机器可读的工件中?已完成的子任务和通过标准、进行中但未完成的子任务和当前状态、尚未开始的子任务。好的进度记录减少 60-80% 的会话启动诊断时间。

工件维度:无过时或歧义的临时工件?调试日志、临时文件、注释掉的代码、TODO 标记——这些都增加下一个会话的认知负担。

启动维度:标准启动路径可用?下一个会话能不能不人工干预就开始工作?环境初始化、代码库加载、上下文获取、任务选择——这些路径不能被破坏。

"以后再清理"是永远不清理

最常见的心理陷阱是"这次来不及清理了,下次再弄"。但下次的 agent 不知道你上次留下了什么——它看到的是一堆混乱的代码和不确定的状态。它会花大量时间推断"这堆代码里哪些是有意的,哪些是临时的"。

更糟的是,每个会话都有自己的任务目标。新会话来的时候是要做新功能的,不是来清理上一个会话的烂摊子的。它会忽略混乱直接开始新工作,然后在混乱的基础上引入更多混乱。这是熵增的正反馈循环。

怎么做才对

1. 清洁状态作为完成的必要条件

在 harness 里明确定义:会话完成 = 任务通过验证 AND 清洁状态检查通过。 缺任何一个,会话不算完成。在 CLAUDE.md 里写:

## 会话退出检查清单
- [ ] 构建通过 (npm run build)
- [ ] 所有测试通过 (npm test)
- [ ] 功能清单已更新
- [ ] 无调试代码残留 (console.log, debugger, TODO)
- [ ] 标准启动路径可用 (npm run dev)

2. 双模式清理策略

结合两种清理模式:

即时清理(每个会话结束时):清理本次会话创建的临时工件、更新功能清单状态、确保构建和测试通过。这是"引用计数式"清理。

定期清理(每周一次):全系统扫描——处理累积的结构性问题、更新质量文档、运行基准测试检测漂移。这是"追踪式"清理。

3. 维护质量文档

质量文档是对每个模块持续评分的活跃工件:

markdown
# 质量文档

## 用户认证模块 (质量: A)
- 验证通过: 是
- agent 可理解: 是
- 测试稳定性: 稳定
- 架构边界: 合规
- 代码规范: 遵循

## 支付模块 (质量: C)
- 验证通过: 部分(支付回调未测试)
- agent 可理解: 困难(逻辑分散在 3 个文件)
- 测试稳定性: 不稳定(2 个 flaky 测试)
- 架构边界: 有违规
- 代码规范: 部分遵循

新会话读这个文档就知道优先处理哪里。质量评分最低的模块先修。

4. 定期简化 harness

harness 里的每个组件之所以存在,是因为模型无法独立做好某件事。但随着模型改进,这些假设会过时。

Anthropic 的实验直接展示了这一点。他们最初的 harness 包含 sprint 拆分机制——把工作分成小块让 Sonnet 4.5 逐个完成。当 Opus 4.6 发布后,模型的原生能力已经可以自主处理工作分解,sprint 构造变成了不必要的开销。移除后,builder agent 能连续工作超过两小时而不会跑偏,反而更流畅。

但 evaluator 的情况不同。即使 Opus 4.6 能力更强,在任务接近模型能力边界时,evaluator 仍然提供了实际价值——捕获 generator 的遗漏功能和存根实现。这意味着 evaluator 不是一个固定的是/否决策,而是取决于任务难度相对于模型能力的位置。

推荐做法:每月挑一个 harness 组件,暂时禁用它,跑基准任务。如果结果没退化,永久移除。如果退化了,恢复或用更轻量的替代。

一个更具体的原则:随着模型改进,harness 的有趣组合不是变少了,而是移动了。 以前必须解决的问题被模型能力覆盖了,但新的能力边界打开了以前不可能的 harness 设计。AI 工程师的工作是持续找到下一个有价值的组合。

5. 高吞吐量改变了 merge 哲学

当 agent 的产出远超人类审查能力时,传统的 merge 哲学需要调整。

OpenAI 团队的经验:在一个 agent 每天开 3.5 个 PR(且后来增加到更多)的环境里,最小化阻塞式 merge gate 是正确的。PR 应该短命。测试 flake 通常用后续运行解决,而不是无限期阻塞进度。在一个修正成本很低、等待成本很高的系统里,快速前进 + 快速修正是比缓慢确认更好的策略。

注意:这在低产出环境里是不负责任的。但在 agent 产出远超人类注意力的环境里,这往往是正确的权衡。关键判断标准:修正一个 bug 的平均成本 vs 等待人类审查一个 PR 的平均成本。 前者低于后者时,快速合并是对的。

5. 清理操作必须幂等

清理脚本要能安全地重复执行:

bash
# 幂等的清理操作
rm -f /tmp/debug-*.log  # -f 确保文件不存在时不报错
git checkout -- .env.local  # 恢复到已知状态
npm run test  # 验证清理未破坏功能

实际案例

一个使用 agent 持续开发的 Electron 应用,12 周演化过程的对比数据:

无清洁策略(对照组):第 12 周,构建通过率 68%,测试通过率 61%,新会话启动 60+ 分钟,过时工件 103 个。

有清洁策略(实验组):每个会话结束时执行完整清洁检查 + 每周清理循环。第 12 周,构建通过率 97%,测试通过率 95%,新会话启动 9 分钟,过时工件 11 个。

到第 12 周,实验组的构建通过率比对照组高 29 个百分点,测试通过率高 34 个百分点,新会话启动时间减少 85%。

关键要点

  • 清洁状态是会话完成的必要条件——不是可选的善后工作,是"完成定义"的一部分。
  • 五个维度缺一不可——构建、测试、进度、工件、启动,每个都要显式检查。
  • 质量文档让代码库健康可追踪——知道哪里在退化才能主动修复。
  • 定期简化 harness——随着模型能力提升,移除不再必要的约束。
  • "以后再清理"等于永远不清理——熵增是默认状态,只有主动的清洁操作才能对抗它。

延伸阅读

练习

  1. 清洁状态检查表:为你的代码库设计一个会话退出检查表,涵盖五个维度。在 5 个连续会话中应用,记录每个维度上的违反次数。

  2. 基准对比实验:固定任务集,两种 harness 变体(有/无清洁状态要求)各跑一遍。比较完成率、重试次数和缺陷逃逸率。

  3. harness 简化实践:选一个 harness 组件,暂时禁用,跑基准任务。比较有无该组件的结果。决定保留、移除还是替换。