Harness Engineering 可以理解为“驾驭大语言模型(Large Language Model,LLM)的工程方法”。它不直接训练一个更强的模型,而是通过上下文、约束、工具、状态机和治理机制,让模型在复杂工程任务里更稳定地工作。
在 AI 编程、需求分析、架构设计、代码生成、测试验证这些场景里,很多团队会把注意力放在两个问题上:
- 用哪个模型?
- 工作流要编排成多少个阶段?
这两个问题当然重要,但它们不是 AI 工程交付系统的长期壁垒。模型会升级,智能体(Agent)框架会变化,状态机也可能从串行流程演进成有向无环图(Directed Acyclic Graph,DAG)。真正能持续积累价值的是团队自己的领域知识:业务规则、架构决策、历史故障、最佳实践、反模式、流程约束。
换句话说,Harness 工作流是管道,知识才是管道里真正流动的东西。
Harness Engineering 解决的不是“模型不够聪明”,而是“模型缺少工程边界”
大模型具备很强的通用推理和生成能力,但工程交付不是纯文本问答。一个真实的软件需求通常会涉及:
- 业务流程是否理解正确;
- 既有系统架构是否被尊重;
- 技术选型是否符合团队约束;
- 历史上踩过的坑是否被避开;
- 代码实现是否符合项目规范;
- 产物是否可追溯、可回滚、可审查。
Harness Engineering 的目标,就是把这些约束组织起来,让 Agent 不只是“回答问题”,而是能够沿着可控流程完成工程任务。
可以把 Harness Engineering 拆成三个支柱:
| 支柱 | 解决的问题 | 典型机制 |
|---|---|---|
| 上下文工程 | Agent 当前应该知道什么,不应该知道什么 | 长短期记忆、知识检索注入、渐进式披露、上下文隔离 |
| 架构约束 | Agent 应该按什么结构行动 | Agent 编排、状态机、降级策略、安全边界 |
| 持续治理 | 工作流和知识如何持续变好 | 质量门禁、知识生命周期、引用追踪、过时清理 |
三者之间的关系可以用一张图表示:
flowchart TB
H[Harness Engineering] --> C[上下文工程]
H --> A[架构约束]
H --> G[持续治理]
C --> C1[长短期记忆]
C --> C2[知识检索注入]
C --> C3[渐进式上下文披露]
A --> A1[Agent 编排]
A --> A2[状态机设计]
A --> A3[安全边界与降级策略]
G --> G1[质量门禁]
G --> G2[知识生命周期]
G --> G3[自动衰减与 Lint]
知识管理不是 Harness Engineering 外围的“资料库”,而是上下文工程和持续治理的核心组成部分。没有知识库,工作流每次都从零开始;有了知识闭环,工作流才会随着交付次数增加而变得更可靠。
为什么知识沉淀比工作流本身更重要
一个 16 阶段工作流、一个多 Agent 协作系统、一个复杂状态机,都可能被替换。今天使用线性状态机,明天可能换成 DAG;今天使用某个 Agent 框架,明天可能换成另一个;今天需要手工设计计划,未来模型也可能内化更强的规划能力。
但类似这样的知识不会因为工具升级而失效:
广告预算扣减在高并发场景下容易出现超扣,需要通过 Redis + Lua 保证扣减逻辑的原子性。
这类知识来自业务和工程实践,模型很难凭空知道。它包含了三个层面的信息:
- 业务对象:广告预算;
- 风险场景:高并发扣减;
- 工程解法:Redis + Lua 原子操作。
如果工作流没有沉淀能力,每次遇到类似需求都要重新推理一次;如果知识库能把它记录下来,后续需求、其他项目、新成员都可以直接复用。
知识的复利效应来自持续积累:
flowchart LR
R1[第 1 次需求交付] --> K1[沉淀 3 条知识]
K1 --> R2[第 2 次需求交付]
R2 --> K2[复用旧知识 + 沉淀新知识]
K2 --> R3[第 3 次需求交付]
R3 --> K3[知识库覆盖更多场景]
K3 --> R4[新项目启动]
R4 --> K4[直接继承成熟经验]
工作流负责执行一次任务,知识库负责让每一次执行都留下可复用资产。
知识应该按三个维度组织
一个可用的 AI 工程知识库,不能只是把 Markdown 文件堆在一起。Agent 要能检索,人要能维护,团队要能协作,知识本身还要能表达可信度。
比较稳妥的设计是使用三维结构:
| 维度 | 要回答的问题 | 设计目标 |
|---|---|---|
| 存储层 | 知识属于个人、团队、业务域还是项目? | 控制共享边界和生命周期 |
| 知识类型 | 这条知识描述的是模型、决策、流程还是风险? | 方便检索、注入和治理 |
| 成熟度 | 这条知识验证过几次,可信程度如何? | 避免未经验证的经验误导 Agent |
五层存储:从个人偏好到项目上下文
不同知识的共享范围不同。个人编辑习惯不应该强加给整个团队,业务域规则也不应该混进某个项目私有目录里。
可以把存储层分成五层:
| 层级 | 目录示例 | 内容 | 共享范围 |
|---|---|---|---|
| Layer 0-P | ~/.ai-team/ | 个人偏好,如缩进、命名习惯、常用工具 | 仅个人 |
| Layer 0-T | team-conventions/ | 团队规范,如代码风格、提交规范、评审标准 | 团队 |
| Layer 1 | tech-wiki/ | 跨项目技术知识,如架构模式、技术陷阱 | 团队跨项目 |
| Layer 2 | biz-wiki/{domain}/ | 业务域知识,如领域模型、业务流程、业务规则 | 团队按业务域共享 |
| Layer 3 | docs/knowledge/ | 当前项目特有知识,如部署环境、项目约束 | 单项目 |
这种分层有两个好处:
- Agent 能根据阶段选择合适范围的知识,不会把个人偏好误认为团队规范;
- 项目里的经验如果具备通用性,可以提升到团队技术库或业务库。
知识提升路径可以这样设计:
flowchart TB
L3[Layer 3 项目知识] --> Q1{是否仅当前项目有效}
Q1 -- 是 --> Keep[留在 Layer 3]
Q1 -- 否 --> Q2{是否属于通用技术经验}
Q2 -- 是 --> L1[提升到 Layer 1 技术知识]
Q2 -- 否 --> Q3{是否属于通用业务域知识}
Q3 -- 是 --> L2[提升到 Layer 2 业务知识]
Q3 -- 否 --> Review[进入人工复核]
五种知识类型:让知识条目可检索、可注入
知识类型要尽量互斥,避免一条知识既像流程又像决策,导致 Agent 检索困难。工程交付场景里,五类已经能覆盖大多数知识形态:
| 类型 | 含义 | 示例 |
|---|---|---|
model | 实体、数据结构、关系模型 | 广告计划包含预算、出价、投放时段三个核心字段 |
decision | 技术选型、架构决策及理由 | 选择事件驱动而非同步远程过程调用(Remote Procedure Call,RPC),因为状态变更需要解耦 |
guideline | 推荐做法或禁止做法 | 公共模块变更后必须执行兼容性检查 |
pitfall | 已知风险、故障模式、排查步骤 | 高并发预算扣减可能超扣 |
process | 业务流程、状态机、操作步骤 | 广告审核流程:提交 → 机审 → 人审 → 上线 |
一条知识只属于一个类型,来源、适用阶段、标签、贡献者等信息放在元数据里。
一个知识条目可以写成这样的 Markdown:
---
id: BK-AD-P001
type: pitfall
title: 广告预算扣减在高并发下可能超扣
layer: 2
domain: advertising
maturity: verified
tags:
- budget
- concurrency
- redis
- lua
applicable_phases:
- ANALYSE_TECH
- ARCHITECT
- IMPLEMENT
evidence:
contributors:
- alice
projects:
- ad-delivery
last_referenced: 2026-04-12
---
## 问题
广告预算扣减如果使用“查询余额 → 判断余额 → 更新余额”的普通读写流程,
在高并发请求下可能出现多个请求同时通过余额判断,最终造成超扣。
## 适用场景
- 广告投放扣费
- 库存扣减
- 配额消耗
- 任何需要并发保护的余额类资源
## 推荐做法
将判断和扣减放进 Redis Lua 脚本中执行,保证同一 key 上的操作具备原子性。
## 反例
不要在应用层用多次 Redis 命令拼接扣减逻辑,否则中间状态会被并发请求打断。
三级成熟度:区分“刚记录”和“可依赖”
知识不是写入后就永远可信。一个人从单个项目里提取的经验,只能算初稿;跨项目验证过的经验,才更适合作为 Agent 的默认约束。
成熟度可以分为三级:
stateDiagram-v2
[*] --> draft: 新提取 / 单一来源
draft --> verified: 在 1 个工作流中成功引用
verified --> proven: 在至少 2 个项目中验证
proven --> verified: 12 个月未引用
verified --> draft: 6 个月未引用
draft --> archived: 长期未引用且 Lint 标记
对应规则如下:
| 成熟度 | 含义 | Agent 使用方式 |
|---|---|---|
draft | 新提取,来源单一,可信度有限 | 可以参考,但不应作为强约束 |
verified | 至少在一个实际工作流中验证 | 可用于阶段决策 |
proven | 多项目、多成员验证 | 可作为默认规则或强约束注入 |
自动衰减很关键。框架升级、业务调整、系统重构都会让旧知识失效。与其让过时知识长期留在活跃索引里误导 Agent,不如让它在长期未引用后自动降级,必要时归档。
团队知识库适合做成独立 Git 仓库
知识库不应该寄生在某个业务项目里。业务项目可能归档、拆分、迁移,但团队知识应该有独立生命周期。
一个典型目录结构如下:
team-knowledge.git
├── knowledge-catalog.md
├── .knowledge-config.yaml
├── team-conventions/
│ ├── coding-standards.md
│ └── commit-conventions.md
├── tech-wiki/
│ ├── catalog.md
│ ├── patterns/
│ │ └── TK-PAT-001.md
│ └── anti-patterns/
│ └── TK-AP-001.md
├── biz-wiki/
│ └── advertising/
│ ├── catalog.md
│ ├── entities/
│ │ └── BK-AD-E001.md
│ └── pitfalls/
│ └── BK-AD-P001.md
├── project-profiles/
└── contributions/
├── pending/
└── conflicts/
独立 Git 仓库带来三个直接收益:
| 设计点 | 收益 |
|---|---|
| 跨项目共享 | 项目 A 沉淀的知识,项目 B 可以直接检索 |
| 生命周期独立 | 项目归档后,经验仍然保留 |
| 权限独立 | 可以单独控制谁能读、谁能贡献、谁能裁决冲突 |
团队成员可以分成三类角色:
| 角色 | 权限 | 适合对象 |
|---|---|---|
maintainer | 审批成熟度提升、裁决冲突、管理成员 | 团队负责人、资深工程师 |
contributor | 创建知识、补充证据、标记矛盾 | 正式成员 |
reader | 检索和消费知识,不直接贡献 | 新成员、外部协作方 |
贡献方式:先暂存,再异步合并
知识贡献不适合要求所有人实时同步编辑。更低摩擦的方式是“贡献暂存 + 异步合并”:
flowchart LR
A[工作流产出知识候选] --> B[写入 contributions/pending]
B --> C{自动合并检查}
C -- 纯新增 --> D[合并到知识库]
C -- 证据追加 --> E[合并 evidence]
C -- 成熟度提升 --> F[更新 maturity]
C -- 内容矛盾 --> G[写入 conflicts]
G --> H[maintainer 裁决]
常见冲突可以这样处理:
| 冲突类型 | 处理策略 |
|---|---|
| 不同条目纯新增 | 自动合并 |
| 同一条目追加验证证据 | 合并 evidence 并去重 |
| 成熟度提升 | 自动合并 |
| 内容结论相反 | 放入 contributions/conflicts/ 等待裁决 |
| 一方提升、一方降级 | 保留较低成熟度,并标记矛盾 |
变更日志建议只追加、不覆盖:
## [2026-04-09] ingest | Steven | 门店履约视图归档 | +1 decision, +2 guideline | #a3f8c2
- 新增 DEC-005: 地图组件选型
- 新增 GL-012: fitBounds 在 flexbox 布局中的替代方案
## [2026-04-12] verify | Alice | 跨项目验证 | maturity +2 | #c5f0e2
- TK-SB-003 "分页查询延迟关联优化" verified -> proven
这样每条知识都能追溯到贡献者、时间、会话和验证记录。
工作流要服务于知识闭环
AI 工程交付工作流不只是把需求推进到上线,还应该在启动时消费已有知识,在结束时沉淀新知识。
一个完整闭环可以分成三段:
flowchart TB
Start[/flow-run 启动] --> Init[INIT: 拉取团队知识库]
Init --> Catalog[注入 knowledge-catalog.md 查询入口]
Catalog --> AnalyseProduct[业务分析阶段]
Catalog --> AnalyseTech[技术分析阶段]
Catalog --> Architect[架构设计阶段]
Catalog --> Implement[实现阶段]
Catalog --> Verify[构建验证阶段]
AnalyseProduct --> Archive[ARCHIVE: 提取知识]
AnalyseTech --> Archive
Architect --> Archive
Implement --> Archive
Verify --> Archive
Archive --> L3[写入 Layer 3 项目知识]
Archive --> Promote{是否可提升}
Promote -- 通用技术 --> L1[推送到 Layer 1 tech-wiki]
Promote -- 通用业务 --> L2[推送到 Layer 2 biz-wiki]
Promote -- 项目特有 --> L3
L1 --> Next[下一次工作流自动受益]
L2 --> Next
L3 --> Next
关键阶段如下:
| 阶段 | 知识动作 | 作用 |
|---|---|---|
INIT | git pull 团队知识库,注入全景目录 | 让 Agent 知道可查询的知识范围 |
| 执行中 | 按阶段检索相关知识 | 避免重复踩坑,复用既有决策 |
ARCHIVE | 从产物中提取 decision、pitfall、guideline 等条目 | 把一次交付变成可复用资产 |
| 提升判定 | 判断项目知识是否可提升到团队技术库或业务库 | 扩大知识复用范围 |
不同阶段应该查询不同知识,而不是把整个知识库塞给 Agent:
| 阶段 | 查询重点 | 适合知识类型 |
|---|---|---|
ANALYSE_PRODUCT | 业务域模型、历史需求、流程规则 | model, process, pitfall |
ANALYSE_TECH | 技术约束、历史架构决策、反模式 | decision, guideline, pitfall |
ARCHITECT | 架构模式、实体关系、技术选型依据 | decision, model |
IMPLEMENT | 编码规范、团队约定、实现陷阱 | guideline, pitfall |
BUILD_VERIFY | 测试反模式、构建失败经验 | pitfall, guideline |
查询预算必须受控。Agent 如果一次读取过多知识,会消耗上下文窗口,也可能被无关信息干扰。Harness Engineering 的重点不是“给模型更多信息”,而是“在正确时机给正确的信息”。
历史项目如何冷启动知识库
很多存量项目没有结构化知识库,经验散落在代码、需求系统、Wiki、评审记录和聊天记录里。冷启动可以使用三段式管道:
flowchart LR
A[@doc-collector<br/>收集多源资料] --> B[@codebase-profiler<br/>生成代码画像]
B --> C[@knowledge-builder<br/>标准化知识条目]
C --> D[写入 team-knowledge.git]
三个 Agent 分工如下:
| Agent | 输入 | 输出 |
|---|---|---|
@doc-collector | Git、需求系统、Wiki、本地文档、口述材料 | 候选资料集合 |
@codebase-profiler | 代码仓库 | 技术栈、模块边界、依赖关系、架构模式 |
@knowledge-builder | 候选资料和代码画像 | 标准化知识条目、项目画像、归档摘要 |
冷启动阶段不追求一次性完美。所有导入知识默认设为 draft,后续通过真实工作流验证后再提升成熟度。
为了避免长时间导入被中断,可以持久化导入状态:
{
"importId": "import-2026-04-09",
"currentStep": "codebase-profiler",
"finishedSources": [
"git",
"iwiki"
],
"pendingSources": [
"tapd",
"local-docs"
],
"generatedKnowledge": 8,
"lastCheckpoint": "2026-04-09T16:30:00+08:00"
}
知识消费要从“预推送”改成“主动查询”
把几十条完整知识一次性塞给 Agent,通常会带来两个问题:
- 上下文膨胀,关键约束被淹没;
- 推送内容不一定匹配当前决策点。
更好的方式是三级渐进式索引:先读全景目录,再读分类清单,必要时才读完整条目。
| 层级 | 文件 | 大小 | 用途 |
|---|---|---|---|
| Layer A | knowledge-catalog.md | 约 50 行 | 了解知识库有哪些分类,每个阶段推荐查哪里 |
| Layer B | 各目录下的 catalog.md | 约 100–300 行 | 查看条目摘要、成熟度、标签、适用阶段 |
| Layer C | TK-*.md / BK-*.md | 约 50–200 行 | 读取完整知识内容、背景、适用场景、证据 |
查询过程如下:
sequenceDiagram
participant Agent
participant Catalog as knowledge-catalog.md
participant List as catalog.md
participant Item as 知识条目
participant Source as 原始产物
Agent->>Catalog: 读取全景目录
Catalog-->>Agent: 返回分类和阶段推荐路径
Agent->>List: 读取相关分类清单
List-->>Agent: 返回条目摘要和标签
Agent->>Item: 按需读取完整条目
Item-->>Agent: 返回知识内容
Agent->>Source: 必要时追溯来源
Source-->>Agent: 返回推导细节
这种方式让 Agent 用几十行上下文获得知识库全貌,用几百行上下文定位候选条目,只在需要时读取完整内容。
引用追踪让知识库自动进化
Agent 使用知识后,需要在阶段产物中记录引用关系:
{
"knowledgeReferences": [
{
"id": "TK-SB-003",
"title": "分页查询延迟关联优化",
"usedIn": "复用评级 Step 2"
},
{
"id": "BK-AD-G004",
"title": "广告预算扣减并发控制规则",
"usedIn": "业务规则参考"
}
]
}
ARCHIVE 阶段统一读取这些引用,更新知识条目的 last_referenced 和验证证据。这样可以形成闭环:
flowchart LR
A[Agent 查询知识] --> B[阶段产物记录 knowledgeReferences]
B --> C[ARCHIVE 汇总引用]
C --> D[更新 evidence.last_referenced]
D --> E{是否满足提升条件}
E -- 是 --> F[提升 maturity]
E -- 否 --> G[保持当前成熟度]
D --> H[长期未引用进入衰减规则]
被频繁使用、跨项目验证的知识会逐步提升;长期无人引用的知识会自动降级,甚至归档。
知识库必须有 Lint 机制
知识库如果只进不出,很快会变成“经验垃圾场”。Lint 的目标是定期检查结构、质量、冲突和时效性。
常见检查项如下:
| 检查项 | 处理方式 |
|---|---|
| 索引和实际文件不一致 | 自动修复目录 |
| 孤儿条目,无引用、无验证 | 降级为 draft |
| 同主题结论相反 | 标记冲突,等待 maintainer 裁决 |
draft 长期未引用 | 自动归档 |
| 重复或高度相似条目 | 标记合并候选 |
| 成熟度超期未引用 | 按规则自动衰减 |
触发方式可以有三种:
1. 每完成 10 个工作流自动执行
2. 手动执行 /knowledge lint
3. 超过 30 天未执行时,在下一次 /flow-run 启动时提醒
Lint 不是为了追求知识库“干净好看”,而是为了避免 Agent 在决策时引用过期、矛盾或低质量知识。
人机交互也要纳入 Harness 设计
很多 Agent 工作流默认操作者一直坐在电脑前,随时能确认架构方案、审批产物、允许进入下一阶段。但真实工作日不是这样。会议、通勤、跨团队沟通都会打断人对工作流的响应。
一个 16 阶段工作流如果在第 7 阶段等待人工确认,而确认人两个小时后才回到工位,Agent 并没有失败,但交付周期被拉长了。
因此,Harness 系统除了设计“Agent 怎么跑”,还要设计“人如何异步参与”。
核心能力包括:
| 能力 | 作用 |
|---|---|
| 状态持久化 | 工作流状态不能只存在内存里,应该落到文件系统 |
| 断点恢复 | 每个阶段都有明确入口、出口和产物 |
| 异步审批 | Agent 提交方案后暂停等待,人可以稍后审批 |
| 跨设备接管 | 手机、平板、浏览器都能查看状态和处理确认 |
| 通知触达 | 架构评审、产物验收等节点主动推送提醒 |
工作流可以设计成这样:
sequenceDiagram
participant Agent
participant FS as 文件系统状态机
participant User as 人类审批者
participant Notify as 通知渠道
Agent->>FS: 写入阶段产物和待审批状态
Agent->>Notify: 推送审批提醒
Notify-->>User: 手机或浏览器收到通知
User->>FS: 异步审批 / 修改意见
FS-->>Agent: 状态变更为可继续
Agent->>FS: 进入下一阶段
如果状态都保存在文件系统里,远程设备看到的就是同一份真实状态。Agent 暂停不会丢进度,人也不必始终守在 IDE 前。
这种设计对知识闭环也很重要。ARCHIVE 阶段只有在工作流完整走完后才能提取知识,如果流程长期卡在人工节点,新经验就不能及时进入团队知识库。异步审批和远程接管可以缩短等待时间,让知识沉淀更快发生。
“文件系统即状态机”适合知识型 Harness
把状态、产物和知识都保存成文件,看起来朴素,但很适合 AI 工程交付系统。
| 设计 | 好处 |
|---|---|
| Markdown 存知识 | 人可以直接阅读、编辑、审查 |
| Git 管版本 | 每次变更都有历史和差异 |
| 文件保存状态 | 工作流可中断、可恢复、可跨设备查看 |
| 不强依赖平台 | 更换模型或 Agent 框架时,知识不会丢 |
| IDE 原生友好 | 工程师可以在熟悉的开发环境里操作 |
数据库当然也能管理知识,但文件系统 + Git 的优势是简单、透明、可迁移。对于团队知识沉淀,透明性往往比平台功能更重要。
模型能力和知识工程不是二选一
“大模型更强”与“Harness 更完善”不是对立关系。更强的模型能更好地理解和使用知识,但不能替代团队私域知识。
可以用一个表格看清两者边界:
| 投入方向 | 能解决什么 | 不能解决什么 |
|---|---|---|
| 更强模型 | 通用推理、代码生成、复杂计划能力 | 不知道团队内部业务规则和历史坑 |
| 更复杂工作流 | 控制执行顺序、拆解任务、降低失控风险 | 如果没有知识积累,每次仍然从零开始 |
| 知识工程 | 复用团队经验、沉淀领域模型、形成长期资产 | 需要持续维护,不能一次建设永久有效 |
比较务实的选择是:模型能力保持开放,Harness 工作流保持可替换,知识资产保持可积累。
每沉淀一条经过验证的知识,后续所有工作流都能受益;每清理一条过期知识,Agent 被误导的概率就会降低。知识工程的收益不是一次性的,而是随着交付次数增加持续放大。
可落地的设计清单
设计 AI 工程交付系统时,可以按这份清单检查知识闭环是否完整:
| 模块 | 必备设计 |
|---|---|
| 知识结构 | 五层存储、五种类型、三级成熟度 |
| 团队协作 | 独立 Git 仓库、角色权限、贡献暂存区 |
| 工作流集成 | INIT 注入、阶段查询、ARCHIVE 提取 |
| 检索方式 | 全景目录、分类清单、完整条目的三级索引 |
| 上下文控制 | 阶段查询预算、按需读取、避免一次性推送 |
| 生命周期 | 引用追踪、自动提升、自动衰减、Lint |
| 人机协作 | 状态持久化、断点恢复、异步审批、跨设备接管 |
Harness 工作流的价值,不在于阶段足够多、Agent 足够复杂,而在于它能不能让一次交付留下下一次可复用的知识。模型、工具链、Agent 框架都会变化,团队在业务领域里验证过的知识才会持续产生复利。