Harness Engineering:模型外面的工程底座
从上下文、工具、权限、计划、恢复、可观测性和结果验证出发,解释 Harness Engineering 如何把模型能力转化为可运行的系统能力。
Harness Engineering:模型外面的工程底座
Harness Engineering 这个词,适合用来描述模型外面的那套运行时工程。
模型负责生成判断和行动意图。Harness 负责把这些意图放到真实环境里执行:给模型上下文,提供工具,控制权限,维护任务状态,记录执行过程,处理失败,并验证结果。
| 问题 | Harness 负责什么 |
|---|---|
| 模型不知道该看哪些信息 | 管理上下文和记忆 |
| 模型需要操作外部环境 | 提供工具运行时 |
| 模型生成的动作有风险 | 做权限控制和确认 |
| 长任务容易跑偏 | 维护计划和任务状态 |
| 工具调用可能失败 | 做重试、降级和恢复 |
| 执行过程需要复盘 | 记录日志、错误和轨迹 |
| 任务看起来完成但结果不确定 | 做验证和完成条件检查 |
一句话概括:Harness 把模型能力变成系统能力。模型越能行动,Harness 越重要。
Harness 这个词在说什么
Harness 原意可以理解成“约束和连接装置”。放到 AI Agent 里,它指的是模型外面的执行系统。
一个聊天模型只要根据上下文生成回答就够了。一个 Agent 要做事,就需要进入真实环境:它要读文件、搜代码、调用工具、执行命令,也要在出错后继续判断下一步。
这些动作大致可以分成三类:
- 获取证据:读取文件、搜索代码、拿到错误输出。
- 执行动作:调用工具、运行命令、修改内容。
- 收束任务:处理错误、维护进度、验证结果。
这些能力不在模型权重里,而在模型外面的系统里。
可以把 Agent 看成两部分:
Agent = Model + Harness
Model 负责理解、推理、生成下一步。
Harness 负责让下一步能被安全执行,并把执行结果交回模型继续判断。
模型外面需要 Harness 的原因
只靠模型,很难稳定完成一个真实任务。
举个简单例子:用户说“帮我修一下这个项目里的登录 bug”。
模型一开始并不知道项目结构,也不知道登录逻辑在哪些文件里。它需要先拿到证据:报错信息、相关代码、配置文件、测试入口,以及修改后可以用什么方式验证。
这些信息不会自动出现在模型上下文里。Harness 需要提供搜索、读文件、执行命令这些能力,让模型逐步拿到证据。
接着模型可能要改代码。这里会进入风险边界:哪些文件可以读,哪些文件可以写,命令是否允许执行,命令是否有破坏性,测试失败后继续排查还是停下来汇报。
这些都属于 Harness 的职责。
所以 Harness 处理的是模型外面的工程问题。模型给出下一步建议,Harness 决定这一步怎么执行、能否执行、结果怎么回收。
Harness 包含哪些模块
一个完整 Agent Harness 通常会包含这些模块。
| 模块 | 作用 |
|---|---|
| Context Management | 决定读什么、保留什么、压缩什么 |
| Tool Runtime | 注册工具、调用工具、回收工具结果 |
| Permission System | 控制文件、命令、网络和敏感操作 |
| Task State / Planning | 维护任务目标、步骤和完成状态 |
| Memory | 保存长期规则、偏好和项目经验 |
| Observability | 记录工具调用、错误、日志、成本 |
| Recovery | 失败后重试、换路、降级或请求人工介入 |
| Verification | 检查任务是否完成到位 |
这些模块不一定都很复杂,但真实 Agent 里基本都会碰到。
Context Management
真实项目很大,模型一次看不完所有内容。
Context Management 要解决的是:哪些信息值得放进上下文。它会影响搜索关键词怎么选、相关文件怎么读、无关目录怎么跳过,也会决定历史对话如何压缩、关键错误输出如何保留、上下文长度如何控制。
上下文选错,模型后面的判断就会偏。很多 Agent 看起来“幻觉”,其实是上下文证据不够。
Tool Runtime
工具让 Agent 能真正动手。搜索文件、读取文件、编辑文件、执行 shell 命令、调用 HTTP 接口、访问数据库、控制浏览器,这些都可以放进工具运行时里。
Tool Runtime 要做的不只是把工具暴露给模型。它还要管理工具输入、执行结果、错误信息、超时和返回格式。
一个工具调用通常长这样:
模型提出工具调用
-> Harness 校验参数
-> Harness 执行工具
-> 工具返回结果
-> Harness 整理结果
-> 结果进入下一轮上下文
工具结果的质量很关键。错误信息太少,模型无法修正;输出太长,又会挤占上下文。
Permission System
Agent 一旦能写文件、跑命令、访问网络,权限系统就很重要。
不同动作风险级别不同:
| 动作 | 风险 |
|---|---|
| 读普通项目文件 | 低 |
| 写项目文件 | 中 |
| 执行测试命令 | 中 |
| 删除文件 | 高 |
| 访问外部网络 | 中到高 |
| 操作生产数据库 | 高 |
Prompt 可以提醒模型谨慎。Permission System 可以真正拦截动作。比如写文件前检查路径,执行命令前判断风险,高风险操作要求用户确认,访问目录和网络能力也可以被限制在明确范围内。
这类控制放在系统层,比只放在提示词里稳定。
Task State / Planning
长任务需要状态。
如果任务只有一步,模型直接回答就够了。复杂任务往往要经历多个阶段:
理解问题
-> 搜索相关文件
-> 定位原因
-> 修改代码
-> 运行测试
-> 修复测试问题
-> 总结结果
Task State 要记录当前做到了哪一步,下一步是什么,完成条件是什么。
Planning 的价值是减少目标漂移。任务越长,越需要显式状态。
Memory
Memory 保存长期信息,比如用户偏好、项目约定、常用命令、团队规范和历史踩坑。
Memory 的难点在于筛选。短期上下文和长期记忆要分开。一次任务里的临时信息不适合全部写进长期记忆。写错的记忆还会污染后续任务。
好的 Harness 会把“当前会话信息”和“长期可复用信息”分开处理。
Observability
Agent 执行过程要能看见。一次任务里调用了哪些工具、输入和输出是什么、哪一步失败、重试了几次、最后怎么验证,这些信息都应该留下轨迹。
没有 Observability,Agent 失败后很难复盘。用户只看到“它没做好”,开发者也不知道问题出在上下文、工具、权限、模型判断还是外部系统。
Recovery
工具会失败,命令会失败,测试会失败,网络也会失败。Recovery 处理的是失败后的路线:重试、换工具、降级、缩小任务范围、请求用户介入,或者停止继续执行。
这里最重要的是避免无效循环。比如同一个命令连续失败,Harness 应该记录失败次数,超过阈值后换路或停下来。
Verification
Agent 最后要证明任务完成。
在代码任务里,验证可能是测试通过、构建通过、lint 通过、报错复现消失,或者用户指定的输出文件已经生成。内容任务里的验证会换一种形式,比如格式检查通过、必填字段存在、输出结构完整、边界问题已经处理。
Verification 是 Agent 收尾的关键。缺少验证,任务很容易停在“看起来完成”的状态。
一个任务在 Harness 里怎么流动
一次 Agent 任务,大概会这样流动:
用户输入目标
-> Harness 加载规则和记忆
-> Harness 选择上下文
-> 模型生成计划或下一步
-> Harness 做权限检查
-> Harness 执行工具调用
-> 工具返回结果
-> Harness 整理结果并更新状态
-> 模型继续判断
-> Harness 处理失败或继续推进
-> Harness 验证结果
-> 输出总结
这个流程里,模型一直在参与判断。实际执行依赖模型和 Harness 一起推进。
Harness 像一个运行时,把上下文、工具、权限、状态和反馈组织起来。模型每次生成下一步,Harness 负责把这一步落到系统动作里。
Harness 和 Prompt Engineering 的区别
Prompt Engineering 主要作用在模型行为上。
Harness Engineering 作用在整个执行系统上。
| 对比 | Prompt Engineering | Harness Engineering |
|---|---|---|
| 作用对象 | 模型输出 | 任务执行系统 |
| 主要手段 | 提示词、规则、示例 | 工具、权限、状态、日志、恢复 |
| 典型目标 | 让模型更按规则回答 | 让系统更稳定地执行 |
| 风险控制 | 依赖模型遵守指令 | 依赖系统限制和检查 |
比如:
Prompt:修改文件前先确认。
Harness:写文件工具遇到敏感路径时触发确认。
再比如:
Prompt:失败后尝试修复。
Harness:记录失败次数,超过阈值后停止或换方案。
Prompt 可以影响模型倾向。Harness 可以改变系统行为。
这就是两者的关键差异。
Harness 太弱会发生什么
Harness 太弱时,Agent 的问题会集中爆发。
第一类是上下文问题。模型没看到关键文件,就容易凭不完整信息判断;历史对话没有压缩好,也会把后续判断带偏。
第二类是执行问题。模型知道有工具,但工具调用缺少稳定格式、错误处理和结果整理;权限边界又太宽时,普通读取和危险写操作会混在一起。
第三类是长任务问题。任务状态维护不好,做着做着就会偏离原目标;失败恢复太弱时,同一个错误可能反复重试,也可能遇到第一次失败就直接停掉。
第四类是收尾问题。执行过程不可见时,出了问题只能看到最终失败;缺少验证时,Agent 可能输出“完成了”,但测试没跑、结果没查、边界没确认。
这些问题通常需要工具层、权限层、状态层和观测层一起处理。
Claude Code 可以作为一个 Harness 样本
Claude Code 这类 coding agent,可以看成一个比较完整的 Harness 样本。
它围绕模型组织了文件读取和搜索、Shell 命令执行、文件编辑、计划状态维护、权限控制、上下文选择、失败恢复、执行过程反馈和结果总结。这些能力共同决定了它能否在真实代码仓库里持续推进任务。
如果想看更细的拆解,可以看我之前写的 Claude Code 工程化拆解系列。那组文章分别拆过 Agent Loop、Tool System、Prompt System、Memory、Context、Planning、Permission、Observability、Fallback、Hooks、Subagent 等模块。
这里把 Claude Code 当成一个样本来看,重点是说明 Harness Engineering 有具体工程形态。一个能持续做工程任务的 Agent,背后一定有类似的运行时系统。
我的判断
Harness Engineering 的价值,是把模型能力变成可执行、可约束、可复盘的系统能力。
模型负责生成下一步。Harness 负责让下一步在真实环境里安全发生。
模型越强,Harness 的作用越明显。因为模型能提出更多行动意图,系统就更需要判断哪些动作能执行、怎么执行、失败怎么处理、结果怎么验证。
一个 Agent 的上限可能来自模型能力,但它的稳定性往往来自 Harness。
所以我会把 Harness 看成 Agent 工程里的运行时底座。工具、上下文、权限、状态、观测、恢复和验证都在这层汇合。缺少这层,Agent 很容易停留在“会说下一步”的阶段;有了这层,模型的判断才更容易变成可靠行动。