Harness工作流排行榜:一场考试撕掉进步遮羞布
在研发工作流的演进过程中,一个常被忽略的问题正逐渐凸显——如何系统性地评判一套工作流的好坏?当团队投入大量精力打磨Rules、调校Skill之后,上线阶段的评估居然只能凭借“感觉这版稳了”这类主观判断。这不是锦上添花,而是关乎系统是否正在失控的关键命题。
一、一个让人不安的事实:你的Harness工作流可能一直在“裸奔”
你是否遇到过这样的场景?团队花了整整两周时间精心调整一套Harness工作流,编写十几条规则、打磨技能,结果上线后大家的评价模糊不清:
- “这版感觉稳了不少。”
- “昨天那版好像更聪明?”
- “我这边用得挺好,你那边怎么就不行了?”
这就是我们半年前的真实窘境——整个团队实际上在用“主观体感”驱动一个复杂系统的迭代。连最基本的问题都回答不了:改了一版rule或skill,到底是在进步还是退步?A说好用、B说难用——谁对?是工作流的问题、模型的波动,还是Prompt本身有歧义?修了一个bad case,可能顺手破坏三个good case,却浑然不知。更关键的是,自家工作流和竞品相比,差距在哪?没有数据支撑,全凭各说各话。
这不是一个锦上添花的衍生问题,而是一个系统正在失控而你毫无察觉的警示信号。
二、核心哲学:为什么Harness工作流比传统软件更需要“考试”
不可量化的东西,不可优化
这是整套系统的第一性原理。传统软件是确定性的:同样的输入必然产生同样的输出,写一个assertEqual就能得到二值且稳定的结果。Harness工作流则完全不同——它本质上是一种“规则驱动的概率程序”。输出由Prompt、Rules、Skills和Model共同决定,任何一个环节的微调都可能引发蝴蝶效应般的行为变化。今天跑一遍是A结果,明天跑一遍可能就是B结果。更致命的是,你甚至无法简单判定“A比B好”还是“B比A好”,因为“好”本身就缺乏清晰的衡量标准。
这种系统如果没有评测体系在背后兜底,面对的不是缓慢退化,而是“薛定谔式的退化”——你永远无法确定它何时已经变差。
从“测试”到“考试”的思维跃迁
软件工程界用几十年实践总结出“测试驱动开发”这条黄金法则。但传统的单元测试、集成测试那套方法论,搬到Harness工作流上远远不够。原因在于,Harness工作流的“正确性”不是一个boolean值,而是一个光谱。同一个任务,工作流可以用无数种方式完成:有的优雅、有的笨拙;有的主动、有的被动;有的严谨、有的草率。你无法简单地用assert output == expected来判定。
因此,我们需要的不是“测试”,而是“考试”。测试验证的是“对不对”,是二值判定;考试评估的是“好不好”——是多维度打分、附上证据、并给出改进建议的完整流程。这个思维跃迁是整个系统的哲学基石:我们不是在写测试用例,而是在出考卷、组织考试、培养阅卷官。
三个不可妥协的原则
在系统设计之初,我们锚定了三个核心原则,后来的所有决策都围绕它们展开:
- 可重复优于精确。一道题跑多次,结果的分布趋势远比单次分数更有价值。我们追求的是“统计显著的信号”,而不是“单次的满分”。
- 可归因优于高分。一道题失败了,系统必须能明确告诉你“为什么失败”——是工作流的规则存在漏洞,是题目本身有歧义,还是模型能力本身不足以应对。不能归因的分数,本质上就是垃圾数据。
- 闭环优于单向。评测的终点不是“出具一份成绩单”,而是“驱动下一次改进”。如果跑完评测只得到一个数字,却不知道下一步该往哪个方向改,这个数字就毫无意义。
三、系统全景:从一道题到一份成绩单
一张图就能说清楚整个系统的面貌。整套系统其实只做三件事——出题、答题、改卷——但将它们串联成了一个可以无人值守运行的闭环。
闭环的关键在于,把“改进”也纳入了链路。每次裁判输出的不只是分数,还会按[工作流]、[题目]、[模型能力]三个维度,给出可操作的改进建议,这些建议直接反哺到下一轮的工作流迭代中。
四、系统设计:出题→答题→改卷的闭环
出题:如何设计一份AI考卷
一道完整的题目,由四个部分组成:题面、阅卷标准、环境前提和元信息,缺一不可。每道题在题库里就是一个独立目录,由四个文件构成(外加可选的fixtures),各司其职:
| 文件 | 角色 | 类比 |
|---|---|---|
| meta.yaml | 题目身份(id、版本、类别、难度、考察目的) | 试卷头 |
| task.md | 题面(给考生看的题目原话 + 给考官看的剧本) | 题干 |
| rubric.md | 阅卷标准(硬性通过项 / 质量项 / 典型失分项) | 答案与给分标准 |
| env.yaml | 环境前提(前置条件 check 命令、关键工件) | 考场布置 |
新出题人完全不需要理解任何代码,只需按模板填好四个文件,五分钟就能新增一道题。降低出题的门槛,意味着题库可以快速扩张,相应的评测覆盖度也能随之提升。这个看似简单的设计背后,有几个深思熟虑的决策:
- 分层建设题库。基础层(一题一焦点)→ 组合层(能力串联)→ 系统层(端到端)。
- rubric必须可量化。所有“硬性通过项”都必须能从transcript或文件系统中找到客观证据,不做任何含糊判定。
- 题面与阅卷分离。“考生”只能看到task.md,永远看不到rubric.md,避免出现“对着标准答案抄”的现象。
为了同一套题目能在不同项目间复用,所有路径、服务名、需求ID统一使用占位符。换一个项目接入评测时,只需要更新一份“变量配置文件”,所有题目就能立刻生效。
我们还将Harness工作流的能力拆解为五个递进的层次,题库按波次逐步覆盖:
| 波次 | 主题 | 重点 |
|---|---|---|
| 1 | 主干闭环 | 规划 → 执行 → 检查 → 归档的最小可用闭环 |
| 2 | 状态机 & 门禁 | HARD GATE 拦截、分支确认、范围锁定 |
| 3 | 知识库闭环 | 检索引用 / 写入冲突检测 / 全量审计 |
| 4 | 周边 skill | 提交规范、TDD 纪律、发布验证 |
| 5 | 韧性场景 | 失败修复循环、Critical 拦截、多分支冲突 |
设计背后的思路很清晰:先把“主干路径”覆盖住,再依次向边界场景、异常场景扩展。这样无论工作流处于哪个发育阶段,都能找到难度合适的题目来测——既不会因为题目太难导致全部挂掉,也不会因为太简单而让所有人都通过,这两种极端都不会产生有价值的信息。
答题:一场精心编排的“模拟考试”
有题目了,谁来监考、谁来答题、谁来判分?
为什么需要考官这个角色?
这是整套系统里最反直觉的一个设计。最朴素的想法是:直接把task.md丢给Agent,让它执行,跑完看结果。但这完全不符合真实使用场景——真实世界中,用户和Agent之间是持续的多轮交互。用户会追问、会纠偏、会补充信息、会在关键节点做出决策。如果评测时去掉了这个交互过程,测试的就不是“Agent在真实场景下的表现”,而是“Agent自嗨的能力”,两者之间的差距巨大。
因此我们引入了考官(Examiner)——由LLM扮演的“用户”,按照task.md中预设的剧本和Agent进行多轮对话。
一场完整的“考试”是这样进行的:
- 考场布置。系统根据env.yaml准备好环境——确认所需文件存在、所需服务可达、工作目录正确。相当于考试开始前,把试卷、答题卡、草稿纸都摆好。
- 考官开场。考官拿到task.md,理解自己需要扮演的用户角色以及要提出的需求,然后向考生发出第一条消息。这条消息就是真实用户通常会说的话——自然、简洁,可能还带点模糊。
- 多轮交互。考生(被评测的Agent)收到消息后开始工作。它可能会提问确认细节、调用工具(读文件、跑命令、写代码)、汇报进展,或者请求决策。考官则会根据剧本回应:该确认的确认,该追问的追问,该为难的为难。
- 考生完成。当考生认为任务完成时,会给出最终总结。考官确认对话结束。
- 全程录像。整个对话过程被完整记录为transcript.jsonl——包括每一轮对话文本、每一次tool call的输入输出、每一条shell命令的执行结果。这份“录像”是后续判卷的唯一依据。
为什么交互记录如此重要?
这里有一个关键洞察:Agent的能力不仅体现在最终结果上,更体现在过程中每一步的决策。两个Agent可能都最终完成了同一个任务,但一个在第一步就主动确认了关键参数,另一个是被追问后才补上的;一个在执行前跑了dry-run验证,另一个直接改了线上配置;一个在遇到异常时主动汇报并等待决策,另一个自行决定了一个有风险的方案。如果只看最终结果,两者都是“pass”,但过程中的行为质量天差地别。这就是为什么我们需要完整的交互记录——判卷时不只看“做没做到”,更要看“怎么做到的”。
为什么判卷要独立于对话?
这是踩过的最深的一个坑。早期设计里,我们让考官“顺便”打个分,逻辑看起来很自然——考官全程参与了对话,最了解过程,打分应该很合理。结果发现误判率高得惊人。原因很简单:考官的视角是对话视角,它只能看到Agent“说了什么”。但Agent的真正工作——写文件、跑命令、调接口——都发生在tool call里,考官在对话层面只看到一句“我已完成操作”。于是出现了一种荒谬的场景:Agent明明完美执行了所有步骤(从tool call记录来看),考官却因为在对话里只看到一句简短汇报,判定“考员没有充分展示执行过程”而判为失败。
教训很明确:判分必须拥有完整的“上帝视角”,对话视角远远不够。
判卷:多维度+证据+改进建议
裁判(Judge)是一个完全独立的进程,与答题对话之间没有任何共享上下文——单独启动、单独运行、没有任何“记忆污染”。它拿到的输入只有两样东西:rubric.md(评分标准)和transcript.for-judge.txt(从原始对话记录精简派生的判卷专用版本)。我们不是把原始的transcript.jsonl(动辄几万行)原封不动地丢给裁判——那样只会用信息洪水将裁判淹没。我们做了一层专门的压缩处理:保留所有关键行为证据(tool call内容、文件写入、shell输出摘要、关键对话节点),去掉冗余信息(重复的系统提示、过长的文件dump等)。这样裁判拥有了完整的“上帝视角”——能看到考生真正做了什么,而不只是嘴上说了什么,同时信息密度足够高,不会因为噪声而判断失准。
拿到这两份材料后,裁判按以下流程完成阅卷:
- 逐项核对硬性通过标准。rubric里每一条“必须达成”的项目,裁判都必须在transcript中找到对应的行为证据。找不到证据=该项不通过,没有“我觉得它应该做了”这种推测空间。
- 评估过程质量。通过了不代表做得好——是主动的还是被动的?是第一时间确认的还是被追问后才补的?是严谨验证过的还是草率跳过的?
- 给出多维度分数。流程遵循度、执行质量、综合分——三个维度各自独立打分,不互相干扰。
- 引用原文作为证据。每个判定都必须附上transcript中的具体引用片段,做到有据可查,不允许出现“考生整体表现不错”这种空泛评语。
- 强制输出改进建议并分类归因。每条建议必须标注维度:[workflow]、[eval]、[capability]。
整个过程可以概括为一句话:拿着标准答案,看着完整录像,逐帧打分,每个判定都要举证。
裁判输出,分层落库
裁判的输出包含8个字段,但采用分层落盘设计——核心指标和详细诊断分开存储。score.yaml包含5个结构化字段(result、compliance、execution_quality、overall、summary);review.md则包含证据和改进建议,每条建议都严格按照[workflow]、[eval]、[capability]三维度分类。这套分类是反复打磨出来的,目的是让改进建议可以直接被路由到不同责任方。跑完一批评测后,batch-insights.md会自动汇总,直接生成“下一轮工作流要改什么”的清单。评测不再是成绩单,而是工作流的迭代驱动器。
执行引擎:把各角色串起来,一键执行评测
当各个功能角色都已准备就绪,如何将“跑题”这件事压缩成一条可无人值守执行的命令?执行引擎是整个系统的骨架——一个用Go编写的单一CLI程序,编译产物即为全部,代码层面只引入了一个外部三方库。没有任何评测框架、没有ORM、没有web server。这个选择是为了实现零环境部署(任意机器上执行go build即可运行)、代码高可读性,以及不被框架绑架的灵活性(评测系统的需求会持续演化,框架越重越难调整)。
几个关键设计:
- git worktree隔离:每个并发run都获得一份独立的sandbox副本,本质上是git worktree出来的目录树,共享git对象库。这一招让“并发跑5道题”时各题之间互不干扰。
- symlink软链接:评测期间用symlink把沙箱环境中的IDE配置目录替换为本轮run内的工作流快照,原始目录先备份后恢复。相当于考试时收走课本、摆上考卷,考完再物归原主。
- transient错误自动重试:对话调用(考官/考生每轮交互)最多尝试2次,间隔2秒;裁判调用(独立判分)最多尝试3次,间隔3秒;对超时(context deadline)不重试、不兜底。
评测结果:让成长的趋势“看得见”
这一节回答的是:跑了几十次之后,如何从一堆run目录中判断工作流到底在变好还是变差。系统产出的结构化产物包括latest.md(汇总表)、latest-stats.yaml(结构化版本)、score-history.yaml(全历史run的扁平记录,每条都带workflow_rev字段)和batch-insights.md(所有run的improvements按维度聚类汇总)。workflow_rev记录了每次run所用工作流的git commit——这意味着当我们遇到“v0.3通过率0.4,v0.4提升到0.8,v0.5又跌回0.6”这类问题时,可以直接定位到具体commit的影响,而不再靠回忆。
五、评测工程的效果
将这套评测工程应用到团队内部的Harness工作流上进行测试与优化,结果如下:
针对仍处于Fail状态的三道题目进行针对性改进后:
整体通过率从之前的82.4%(14/17)提升到了100%(17/17)。通过工作流的标准化考题、4轮workflow_rev迭代、50余次自动化运行,系统性地暴露了团队内部Harness工作流在范围锁定、Critical拦截、归档沉淀、提交规范、TDD纪律等多个环节的缺陷,并通过“评测-修复-回归”的闭环逐一修复。多道关键题目的overall分数从1-2分修复到了满分5分。同时,评测系统本身也沉淀为可复用的工程基础设施和方法论文档,具备了向其他工作流平移的通用性。
六、写在最后
回过头来看,我们做的事情可以抽象为一句话:为一个“行为不确定”的Harness工作流,建立可重复、可归因、闭环的质量度量体系。软件工程界用几十年总结出“测试驱动开发”,而Harness工作流的复杂度和不确定性比传统软件更高,更需要这种思路:产出可复现的评测题目,驱动工作流自动执行验证,根据统一规则量化评分,基于数据驱动持续迭代。这套方法论不绑定任何平台,也不局限任何场景。但凡存在行为效果难以直观判定优劣的Harness类工作流,均可直接使用这套评估体系的思想。
为什么这件事现在特别重要?Harness正在从“新鲜玩具”向“生产工具”转变。当它真正进入工作流的关键路径时,“好不好用”不再是一个可以靠体感回答的问题——它关系到交付质量、研发效率,甚至线上安全。任何不可量化的东西都不可优化。如果不能回答“昨天那版和今天这版到底谁更好”,所谓的“持续改进”不过是自我感动。在一个充满概率和不确定性的领域里,“确定性”是最稀缺的资源。而获取确定性的方式,从来都只有一个:量化它,追踪它,用数据说话。






