Harness Engineering 给我的启发:用 AI 做 Android 需求,怎么不翻车

最近读到一篇文章,把 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/ 目录里,和代码一起 commit:

节点一:需求理解文档

在需求拆解结束后生成,让 AI 输出:

• 需求拆解:把一句话需求拆成具体的功能点

• 边界确认:哪些在范围内,哪些明确不做

• 疑问列表:AI 不确定的地方列出来,让你当场确认

这一步的价值不只是备忘,更重要的是:让你在进入实现之前,就发现 AI 对需求的理解和你的理解有没有偏差。

节点二:技术方案文档

方案确定后生成:

• 涉及文件列表(精确到文件路径)

• 改动范围描述

• 关键决策及理由(为什么选这个方案,备选方案是什么,为什么没选)

「关键决策及理由」这一条很多人会跳过,但它恰恰是换窗口之后最难重建的信息。AI 下次进来,看到这条,就知道「这个方案是故意这样设计的,不是因为没想到其他方式」。

节点三:实现上下文文档

每次中断开发前更新,格式固定:

markdown 复制代码
# 当前进度
> 正在做:HomeViewModel 的状态管理重构

## 已完成
- [x] DataRepository 接口定义完成
- [x] 本地缓存逻辑迁移完成

## 待完成
- [ ] HomeViewModel 注入新 Repository
- [ ] UI 层 collect StateFlow 改造
- [ ] 单测补充

## 已知问题 / 注意事项
- UserSessionManager 是全局单例,不能在 ViewModel 里持有强引用
- 网络请求统一走 NetworkModule,不要直接 new

格式不重要,重要的是下次打开新窗口的时候,把这个文件贴进去,AI 能在 3 句话内恢复现场,不用你重新交代。

节点四:收尾文档

需求完成后生成,写给下一个需求用:

• 改了什么(精确到模块)

• 没改什么(哪些地方绕开了,为什么)

• 遗留问题(临时方案、技术债、已知 bug)

• 下次继续的入口(如果还有后续工作)

三、第二层:重复操作,沉淀成 Skill

Harness Engineering 里有一条原则:给模型最小化、最精确的能力集。工具越少越聚焦,AI 的执行越可靠。

对应到开发流程里:把高频重复的操作从每次临时描述,变成可复用的标准 Skill

做了一段时间 AI 辅助开发之后,你会发现有些 prompt 你反复在写:

• 「帮我 review 这段代码,关注空指针、线程安全、内存泄漏」

• 「按照项目的 ViewModel 规范帮我生成骨架,用 StateFlow,错误状态用 sealed class」

• 「帮我分析这个 ANR 日志,找出主线程被谁 block 了」

每次临时写,每次措辞不一样,AI 的输出质量也不稳定。把这些提炼成 Skill 文件,存到 .ai/skills/ 目录下:

bash 复制代码
.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 的核心内容:

ruby 复制代码
# 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,持续维护以下内容:

架构决策

markdown 复制代码
## 架构决策
- 使用 MVI 而非 MVVM:因为状态变更来源复杂(网络+本地+用户操作),
  单向数据流更容易追踪,不是因为追潮流
- 网络层用自研 HttpEngine 而非 OkHttp:历史原因,已有大量业务依赖,
  不要引入 OkHttp,哪怕只是试验
- 图片库用 Glide 不用 Coil:团队熟悉度,且 Glide 在我们的 GIF 场景
  表现更稳定

禁区清单

markdown 复制代码
## 禁区(不要动,动了会出问题)
- UserSessionManager:全局单例,状态管理极其复杂,任何改动需要专项评审
- BaseActivity/BaseFragment:所有页面的基类,改一行影响全局
- NetworkInterceptorChain:鉴权逻辑在里面,不能随意增删拦截器

历史踩坑

markdown 复制代码
## 历史踩坑
- MessageListAdapter 的 DiffUtil:曾经因为 areContentsTheSame 
  实现有 bug 导致消息列表闪烁,2025-Q3 修复,见 commit a1b2c3d
- 横竖屏切换时 ViewModel 数据丢失:根因是某个 ViewModel 没走
  SavedStateHandle,2025-Q4 全量排查过一次
- 大图预览内存溢出:超过 4MB 的图片要用 BitmapRegionDecoder
  分块加载,不能直接 decodeStream

当前技术债

