Harness 工程:让 Agent 真正把任务做完

一个模型会调用工具,并不等于它已经是可靠的 Agent。

最简单的 Agent 循环并不复杂:把任务交给模型,模型选择工具,系统执行工具,再把结果送回模型。循环持续到模型认为任务已经完成。

Demo 往往能顺利跑起来。进入真实项目后,问题会接连出现:工具超时,文件修改失败,模型重复同一个动作,测试没有通过,运行中断后进度全部丢失。更危险的情况是,模型只是"觉得"完成了,系统就直接把结果交给用户。

Harness 工程处理的是这些模型外部的问题。

右侧才是一套完整 Harness:模型之外还有任务状态、工具执行、结果验证和失败恢复。

Harness 是什么

Harness 可以理解为 Agent 的运行系统。模型负责判断下一步,Harness 负责把判断转换为真实操作,并控制操作的边界。

一套常见的 Harness 会管理:

  • 模型与工具之间的执行循环;
  • 当前任务和子任务状态;
  • 文件、命令行与外部服务;
  • 工作记忆和完整事件记录;
  • 测试、检查项与结果验证;
  • 失败重试和中断恢复;
  • 权限、凭证与沙箱隔离。

这些模块不一定都很庞大。一个几十行代码的工具循环也可以算最小 Harness。区别在于,系统是否开始对模型的行动负责。

模型的判断不能直接等于事实

假设 Agent 收到一个任务:修复注册接口的重复提交问题。

模型找到相关代码,增加了一段去重逻辑,然后回答"问题已经修复"。如果系统到这里就结束,所谓完成只是模型的一次文本判断。

更可靠的流程会继续检查:

text 复制代码
代码是否成功写入?
项目能否编译?
原有测试是否通过?
重复提交测试是否真的补上?
接口行为是否符合需求?

这些问题可以由文件系统、测试框架和验收规则回答,不必依赖模型自评。

Harness 的一条基本原则,是尽可能把"我认为正确"换成"环境证明正确"。代码要用测试验证,文件要检查是否存在,网页操作要读取页面状态,数据写入要查询结果。

一个循环怎样持续工作

Agent 每轮通常经历四个步骤:读取状态、构造上下文、请求模型决策、执行动作。

text 复制代码
读取任务状态
    ↓
向模型提供当前上下文
    ↓
模型选择下一步动作
    ↓
执行工具并记录结果
    ↓
回到下一轮

真正麻烦的是循环中的异常情况。

工具可能返回错误,模型也可能给出不存在的参数。Harness 需要把机器错误转换成模型能继续处理的信息,并决定是否允许重试。连续多次调用同一工具时,还要判断这是合理迭代还是陷入死循环。

因此,一个成熟的循环通常会设置最大轮数、重复动作检测、超时和失败类型。达到边界后,系统可以重新规划,或者停下来请求人工处理。

任务状态要放在模型之外

只把进度写在对话历史中并不稳妥。上下文可能被压缩,进程也可能意外退出。

任务列表应当有独立状态,例如:

text 复制代码
pending     尚未开始
in_progress 正在处理
completed   已通过验收
failed      当前方案失败

每次状态变化都要有依据。Executor 生成了一份文件,只能说明动作已经执行;文件是否符合要求,还需要 Validator 检查。验证通过后,任务才能进入 completed

状态放在外部还有一个好处:Harness 重启后可以从上次位置继续,而不是让模型凭一段残缺历史猜测已经做过什么。

工具应该为模型设计

人使用命令行时,可以阅读帮助文档,也能根据报错临时调整。模型依赖工具名称、描述和返回值来判断下一步,所以工具接口是否清楚会直接影响执行质量。

一个适合 Agent 的工具通常有明确用途,参数数量有限,返回结果也经过整理。

例如,文件编辑失败时,只返回 error 没有什么帮助。把完整运行栈全部返回,又会浪费上下文。更好的结果是:

text 复制代码
编辑未应用:目标片段在文件中出现 3 次。
请补充行号范围,或提供更长的匹配内容。

模型知道失败原因,也知道可以怎样修正。

工具之间还要减少重叠。如果 searchfindlookupquery 都能查文件,却没有清楚区别,模型会把精力浪费在工具选择上。少而明确的工具集通常更稳定。

miniMaster 的三种角色

miniMaster 把运行过程分成 Planner、Executor 和 Validator 三种职责。

