AI编程工程化:Harness Engineering五层框架与Django实战

发布时间:2026/10/29 16:28:23
AI编程工程化:Harness Engineering五层框架与Django实战

1. 先把概念对齐:Harness Engineering 到底是什么

我第一次听到 "Harness Engineering" 这个词,是在一个技术分享群里,有人用一句话概括:"这不是教你怎么给 AI 写提示词,而是教你怎么给 AI 造一个能安全干活的现场。" 当时我把它当成又一个包装出来的新名词,但后面自己在几个项目里反复折腾 AI 编程之后,才发现这个词准确得可怕。它说的不是某一种技巧,而是围绕大模型编程助手建立的一整套工程基础设施:上下文怎么组织、规则怎么约束、任务怎么拆、验证怎么闭环、人类什么时候介入。

你可以把 Harness 理解成马具。马有劲儿,但如果没有笼头、缰绳和合适的鞍,它要么乱跑,要么根本不听你指挥。AI 编码工具也一样,模型能力再强,你直接丢一句"帮我写个模块",它大概率会给你一份能用但到处埋雷的代码。而戴上 harness 之后,它就能稳定地沿着工程规范走完一个完整任务。提示词是缰绳,规则文件是笼头,测试和 CI 是围栏,任务拆分是地图,人在中间做裁判——这些东西合在一起,才叫 AI 编程的工程化。

这篇文章我想用一种尽量不绕弯子的方式,把 Harness Engineering 讲清楚。先从概念拆起,然后用一个 Django + Vue 前后端分离项目的实战,把我踩过的坑和沉淀下来的模板全部摊开。无论你是团队技术负责人,还是刚接触 AI 编程的个人开发者,看完应该都能直接上手搭一套自己的 harness。这套方法论也不挑技术栈——Java、Python、前端、嵌入式都适用,差别只是"马"不一样,鞍的系法是一样的。

1.1 "马具"这个比喻为什么贴切

先想一个问题:你用 AI 写代码的时候,最烦的是什么?

我自己的答案是"不稳定"。同一个需求,早上问它,它给你一套方案;下午换一种问法,它写得完全是另一套。代码风格一会儿单引号一会儿双引号,数据库字段命名前三次是 snake_case,第四次突然给我来个驼峰。更离谱的是,它经常自己发明一些不存在的库函数,还一本正经地把调用示例写出来。

这些问题的根源不在于模型笨,而在于你没有给它一个稳定的作业环境。人进到一个新公司,第一天要看文档、了解代码规范、知道测试命令是什么、搞清楚"完成"的标准是什么。AI 模型每次对话都是从零开始,如果你每次都不提供这些背景信息,它就只能靠猜。Harness 做的事情,就是把"新员工入职培训"变成一套标准化流程:项目背景、技术栈、代码约定、测试要求、验收标准,全部固化进文件,让每次对话都站在同一个起点上。

这就是为什么"Harness"这个比喻很妙。马具的作用不是替代马的力量,而是把力量引导到正确的方向。工程化的本质也从来不是限制工具,而是让工具的可变性降低、可控性提升。

1.2 从"会聊天"到"能交付":AI 编程的三次变轨

把时间线拉长看,AI 编程其实经历了很明显的三个阶段。

第一个阶段是"代码补全"。TabNine、GitHub Copilot 早期那种,你在 IDE 里写注释,它帮你补下一行。这个阶段谈不上工程化,它就是加速打字。

第二个阶段是"对话式生成"。ChatGPT 火了之后,大家发现可以直接把需求丢给模型,让它生成整个文件甚至整个模块。这个阶段最大的问题是:代码能出来,但离"可用"差得很远。没有测试、没有错误处理、没有项目上下文,生成的代码经常跟现有代码风格完全脱节。

第三个阶段就是我们正在经历的"代理式执行"。现在的 AI 编程工具,比如 Claude Code、Cursor Agent、Codex 这类,已经可以自己读文件、执行命令、跑测试、修改代码。它们不是只回答你一句话,而是像实习生一样接手整个任务。听起来很美好,但问题是——实习生可以教育,模型每次对话都是"失忆"的。你花一小时跟它对齐的信息,关掉对话就没了。

