Agent 项目面试怎么讲?从系统架构、技术选型到 Badcase 复盘
Agent/AI 应用方向的面试,基本不会停留在背概念,一般都是结合你的项目往深了问:为什么这样设计、线上出过什么问题、怎么定位和修复。
如果你在面试之前,只背 ReAct、RAG、Memory、MCP、Function Calling 等核心概念,通常应付不了面试追问:
- 你做的到底是不是 Agent,为什么不能用普通接口或固定工作流解决?
- 一个请求进来后,经过了哪些组件,状态和数据怎么流转?
- 关键方案是根据什么约束选出来的,代价是什么?
- 项目失败过什么,你怎么定位、修复并防止它再次发生?
为了方便大家更容易理解,我在文中会以一个智能售后工单 Agent 为例,来串起来这些问题。
不论你的项目是不是类似的,都没关系,文中分享的方法都是通用的。你在准备自己的项目时,业务背景、职责、数据规模和指标都要换成真实内容。
Agent 项目面试到底在考什么?
先看面试官为什么这么问。Agent 项目不像 CRUD 项目有成熟的评价标准,面试官没法只凭“做过”两个字判断你的水平,只能靠追问来核实三件事:
- 项目是不是真的。 真做过的人说得出约束、数据和踩过的坑,背项目的人只能复述架构图。追问到第三层,两者的差距会立刻显现。
- 你有没有做技术决策的能力。 Agent 领域同样没有银弹,同一个问题可以用 Prompt、工作流、RAG、工具调用或 Multi-Agent 解决。面试官想知道:面对你的具体约束,你能不能权衡出合理方案,而不是教程/网上是这么做的,或者 AI 直接给你提供的方案。
- 你对系统边界的认知。 模型输出不可靠、状态可能不一致、工具会失败——知道这些风险、并且用工程手段兜住的人,才是能上生产的人。
对应地,“项目效果很好”“架构可扩展”“模型准确率高”这类回答为什么不行?因为它们是结论,不是论证。面试官听到的信息量是零:既判断不了真假,也判断不了你的参与深度。真正有区分度的回答,是把约束、选择、代价和证据放到一起:
在什么约束下,我做了什么选择;它解决了什么问题,又引入了什么代价;最后用什么证据确认这个选择有效。
这四样东西缺一个,回答都会塌:
- 缺约束,选择就变成“大家都这么用”,体现不出判断力;
- 缺代价,说明没真正上过线——任何方案都有代价,Multi-Agent 拆了之后调试成本、上下文传递、延迟都会上升;
- 缺证据,效果就只是主观感受,“工具选错率从 8% 降到 2%,评测集 200 条”才可核对;
- 缺替代方案,面试官无法确认你是做过权衡,还是只会一种做法。
例如,“我们用了 Multi-Agent 提升效果”没有交代拆分的原因和代价。回答时可以补上这次决策的经过。
最初是单 Agent,工具数量增加后,退款政策查询和工单写入的工具容易选错。我们没有直接拆成多个 Agent,而是先缩减工具集、重写工具描述并补充路由评测,选错率从 8% 降到 3%。后来不同业务域需要独立上下文,并改由不同团队维护,我们才按业务域拆分 Agent。代价是跨域任务需要一层路由,整体延迟多了几百毫秒,所以我们把路由做成了基于意图分类的轻量调度,而不是再引入一个“管理 Agent”。
对比一下就能看出差别:原版回答只有“用了什么”,展开版交代了现象(工具选错)、选择(先治理工具再拆分)、替代方案(不拆也能解决一部分问题)、判断依据(路由评测数据)和代价(延迟增加及其应对)。面试官从这段话里能同时核实项目的真实性和你的决策过程,这比报出一串框架名的信息密度高得多。
而且这段回答还有一个作用:它主动给面试官留了追问的钩子——路由评测怎么做、意图分类为什么不用 LLM 路由、上下文怎么传递。这些钩子应该都是你提前准备好的领域,让深挖发生在你的主场,而不是被动地被问到知识盲区。
项目复盘表应该写什么?
准备回答前,建议先按下面这张表复盘项目。表里记录面试官继续追问时,你能够拿出来核对的事实,不承担简历的展示功能。
| 项目要素 | 需要写清楚的内容 | 常见空话 |
|---|---|---|
| 业务问题 | 谁在什么场景下遇到了什么问题 | “提高用户体验” |
| 成功标准 | 什么结果才算任务完成 | “回答得更准确” |
| 输入与输出 | 用户输入、系统最终产物、是否修改外部状态 | “支持自然语言交互” |
| 原有方案 | 人工流程、规则系统或普通 RAG 的不足 | “传统方案不智能” |
| 个人职责 | 自己负责的模块、决策和排障工作 | “参与整体建设” |
| 关键约束 | 延迟、成本、权限、数据、模型能力和上线时间 | “要求高可用” |
| 方案选择 | 候选方案、选择理由和已知代价 | “经过调研选了某框架” |
| 质量证据 | 数据集、指标口径、基线、样本量和评测版本 | “准确率提升 30%” |
| 失败案例 | 输入、Trace、根因、修复和回归用例 | “优化 Prompt 后解决” |
| 证据位置 | 代码类、测试用例、Trace、数据集或提交记录 | “代码里有实现” |
如果某个格子没有真实材料,先留空。尤其不要补造 QPS、准确率、节省人力等数字。面试官继续追问统计口径、时间范围和基线时,虚构的数据很容易穿帮。
对尚未上线的个人项目,也完全可以提供可信证据:固定的测试集、可复现的 Trace、错误分类、压测结果和设计取舍都可以。关键是说清楚“这是离线实验结果”,不要把它包装成生产数据。
项目处在哪个阶段也要提前说清楚:跑通 Demo、完成离线评测、小流量试点和正式生产不是一回事。没有真实用户时,可以讲测试集和故障注入;没有线上事故时,可以讲评审阶段发现的风险和设计预案,但不能换个说法把它包装成生产 Badcase。
个人职责可以用一句话拆开:团队最终完成了什么,我具体负责哪一段,亲自做过哪些决策或排障,哪些工作由其他同学负责。这样比“我负责整个 Agent 项目”更可信,也方便后面所有回答都守住同一条边界。
如何用一个案例讲清 Agent 项目?
假设项目是一个智能售后工单 Agent。用户可以用自然语言描述问题,系统会查询订单、检索售后政策、判断还缺哪些信息,并在用户确认后创建售后工单。
这里故意同时放入了三类能力:
- 检索售后政策,属于 RAG;
- 查询订单、创建工单,属于工具调用;
- 根据当前信息决定继续查询、追问还是结束,属于 Agent 决策。
其中,“创建工单”会修改外部状态,不能只依赖模型输出一个合法 JSON。权限校验、用户确认、幂等和执行结果核验都必须由业务系统负责。
项目中的 Agent Loop 可以采用 ReAct 这类执行方式:模型提出下一步动作,拿到环境返回的 Observation 后,再决定继续调用工具还是结束。
ReAct 指的是动作与观察交错推进,不是调用一次工具就算完成了 Agent 设计。生产 Trace 记录动作、工具结果、状态摘要和可核验依据即可,不需要保存模型的私有思维链。
30 秒版本怎么说?
30 秒版本只回答项目是什么、为什么需要 Agent、你负责什么和最难的问题是什么。
这里还是以智能售后工单 Agent 为例:
我做的是一个智能售后工单 Agent。除了知识库问答,它还会根据用户描述动态查询订单、检索售后政策、补充缺失信息,并在用户确认后创建工单。整体采用固定工作流加局部 Agent Loop:鉴权、权限校验、确认和写入是确定性节点,模型只负责意图理解、信息补全和下一步工具选择。
我主要负责 Agent 编排、工具治理和评测。项目里最典型的两个问题是相似工具误选,以及写接口超时后无法判断是否已执行,我们分别用工具契约优化和“幂等键 + 状态查询 + 对账”解决。
千万不用讲太细节,比较聪明的做法是预留下自己提前准备好可被追问的内容:为什么是混合架构、工具怎么治理、写操作为什么不能盲目重试、评测怎么做。
3 分钟版本怎么展开?
3 分钟版本可以按下面的顺序:
- 业务问题与成功标准;
- 一次请求的完整链路;
- 两个关键技术选择;
- 一个最有代表性的 Badcase;
- 结果与自己的职责边界。
不要按“Spring AI、Redis、Milvus、MCP……”的顺序报技术栈。技术栈应该出现在具体决策里,而不是单独占一段。
如何从一次请求讲清系统架构?
“我们采用分层架构”很抽象。面试时可以先带面试官走完一次请求,再回头解释每层的职责。

