Harness Engineering实践心得与高效技巧

2026-06-05阅读 0热度 0
其他

引言

Harness Engineering 的概念在业内已讨论多时。宽泛的定义将其视为 Harness = Agent - Model——模型之外附加的所有能力,如 MCP、Skill、提示词等,皆属于 Harness 范畴。本文聚焦更具体的场景:Claude Plugins 中的 Harness 落地实践。虽与广义定义略有差异,核心目的一致——确保模型稳定输出结果。

为避免概念混淆,此处仅简析 Prompt、Context 与 Harness 三种范式的区别:

维度Prompt EngineeringContext EngineeringHarness Engineering
核心定义如何提问让模型获知哪些信息为模型构建执行环境
实现方式自然语言描述滑动窗口、向量库管线搭建、状态管理、校验、外部API集成
层级关系最内层:使用模型的基础手段中间层:上下文信息管理最外层:包含上下文工程与提示词工程

实践动机

先交代背景。团队开发了一款服务端代码改造影响面分析工具 Claude Plugins。起因是 Q2 起团队逐步向 AI 全栈转型,挑战在于用 AI 交付 Java 项目。当前多数模型在新项目中编写代码已较可靠,但对历史包袱沉重的遗留项目,模型仍会出现 Bug——即便采用了 Sdd/SuperPowers 等增强开发范式。

已上线的两个服务端项目中,有一个出现线上事故。根因是 AI 误改了本不该改动的业务入口。因此,为提升质量保障,工具箱中急需一款能精准评估改动影响面的工具。

对 AI 而言,分析代码影响面属于高复杂度任务:需要全局检索代码引用(已有 GodeGraph/GitNexus 深度优化)、梳理业务链路、评估风险、整理输出等。相信不少人有过类似经历:把复杂任务直接通过提示词交给模型,执行过程中模型可能偷懒或偏离方向。无论如何调整提示词,最终结果总与预期存在落差——这通常源于模型的认知局限与上下文窗口约束。而 Harness 的作用之一,正是尽可能减少此类偏差。

架构拆解

针对该分析插件,我们设计了多项工程化手段。以下说明具体做法及其背后的思考。

1. 整体工作流 —— 用确定性工程流程管控非确定性模型输出

如图所示,Plugin 通过暴露 Skill 作为用户交互入口。Skill 内嵌脚本驱动流程推进(Step1 → Step2 → …)。每个 Step 中的创造性任务仍交由模型处理,模型执行后,脚本将结果记录到 yaml(状态机)、校验成果,再进入下一 Step,直至结束。

此设计带来三点好处:

  1. 流程可控:由脚本决定“当前执行哪一步”“是否允许进入下一步”,避免模型提前收工或跳过步骤。若仅靠提示词告知 Step1/2/3,模型会因注意力稀释、追踪失效、位置偏差等问题导致结果不可靠。

  2. 状态可追溯:关键步骤执行结果以文件形式记录(此处使用 yaml)。以影响面分析 Skill 为例,让模型直接调用 py 脚本,在脚本中生成待处理任务列表,为每项任务标记 status: WAITING/DONE/FAILED。脚本派发任务给模型并更新状态,执行期间可清晰获知任务完成情况。最终由脚本校验 .yaml,针对未完成任务要求模型回补,确保处理全覆盖。

  3. 上下文可控:模型在脚本执行后能拿到的上下文,完全由脚本决定。示例:

    ---name: xxdescription: xx---
    
    ## 作用
    xx...
    
    ## 执行步骤
    
    ### Step1 - 生成改动任务
    执行
    ```bash
    python3 ${PLUGIN_ROOT}/script/generate.py" --create 
    ```
    
    ### Step2 - xxxxxx
    ...
    
    def main():
        # ...
        print(f"脚本输出的内容会被模型读到,可以输出你想让模型知道的上下文")
    if __name__ == "__main__":
        main()
    

    模型能获取哪些上下文,完全由脚本中 print 的内容决定。利用此机制可在脚本中精心设计——例如告知模型当前执行结果、下一步操作、所需参数等。

2. 状态机 —— 全/跨流程状态管理

状态机主要解决两个问题。

问题一:记录任务状态,兜底模型提前收工

面对任务繁多且复杂的场景,模型可能因上下文窗口限制、追踪失效等问题提前收工。典型表现为:模型在对话中宣称所有任务已完成,但人工审核发现仍有遗漏。反问“这块是否未处理”,模型才会意识到还有未完成项。