markdown 复制代码
## 已知技术债(临时方案,不要学,不要扩散)
- HomeFragment 里有一段硬编码的配置,计划 Q2 迁移到远端配置
- ProfileRepository 的缓存策略是手写的,后续统一换 Room
- 推送通知的渠道 ID 是 hardcode 字符串,应该用常量管理

这份文件的价值不只是给 AI 看的。新人入职、交接需求、写技术方案------贴进去,上下文立刻到位。

📌 维护这份文件的关键不是「写得全」,是「写得及时」。每次做完一个需求,花五分钟更新一下踩坑记录和技术债清单,长期下来价值极大。

五、高风险操作前,停下来确认

Harness Engineering 里的「危险操作拦截」:涉及外部写入、数据删除、发送消息的操作,不能靠提示词约束,要在代码层做硬拦截。

对应到开发流程里:涉及架构变动、公共组件修改、不熟悉模块的时候,主动停下来,不要让 AI 直接执行

这条看起来像废话,但它是大多数翻车的真正原因。AI 给你一个改动方案,你觉得看起来挺对,直接让它改了。改完发现影响了你没想到的地方。

建议在 PROJECT_MEMORY.md 里维护一个「变更前需要人工评估」的清单,在开始新需求时让 AI 先读一遍:凡是这次改动涉及清单里的任何一项,先给我分析影响范围,不要直接动代码。

六、三层结构串起来

文档、Skill、Memory,三层分工很清楚:

flowchart TD A[开始一个需求] --> B[冷启动:注入 PROJECT_MEMORY.md] B --> C[需求拆解] C --> D[生成需求理解文档] D --> E[技术方案设计] E --> F[生成技术方案文档] F --> G{涉及禁区?} G -->|是| H[人工确认影响范围] H --> I[开始实现] G -->|否| I I --> J[使用对应 Skill 辅助编码/Review] J --> K{中断开发?} K -->|是| L[更新实现上下文文档] L --> M[下次:冷启动恢复现场] M --> I K -->|否| N[需求完成] N --> O[生成收尾文档] O --> P[更新 PROJECT_MEMORY.md]

三层的关系:

文档是当次任务的上下文,解决「换窗口后恢复现场」的问题

Skill 是可复用的能力,解决「高频操作标准化」的问题

Memory 是长期的项目认知,解决「AI 每次进场世界观一致」的问题

类比一个说法:文档是工作日志,Skill 是工具箱,Memory 是老员工的经验手册。

七、最后

Harness Engineering 的核心洞察是:大多数 Agent 出问题,不是模型的问题,是脚手架的问题。

用 AI 辅助开发也一样:大多数「AI 没帮上忙」,不是模型不够聪明,是我们没有给它一个可以稳定工作的框架。每次裸着进,每次从头开始,输出质量当然不稳定。

这套三层结构------文档 + Skill + Memory------搭起来之后,AI 换窗口不再是负担,你积累的越多,AI 对你的项目越「懂」,新需求的启动成本也越低。

工具在变,模型在迭代,但这个问题始终不变:怎么在 AI 的不确定性上,构建你工作流程的确定性

下一篇打算聊多步任务的 checkpoint 设计------当一个需求跨越多天、涉及多个模块的时候,怎么设计断点,让任务可以从中途恢复而不是推倒重来。

相关推荐
程序员鱼皮3 小时前
我的免费 OpenClaw 零基础教程,爆了!
ai·程序员·编程·ai编程·openclaw
ApeAssistant4 小时前
AI 都能写代码了,我们还在意光标是否丝滑吗?
ai编程·intellij idea
CaracalTiger4 小时前
Windows 环境下 OpenClaw 的安装与千问Qwen、Kimi、MiniMax、GLM国产大模型配置完全指南
运维·ide·windows·开源·github·aigc·ai编程
AI_Ming4 小时前
从0开始学AI:Transformer,原来是这回事!
人工智能·openai·ai编程
AI_Ming4 小时前
从0开始学AI:Embedding,原来是这回事!
算法·ai编程
怕浪猫5 小时前
第5章 输出解析:让模型返回结构化数据
langchain·llm·ai编程
逆向新手5 小时前
chrome-devtools-mcp不能远程调试的问题与解决方法_2026-03-25
爬虫·ai编程·逆向
小程故事多_805 小时前
Claude Code实战指南,OpenSpec与Superpowers协同开发,让后端开发更规范、更高效
数据库·人工智能·架构·aigc·ai编程
咕噜签名-铁蛋5 小时前
鲲鹏CCA赋能OpenClaw,筑牢AI安全防线,开启AI智能体安全新纪元
人工智能·安全·ai编程