Harness Engineering 03Eval Trace Harness验证和追溯的工程组织activity-dev-harness 在第三周遇到一个典型事故Prompt 微调后团队手试了 5 个 case 感觉更好了直接上线。三天后用户反馈质量下降拉全量回归一看——通过率从 78% 跌到 61%。追查过程更痛苦回归能看到跌了但看不到从哪一步开始跌的。是上下文变了工具调用变了还是模型决策路径变了没有执行轨迹全靠猜。最后花了两天才定位到根因Prompt 微调改变了 Developer Agent 的工具选择倾向原本优先用 grep 精确定位的行为变成了先用 file_read 大面积扫描导致 token 消耗膨胀、上下文质量下降。这次事故暴露了两个缺失没有自动化回归Eval 缺失没有行为级追溯Trace 缺失。分别补上后类似问题再没发生过。手记系列讲了什么是评测和观测这篇讲Harness 怎么组织它们手记 03 已经覆盖了评测和可观测性的基础概念AI 测试金字塔、非确定性回归、5 层可观测模型。这篇不重复那些内容。它要回答的是一个更具体的工程问题当你有一套 Agent 系统Eval 和 Trace 应该怎么组织成闭环才能真正防住质量退化手记 03 的视角 本篇的视角 ────────────── ────────────────── 什么是 Eval Eval 在 Harness 里怎么组织 什么是可观测性 Trace 记什么、怎么用、服务谁 评测集怎么分类 Eval Trace 怎么串成闭环 非确定性回归的原理 真实系统里的 Eval 流水线长什么样Eval Harness不是跑几个 case是验证流水线大多数团队的评测停留在手动阶段改完 Prompt → 手试几条 → 感觉不错 → 上线。问题在于Agent 系统的变化维度太多手动试验完全覆盖不了❌ 手动评测的覆盖盲区 你手试了 5 个 case感觉更好了。但全量 35 个 case 里 case 类型 手试覆盖 实际表现 ──────────── ──────── ──────── 简单 case20个 3/20 ✓ 18/20 PASS确实更好了 边界 case10个 2/10 ✓ 5/10 PASS退化了但你没测到 历史故障5个 0/5 1/5 PASS严重退化完全没覆盖 你的结论更好了 ✓ 真实情况主流程更好了边界和历史故障退化了 ✗Harness 视角下的 Eval 不是跑 case是一条自动化验证流水线┌──────────────────────────────────────────────────────────────────────┐ │ Eval Harness 验证流水线 │ ├──────────────────────────────────────────────────────────────────────┤ │ │ │ 触发条件 │ │ ├── Prompt 变更 │ │ ├── 模型版本升级 │ │ ├── 工具/检索策略变更 │ │ └── 定时回归每日/每周 │ │ │ │ │ ▼ │ │ ┌───────────────────────────────────────────────────┐ │ │ │ 评测集分层 │ │ │ │ ├── gold case × 3 基准验证必须全 PASS │ │ │ │ ├── regression × 25 回归覆盖统计通过率 │ │ │ │ └── failure × 7 历史故障回收防重复犯错 │ │ │ └────────────────────────────┬──────────────────────┘ │ │ ▼ │ │ ┌───────────────────────────────────────────────────┐ │ │ │ 评估函数三层 │ │ │ │ ├── 结果层SH-01~10 确定性检查PASS/FAIL │ │ │ │ ├── 行为层DC-01~07 深度一致性检查 │ │ │ │ └── 稳定层同 case 跑 5 次波动率 15% │ │ │ └────────────────────────────┬──────────────────────┘ │ │ ▼ │ │ ┌───────────────────────────────────────────────────┐ │ │ │ 决策 │ │ │ │ ├── gold case 任一 FAIL → 自动阻断不允许上线 │ │ │ │ ├── 回归通过率 基线 5pp → 黄灯需人工审查 │ │ │ │ └── 回归通过率 ≥ 基线 → 绿灯可上线 │ │ │ └────────────────────────────┬──────────────────────┘ │ │ ▼ │ │ ┌───────────────────────────────────────────────────┐ │ │ │ 回收 │ │ │ │ 线上故障 case → 加入 failure 评测集 → 下次回归覆盖 │ │ │ └───────────────────────────────────────────────────┘ │ │ │ └──────────────────────────────────────────────────────────────────────┘评测三层结果、行为、稳定性只评结果对不对远远不够。Harness 视角下的评测至少三层评测层 评什么 怎么评 为什么重要 ────── ──────────── ────────────────── ────────────────── 结果层 最终输出是否正确 SH 脚本文件存在、 最基础的质量底线 空壳检测、参数一致 行为层 过程是否合理 DC 脚本逻辑一致性、 防止结果对了但过程 边界检查、依赖完整 不可接受 稳定层 多次运行是否一致 同 case 跑 N 次 防止这次对了下次 计算波动率 就不对了activity-dev-harness 的真实评测数据评测集 case 数 评估函数 基线通过率 当前通过率 ────────────── ──────── ───────────── ────────── ────────── gold case 3 SH×10 DC×7 100% 100% regression set 25 SH×10 DC×7 72% 78% ↑ failure recovery 7 SH×10 DC×7 43% 71% ↑↑ ──────────────────────────────────────────────────────────────────────── 加权通过率 68% 79% 稳定性评测gold case每 case 跑 5 次 case-001: 5/5 PASS 波动率 0% case-002: 4/5 PASS 波动率 20% → 需要调查 case-003: 5/5 PASS 波动率 0%Trace Harness不是多打日志是行为级追溯Eval 告诉你跌了。但从哪一步开始跌的只有 Trace 能回答。日志 vs Trace 的关键区别 普通日志 Trace ──────── ────── [INFO] tool_call: grep ┌─ Task: case-017 暴击伤害修复 [INFO] tool_result: 3 files found │ [INFO] tool_call: file_write ├─ Step 1: 意图解析 [ERROR] test failed │ 意图: 修复 calculateDamage 暴击倍率 │ 约束: 只改 combat/ 目录 记录事件 │ 无因果关系 ├─ Step 2: 环境探索 无法回答为什么选了这个工具 │ grep damage → 6 results │ 选择: combat/damage.lua (置信度高) │ 跳过: utils/calc.lua (旧版标记为 archive) │ ├─ Step 3: 代码修改 │ 修改: combat/damage.lua:42-48 │ diff: 3 -1 lines │ 边界检查: 修改在 combat/ 内 ✓ │ ├─ Step 4: 验证 │ pytest tests/test_damage.py → PASS │ SH-01~03 → ALL PASS │ └─ Result: PASS 耗时: 22s | tokens: 6.2K | 成本: $0.08 记录因果链 能回答为什么选了 combat/damage.lua 而不是 utils/calc.lua 能回答跌了的话是从第几步开始跌的Trace 五类必记信息一条能用于排障、评测和治理的 Trace至少记录五类信息类别 记什么 用于什么 ────── ──────────────────── ────────────────── 1. 任务起点 任务 ID、目标、约束、成功标准 归因是不是意图就不对 2. 环境快照 读了哪些文件、检索了什么、 归因是不是看到了错误信息 加载了什么上下文 3. 决策节点 选了哪个工具、为什么选、 归因是不是决策逻辑变了 还有什么候选 4. 动作结果 调了什么、参数、返回值、 归因是不是工具出了问题 成功/失败/异常 5. 反馈终局 测试结果、评测分数、 归因是不是反馈链断了 人工审核结论、接受/拒绝原因真实案例Trace 如何在 3 分钟内定位 Prompt 退化回到开头的故事。Prompt 微调后通过率从 78% 跌到 61%。有了 Trace 之后的排查过程排查步骤 发现 耗时 ────────────── ────────────────────── ────── 1. 拉退化 case 的 Trace 全部退化 case 都在 Step 2 出现异常 30s 2. 对比 Step 2 的决策节点 旧版优先 grep 精确搜索 1min 新版优先 file_read 大面积扫描 3. 对比 token 消耗 旧版 Step 2: 平均 2.1K tokens 30s 新版 Step 2: 平均 6.8K tokens224% 4. 定位根因 Prompt 微调增加了先全面了解再动手 1min 的引导语改变了工具选择倾向 总排查时间3 分钟 没有 Trace 时的排查时间2 天Eval Trace 闭环从跌了到知道为什么跌Eval 和 Trace 不是两个独立工具而是闭环的两个环节┌───────────────┐ │ 变更发生 │ Prompt / 模型 / 工具 / 检索策略 └───────┬───────┘ ▼ ┌───────────────┐ │ Eval 回归 │ 自动跑评测集对比基线 └───────┬───────┘ │ ┌───────────┼───────────┐ ▼ ▼ ┌──────────────┐ ┌──────────────┐ │ 通过率 ≥ 基线 │ │ 通过率 基线 │ │ → 绿灯放行 │ │ → 触发排查 │ └──────────────┘ └──────┬───────┘ ▼ ┌───────────────┐ │ Trace 对比 │ 拉退化 case 的 Trace │ │ vs 基线版本的 Trace └───────┬───────┘ ▼ ┌───────────────┐ │ 定位退化层 │ 决策变了工具变了 │ │ 上下文变了环境变了 └───────┬───────┘ ▼ ┌───────────────┐ │ 修复 回收 │ 修复退化 加入 │ │ failure 评测集 └───────────────┘没有 Eval你不知道跌了。没有 Trace你知道跌了但不知道为什么。两者串起来才是完整的质量防线。性能基准Eval 管质量Benchmark 管容量除了质量评测Harness 还需要性能基准。因为答对了不等于跑得起来activity-dev-harness 性能基准数据 指标 单 case 35-case 全量 高峰期并发×3 ────────────── ────────── ────────── ──────────────── 端到端时延中位数 22s --- --- 端到端时延P95 48s --- --- 单 case 成本 $0.08 $2.80 $3.5025%重试 推理排队等待中位数 0.3s 1.2s 4.8s 推理排队等待P95 1.1s 5.6s 18.2s ← 不可接受 通过率 82% 78% 71%退化 7pp 发现的问题 1. P95 时延是中位数的 2.2 倍 → 复杂 case 时延爆炸 2. 并发×3 时推理排队从 1.2s 涨到 4.8s → 推理服务是瓶颈 3. 高峰期通过率下降 7pp → 排队导致上下文超时重试增加性能基准的三层结构层级 测什么 发现什么 ────── ──────────────── ──────────────────────── 组件基准 单次推理延迟 Sonnet TTFT: 0.8s, 全量: 4.2s 单次工具调用 pytest: 3.1s, grep: 0.2s 单次检索 向量检索: 120ms, Rerank: 80ms 链路基准 一个完整 case 从头到尾 Developer 生成: 8s 各阶段耗时占比 Developer 自测: 5s × 3 15s Reviewer 审查: 6s 总计: 29s理想路径 工作负载基准 35 case 全跑 并发度: 3-5 高峰期模拟 推理服务排队情况 尾延迟分布 P99 是否可控早期团队的最小 Eval Trace 方案阶段 做什么 成本 ────── ──────────────────────── ────── Week 1 固定 3 个 gold case 基线结果 半天 Week 2 每次重要变更后跑 gold case 回归 10 分钟/次 Week 3 补 Trace记录任务起点 决策节点 1 天 动作结果 Week 4 补 failure 评测集回收线上问题 持续 Month 2 自动化变更触发 → Eval → 报告 2 天 Month 3 Trace 对比退化 case 自动拉两版 3 天 Trace 差异 不要先做什么 ❌ 评测平台先用脚本跑 ❌ 可视化仪表盘先用文本报告 ❌ 全量 Trace 存储先记关键节点 ❌ 实时告警先做每日回归Eval Trace 在不同项目里的组织差异项目 Eval 重点 Trace 重点 ──────────── ────────────────── ────────────────────── activity-dev 多轮循环通过率 每轮 Developer/Reviewer harness 稳定性同 case 5 次 的决策路径 工具选择变化 AIReview 规则命中精度 检索召回 → Rerank 排序 → 漏报率/误报率 最终引用的完整链路 配置表风险 批量准确率 每张表的风险判定依据 评估 高风险召回率 RAG 命中的规则版本 Crashsight 根因分析准确率 历史相似 crash 匹配 → 与人工分析的一致性 根因推理路径Eval Trace Harness 的核心判断Eval 防退化Trace 解释退化。没有 Eval 的系统靠直觉迭代没有 Trace 的系统靠运气排障。两者串成闭环才是 Harness 视角下的质量验证体系——不是有评测就行而是变更 → 回归 → 归因 → 回收这条完整链路必须自动化运转。