src/main/java/com/example/OrderService.java:
analysis_steps:
  - step1_分析影响面: WAITING/PROCESSING/DONE/FAILED
  - step2_分析风险点: WAITING/PROCESSING/DONE/FAILED

解决方案:为每项任务添加状态标记,任务执行后通过验证门校验状态,校验通过才放行,否则打回重新执行。工作流示意:

(图片占位)

问题二:跨 Agent(mainAgent、subAgent)协作时的任务状态追溯 / 跨 Skill 工作流时的任务状态追溯

将关键步骤的执行结果写入 .yaml 文件,其他 Agent/Skill 执行时也可读取该记录,实现跨 Agent/Skill 协作。设想一个全流程需求交付的 Plugin,从 PRD → 系分 → 开发 → 测试 各阶段对应不同 Skill,下一步必然依赖前一步的执行结果,此时状态管理不可或缺。

3. Diff 切割 —— 降低模型不确定性

核心思路:将模型容易产生幻觉的任务拆解出来,用脚本辅助完成,或直接全部由脚本完成,减少模型的不确定因素。

例如,本 Plugin 中识别“当前分支相比 origin/master 改动了哪些文件、哪些代码块”对模型来说容易产生幻觉。因此直接通过脚本梳理后再喂给模型。当每个模型可能出错的小任务都增加一层保障,整个工作流自然更稳定。

4. SubAgent 并发 —— 避免上下文窗口限制

执行复杂任务时,将所有任务交给单一 Agent 容易触发上下文窗口限制及注意力分散问题。Anthropic 也报告过类似现象:上下文达到一定量时(40%),模型会变得犹豫,甚至倾向提前收工,即使任务未完成。

一些 AI IDE 支持开启 subAgent,如 Claude CodeCursor。因此我们采用另一种模式:由一个 mainAgent 控制主流程,复杂任务由 mainAgent 派发 subAgent 执行。这样 subAgent 拥有干净的上下文,不会出现提前收工问题,主流程也不会上下文溢出。

有人可能疑惑 mainAgent 如何获取 subAgent 的运行结果。IDE 会自动将 subAgent 的结果回传给 mainAgent,无需额外处理。但从稳定性和状态管理统一性的角度,通过回写状态机的方式更为稳妥。工作流示意:

(图片占位)

5. 验证门 —— 把控模型交付质量

验证机制是 Harness 理念中的关键层。在纯 Prompt 工程中,若想验证结果,可能写“Review 你的成果,识别有无问题”。但仔细想想,让本身就带有不确定性的模型来 Review 自己的产出,好比让人用同一双眼睛检查自己的作业。我们曾做过尝试:让模型生成一份方案文档,之后新建会话保持干净上下文,继续让模型 Review 该方案,重复此过程。最终结论是:每次 Review 都会发现新问题。让模型自我审查并非一个趋于稳定的方案。

本次实践中,验证部分的做法是将大任务进行拆解。例如在代码改动分析任务中,diff 里的每个文件可拆为小任务,而每个文件中的改动又有不同维度需分析(调用链、影响面、逻辑错误、性能风险等),每个维度也可继续拆解。任务类型也不同,有的只需执行即可,有的则要求模型分析全面。最终验证门需做两件事:

  1. 结合状态机中任务的 status 校验是否执行完
  2. 结合状态机中任务执行结果 .yaml 文件校验模型执行是否到位

校验不通过则不允许放行,要求模型重新执行。实现方式仍通过脚本控制,只需在脚本执行后 print 结论,模型即可据此处理后续步骤。不过建议针对整个工程设计一套结构化的输出范式,强化模型对脚本执行结果的关注度。工作流与状态机类似,只是校验粒度更细,此处不再附图。

6. Skill Prompt 设计

尽管有了不少工程化手段,Prompt 设计依然重要。这方面我们踩过一些坑,总结出几点实践经验。

简单 Prompt vs 复杂 Prompt

尝试过两种风格。一种是详细版:列出各场景下正确的 case、错误的 case,用大量自然语言举例说明对错,并补充边界情况。另一种是极简版:整个 Prompt 仅包含要执行的 Step。最后发现 Prompt 越精简,模型执行越稳定——过多的 Prompt 会导致模型注意力分散。不过此结论可能因模型而异,各团队观点也不同,例如 OpenAI 倾向详细 Prompt,Anthropic 则建议定期精简 Prompt。