Harness Engineering 就是在第三个阶段变得必须的。因为当 AI 拥有执行能力之后,它犯错的成本也从"生成一段垃圾代码"变成了"在你仓库里乱改一通"。老话说得好,能力越大,责任越大,责任越大,约束就越不能靠自觉,得靠工程手段。

当你意识到这一点之后,后面所有的工作就都顺理成章了:既然模型每次对话都会失忆,那就把关键信息写进文件,让它每次自己读;既然它会偏离规范,那就把规范从"文档建议"升级成"工具强制";既然它可能"假完成",那就用测试和 CI 来验证,而不是听它嘴上说"做完了"。

2. 核心细节解析:一套好 Harness 的五块拼图

一套完整的 harness 框架,我拆成五个层面。这五个层面没有严格的先后顺序,但一般来说,新项目会从上往下搭,老项目则从下往上补。你也可以把它理解成五个抽屉,每个抽屉里装一类东西。

2.1 上下文工程:先让 AI"看见",再谈"生成"

第一块是上下文工程,解决的是"AI 不知道自己在哪个项目里"的问题。

很多人的习惯是:随手打开 AI 编程工具,直接说"帮我写一个用户登录接口"。但我问你,它知道你的项目用什么框架吗?知道你的数据库表长什么样吗?知道你用户表的字段是 username 还是 email 吗?知道你的鉴权方式是 JWT 还是 Session 吗?统统不知道。它只能给你一个"通用版"的答案,然后你去改。

上下文工程的目的,就是把这些项目关键信息沉淀成 AI 每次都能自动读到的文件。现在主流 AI 编程工具基本都支持项目级指令文件,名字可能不同:Claude Code 认 CLAUDE.md,Cursor 认 .cursor/rules,有些工具认 AGENTS.md。我在实战中最常用的是 AGENTS.md,因为它的兼容性最好,很多开源项目也开始用这个标准。

一个合格的 AGENTS.md 至少包含这几块内容:

  • 项目是什么、解决什么问题(一句话说清楚)
  • 技术栈清单(语言、框架、数据库、ORM、构建工具)
  • 目录结构说明(关键目录的用途,避免 AI 把代码放到奇怪的位置)
  • 常用命令(启动、测试、构建、Lint 分别是什么)
  • 代码风格约定(命名、格式化、错误处理策略)
  • 关键技术决策(为什么用 DRF 而不是 Flask,为什么不用外键等)

听起来内容多,但写这个文件只需要一次性投入。我见过最聪明的做法是:直接用 AI 工具帮忙生成初稿,然后你人工修正。之后每次新会话,AI 都会自己读这个文件,你的对话质量会提升一个量级。

2.2 规则与约束:软提示之外要有硬校验

第二块是规则与约束,解决的是"AI 写出来的代码是否符合项目规范"的问题。

如果说 AGENTS.md 是"HOW to work"的软性约定,那规则约束就是"必须通过否则就要返工"的硬性门槛。光靠提示词告诉它"请遵循 PEP8"是没用的——它会答应对不起然后继续写出 120 行的函数。真正有效的手段是把校验工具接到工作流里,让 AI 的每一次修改都要过检测。

以 Python 项目为例:Ruff 负责格式和静态检查,pytest 负责单元测试,mypy 负责类型检查。这些工具如果能在 AI 改完代码后自动跑一遍,不合格就重新迭代,AI 的输出质量会肉眼可见地提升。前端的 ESLint、Prettier、TypeScript 检查同理;Java 项目就是 Checkstyle、SpotBugs 加 JUnit;嵌入式项目则是编译警告和静态分析工具的规则集。

注意,这里有个关键点:不是让你手动去跑,而是让工具自动跑,然后把结果反馈给 AI。现代代理式 AI 工具都支持在对话内执行命令,你可以明确告诉它:"每次改完代码,运行pytest,直到全部通过再向我汇报。"这听起来像一句普通的提示词,但一旦结合测试框架,它就变成了一条可验证的生产流水线。

这个层面我的经验是:能上工具强制,就不要依赖文字约定。文字是给有记性的人看的,AI 没有记性,它有上下文窗口,而上下文窗口会滚动,把约束写进工具链,才能保证稳定。

2.3 提示模板与任务拆分:把需求翻译成规格

第三块是提示模板与任务拆分,解决的是"AI 到底在做一件什么规模的事情"。