以“这个订单的耳机坏了,帮我申请售后”为例,一次请求可以这样流转:
- 接入层完成身份认证、租户识别、限流,并生成
requestId和runId。 - 编排层读取当前任务状态,判断订单号等必要信息是否齐全。
- Agent 根据可用工具及上下文选择订单查询工具。业务执行层再次检查用户是否有权查看该订单。
- 系统根据订单商品、购买时间和问题类型检索对应售后政策,并把证据注入本轮上下文。
- 如果信息不足,Agent 向用户追问;如果条件满足,则生成待创建工单的结构化草稿。
- 写操作执行前,系统展示关键字段并等待用户确认。确认后再校验权限、业务规则和幂等键。
- 工单服务返回结果后,系统不能只相信“调用成功”的文本,而要保存业务工单号和最终状态。
- 记录模型调用、Prompt、检索、工具、审批、耗时和结果,供评测与 Badcase 回放使用。
对应到系统分层,可以压缩为下面七层:
| 层次 | 主要职责 | 不能交给模型的工作 |
|---|---|---|
| 接入层 | 鉴权、租户、限流、流式连接、请求标识 | 身份和租户边界 |
| 编排层 | Workflow、Graph、Agent Loop、停止条件 | 超时预算、最大步数、强制分支 |
| 模型层 | 模型路由、Prompt、结构化输出 | 供应商降级和成本硬限制 |
| 上下文层 | RAG、会话历史、Memory、上下文裁剪 | 数据访问权限和事实来源校验 |
| 工具层 | 工具发现、参数校验、执行和结果回传 | 业务校验、授权、事务和幂等 |
| 状态层 | 任务状态、检查点、业务产物和记忆 | 权威业务状态的一致性 |
| 治理层 | Trace、评测、审计、告警、灰度和回滚 | 发布门禁和高风险动作审批 |
如果项目没有这么多独立服务,不要硬说成七个微服务。这里描述的是逻辑职责,早期完全可以放在同一个应用中。面试官更关心边界是否清楚,不是服务数量是否足够多。
Agent 项目的技术选型应该回答哪些问题?
前五个问题用于解释每一项选择,第六个问题决定方案能否经得住验证:
- 当时的业务约束是什么?
- 比较过哪些候选方案?
- 为什么当前方案更合适?
- 它牺牲了什么,又如何控制代价?
- 用什么评测或运行数据验证?
- 如果约束变化,什么情况下会换方案?
为什么用 Agent,而不是普通 Workflow?
固定 Workflow 可以读取中间状态、走条件分支,也可以把 Agent 放进某个节点。选择方案时,需要确认下一步究竟由预定义代码或图规则控制,还是由模型在运行时选择动作、工具和路径。
在售后案例中,鉴权、确认、工单写入和审计都能提前确定,应该放进 Workflow。用户可能只说“坏了”,也可能提供订单号、故障照片和已经尝试过的处理方式;如果候选路径难以靠有限规则穷举,并且评测证明模型决策确实带来收益,查询订单、检索政策还是继续追问这一小段才适合交给 Agent。
反过来,如果工单类别、必填字段和处理规则都有限且稳定,“意图分类 + 表单补齐 + 固定规则”可能已经够用。自然语言入口本身不能证明项目必须使用 Agent。
这个案例适合采用混合架构:
用确定性 Workflow 固定安全边界,在路径不确定的局部嵌入 Agent Loop。
关于 Workflow、Graph 和 Loop 的区别,可以继续看 AI 工作流中的 Workflow、Graph 与 Loop。
为什么先做单 Agent,而不是直接 Multi-Agent?
单 Agent 的状态、Trace 和故障链路更短,通常也更容易评测。工具多并不等于必须拆成多个 Agent,可以先尝试:
- 按场景动态加载工具;
- 合并功能重叠的工具;
- 重写名称、描述和参数 Schema;
- 用代码路由处理边界清楚的分类;
- 为复杂任务隔离子上下文。
任务可以独立拆分,不同角色又需要大量专属上下文、差异明显的工具权限或独立维护责任时,Multi-Agent 带来的收益才可能抵消通信、成本和调试开销。
多 Agent 也不等于并行。它可以按固定顺序执行,可以在没有依赖的分支并行,也可以由 Manager 动态委派,或者把当前回合 Handoff 给 Specialist。
面试时要继续说明:拓扑由代码固定还是由模型决定,上下文是共享还是隔离,Agent 之间用什么结果契约,部分失败和并行写冲突怎样处理,最终由谁对结果负责。
关于 Multi-Agent 相关问题的总结,可以参考多 Agent 协作系统设计这篇文章。
RAG、Memory、Context 和 State 怎么区分?
这四个概念经常在项目介绍里混在一起。
下面采用的是本文在售后项目里的工程口径,不是所有框架都统一遵守的一套类型定义。
| 概念 | 在售后案例中的内容 | 主要回答的问题 |
|---|---|---|
| RAG | 售后政策、产品手册、服务网点资料 | 外部知识里有哪些相关证据? |
| Memory | 用户偏好、经过确认且允许长期保留的信息 | 跨轮次或跨会话需要记住什么? |
| Context | 本轮实际发给模型的指令、证据、工具和历史 | 模型这一次能看到什么? |
| State | 当前订单、缺失字段、审批状态、已执行动作、工单号 | 任务现在进行到哪一步? |
短期 Memory 在一些框架里本来就是 Agent State 的一部分,Checkpoint 也可能保存某个时刻的 State。名称会变,但边界不能混:Memory、Agent State 和工作流 Checkpoint 都不能代替权威业务数据库。把“工单是否已创建”只保存在对话历史里,是很危险的设计。
详细原理可以分别看 上下文工程实战指南 和 AI Agent 记忆系统详解。
项目里如果真的用了长期 Memory,还要能回答哪些信息允许写入、来源由谁确认、保存多久、用户怎样查看和删除,以及恶意内容写入后如何清理。只保存了几轮 Chat History,就按会话历史来讲,不要包装成完整的长期记忆系统。
RAG 部分也不能停在“接了向量数据库”。至少准备好文档怎么解析和切块、索引如何更新、向量与关键词怎样召回、是否使用 Reranker、Top-K 怎么定、ACL 在哪里生效,以及引用与知识版本如何回放。评测时把检索命中和最终回答分开看,不然很难判断问题出在召回还是生成。
Function Calling、MCP 和 Agent 分别负责什么?
Function Calling 让模型用结构化参数表达“想调用哪个函数”;MCP 负责 Host、Client 和 Server 之间的上下文交换,可提供 Resources、Prompts、Tools 等原语;Agent 负责结合目标和状态决定下一步做什么。
它们不在同一个层次,也不能互相替代。
如果工具只服务于当前应用,直接注册本地函数通常更简单。如果同一套能力要被多个 Agent、IDE 或模型客户端复用,再评估 MCP。采用 MCP 后,权限、参数校验和副作用治理仍然要在业务侧完成。