Planner 负责安排任务,Executor 执行,Validator 验收;检查失败后,任务回到执行阶段。

Planner 关注全局。它把用户目标拆成任务,安排顺序,并在执行受阻时调整计划。

Executor 处理当前任务。它读取文件、调用搜索、执行命令,或者修改代码。每次行动的结果都会写入工作记忆。

Validator 根据完成条件检查产出。它不会因为 Executor 声称"已完成"就直接通过,而是寻找测试结果、文件内容或其他证据。

如果 Validator 发现缺项,任务会回到 Executor。相同问题反复出现时,Planner 可以改变方案。

三种职责可以由同一个模型在不同上下文中承担,也可以分给多个模型。重点是执行和验收之间要有边界。

失败后怎样继续

长任务很难一次走通。网络会断,外部接口会限流,生成的代码也可能编译失败。

Harness 需要区分失败类型。

临时网络错误可以等待后重试;参数错误应当把具体原因交给模型修正;权限不足不能靠重复调用解决;测试失败则需要回到代码分析阶段。

重试记录也不能简单丢掉。保留失败动作和错误摘要,可以避免模型再次采用同一方案。记录过长时,可以把旧尝试压缩归档,但原始日志仍应能够查询。

如果运行状态和事件日志已经持久化,即使 Harness 进程崩溃,新实例也能读取历史并继续执行。模型上下文可以重建,任务本身不必从头开始。

权限和沙箱不能交给提示词

在系统提示词里写"不要读取密钥",不能构成真正的安全边界。模型可能受到错误指令或提示注入影响,也可能无意间执行危险命令。

安全限制必须落实在模型之外。

文件工具可以限定允许访问的目录,Shell 命令可以运行在隔离沙箱中,高风险操作可以要求人工确认。访问外部服务时,凭证应由代理层注入,而不是直接暴露给模型或执行环境。

即使模型作出错误决定,底层权限仍然应当阻止它越过边界。

Harness 也需要随模型变化

Harness 经常用于补偿模型当前的弱点,例如频繁提醒目标、强制拆解步骤或定期重置上下文。模型升级后,其中一些机制可能不再有用,甚至妨碍新模型发挥能力。

因此,Harness 不应写成一团无法替换的流程。会话记录、工具执行、模型循环和沙箱最好通过稳定接口连接。底层策略变化时,可以单独替换,不必重写整个系统。

还要用真实任务持续评估。某个重试策略究竟提高了成功率,还是只增加了调用次数,需要从运行轨迹和结果中判断。

哪些任务值得使用 Harness

一次摘要或翻译通常不需要复杂 Harness。重新生成一次的成本很低,过程也不会修改外部环境。

当任务包含连续工具调用、中间状态保存、真实文件修改或明确验收标准时,Harness 才有明显价值。任务运行越久,失败成本越高,对状态、验证和恢复的要求也越高。

可靠的 Agent 并不是从不出错的模型。更现实的设计,是允许模型在局部犯错,同时让系统保留现场、限制风险、提供反馈,并在交付前检查结果。

模型决定下一步往哪里走,Harness 确保它没有在半路停下,也没有把未经验证的结果当成终点。

相关推荐
打工仔折腾 AI2 小时前
Prometheus 告警推钉钉:从单群 Webhook 到跨网络 Alertmanager 实战
人工智能·后端·python·性能优化
人工智能AI技术2 小时前
LLM 应用的 Bulkhead 设计
人工智能
Ivanqhz2 小时前
Ping-Pong 双缓冲
开发语言·人工智能·python·深度学习·mlir
yt004yt2 小时前
绿岛数字化平台搭建:VOCs 监测与能碳数据一体化方案
大数据·分布式
bmxy小明同学2 小时前
2026-09-18-embedding选型
人工智能
superxxd2 小时前
基于rust的多平台原生GIS引擎
人工智能·物联网·实时音视频
就叫你天选之人啦2 小时前
安装torch+vllm+flash_attn的prompt
人工智能·pytorch·python
音视频牛哥2 小时前
从 LLM、VLA、LLA、SLIM 到实时音视频感知底座:具身智能真正需要的不只是大模型
人工智能·llm·机器人视觉·slam·vla·多模态感知·机器人音视频
code2cat3 小时前
【随笔】从聊天到调用工具:理解MCP在AI应用中的位置
java·人工智能