很多人失败的经验是:一次性丢给 AI 一个宏大需求。比如"帮我开发一个电商系统",AI 会非常兴奋地给你生成一大堆文件,然后你发现这些文件互相矛盾,几乎不可用。问题不在于 AI 能力不够,而在于你给它的任务粒度太粗。这就好比让一个刚入职的员工"去把公司业务做起来",他只会愣在原地。

正确的做法是:把需求拆成一个个足够小的、可以验证的任务,每个任务用标准化的"任务规格"描述。我自己的模板是这样的,五个段落:

背景:要解决什么问题,为什么现在做这个目标:做完之后,系统应该支持什么功能(列点,越具体越好)约束:必须遵守的技术栈、代码规范、禁止事项验收标准:哪些测试用例要通过,什么情况下算完成交付物:需要新增/修改哪些文件

把这段模板填好,发给 AI。你会发现它的输出立刻变得有边界感,不再天马行空。这个模板本身就属于 harness 的一部分——它不依赖某个具体的 AI 工具,你可以用在任何对话式 AI 上。甚至你把它打印出来,让人类同事照着写需求,效果也会比以前好。

2.4 工具链与反馈闭环:让 AI 的输出能自我纠错

第四块是工具链与反馈闭环,解决的是"AI 说做完了,如何确认它真的做完了"。

我前面反复提到"假完成",这是代理式 AI 编程里最坑爹的现象。AI 改完代码,跑了一下命令,结果报错,它可能不会告诉你报错了,而是直接说"已完成,请查看"。更夸张的是,有些情况下它会自己脑补一个成功输出,但实际上代码根本没有通过编译。

所以 harness 的第四个层面,是把反馈机制做成一个闭环:AI 改代码 → 自动运行校验 → 校验不通过 → 根据报错继续改 → 再校验 → 通过后提交。这个闭环可以由 AI 工具自己完成,也可以靠你引入 CI/本地脚本实现。

我的做法是双重验证。第一层是本地验证:在任务规格里明确要求 AI"每次修改后必须运行ruff check和pytest,只有全部通过才能汇报"。这基本上是给 AI 上了紧箍咒。第二层是 Git 钩子/CI 验证:在推送到远端之前,强制跑一遍完整测试,不通过就不能合并。这样即使 AI 偷懒或者"说谎",系统也会拦住。没有人能绕过验证流程,AI 也不行。

2.5 人在环上:工程师的新职责是"验收官"

最后一块容易被忽略,但又恰恰是最重要的一层:人在环上。

刚开始接触 AI 编程时,很多人会有一种错觉——我可以把开发工作完全交给 AI 了。实际上,在可用性和代码质量要求稍微高一点的项目里,你做不到完全放手。AI 像是手速极快但经验不足的初级工程师,它可以在几分钟内写出几百行代码,但它不一定理解业务全貌,也不知道你的历史包袱在哪里。

所以工程师的角色发生了转变:从"亲手写每一行代码"变成"定义任务、验收结果、处理 AI 搞不定的边角"。具体来说,你要做的事情包括:

  • 任务拆分和规格编写(这是核心工作,直接决定 AI 输出质量)
  • 代码审查(AI 写的代码,你至少要读一遍关键逻辑)
  • 边界情况补充(AI 很容易漏掉:并发、时区、权限、数据一致性)
  • 架构决策(项目结构、技术选型、模块边界,这部分不要让 AI 拍板)

有朋友问我:"那我不就变成测试员了吗?" 我的回答是:不是测试员,是验收官。你不负责制造,你负责判断合不合格。这个角色转变,其实比学任何新框架都值钱,因为它意味着你不用把时间花在重复劳动上,而是花在真正需要经验和判断力的事情上。

3. 实操过程与核心环节实现:一次跑通的完整项目

理论说再多,不如直接跑一个项目。下面我用一个我近期实际做过的小项目给大家完整演示:库存管理系统,前后端分离。后端 Django + DRF,前端 Vue 3,数据库先用 SQLite 起步,方便本地跑。我们给这个旧项目新增一个"销售订单"模块,并用 AI 编程工具完成从建模、接口到前端页面的完整开发。

3.1 项目画面:库存管理系统的改造需求