这部分容易被追问,建议配合 大模型结构化输出详解 和 MCP 协议详解 一起复习。
模型怎么选?
不要用“某模型效果最好”作为唯一理由。模型选择至少要同时看:
- 目标任务上的成功率;
- 工具选择和参数填写能力;
- 长上下文或多轮稳定性;
- 首 Token 延迟和完整响应延迟;
- 输入、输出及缓存 Token 成本;
- 结构化输出、工具调用和多模态等能力是否受支持;
- 数据合规、地域和供应商可用性。
比较稳妥的做法是先用能力较强的模型建立质量基线,再逐个节点尝试更小、更便宜的模型。分类、简单抽取和格式转换未必需要最强模型;规划、复杂判断和最终综合可能需要更强模型。每次替换都跑同一套评测集,避免只凭几次手工对话下结论。
为什么要引入模型网关?
项目只接一个模型、还处在验证阶段时,可以先直接调用 API。供应商增加或多个业务开始共享调用能力后,再用模型网关统一处理鉴权、模型路由、限流配额、重试、降级、成本归因和审计。
具体设计可以看 大模型网关详解。
哪些是框架能力,哪些是项目自己实现的?
面试中提到框架时,最好同时给出版本和能力边界。框架帮你跑通 Tool Loop,不代表它已经替项目完成业务状态、权限、幂等和审计。
以本文核对时的实现为例:Spring AI 2.0.0 可以通过 ToolCallingAdvisor 和 ToolCallingManager 管理工具循环,ToolCallbackResolver 可以动态解析工具;具体用户能不能退款、是否需要审批,仍由业务代码判断。AgentScope Java 2.0.1 的 AgentStateStore 可以保存 Agent 会话状态,但它不是订单数据库或工作流业务 Checkpoint;streamEvents() 提供事件流,也不等于系统已经持久化了完整 Trace。
如果项目用了其他版本,按实际 API 重新核对。回答时可以直接分成两句:“框架提供了什么”“我在框架外补了什么”,不要把封装层能力全部算成自己的架构设计。
工具调用为什么不能只看模型输出?
模型返回合法参数,只能说明格式通过,不代表这个动作允许执行。
一条完整的工具调用链至少有下面几道检查:
- Schema 校验。检查字段类型、枚举、格式和必填项是否合法。
- 业务校验。检查订单状态、售后时限和字段组合是否满足规则。
- 身份与权限。确认当前用户能否访问目标资源。
- 风险判断。分别定义只读、可逆写入和不可逆写入的执行策略。
- 人工确认。根据风险等级判断是否需要展示最终参数并等待确认。
- 幂等控制。防止重试或重复点击产生多次副作用。
- 结果核验。检查外部系统的最终状态是否符合预期。
- 审计记录。记录谁在什么时间以什么参数执行了什么动作。