直接给代码 > 文字描述

原因简单:某些模型的编码、预训练数据、分词逻辑天然偏英文,解析中文可能产生偏差。测试表明,即使很短的描述也有概率出现幻觉,而代码是通用且无歧义的。

维度不宜太分散,否则模型每次执行重点不一致

最初在代码中放入一份包含 34 个风险点的 md 文档,要求模型逐一分析。多次测试后发现模型输出的风险点有时不一致,甚至偏差较大。排查后发现风险点过于分散。后来将 34 个具体风险点整合为 10 个,并从具体点转向为模型提供引导方向。

以下是几个主要 Skill 的最终提示词设计概览:

(Skill Prompt 模板占位)

7. 整体目录设计

Plugin 不同于单个 SkillPlugin 可以是 Skill 的集合,因此目录设计需考虑通用性。

├── .claude-plugin/plugin.json          # 插件元信息
├── .cc-version                         # 版本号 (1.0.0)
├── README.md                           # 项目文档
├── constants/
│   ├── analysis_diff_risk/
│   │   └── filter-rules.yaml           # 文件过滤规则
│   └── common/
│       ├── runtime-constants.yaml      # 公用运行时配置
│       └── output-messages.yaml        # 输出消息模板
├── docs/
│   └── analysis_diff_risk_point.md     # 风险检查文档
│   └── analysis-diff-risk-step2.md     # 风险检查文档
├── script/analysis_diff_risk/
│   ├── analyze_diff.py                 # Git diff 解析 + YAML 生成
│   ├── execute_analysis.py             # 状态机引擎(列表/收集/汇总)
│   └── cleanup_state.py                # 清理临时状态
├── state/analysis_diff_risk/           # 运行时状态机
│   └── impact-analysis-${hash_id}.yaml # 待执行的任务列表
│   └── results_${hash_id}_batch.yaml   # subAgent执行任务的结果
├── skills/fe-analysis-diff-risk/
│   └── SKILL.md                        # Skill 入口定义
└── template/
    └── analysis_diff_risk_result.md    # 输出报告模板
    └── subagent_analyze_prompt.md      # subagent提示词

踩过的坑

  1. 脚本输出执行结果时,print 中的文字描述必须准确,否则会导致模型偏离方向。最好附带下一步操作建议。

  2. 能力一般的模型统计 diff 行数时易出现偏差。解决方案是直接用脚本计算每段 diff 的 start_line、end_line,再喂给模型。

  3. 改动量较大时,模型检索耗时会明显增加。因为模型常用的检索方式是 grep / ripgrep(rg),这些命令本质是用正则模糊匹配代码字符,匹配完成后还需模型判断是否属于正确场景。

举例:告诉模型“把项目中所有的 start 换成 star”,模型开始执行 grep 命令。因仅靠正则模糊匹配,它无法区分语境,可能匹配出各种情况。然后模型再逐一分析上下文,判断哪些是预期场景,循环下来拖慢检索速度。

好消息是社区已有开源库解决此问题,例如 codegraph。它先将代码解析成结构图(AST + 符号关系图),记录“谁是什么角色”。检索时可直接查索引,清楚哪些是变量定义、哪些是函数引用,甚至知道代码在哪些地方被实际使用。实测可减少约 30% 耗时,且比模型更稳定,后续计划集成到 Plugin 中。

效果与局限

  1. 测试了 Sonnet 4.6Opus 4.8deepseek-v4-proQwen3.6 Plus,均能按预期执行。
  2. 服务端场景可能涉及跨上下游调用。此时上游或下游代码位于其他项目中,Skill 读取不到会造成上下文不完整。简易解决方式是将上下游项目放在同一文件目录下。

总结:Harness 的核心启示

  1. 我们当然期待更强的大模型能一键完成所有工作,但模型的稳定性与边界不可忽视。
  2. 除了会用模型,还应该探索模型更深层的能力,以提升未来竞争力。
  3. 在前端/服务端积累的工程化能力,在 AI 时代依然有效。日常需重视基础积累。
免责声明

本网站新闻资讯均来自公开渠道,力求准确但不保证绝对无误,内容观点仅代表作者本人,与本站无关。若涉及侵权,请联系我们处理。本站保留对声明的修改权,最终解释权归本站所有。

相关阅读

更多
欢迎回来 登录或注册后,可保存提示词和历史记录
登录后可同步收藏、历史记录和常用模板
注册即表示同意服务条款与隐私政策