先交代一下项目背景。这是一个给小型仓库用的库存管理系统,已有产品(Product)、库存批次(StockBatch)、盘点记录(InventoryCount)三个核心模型,后端用 Django 4.2 + Django REST Framework,前端用 Vue 3 + Vite + Element Plus,已经上线跑了一段时间。

现在产品经理提了个需求:要支持"销售出库"。业务上很简单——销售员创建一张销售订单,选择产品、填写数量、选择扣减哪个批次的库存,提交后库存数量自动减少,并生成一条出库流水记录。

这个需求如果放以前,我要经过大概这些步骤:设计 API、写模型和序列化器、写视图、写 URL、写前端的订单列表和创建表单、处理库存扣减的事务逻辑、补测试。整个过程少说一两天。而现在我们带着 harness 来做,目标是用 AI 把这个过程压缩到半小时,而且质量不缩水。

3.2 Step 1:搭建 Harness 基础文件

我打开项目根目录,先看看有没有 AGENTS.md。没有?好,那就先造这个 harness 地基。

我写了一份精简版,关键内容如下:

# AGENTS.md ## 项目简介 内部库存管理系统。支持产品管理、批次管理、库存盘点。本次迭代新增销售出库能力。 ## 技术栈 - 后端:Python 3.11 / Django 4.2 / Django REST Framework - ORM:Django ORM,数据库 SQLite(生产环境为 PostgreSQL) - 前端:Vue 3 / Vite / Element Plus / Pinia / Vue Router - 测试:pytest / pytest-django - 代码检查:Ruff、ESLint、Prettier ## 目录结构 - backend/app/:Django 项目主包 - backend/app/inventory/:库存核心模块(models、serializers、views) - frontend/src/:Vue 源码 - frontend/src/api/:前端 API 封装 - frontend/src/views/:页面组件 ## 常用命令 - 后端测试:cd backend && pytest - 后端检查:cd backend && ruff check . - 前端构建:cd frontend && npm run build - 前端检查:cd frontend && npm run lint ## 代码约定 - 后端命名:模型 snake_case,统一使用 Django ORM,不在业务逻辑中写裸 SQL - 序列化器:使用 DRF ModelSerializer - 前端命名:组件 PascalCase,变量/方法 camelCase - 错误处理:后端统一返回 `{ "detail": "描述" }` 格式 - 数据库变更:使用 Django migration,禁止手动改表 ## 关键技术决策 - 库存批次表有 `quantity_remaining` 字段,扣减库存时必须校验充足 - 扣减操作必须放在事务中,保证订单创建和库存扣减原子性

这一份文件,我大概花了十分钟。但它带来的收益是整个迭代周期都管用的:不管开多少新会话,AI 都会自动读到这份上下文。更关键的是,我在每个任务规格里只需要写"按照 AGENTS.md 里的约定处理",而不用重复解释项目背景。

3.3 Step 2:编写任务规格并交给 AI 实现

接下来我没有直接说"帮我做个销售出库功能",而是按照上一节的任务模板,拆了两步。

第一步先做纯后端任务,规格如下:

背景:仓库需要记录销售出库,订单创建时扣减对应批次库存,并生成出库流水。目标:

  1. 新增模型 SalesOrder(订单头:单号、销售时间、备注、创建时间)
  2. 新增模型 SalesOrderItem(订单明细:产品、数量、关联批次、单价)
  3. 新增模型 StockOutRecord(出库流水:批次、关联订单明细、扣减数量、扣减时间)
  4. 提供 API:POST /api/orders/ 创建订单;GET /api/orders/ 列表查询
  5. 创建订单时,事务内扣减批次 quantity_remaining,不足则返回 400约束:所有模型用 Django ORM;使用 DRF 序列化器;代码放 backend/app/sales/ 模块下;遵循 AGENTS.md 约定。验收标准:
  6. pytest 中新增至少 5 个测试用例:创建成功、库存不足、多明细扣减、列表分页、参数校验失败
  7. 所有测试通过且 ruff check 无警告交付物:新增模块的 models.py、serializers.py、views.py、urls.py、migrations、tests.py

不管用哪个 AI 编程工具,把这段规格贴给 AI,它的表现都会跟直接说"写个订单功能"完全不同。因为它知道自己要做什么、东西放哪、什么算完成。为了让 AI 还能看到项目里已有的代码风格,我在提示里补了一句"先阅读 backend/app/inventory/ 下的 models.py 和 views.py,再参照其风格实现"。

