作业帮 Agent 开发一面:评测体系与 Trace 闭环
- 轮次
- 一面
- 时间
- 2026-09
- 来源
- 牛客网
《面试题目》
- 你们的 Agent 主要是用来做啥的?
- Agent 在执行时工具调用的幂等性怎么保证?
- 前端断开连接后,你们怎么保证重连后消息可以继续正确接收?
- 你们的 Agent 是否具备审计能力?审计信息主要用于发现哪些问题?
- 如何收集真实用户对话产生的 Trace,并将这些离线数据用于 Agent、Skill 和 CLI 的迭代?
- 你们的 Agent 评测体系由哪些部分组成?
- 评测集是如何构建的?如何将业务用户提出的 Oncall 问题沉淀为可复用的评测 Case?
- 初始评测集有多少条 Case?人工 Review 后保留了多少条,如何保证 Case 的有效性?
- 评测中使用了哪些确定性指标?如何统计工具调用次数、成功率、禁用工具调用和 Token 消耗?
- 无法通过代码直接判断的回复质量如何评估?Agent Reviewer 主要检查哪些方面?
- 如何综合确定性指标和 Agent Reviewer 的评分生成报告?
- 如何根据低分 Case 对 Agent 或 Skill 进行定向调优?
- 评测集是固定的吗?后续如何持续更新和迭代?
- 如果让你重新设计,你会怎么优化?
《参考解析》
工具调用幂等:把「可能重试」当成常态来设计
Agent 会重试(超时、模型重规划、网络抖动、用户重复触发),所以每个有副作用的工具都要能安全地被执行多次。可落地的做法分几层:① 幂等键——由调用方生成一个全局唯一 ID(通常由「会话 ID + 步骤 ID + 工具名 + 参数哈希」拼成),工具侧以它为唯一索引落库,重复请求直接返回首次的结果而不是再执行一遍;② 读写分离——把工具明确标成读操作(可自由重试)或写操作(必须带幂等键、必须可查询状态),写操作优先设计成「先查状态再决定是否执行」,即把「创建」变成带客户端 ID 的 upsert;③ 状态机 + 补偿——长耗时副作用(下单、发通知、提交审批)在本地落一张任务表,记录 pending/success/failed 与外部单号,失败进入可重试队列,超过阈值人工介入,而不是靠模型再想一次;④ 对不可幂等的外部接口,用「预留 + 确认」两阶段,或让工具返回「已受理」并异步对账。面试官通常会追问「幂等键谁来生成、存在哪、过期策略如何」,答的时候要把并发下的唯一约束(数据库唯一索引,而不是先查后写)说清楚,这才是真正挡住重复的机制。
断线重连不丢消息:服务端持久化 + 序号 + 游标重放
保证「重连后消息继续正确接收」的前提是消息不只存在于连接里。做法:服务端为每个会话维护单调递增的序号(或消息 ID 有序),每条消息先落库再推送;客户端本地记录「我已收到的最大序号」,重连时带上该游标,服务端把游标之后的消息按序补发,客户端按序号去重(乱序、重复到达都能处理)。推送阶段注意几点:连接是有状态的,重连可能落到另一台机器,所以要么把会话路由到固定实例,要么把订阅关系放到共享存储(Redis pub/sub 或消息队列);发送端支持至少一次投递,接收端靠序号做幂等,这样「丢」和「重」被分开处理——丢了能补,重了能去重。还要处理流式输出中断的情况:把「正在生成的消息」也持久化成可续写状态,重连时先补已生成的部分再从断点续推,否则用户会看到半句话消失。最后要有超时与心跳,让「连接已经死了但客户端不知道」这种状态尽快被发现。
评测体系:确定性指标打底,LLM Reviewer 补语义,两者都要可复现
一套能用的 Agent 评测体系一般包含四块:数据集(Case 集合与其预期结果)、执行器(能在固定环境里跑 Case,记录完整 Trace)、判分器(规则 + 模型评审)、报告与回归(对比基线、锁定版本)。确定性指标负责「机器能判的」:工具调用次数与顺序、是否调用了被禁用的工具、必填参数是否正确、成功率/失败率、端到端时延、Token 消耗与成本、是否命中预期的查询对象。这些指标应该直接从 Trace 里算,不依赖模型。
语义类的质量(回答是否切题、有没有幻觉、指令遵循、格式是否合规)交给 Agent Reviewer:写一个评分 Prompt,给出评分维度、明确的评分档位与反例,让它基于 Trace 与参考答案输出分数和理由;为了减少漂移,同一 Case 用固定温度、必要时多次采样取一致性,并且要定期用少量人工标注校准 Reviewer 与人的一致性。最后把两类信号合成报告时,建议分层呈现而不是简单加权成一个总分:先看确定性指标是否出现硬失败(调错工具、越权、超时),硬失败直接判负;再看语义得分分档。这样调优时才知道该改工具契约还是改 Prompt。
从低分 Case 到定向调优,以及评测集的持续迭代
低分 Case 的价值在于它指向了具体的责任层,所以复盘时要给失败分类:工具契约问题(参数设计不清、返回结构不稳定、缺少分页)、Prompt/Skill 问题(指令矛盾、缺少示例、步骤顺序错)、检索问题(召回不到或召回噪声大)、模型能力问题(推理深度不够、长上下文丢失)、还有环境问题(超时、限流导致的偶发失败,这类要从统计里剔除或单独看)。分类之后动作就明确了:工具问题改 schema 与返回契约,Skill 问题改流程与示例,检索问题调切分与排序,能力问题才考虑换模型或加拆解步骤。每条低分 Case 修完都要回到评测集里当回归样本,并记录「哪个版本修好、改动是什么」。
评测集绝不能是固定不变的:Oncall 工单、用户投诉、人工抽检发现的坏例都要按同一套格式沉淀成 Case(带上输入、期望、约束、来源),定期去重、标注难度与业务重要性,并把过时的 Case 下架。比较健康的做法是给评测集分层——核心回归集(小而稳,每次必跑)、业务场景集(按域组织)、探索集(新能力、新工具用),CI 里只跑核心集控制时间,发版前跑全量。只有评测集持续吸收线上真实问题,它才代表用户实际会遇到的世界。