一个实用的工具风险分级如下:
| 等级 | 示例 | 建议策略 |
|---|---|---|
| 低风险只读 | 查询公开政策、读取用户自己的订单 | 权限校验、参数限制、超时和审计 |
| 中风险可逆写入 | 创建草稿、添加标签 | 幂等、结果核验、撤销入口 |
| 高风险写入 | 退款、取消订单、发消息 | 明确确认、额度限制、审批或人工接管 |
| 禁止自动执行 | 超出授权范围或无法补偿的动作 | 拒绝执行,只提供解释和人工入口 |
工具描述本身也要进入评测。名称含糊、功能重叠、返回内容过长,都会让 Agent 选错工具或污染上下文。
工具结果、RAG 文档、网页和 MCP Server 描述都可能夹带间接 Prompt Injection。它们进入下一轮上下文时仍是不可信数据,不能改变服务端身份、资源权限和工具风险等级。更完整的威胁模型见 LLM/Agent 安全实战。
Agent 项目的稳定性如何设计?
为什么超时不能直接判定为执行失败?
面试官问“模型或工具超时了怎么办”,不少人的第一反应是“重试几次不就行了”。如果继续追问“写操作已经执行成功,只是响应丢了呢”,原来的回答就不够用了。
这时再按原样重试一次,可能导致重复创建工单或重复退款。
问题出在对超时的理解上。超时只说明调用方在期限内没拿到结果,服务端那边可能是三种状态里的任何一种:请求根本没到达、正在执行、已经执行完但响应丢在了网络上。调用方无法区分,所以不能把超时直接当成失败。
查询类接口好办,读操作没有副作用,可以在总时间预算内对瞬时错误做有限重试。写操作不行,创建工单、退款这类请求一旦盲重试,就可能造成重复副作用。
更稳妥的方案是:
- 创建逻辑动作时生成一次稳定的
actionId,并用它参与业务幂等键;同一动作在 SDK 重试、消息重投和人工恢复中始终复用,新动作才生成新 ID; - 服务端用唯一约束或请求记录识别重复请求;
- 同一幂等键携带不同参数时确定性拒绝,不能静默返回第一次结果;
- 超时后先按幂等键查询执行状态;
- 状态仍不明确时进入对账或人工处理,而不是无限重试;
- 将最终业务对象 ID 回写到任务状态和审计日志。