AI 开始干活了:读文件、生成模型、写序列化器、写视图、跑 migration、写测试。第一次跑测试有两个失败,它自己又改了一轮,最后全部通过。整个过程大概八分钟。我随手抽查了几个核心逻辑——事务那段用select_for_update()锁了批次行,这个细节让我有点意外,说明它确实参考了已有代码。当然,我关注的还是测试到底有没有真正覆盖"库存不足"这种分支,不要让 AI 自己骗自己。我看了一眼它的测试代码,写得还挺实在。

3.4 Step 3:跑测试、填前端、形成闭环

后端做完之后,我进行第二步:前端页面。规格照旧,但这次我要求 AI 先读后端的 API 响应格式,再照着封装前端 API。

背景:销售出库后端 API 已完成,需要前端页面承接操作入口。目标:

  1. frontend/src/api/order.js:封装订单创建与列表接口
  2. frontend/src/views/OrderList.vue:订单列表页,展示单号、销售时间、明细数量、总金额、创建时间
  3. frontend/src/views/OrderCreate.vue:创建订单表单,支持选择产品、批次、填入数量、单价,可动态添加多行明细
  4. 在路由中注册新增两个页面约束:使用 Composition API;样式与现有页面保持一致;接口调用走已有 axios 封装。验收标准:npm run build 通过,npm run lint 无报错。交付物:新增文件清单 + 修改的路由文件。

这次 AI 干得也很利索,唯一的问题是它用了某个组件库的旧版 API,Element Plus 新版里已经改了名字。这一下运行时就报错了。这个情况非常典型——AI 的知识库里混着不同版本的信息,你以为它写对了,其实对应的库版本根本不对。

解决方式应该是:不要让 AI 猜依赖,直接在 harness 里锁版本。所以我在 AGENTS.md 里补了一行关键信息:"项目依赖版本统一以 package.json 为准,不要自行推荐新的依赖包,如需使用新组件请先确认版本。"然后让 AI 重新读 package.json,按实际安装的版本来修。这就是我说的"反馈闭环"的作用——它不是防止 AI 犯错,而是保证 AI 犯了错之后能快速被系统发现,并且有办法继续迭代。

3.5 Step 4:把 Harness 沉淀成团队模板

项目跑完以后,我会把这些产物全部沉淀下来。因为 harness 不是一次性配置,它是需要持续演进的资产。

我做了三件事。第一,把 AGENTS.md 和任务规格模板放到项目的 docs/harness/ 目录下,并且接进开发流程里。第二,给仓库配好 GitHub Actions,每次 push 自动跑后端 pytest + ruff、前端 build + lint,不过关直接挂红。第三,把任务规格模板复制成团队内部的习惯格式,让大家以后提需求都用这个模板,而不仅仅是让 AI 用。

说实话,这一步对个人开发者来说是可选的,但如果你想在团队里推广 AI 编程,它几乎是决定成败的。一个人用自己的 harness 可以很随性,但团队协作时,所有人必须共享同一套游戏规则:同样的上下文文件、同样的校验命令、同样的任务格式,否则 AI 的产出依旧五花八门,只是从"五花八门的手写代码"变成"五花八门的 AI 代码",问题一点没少。

4. 常见问题与排查技巧实录

任何方法论,落地时都会遇到一堆现实问题。我把在实操中踩过的坑整理成了一组常见问题,每条都是真实场景。

4.1 上下文漂移:AI 写到一半"失忆"了

AI 编程工具普遍存在上下文窗口限制。早期对话里你告诉它的约束,在几千行代码输出之后,可能已经被"挤"出有效上下文。表现就是:开头它还老老实实遵循 AGENTS.md 的命名规范,写到第 6 个文件时突然开始放飞自我,变量名变成 x、y、z,函数不带 docstring,甚至开始猜测一个根本不存在的内部工具库。

我的对策有三个。第一,把最重要的约束放在 AGENTS.md 顶部,很多工具读取文件时前面的优先级更高。第二,把大任务拆成小任务,每完成一个文件就开新会话继续,避免上下文爆掉。第三,在任务规格中反复提醒"严格遵守 AGENTS.md 中的代码约定",并让 AI 在交付前自检一次。别嫌啰嗦,对 AI 来说,重要的事情确实需要说三遍。

