最近读到一篇深入剖析 Agent 工程演化路径的文章,其梳理出的演进路线令人印象深刻:
ReAct(2023 年初)→ Plan & Execute(2023 年末)→ Multi-Agent(2024 年)→ Context Engineering(2025 年)→ Harness Engineering(2025 年及以后)
文章附有一句值得反复琢磨的话:「名词换了五六轮,核心问题从未改变——如何在不确定性之上构建确定性。」
Harness Engineering 的核心思路是:不要试图通过提示词说服 AI 表现更好,而应依靠工程框架约束 AI 的行为边界。这一理念原本面向的是「开发 AI 产品」的工程师,但深入推敲后会发现,同样的逻辑完全适用于日常开发——当你借助 AI 完成 Android 需求时,是否也为 AI 搭建了「框架」?
遗憾的是,大多数开发者并未这样做,于是翻车便成了家常便饭。
一、一次典型翻车复盘
分享一个真实场景。一个中等规模的 Android 需求,原计划三天完成,期间更换了两次对话窗口。
第一天:利用 AI 拆解需求,理清了逻辑,并确定了技术方案。
第二天:在新窗口中重新描述需求,AI 给出的方案与昨天存在出入,改动范围扩大。花费半小时对齐信息,才找回前一天的节奏。
第三天:再次换窗口,这次忘记告知 AI 项目中存在一个不可改动的公共组件。AI 自然地修改了该组件,导致另一个模块受影响,回滚耗费了一个多小时。
翻车清单:
- 需求被重新理解,出现偏差
- 第一天确定的技术决策丢失
- 相同的背景信息重复交代了两遍
- AI 无法识别禁区,贸然踩雷
这些问题表面上看是「AI 不够智能」,实际上是「没有为 AI 提供一个稳定的工作框架」。换言之,AI 每次进场都裸奔,缺乏上下文承接,只能依赖当前对话中你给出的信息。
Harness Engineering 的核心洞察在此刻恰好适用:凡是希望 AI「一定」做到的事,不要依赖提示词,而要依赖结构。
二、第一层:关键节点,强制产出文档
Harness Engineering 中存在一个原则:工具描述属于人机协议,而非注释。也就是说,工具的边界、使用时机、返回格式都必须显式写明,不能依靠 AI 自行猜测。
映射到开发流程中:每个关键节点的产出,就是下一个窗口的入口协议。
一个可行的思路是,在完成需求的过程中,强制在四个节点生成文档,存储在项目 .ai/ 目录中,并与代码一同提交:
节点一:需求理解文档
在需求拆解结束后生成,让 AI 输出:
- 需求拆解:将一句话需求拆解为具体功能点
- 边界确认:哪些功能在范围内,哪些明确不做
- 疑问列表:AI 不确定的地方列出,供你现场确认
这一步的价值不仅是备忘,更重要的是:在进入实现之前,就能发现 AI 对需求的理解与你的理解是否存在偏差。
节点二:技术方案文档
方案确定后生成:
- 涉及文件列表(精确到文件路径)
- 改动范围描述
- 关键决策及理由(为什么选这个方案,备选方案为何放弃)
「关键决策及理由」这一条很多人容易忽略,但恰恰是换窗口后最难重建的信息。AI 下次进场时看到这条,就能明白「这个方案是故意这样设计的,并非因为没有想到其他方式」。
节点三:实现上下文文档
每次中断开发前更新,格式固定:
# 当前进度
> 正在做:HomeViewModel 的状态管理重构
## 已完成
- [x] DataRepository 接口定义完成
- [x] 本地缓存逻辑迁移完成
## 待完成
- [ ] HomeViewModel 注入新 Repository
- [ ] UI 层 collect StateFlow 改造
- [ ] 单测补充
## 已知问题 / 注意事项
- UserSessionManager 是全局单例,不能在 ViewModel 里持有强引用
- 网络请求统一走 NetworkModule,不要直接 new
格式不重要,重要的是下次打开新窗口时,直接粘贴这个文件,AI 就能在几句话内恢复现场,无需你重新交代背景。
节点四:收尾文档
需求完成后生成,供下一个需求使用:
- 改了什么(精确到模块)
- 没改什么(哪些地方绕开了,原因是什么)
- 遗留问题(临时方案、技术债、已知 bug)
- 下次继续的入口(如果还有后续工作)
三、第二层:重复操作,沉淀成 Skill
Harness Engineering 中有一条原则:给模型最小化、最精确的能力集。工具越少越聚焦,AI 的执行越可靠。
映射到开发流程中:将高频重复的操作从每次临时描述,转变为可复用的标准 Skill。
经过一段时间的 AI 辅助开发后,你会发现有些 prompt 需要反复书写:
- 「帮我 review 这段代码,重点关注空指针、线程安全、内存泄漏」
- 「按照项目的 ViewModel 规范帮我生成骨架,使用 StateFlow,错误状态用 sealed class」
- 「帮我分析这个 ANR 日志,找出主线程被谁阻塞」
每次临时写,措辞不一致,AI 的输出质量也不稳定。将这些提炼成 Skill 文件,存储在 .ai/skills/ 目录下:
.ai/skills/
android-code-review.md # Android 代码 review 标准
viewmodel-generator.md # ViewModel 骨架生成规范
anr-analyzer.md # ANR 日志分析流程
unit-test-template.md # 单测生成模板
context/
current-task.md # 当前任务上下文(节点三)
tech-decision.md # 本次技术决策(节点二)
PROJECT_MEMORY.md # 项目长期记忆(见下一节)
Skill 文件的内容并不复杂,就是一个结构化的 prompt 模板,需写明:触发时机、输入格式、期望输出、项目特有约束。
举例来说,android-code-review.md 的核心内容:
# Android Code Review Skill
## 触发方式
用户说"review 一下这段代码"或"帮我看看这个"时使用
## 必须检查的维度(按优先级)
? 严重:空指针/NPE 风险、内存泄漏、线程安全问题
? 一般:异常未处理、资源未关闭、魔法数字
? 建议:命名规范、方法长度、重复代码
## 项目特有约束
- 所有网络请求必须在 IO dispatcher 执行,不能在 Main
- Context 引用只能用 ApplicationContext,禁止持有 Activity
- 错误状态统一用 sealed class Result
## 输出格式
每个问题:严重程度 | 文件:行号 | 问题描述 | 修复建议(附代码)
积累路径非常自然:第一次临时写 prompt,觉得好用,就提炼成 Skill 文件,下次直接 @skills/android-code-review.md 引入。时间长了,你的 Skill 库就是你自己团队对 AI 的使用规范。
四、第三层:全局认知,固化成长期 Memory
Harness Engineering 中的另一条原则:让模型的初始状态可重现,而非随机。每次对话开始时注入的内容必须是固定结构,不能随窗口漂移。
映射到开发流程中:将项目的全局认知固化成一份 Memory 文件,确保每次 AI 进场时的「世界观」保持一致。
在项目根目录建立 PROJECT_MEMORY.md,持续维护以下内容:
架构决策
## 架构决策
- 使用 MVI 而非 MVVM:因为状态变更来源复杂(网络+本地+用户操作),单向数据流更容易追踪,并非出于追潮流
- 网络层用自研 HttpEngine 而非 OkHttp:历史原因,已有大量业务依赖,不要引入 OkHttp,哪怕只是试验
- 图片库用 Glide 不用 Coil:团队熟悉度,且 Glide 在我们的 GIF 场景表现更稳定
禁区清单
## 禁区(不要动,动了会出问题)
- UserSessionManager:全局单例,状态管理极其复杂,任何改动需要专项评审
- BaseActivity/BaseFragment:所有页面的基类,改一行影响全局
- NetworkInterceptorChain:鉴权逻辑在里面,不能随意增删拦截器
历史踩坑
## 历史踩坑
- MessageListAdapter 的 DiffUtil:曾经因为 areContentsTheSame 实现有 bug 导致消息列表闪烁,2025-Q3 修复,见 commit a1b2c3d
- 横竖屏切换时 ViewModel 数据丢失:根因是某个 ViewModel 没走 SavedStateHandle,2025-Q4 全量排查过一次
- 大图预览内存溢出:超过 4MB 的图片要用 BitmapRegionDecoder 分块加载,不能直接 decodeStream
当前技术债
## 已知技术债(临时方案,不要学,不要扩散)
- HomeFragment 里有一段硬编码的配置,计划 Q2 迁移到远端配置
- ProfileRepository 的缓存策略是手写的,后续统一换 Room
- 推送通知的渠道 ID 是 hardcode 字符串,应该用常量管理
这份文件的价值不仅面向 AI。新人入职、需求交接、编写技术方案时,直接粘贴进去,上下文便瞬间到位。
五、高风险操作前,停下来确认
Harness Engineering 中的「危险操作拦截」:涉及外部写入、数据删除、发送消息的操作,不能靠提示词约束,必须在代码层做硬拦截。
映射到开发流程中:涉及架构变动、公共组件修改、不熟悉模块时,主动停下来,不要让 AI 直接执行。
这条建议看似废话,但却是大多数翻车的真正原因。AI 给你一个改动方案,你觉得看起来合理,便直接让它执行。结果发现影响到了你未曾预料的地方。
建议在 PROJECT_MEMORY.md 中维护一个「变更前需人工评估」的清单,在新需求开始时让 AI 先读一遍:凡是本次改动涉及清单中的任何一项,先进行影响范围分析,不要直接动代码。
六、三层结构串起来
文档、Skill、Memory,三层分工非常清晰:
三层的关系:
- 文档是当次任务的上下文,解决「换窗口后恢复现场」的问题
- Skill 是可复用的能力,解决「高频操作标准化」的问题
- Memory 是长期的项目认知,解决「AI 每次进场世界观一致」的问题
一个形象的类比:文档是工作日志,Skill 是工具箱,Memory 是老员工的经验手册。
七、最后
Harness Engineering 的核心洞察是:大多数 Agent 出问题,不是模型的问题,而是脚手架的问题。
用 AI 辅助开发也一样:大多数「AI 没帮上忙」,并非模型不够聪明,而是我们没有给它一个可以稳定工作的框架。每次裸着进场,每次从头开始,输出质量自然波动不定。
这套三层结构——文档 + Skill + Memory——搭建起来之后,AI 换窗口不再是负担。你积累得越多,AI 对项目越「懂」,新需求的启动成本也越低。
工具在变,模型在迭代,但这个问题始终不变:如何在 AI 的不确定性之上,构建你工作流程的确定性。
下一篇打算聊多步任务的 checkpoint 设计——当一个需求跨越数天、涉及多个模块时,如何设计断点,让任务能够从中途恢复,而非推倒重来。
