过去大半年,我一直在做Agent方向的设计评审和面试。这个岗位名字可能五花八门,但做的事情高度一致:把大模型从"会聊天"推到"会干活",而且是能在生产环境里稳定干活。为了叙述方便,下面统一叫Agent工程化。
面了这么多候选人之后,我最大的体感是:大部分人对Agent的"开发"是有感觉的——扯起Prompt、工作流、工具调用头头是道;但一旦话题切到"评测怎么做、线上出了问题靠什么定位、并发上来会不会被打爆、多Agent到底该不该上",对话质量就断崖式下降。这篇文章就是把我面试中固定要用的5个关键问题,连同我背后的考察逻辑完整复盘一遍。如果你正要去面Agent方向的岗位,建议拿它做自查清单;如果你是带团队的,也可以直接把这套问题搬回去用。
1. Agent面试和普通后端面试到底差在哪
1.1 这个岗位真正在找什么样的能力
我理解很多候选人会觉得奇怪:我算法八股背得挺熟,怎么Agent面试还是被挂。因为Agent工程化岗位要的不是"能调通模型"的人,而是"能把一个概率系统变成确定性服务"的人。普通后端面试考察的是确定的逻辑、稳定的API、可预期的性能;Agent面试在此基础上多了一层麻烦:系统里有一个"非确定性引擎"LLM。它可能今天答对、明天答错,输入差一个字输出就差十万八千里,还会一本正经地把错误信息当事实输出。
所以这个岗位在找三种能力。第一种是对模型行为边界的理解——知道哪些能力应该交给推理,哪些应该交给代码和规则。第二种是对任务流程的工程拆解——能把业务目标拆成步骤、状态、分支和失败处理。第三种是对生产环境的敬畏——评测、观测、限流、降级、回滚,每一样都要落在系统设计里。这三种能力,光靠背Prompt技巧背不出来,必须在真实项目里被问题逼过一遍。
1.2 从开发到部署的五段链路和考察全景
我面试时不会东一榔头西一棒槌地问,而是沿着Agent的生命周期走一条完整的线:设计工作流 -> 验证质量 -> 排障复盘 -> 稳定上线 -> 横向扩展。对应地,我固定会问五个问题:
| 序号 | 我会问的方向 | 对应链路 | 我想收集的信号 |
|---|---|---|---|
| 1 | 一条Agent工作流怎么设计才不是玩具代码 | 开发期 | 模块分层、状态管理、失败路径 |
| 2 | 凭什么说Agent的输出是"对的" | 测试期 | 评测体系、结构化校验、兜底策略 |
| 3 | Agent管线崩了,靠什么定位 | 运行期 | 链路追踪、回放、异常定位思路 |
| 4 | Agent从原型到线上,哪些坑躲不掉 | 部署期 | 并发、缓存、超时重试、灰度回滚 |
| 5 | 当Agent不止一个,边界怎么划 | 扩展期 | 单/多Agent判断力、路由、协议隔离 |
这五个问题不是孤立的知识点,它们有一条隐形主线:风险。LLM不可控、外部工具会挂、系统会过载、代码会出错。工程化的本质就是在每个环节给风险加一层控制。候选人回答任何一个问题时,只要主动谈风险控制,在我这里的得分一定会上去。
1.3 面试评分表上我最看重的四个维度
在具体讲五个问题之前,先透个底:我打分不看重候选人是不是追到了最新模型,也不看重他用过哪个主流框架。我评分的核心是四个维度。
- 架构合理性:模块边界是否清晰,状态是否被妥善管理,扩展是否有明确方向;
- 损失控制意识:当某一步失败时,候选人能讲清楚代价是什么、如何止损、如何兜底;
- 可观测意识:候选人有没有主动设计日志、trace、回放的意识,而不是出了事才想到补;
- 成本敏感度:每个环节的token成本、推理延迟,候选人心里有没有一笔账。
这四个维度会在后面的五个问题里反复出现。你说完任何一个方案,我都会在心里问一句:"如果这个环节出了事,你的方案疼不疼?"
2. 问题一:一条Agent工作流怎么设计才不算"玩具代码"
2.1 我一般会怎么问
"假设我们现在要给内部做一个文档问答Agent,它需要检索企业文档、支持多轮追问、还能调用一个外部计算工具。你不用写代码,先告诉我整体工作流怎么组织,代码大概会分哪几层。"
这个问题很开放,但它能直接暴露一个关键事实——候选人脑子里有没有一张工程图。回答只有"先把问题给模型,模型决定调工具,我执行完再交回给它"的候选人,我基本能确定他只写过Demo。这个回答描述的是"一次循环",不是"一套可维护的系统"。
如果候选人反过来问几句,比如"多轮对话的记忆放哪里""外部工具失败怎么办""这一步的权限边界是什么",我会比较开心。因为真正设计过系统的人,第一反应一定是补边界条件,而不是急着给方案。一个只能顺着思路往下讲的候选人,和一个能主动堵住漏洞的候选人,差距就在这些反问里。
2.2 高分答案的骨架:编排层、执行层、基础层
我认可的典型结构是三个平面。编排层负责整条任务的管理。它定义Agent的入口状态、目标拆解方式、步骤推进逻辑和终止条件。这层可以把运行流程实现为有限状态机,例如:IDLE -> PLANNING -> EXECUTING -> WAITING_INPUT -> DONE / FAILED。每一步之间是显式转换,不是靠模型自由发挥跳转。
执行层负责把编排层的决策落地。比如调用检索接口、格式化结果、检查工具返回、把结果重新组装成模型能读的文本。基础层则是模型接口、各类外部工具、状态存储、配置中心。
为什么这样分?因为这是标准的分层思想。编排层决定了Agent"下一步做什么",执行层决定"具体怎么做",基础层决定"用什么资源做"。三层各改各的,互相不污染。举例来说,你想把某个工具的返回格式从JSON换成XML,只需要改执行层;你想在工具执行前增加一道审核确认,只动编排层即可。很多失败Demo的问题,就是把这三层全塞进一大段Prompt和回调里,最后谁也改不动。
2.3 状态管理:这一题能筛掉一半候选人
工作流设计里我最深追的就是状态管理。常见追问是:"如果任务执行到一半,进程重启了,你能恢复现场继续跑吗?"
很多候选人完全没有想过这个问题。他们会说:把对话历史全部塞进上下文,重启后让模型接着读,不就行了吗?其实这样在多数情况下都恢复不了——模型并不知道当前任务执行到了哪一步、哪些工具已经跑成功、哪些还没跑。
Agent在运行期至少有三类状态。交互状态是用户和Agent的多轮对话;任务状态是当前计划、已完成步骤、待办步骤、中间产物;外部状态是工具调用的幂等键、写操作结果、外部系统事务标记。合理的做法是把任务状态结构化成快照存进数据库或缓存,每完成一个关键步骤写一版。下面是一个很简化的快照示例:
{ "task_id": "task_001", "goal": "整理本季度销售数据并生成摘要", "plan": ["检索数据", "计算同比", "写摘要"], "completed_steps": ["检索数据", "计算同比"], "next_step": "写摘要", "checkpoint_time": "2025-06-12T10:30:00Z" }有这个快照,进程崩了、任务超时、用户重新进来,都可以从next_step接着跑,而不是从头再来。我自己在做一个内部小工具Agent时就踩过这个坑:状态全放内存,服务一重启,用户只能重来。后来补上检查点机制,体验立刻不一样。我特别看重这个点,因为它区分了"脚本"和"系统"。
2.4 失败路径的追问:重试、备选、降级
第二个深追点是失败处理。我会直接追加:"如果把第三步的工具调用超时了,你会让Agent做什么?"好的回答不是"让模型自己决定",而是设计一组明确的动作。
首先是重试,1到2次,带退避,避免雪崩。然后是备选路径:如果A检索服务超时,是否可以用B索引的只读副本;如果天气服务不返回,是否可以换一个数据源。再往下是降级:明确告诉用户当前拿不到完整信息,先给出已获得的部分结果,或者把任务转人工。
还有一个细节值得提:给每一步设置硬超时。很多Agent卡死的根因就是某次工具调用没有超时上限,一条任务能原地等一分钟。设置"单步执行上限+全局执行上限"后,系统哪怕出问题也只是局部问题,不会整条任务悬死。能答出这些层次的候选人,说明他真正把Agent当成一套分布式系统在设计。
3. 问题二:凭什么说Agent的输出是"对的"
3.1 这个问题为什么一票否决
第二个问题我会非常直接:"Agent跑通了,你用什么方法证明它的输出是对的,而且能持续对?"
这个问题能淘汰大批候选人,因为他们对"对"的定义很模糊。你想,LLM是采样生成的,同一个Prompt今天跑和明天跑结果可能不一样;一个任务里又有多次推理和多次工具调用,任何一环错了,最后结论都可能是错的。如果候选人没有评测体系,只有一个Demo,那他交上来的系统在线上就是一颗定时炸弹。
什么叫"持续对"?不是这次对,而是每次改动任何参数、提示词、模型版本后,行为都能回到基线以上。没有回归评测的Agent,根本不敢做迭代。这里我是拿出品控标准来要求候选人的:模型输出是概率的,那你就必须用工程手段把概率问题变成可统计、可比较、可收敛的问题。
3.2 三层评测集:从任务级到步骤级到回归护城河
靠谱的做法是建立三层评测集。
端到端任务评测,用完整业务场景看Agent最终能不能达成目标。比如"帮用户把本季度销售Excel整理成报告",跑完整条链路,按可量化的标准判分,而不是仅仅"看起来还可以"。子步骤评测,单独验证中间的零件。比如工具调用生成的参数是否正确、检索到的文档片段是否和问题相关、摘要是否忠于原文。这一步的价值是精确定位质量瓶颈,避免整条任务失败后还要一层层猜。
回归评测是最容易被忽视的一层。把曾经翻过车的case不断补充进去,每改一次Prompt、换一次模型、调整一次工作流,就把这批case重跑一遍,确认真实行为没有退化。我面试时会问:"你上个月修过的最有价值的一个bug,有没有变成评测用例?"这个问题基本能看出候选人的工程习惯。
这里给一个常用指标参考:
| 指标 | 含义 | 为什么重要 |
|---|---|---|
| 任务成功率 | 完整目标达成的比例 | 反映端到端效果 |
| 工具调用准确率 | 工具名称与参数是否合法 | 防止脏请求打到外部系统 |
| 无效动作率 | 模型做了不该做的操作 | 衡量Agent的克制力 |
| 错误信息率 | 输出中包含不实信息的比例 | 幻觉的直接度量 |
| 平均步数/耗时/token成本 | 一次任务消耗多少资源 | 衡量效率与成本收益 |
3.3 输出校验闭环:不能只靠"模型自觉"
评测集是事后验证,但工程上还需要运行时守门。我特别认可候选人谈到"输出校验闭环":Agent让模型输出的时候,尽量约束成结构化格式,比如JSON;拿到结果后先用JSON Schema或自定义校验器检查,不合法就修正或重试;仍然不行就进入兜底。
更细的一层,是针对每个工具定义参数校验器。例如一个查询订单的工具,参数"订单号"必须是合法编号,"日期范围"的结束时间必须晚于开始时间。模型填错了,直接拦截,不让脏参数发出去。这个动作看起来简单,但能把很多"模型胡来"的问题挡在系统外面。我见过一些前期图省事不做校验的团队,线上最常出现的故障就是工具收到一堆莫名其妙的参数,外部系统被搅得乌烟瘴气。
还有一点值得谈:结构化输出不是限制模型的创造力,而是把模型语言的自由度和工程接口的确定性做隔离。它让系统的其他部分可以稳定依赖输出格式,不用处理自然语言的歧义。
3.4 兜底策略:成熟系统要敢承认"不知道"
一个让我比较看重的回答,是候选人会不会主动设计兜底。因为不管评测集多全、校验多严,总会有模型答不上的输入。成熟的Agent至少要有几级兜底。
一是明确拒绝并给出替代路径,比如"我暂时查不到,你可以先确认订单号"。二是降级方案,比如主模型判断不了,换个更保守的小模型或固定Prompt走一遍。三是从自由生成降级到选择题,让用户在有边界的选项里确认意图。四是转人工,把上下文结构化整理后交给坐席继续处理。
我举一个印象不错的例子。某客服Agent在拿不准用户意图时,不会硬猜,而是转成"我先帮您记录,稍后专人跟进",同时把对话摘要、已尝试的动作、置信度一并传给人工。这样既控制了风险,又保留了体验。工程化不是逼模型全知全能,而是给不确定留一条不丢分的退路。
4. 问题三:Agent管线崩了,你靠什么定位
4.1 一次真实事故,问出最原始的排障本能
第三个问题我习惯直接抛场景:"现在线上一个Agent,某次任务跑了30秒、调用了7次工具,最后给用户一个完全错误的结论。你会怎么开始排查?"
这个问题很像后端面试里的"线上超时怎么查",但Agent更难:中间有多次LLM推理、多次工具调用,错误还有传导性。普通日志给到手里,基本是一大堆无结构的文本,根本看不出是哪一步出了错——到底是检索到了一篇不相关的文档,还是模型规划错了,还是工具参数传错了,又或者是最后生成的时候把信息拼错了。
没有结构化的记录,排查就是大海捞针。很多候选人到这里会卡住,原因很简单:他从来没把"观测"当成Agent系统的必备组件来设计,而是当成事后补救。可观测性这种东西,事后补是补不回来的,因为事故发生时你根本不知道要留下哪些现场。
4.2 给一次任务一条trace,把决策切成可观测的切片
正确的起点是链路追踪。给每次任务分配一个trace_id,再把任务里的动作都记成带父子关系的span。关键的span有这么几类:LLM调用过程,包括上游Prompt全文、模型名称、返回内容、token数、耗时;工具调用过程,包括方法名、入参、出参、报错信息、耗时;编排决策过程,包括进入了哪个分支、为什么进入、状态快照ID;中间结果,比如检索命中的文档标题、摘要等关键产物。
我常用的一个span字段模板:
| 字段 | 例子 | 排查价值 |
|---|---|---|
| span_id / trace_id | 一条trace下的span_01 | 关联整条链路 |
| event_type | llm_call / tool_call / state_transition | 快速定位环节 |
| input_summary | 本轮Prompt关键片段 | 检查上下文是否被污染 |
| output_summary | 模型输出或工具结果摘要 | 判断哪一步产出异常 |
| cost | token数与延迟 | 判断是否在异常烧钱 |
| error | 报错信息或拒答标记 | 快速过滤失败段 |
为什么这么强调调用链记录?因为Agent最常见的Bug就是"上下文污染":某轮错误信息混进了下一轮的Prompt,结果模型被带偏。如果你的系统连上一次模型输出了什么都没留,这种问题根本无法复现。有trace之后,你可以把每一步的input/output摊开看,问题往往一眼就能找到。
4.3 回放能力:把线上一次锅变成本地一个用例
比日志更进一步,是我特别看重的回放能力。把线上一次任务完整的输入事件、中间产物、模型返回都保存下来,然后在测试环境重放一遍。
这个能力有三层价值。第一,可复现。线上偶发问题如果能被重放,就不再是"幽灵Bug"。第二,可验证修复。修完代码后拿同一份回放数据跑一遍,确认行为符合预期。第三,可沉淀。重放并通过修复的事件,顺手就变成第3章里说的回归评测用例。
要做好回放,关键是提前设计事件审计表。你是先记录好完整数据,还是等出事后才发现缺字段,这个差别非常大。很多人踩过一个坑:事故发生后,日志里只有最终回答,没有中间的模型输入输出,等于没留现场。所以我会在系统设计阶段就要求:所有LLM调用、工具调用都默认落审计表,至少在排查窗口内保留完整原始数据。
4.4 区分"模型抽风"和"代码Bug"的排查顺序
Agent排障里最头疼的是同一输入时好时坏。我通常按下面的顺序来定位。
第一步,先看trace,确认哪一步产出的东西开始异常。第二步,把这一步的输入摘出来,用固定Prompt固定模型参数反复跑5到10次。第三步,如果稳定出错,说明多半是逻辑或上下文问题;如果时好时坏,说明模型随机性占主导。第四步,再把同样的输入降级到更简单的模型或Prompt上跑一遍,判断是不是因为复杂推理导致问题。第五步,检查是不是历史消息太长把注意力带偏,精简上下文后重试。
我遇到过的多数线上Case,最后都指向同一个原因:上下文里塞了太多无关历史信息,模型"忘"了当前目标。这种问题不是换一个大模型就能解决的,而是要在工程上做上下文裁剪和注意力聚焦。能把这个经验讲出来的候选人,我会认为他真实地在生产环境里调过Agent。
5. 问题四:Agent从原型到线上,哪些坑是躲不掉的
5.1 第一笔账:你这个服务扛得住100个并发吗
进入部署话题,我会问一个很直白的问题:"线上突然来了100个并发任务,你的服务会怎么样?"
注意,这里考察的不是你调了多少并发参数,而是候选人心里有没有一笔成本账。一次Agent任务通常不止一次LLM调用,可能是3到8次。假设平均每轮输入加输出合计5000 token,一次任务就是2万到4万 token。100并发、假设每个任务需要4轮推理,一分钟可能就是80万到160万token的量级。这个量级换到成本上非常可观,延迟也会迅速恶化。
好的回答会先做容量规划:单任务的推理次数、token量、外部工具调用量;然后设计队列和并发控制,让请求排队而不是无脑往模型服务上怼。很多方案会把并发线程数拉得很高,结果模型服务被打爆、超时率直线上升。正确的思路是"流控优先,能力为王",先保证核心任务能稳定完成,再谈吞吐。
5.2 缓存:不是每个问题都值得让模型再算一遍
Agent部署上的一个低成本高收益优化是缓存。很多问题的答案是稳定可复用的,没有必要每次都让模型从头推理。
缓存有三个级别。精确缓存,完全相同的输入直接返回历史结果,适合固定模板类任务。模块级缓存,缓存中间计算结果,比如文档检索结果、工具返回数据、规划结果。语义缓存,用向量检索把近似意图的旧答案召回,适合高频、低敏感性的场景。
用缓存要注意边界和安全。涉及用户私有数据的一定不能进共享缓存,需要按租户或用户维度隔离;还要设计失效策略,比如让Agent永远不会被缓存卡在某天之前的旧答案里。另外,带了随机性的模型输出建议做低层缓存而不是全文缓存,否则用户会明显感觉"答案永远一样"。
5.3 超时、重试、熔断、限流:保护下游就是保护自己
Agent系统的下游有好几个:模型服务、外部工具、数据库。每一个都值得做可靠性设计。这里不复杂,但需要系统化。
超时方面,给单次LLM调用设置硬超时上限,比如10到15秒;给单工具调用设置更短上限,比如5秒,防止一步卡死全任务。重试方面,遇到模型服务5xx或限流时,用指数退避重试,但最多2到3次,不要无限重试。熔断方面,连续N次失败就快速打开熔断开关,短时间内不再把流量打到已经故障的系统上。限流方面,按用户维度、任务维度、总维度分别控,防止某个用户或某类任务吃光全部资源。
一个特别要注意的细节是幂等键。工具调用时如果客户端超时了,服务端其实可能已经执行成功了;没有幂等键,重试会重复执行操作,特别是在转账、发送消息这类场景里会出大问题。所以凡是会写外部系统的Agent动作,都要设计幂等机制。
5.4 灰度上线与版本回滚:Agent是代码、Prompt、模型的三合一
最后一个是版本管理。后端项目发版会回滚代码,Agent系统更麻烦:一个线上行为往往由代码版本、Prompt版本、模型版本、工具配置共同决定。上线一个新Prompt,可能就砸掉一批case;切换模型版本,也可能引发行为漂移。
我的提醒是:每一个线上Agent发布都应该是一个可回滚的组合包。把代码、Prompt、模型标识做成配置化依赖,发布时锁定版本组合;先做灰度,喂给种子用户或用模拟流量跑一遍,用评测集卡质量线,成功率下滑超过阈值就自动切回;保留最近N个版本的回滚能力,不只是代码侧,模型侧也要能切回上一版本。
没有这套版本意识的Agent系统,每次改Prompt都是在玩火。敢把"改Prompt也可能上线事故"讲得这么具体的候选人,是真的踩过这个坑的。
6. 问题五:当Agent不止一个,边界怎么划
6.1 先回答"要不要":单Agent能解决的,别硬上多Agent
最后一个问题常从"你现在的Agent会越来越多"切入:"如果每个部门都想有自己的Agent,你打算怎么组织?"
很多候选人一听就兴奋,开始说我要搭一个多Agent编排平台。但我的第一个期待是反问。好的候选人会先判断需求:单Agent加工具能不能覆盖?一个工作流里顺序调用几个工具,已经能解决绝大多数业务问题。
多Agent不是银弹。每多一个Agent,就多一份模型调用成本、多一段链路延迟、多一个容易出错的分发和汇总环节。我见过一个内部演示项目,把"读文档、做摘要、列大纲"拆成了三个角色Agent互相聊天,结果又慢又贵,最后一步提示词错误整条链路都挂了。如果把它放回工作流里顺序执行,半天就能维护完。所以,当候选人表现出"多Agent需要克制"的判断力时,我会给高分。
6.2 边界怎么划:权限、上下文、协议三件套
如果确实要上多Agent,边界设计是核心。我的经验是划三层边界。
第一层是权限边界。给不同Agent挂不同最小权限凭证,比如只读Agent不能调用写接口,数据敏感类Agent不能访问全量库。不要让一个万能Agent掌握所有工具,那是对系统安全的极度不负责。
第二层是上下文边界。不要让所有Agent共享一个大Context,否则一个Agent的中间错误会污染全局。每个Agent维护自己的记忆,只在需要时通过结构化消息对外传递结果。
第三层是协议边界。Agent之间不要传递自由散文,用统一的Message Schema和动作编码,比如明确的消息类型、payload结构、错误码。这能让整个系统像微服务一样可测、可观测。很多多Agent翻车的原因就是A的输出直接塞给B的Prompt,两边措辞一变,配合就乱了。
6.3 路由与编排:让"谁来干"这件事可控制
多Agent系统还需要回答"任务如何分发"。我认可一种稳妥模式:前置路由 + 集中编排。
入口处先用分类器或规则识别意图,把任务路由到对应子Agent;子Agent执行完按标准协议返回结果;主控流程统一收集结果、处理冲突、决定是否追加追问。整个过程是集中式控制,子Agent之间不自由协商。为什么这么设计?因为自由协商意味着大量无谓的模型往返,费钱费时且结果不可控;集中式编排则把决策点集中在少数代码里,可以配置、可以测试、可以回滚。
从故障域角度看,这种模式也更好。某个子Agent出问题时,主控可以把它的任务降级为固定规则流程或转人工,而不是让整个编排死掉。多Agent的工程价值,不是"看起来智能",而是"拆得开、挡得住、换得起"。
6.4 什么时候我才会考虑多Agent
最后再补一个判断标准:我什么时候会主动选多Agent,而不是用单Agent加工具?
一是模块间有强烈的领域隔离需求,比如一个Agent负责内容生成、一个Agent负责审核,两者需要不同权限、不同模型、不同数据源。二是某个子能力有独立的迭代节奏,团队想并行开发、独立上线。三是不同子任务对延迟、成本、模型的偏好明显不同,比如检索类用轻量模型,写作类用更强模型。
如果这些条件都不太满足,那我倾向于先从单Agent加好工具链开始。系统变复杂的驱动力应该来自真实约束,而不是架构审美。能讲清楚这条的候选人,我认为他真的想过"什么不该做"。
把五个问题聊完之后,说一点我自己的体会。做Agent方向的技术面试,我最终收的信号一直不是"你用没用过某某框架"、"是不是追到了最新模型",而是三件非常朴素的事情:出问题能不能查,降级之后能不能兜,量起来之后能不能扛。你在任何一个方向上准备好一个真实的踩坑故事,把排查链条讲清楚,都比背十个八股概念有用。准备面试的朋友,建议把所有Agent知识点都折叠到"从开发到部署"这条线上想一遍,而不是散装地记忆。这是我面了一轮又一轮之后最想强调的一点。