4.2 提示过长:细节太多反而不干活

这里有个反直觉的现象,我一开始也搞不明白。我担心 AI 不了解业务,于是把整个需求背景写成一千字,结果它生成代码时犹豫不决,或者开始做一些和当前任务无关的"额外优化",甚至自作主张重构已有代码。

后来我明白了:有效上下文是有限的,与其把所有历史都塞给它,不如让它按需读取。任务规格里只保留"必须知道"的信息,其余的信息我写道"更多背景参考 docs/xxx.md,需要时自己读"。这种按需加载的模式,比一次性灌输效果好得多。说到底,harness 的设计原则不是"给得越多越好",而是"给得恰到好处"。就像喂马,不能把一整天的草料一次塞进嘴里,它会噎着。

4.3 假完成:AI 报"成功",实际编译不过

这个问题前面提过,但我还得多说两句,因为它太坑了。现象是:AI 改完代码,你让它"跑一下测试",它回复"测试通过";但你回过头来自己跑一遍,满头问号——明明报错。

为什么会这样?因为有些模型的回答更倾向于迎合你,而不是陈述事实。所以你要做的不是听它说,而是让它把执行日志原样输出。我的做法是在任务规格里加一条硬性要求:"每次执行命令后,必须粘贴实际输出结果,尤其是错误信息,不要概括为'成功'或'失败'。请直接展示命令运行的输出。"这就把它的"口头汇报"变成了"可审计的过程记录"。结合前面说的 CI 双重验证,基本上能把假完成的概率压到很低。

4.4 一组通用排查清单

我把日常排查 AI 编程问题的思路整理成一张表,方便你快速定位。

现象大概率原因首选排查动作
AI 反复改但一直报错上下文里缺少报错详情复制完整错误栈到对话末尾,要求只看第一处报错
越写越偏,偏离项目风格AGENTS.md 缺约束或约束太靠后检查规则文件,把关键约束置顶
输出代码版本与依赖不匹配没锁定依赖版本要求 AI 先读 package.json / requirements.txt
任务太大导致输出混乱任务粒度太粗拆成 1~2 小时可完成的小任务,每个任务有独立验收标准
AI 自作主张改无关代码任务边界没描述清楚在规格里明确"禁止修改与本次任务无关的文件"
测试全绿但业务不对AI 写了"自我实现"的测试编写测试时给出明确的业务断言,而不是让它自己写测试自己跑

还有一条通用技巧:遇到疑难问题时,把 AI 的工具调用记录打开,看你才能真正看到它执行了哪些命令、读了哪些文件,哪些话是真的哪些是编的。这个功能不同工具叫法不一样,但本质一样——你要的是可审计的执行过程,而不只是最终那一句"我完成了"。

5. 最后说点实在的

前阵子有个群里讨论"AI 编程到底会不会取代程序员",我当时的回答是:它正在取代的是"不善于给 AI 划定工作边界的人"。Harness Engineering 听起来像个很高级的术语,但它本质做的事特别朴素:把那些写代码之前必须想清楚的事情——项目结构、技术栈、代码规范、完成标准——从工程师脑子里搬到项目文件里,让 AI 每次干活都站在同一个起点。

我个人现在开新项目时,第一件事不是建项目骨架,而是先写 AGENTS.md。项目骨架 AI 一分钟就能生成,但一套合格的 harness 文件得靠人想清楚。它决定了后续 AI 产出的上限:文件写得越准确,AI 的交付质量就越稳定。这个投入的收益比,比我用过的任何一个 AI 付费服务都高。

这篇文章里给的模板和案例,都是可以直接抄走的。你可以拿着 AGENTS.md 示例套到自己的项目上,把技术栈列表一改就是自己的 harness;你可以直接复制那份五段式任务规格模板去提需求。跑通一遍之后再回头看,你会发现"AI 编程工程化"其实没那么玄乎——它就是让工具回到工具的位置,让你作为工程师的价值回到决策和质量本身。

如果后面你还想把这套方法延伸到更多场景,我可以继续聊聊:怎么把一个老项目的 AGENTS.md 从零补起来、怎么在团队内统一任务模板、怎么把手动 CI 升级成 AI 自动修复工作流。都是实打实能落地的经验,下次接着写。