重试还需要指数退避、随机抖动、最大次数、总截止时间和重试预算。模型 SDK、网关、HTTP Client、工具适配器和工作流节点不能各自独立重试三次,否则调用次数会被乘法放大。比较稳妥的做法是共享总 Deadline 和 Retry Budget,并在 Trace 中记录每一层的 attempt。
调用方超时、Future 被取消或者用户断开 SSE,也不代表远端写操作已经停止。副作用可能稍后成功,所以取消之后仍要保留幂等键、状态查询和对账。参数错误、权限失败和业务拒绝属于确定性错误,应立即失败;限流、临时网络错误等才可能在预算内重试。详细内容见 超时和重试机制详解 与 接口幂等性。
模型或工具持续不可用时怎么降级?
重试主要处理限流、临时网络错误等瞬时故障。模型供应商长时间不可用,或者某个工具持续报错时,继续消耗重试预算只会拉长响应时间。这时要及时熔断故障依赖,停止向它发送新请求,并根据任务风险选择备用模型、缓存结果、返回部分结果或转人工。
切换备用模型前,要用同一套评测集确认它能否承担当前任务。低风险的文本总结可以降级到能力较弱的模型;涉及退款、发消息等写操作时,模型能力下降可能同时影响工具选择和参数生成,这类任务更适合暂停执行或转人工,不能为了维持可用性静默降低安全要求。
工具降级也要看它在任务中的作用。可选工具不可用时,可以临时从工具集合中移除;缺少它仍能回答的问题,可以明确告知限制后返回部分结果;订单、权限或政策证据等必要数据拿不到时,应停止生成确定性结论。系统还要把熔断原因、降级路径和最终结果写入 Trace,方便区分“正常完成”和“降级完成”。
流量上来后还要看模型配额、工具并发、线程池、连接池和队列长度。限流与背压应尽量靠近入口,慢工具使用独立并发舱壁,避免一个第三方接口拖住全部 Agent Run。并行分支会写共享 State 时,还要提前定义合并和冲突规则。
如何给 Agent Loop 设置退出边界?
Agent 拿不到关键信息时,可能反复查询同一个订单,或者连续调用参数相同的工具。模型仍在返回下一步动作,任务却没有任何进展。如果执行器不主动终止,这个循环会一直消耗时间和 Token。
任务开始时,执行器要确定总截止时间、模型和工具的最大调用次数,以及 Token 和费用预算。每次准备调用模型或工具前,先检查剩余预算;单个工具还要有自己的超时时间,避免一次慢调用占满整条任务的期限。
次数没有超限也可能陷入死循环。系统可以比较连续几步的工具名、规范化参数和 State 版本。相同动作反复出现,或者执行多步后状态仍未变化,就按“无进展”停止。遇到退款等高风险动作则暂停任务,等待用户确认。
停止后要记录具体原因,并根据已完成的部分决定返回当前结果还是转人工。这些判断由执行框架或业务代码执行,Prompt 里的“最多调用十次”只能作为行为提示,不能代替系统限制。
长任务和人工确认怎样恢复?
以退款为例,Agent 已经收集完信息,真正执行前需要等待用户确认。用户可能几小时后才回来,系统不能继续依赖原来的进程和内存状态。暂停时要保存 runId、Checkpoint、待执行工具、规范化参数、当前 State、actionId,以及工具 Schema 和策略版本。
用户确认时,系统先校验确认人的身份和权限,并检查这次确认是否已经过期。恢复任务后还要重新读取订单状态。等待期间如果退款金额、订单状态、工具 Schema 或策略发生变化,原来的确认立即失效,系统需要展示新参数并再次确认。
部分框架恢复时会从节点起点重新执行。写操作节点因此仍要复用同一个 actionId,先查询外部状态,再决定是否执行;确认事件也只能消费一次。这样即使恢复动作被重复触发,也不会重复退款或重复创建工单。
Agent 项目的指标应该怎么讲?
面试时先讲任务有没有完成,再补充执行过程、成本和安全。一个脱离测试集与统计口径的“准确率 85%”,很难说明项目是否真的可用。
| 要回答的问题 | 可用指标 |
|---|---|
| 任务完成了吗 | 任务完成率、最终业务状态正确率、事实有据率 |
| 执行过程对吗 | 工具选择与参数正确率、多余调用率、越权调用数 |
| 成本能接受吗 | 端到端 P50/P95、模型调用数、Token、单任务成本 |
| 失败后可控吗 | 故障恢复率、转人工率、重复副作用数、误拦截率 |
说完指标,还要交代测试集从哪里来、怎样判定成功、同一个任务运行几次,以及相对哪个版本比较。已经上线的项目可以再补自助解决率、处理时长等业务指标,同时说明统计时间和对照组。项目还没有上线,就展示离线评测集和错误分布,不要把实验结果包装成生产数据。
售后案例中,工单是否正确创建属于 Outcome;调用了哪些工具、参数是否正确、有没有越权或重复执行,则要回到 Trace 检查。开放任务可能有多条正确路径,评测时先验证最终业务状态和必须满足的安全规则,不要求执行顺序和一条 Golden Sequence 完全一致。
一条固定输入和成功条件组成一个 Task,每次执行是一次 Trial。Agent 输出有随机性,关键任务需要运行多次。Grader 可以使用代码规则、LLM-as-Judge 或人工,Eval Harness 负责执行这些 Trial、保存 Trace 并汇总结果。

完整方法可以看 AI 应用评测体系。
Agent 项目的 Badcase 应该怎么复盘?
只说“模型答错了,然后优化 Prompt”,无法说明根因是否找对。一个合格的 Badcase 复盘要留下可复现的定位证据。
可以按下面七步回答:
- 保存现场。 保留输入、模型与 Prompt 版本、上下文、检索结果、工具请求与响应及外部状态。
- 描述现象。 写清预期结果、实际结果和影响范围。
- 分层假设。 分别检查数据、检索、上下文、模型、工具、编排和第三方系统。
- 控制变量。 一次只替换一个变量,避免同时修改模型、Prompt 和检索参数。
- 确认根因。 拿出能够稳定复现问题的证据,不能停在相关性上。
- 实施修复。 说明修复放在哪一层,并解释为什么不能只改 Prompt。
- 加入回归用例。 把原始 Case 和相邻边界 Case 加入回归集,再观察线上指标。
下面看两个容易被追问的例子。回答自己的项目时,先交代证据属于真实生产事故、离线故障注入还是设计预案。没有生产记录,就不要把模拟复现说成线上事故。
Agent 为什么会选错相似工具?
系统里有两个名字很像的工具。query_after_sale_policy 查询通用售后政策,不需要具体订单;check_after_sale_eligibility 接收订单号,判断这笔订单能否申请售后。用户已经提供订单号时,Agent 本应调用后一个工具,却选了前一个。它返回的政策说明可能没有事实错误,却回答不了“我的订单到底能不能申请”。
排查要先看 Trace。订单号没有进入模型上下文,说明状态组装出了问题;模型看到了订单号却仍然选错,才继续检查两个工具的名称、描述和参数是否容易混淆。固定输入后一次只改工具描述、Prompt 或模型,也能判断究竟是哪项修改让错误消失。
修复时,先把两个工具的职责和前置条件写清楚,并把订单号放进简短的状态摘要。如果路由规则能够由代码确定,例如只有拿到订单号才能检查具体订单,就直接缩小这一轮暴露给模型的工具集合。代码会先排除不满足前置条件的工具,没有订单号的请求也不会被 Prompt 里的固定优先级带偏。
最后把“有订单号”“没有订单号”“订单不属于当前用户”和“订单号格式错误”放进同一组回归测试。样本多了以后,再用工具混淆矩阵观察两个工具是否仍被频繁选错。
创建工单超时为什么会产生重复记录?
第一次创建请求已经在工单服务中执行成功,返回响应时网络却超时了。Agent 执行层只看到超时,于是生成一个新请求再次调用接口。工单服务无法识别两次请求属于同一个业务动作,最终创建出两张工单。
这个 Badcase 发生在工具执行层。调用方把超时记成了失败,接口又缺少幂等约束。实际上,超时只代表结果暂时未知,第一次请求可能失败、仍在执行,也可能已经成功。
创建动作开始时生成一个稳定的 actionId,后续的 SDK 重试、消息重投和人工恢复都复用它。工单服务使用这个标识建立幂等记录和唯一约束;同一个 actionId 携带不同参数时直接拒绝,避免悄悄返回一份不匹配的旧结果。
调用超时后,执行层先按 actionId 查询原请求状态。查到成功就回填工单号,明确失败后才允许按策略重试,状态仍不确定则进入对账或人工处理。Trace 也要区分 FAILED、TIMED_OUT_UNKNOWN 和 SUCCEEDED,不能把三种结果都记成调用失败。
回归测试需要故意制造“服务端已经写入,响应在返回途中丢失”的情况,确认多次恢复最终只会得到一张工单。
如何用 Trace 还原 Agent 的执行过程?
普通接口抛出异常时,状态码和异常栈通常能指出出错位置。Agent 即使没有抛异常,也可能在前几轮拿错文档、选错工具,最后生成一段看起来合理的错误答案。Trace 按时间还原这段执行过程,记录系统实际看到的输入、产生的输出和执行的动作。它不保存模型的私有思维链,也不能证明模型内部为什么作出某个判断。
以一次售后工单请求为例,Trace 可以按下面的顺序记录。
- 请求进入系统时生成
requestId和runId,同时关联脱敏后的用户、租户标识,以及本次运行使用的代码、Prompt 和工具 Schema 版本。 - 每次调用模型时保存脱敏后的输入摘要与模型输出,并记录 Token、耗时和停止原因,避免只留下最终回答。
- 发生检索时记录查询内容、命中文档 ID、分数和真正注入模型的片段,并带上知识库版本。
- 调用工具时生成
toolCallId,记录参数摘要、权限判定、执行结果和错误类型。重试还要带上attempt、父 Span 和幂等键摘要,才能看出同一个动作执行了几次。 - 任务结束或暂停时记录状态变化、Checkpoint、人工确认、最终 Outcome、总调用数、总成本和降级原因。
排查时从最终结果往前看,找到第一次偏离预期的位置。检索阶段拿错文档,就查切块、召回和 Reranker;证据已经正确,Agent 却选错工具,再查上下文与模型;工具返回成功而业务状态没有变化,则检查工具适配器和结果核验。这样能把“回答错了”缩小到某一次检索、模型调用或工具执行。
模型输入、工具参数和检索片段可能包含个人信息或业务机密,生产环境通常只保存脱敏摘要,并配合采样、访问控制和保留期限。排障需要的字段可以留下,完整原文不应默认长期保存。
回放某一次请求看 Trace,观察一段时间的延迟和错误率看 Metrics,核对谁批准了退款等外部操作看 Audit,比较不同模型或 Prompt 版本看 Eval Record。具体异常日志可以挂到对应 Span 上。这些记录通过同一个 runId 关联,不需要塞进一张大表。
Session、Run、Trace、Span 和 Attempt 的划分、异步任务的上下文传播,以及采样和敏感数据处理,详见 AI 可观测性与 Trace。
面试前要做哪些准备?
每个 Agent 项目至少准备下面这些内容:
- 一份项目复盘表;
- 30 秒、3 分钟和 10 分钟三个版本的介绍;
- 一张能从入口讲到最终结果的架构图;
- 两个有备选方案的技术选型;
- 两个不同根因的 Badcase,最好一个效果问题、一个工程问题;
- 一份评测集分类和指标定义;
- 一条可以逐节点解释的 Trace;
- 当前使用的模型、框架、协议和工具 Schema 版本;
- 项目当前明确存在的限制和下一步计划;
- 自己负责与未负责的边界。
最后可以用下面这组问题做一次自测:
- 去掉大模型后,原流程是什么?
- 为什么是 Agent,不是 RAG 问答或 Workflow?
- 模型、工具、Memory、RAG 和 State 的边界分别是什么?
- 哪些决策由模型做,哪些必须由代码做?
- 写操作如何授权、确认、幂等和核验?
- 如何限制死循环、成本和总时延?
- 指标的公式、样本和基线是什么?
- 最严重的一次失败如何复现?
- 修复后如何证明没有引入新的回归?
- 如果流量扩大十倍,最先出现瓶颈的环节是什么?
requestId、runId、sessionId、toolCallId和actionId分别解决什么问题?- HITL 暂停后如何持久化、过期、恢复并重新校验业务状态?
- RAG、工具结果、MCP Server 和长期 Memory 的信任边界在哪里?
- 哪些能力由框架提供,哪些权限、状态和可靠性机制是项目自己实现的?
- 当前结论哪些来自生产、哪些来自离线实验、哪些只是设计预案?
如果这些问题都能基于真实证据回答,项目介绍基本不会停留在“套壳 Demo”层面。
