1. 为什么“会写Agent”和“能上线Agent”是两回事
面试过不少做Agent方向的同学,简历上写着“熟悉LangChain、AutoGPT、多智能体协作”,聊起来也能把ReAct、CoT、ToT这些概念讲得头头是道。但一旦问到“你这个Agent上线之后,QPS多少?单次调用成本多少?失败率怎么监控?”,场面就冷下来了。
这不是个例。Agent从开发到部署,中间隔着一道巨大的鸿沟。开发阶段你面对的是一个理想环境:模型响应稳定、工具调用永远成功、上下文长度永远够用、用户输入永远合理。但部署阶段你面对的是真实世界:模型会超时、工具会挂、上下文会爆、用户会输入各种奇怪的东西、老板会问你为什么这个月API账单涨了三倍。
这道鸿沟,就是Agent工程化要解决的问题。而面试官问的“从开发到部署的5个关键问题”,本质上是在考察你有没有真正把Agent当成一个生产系统来对待,而不是一个Demo。
我面过的人里,能把这5个问题答清楚的不超过两成。大部分人卡在第一个问题上就露馅了。下面我把这5个问题拆开,结合我自己的踩坑经验,一个一个讲透。
2. 第一个问题:你的Agent状态管理是怎么做的
2.1 为什么状态管理是Agent工程化的第一道坎
很多人做Agent的时候,状态是散落在各处的。对话历史存在一个list里,工具调用的中间结果存在另一个dict里,任务进度又存在某个全局变量里。开发阶段跑单条请求没问题,一旦并发上来,状态就乱了。
面试官问状态管理,其实是在问三个层面的东西:
- 会话状态:同一个用户的多轮对话,上下文怎么维护?存哪里?过期策略是什么?
- 任务状态:一个复杂任务被拆成多个子步骤,中间状态怎么持久化?失败了怎么恢复?
- 执行状态:Agent正在调用工具的过程中,如果进程挂了,怎么保证不重复执行、不丢状态?
这三个层面,开发阶段往往只考虑了第一个,而且是用最简单的方式——内存里的一个list。部署阶段这三个都得考虑,而且要考虑并发、持久化、恢复。
2.2 我踩过的坑:内存态会话在并发下直接崩了
早期我做过一个客服Agent,会话历史直接存在Python进程的内存里,用一个dict,key是session_id,value是消息列表。单机测试的时候一切正常,上线之后用户量一上来,问题就来了。
第一个问题是内存暴涨。每个会话的消息列表越来越长,几千个活跃会话就把内存吃满了。第二个问题是进程重启后所有会话丢失,用户得重新开始。第三个问题最致命:我们做了多实例部署,用户的请求被负载均衡打到不同实例上,结果同一个用户的对话历史在两个实例上不一致,Agent的回答前后矛盾。
后来改成了Redis存储会话状态,每个会话设置TTL,消息列表超过一定长度就做摘要压缩。任务状态用数据库持久化,每个子步骤执行前先写一条记录,执行完更新状态。执行状态用分布式锁加幂等键,保证同一个任务不会被重复执行。
这套方案不复杂,但开发阶段根本不会想到要做这些。面试的时候如果你能主动说出“会话状态用Redis加TTL,任务状态用数据库持久化,执行状态用幂等键加分布式锁”,面试官就知道你是真上过线的。
2.3 状态管理的选型逻辑:别一上来就上重型方案
这里有个反直觉的点:不是所有Agent都需要完整的状态管理方案。我见过有人做一个单轮问答的Agent,也搞了一套Redis加数据库加消息队列的状态管理,纯属过度设计。
选型的逻辑应该看两个维度:会话是否需要跨轮次保持上下文,任务是否需要多步骤执行且允许失败重试。
| 场景 | 会话状态 | 任务状态 | 执行状态 |
|---|---|---|---|
| 单轮问答 | 不需要 | 不需要 | 不需要 |
| 多轮对话 | Redis + TTL | 不需要 | 不需要 |
| 多步骤任务 | Redis + TTL | 数据库持久化 | 幂等键 |
| 长时任务+高并发 | Redis集群 + TTL | 数据库 + 消息队列 | 幂等键 + 分布式锁 |
这张表是我自己总结的,面试的时候如果能画出来,基本能镇住场子。关键是要说清楚每一行为什么这么选,而不是背下来。
3. 第二个问题:工具调用的失败处理你考虑了几层
3.1 工具调用失败是常态,不是异常
开发阶段我们假设工具调用会成功。你写一个查天气的工具,测试的时候返回了温度,你觉得没问题。但部署之后你会发现:API可能超时、可能返回429限流、可能返回格式变了、可能返回了但内容是错的、可能调用到一半网络断了。
这些情况在开发阶段都是“异常”,在部署阶段都是“常态”。面试官问工具调用的失败处理,就是在看你有没有把这些常态当成一等公民来对待。
我一般把工具调用的失败分成四层来处理:
- 第一层:超时与重试。每个工具调用设置合理的超时时间,超时后根据幂等性决定是否重试。重试要有退避策略,不能立即重试。
- 第二层:降级与兜底。工具调用失败后,Agent不能直接崩溃,要有一个降级路径。比如查天气失败,可以返回“暂时无法获取天气信息”,而不是抛异常。
- 第三层:熔断与限流。如果某个工具连续失败,要能自动熔断,避免雪崩。同时要对工具调用做限流,防止把下游打挂。
- 第四层:可观测与告警。每次工具调用的耗时、成功率、错误类型都要记录,异常时触发告警。
3.2 一个真实的翻车案例:重试把下游打挂了
有一次我们做一个电商导购Agent,里面有一个查库存的工具。上线第一天流量不大,一切正常。第二天做活动,流量涨了十倍,查库存的工具开始超时。我们的代码里写了重试逻辑,超时就重试三次。结果就是:工具超时导致重试,重试导致请求量翻三倍,下游库存服务直接被我们打挂了。
事后复盘,问题出在两个地方:一是重试没有退避,三次重试几乎是同时发出去的;二是没有熔断,工具已经明显不可用了还在继续重试。
后来改成了指数退避重试,第一次重试等1秒,第二次等2秒,第三次等4秒。同时加了熔断器,连续失败10次就熔断30秒,期间直接走降级逻辑。改完之后再也没出现过类似问题。
这个案例我在面试的时候经常讲,因为它很典型:开发阶段你只会想到“失败了要重试”,部署阶段你才会想到“重试本身也可能造成故障”。
3.3 工具调用的幂等性设计:一个容易被忽略的细节
工具调用的失败处理里,最容易被忽略的是幂等性。有些工具是只读的,比如查天气、查库存,重试没问题。但有些工具是有副作用的,比如下单、发消息、扣款,重试就可能导致重复操作。
面试的时候如果被问到“工具调用失败怎么处理”,一定要区分只读工具和写工具。只读工具可以放心重试,写工具必须做幂等设计。常见的幂等方案是给每次调用生成一个唯一的idempotency_key,工具端根据这个key去重。
如果工具端不支持幂等,那Agent端就要做补偿逻辑。比如下单失败后,先查询订单状态,确认没下单成功再重试。这个逻辑写起来麻烦,但比重复下单要好得多。
4. 第三个问题:上下文窗口不够用的时候你怎么办
4.1 上下文爆炸是Agent部署后的必然问题
开发阶段你测试的时候,对话轮次少,工具返回结果短,上下文窗口绰绰有余。部署之后你会发现:用户会跟你聊几十轮,工具会返回大段大段的文本,多Agent协作的时候每个Agent都要塞一堆上下文。上下文窗口很快就不够用了。
面试官问这个问题,是在看你有没有处理过真实场景下的上下文压力。常见的处理策略有四种:
- 截断:最简单的策略,保留最近N轮对话,前面的直接丢掉。缺点是会丢失重要信息。
- 摘要:把历史对话做摘要压缩,保留关键信息。缺点是摘要本身也要消耗token,而且可能丢失细节。
- 检索:把历史对话存到向量数据库,需要的时候检索相关片段。缺点是检索质量不稳定。
- 分层:把上下文分成系统提示、任务状态、近期对话、历史摘要几层,每层有不同的保留策略。
这四种策略没有优劣之分,关键是要根据场景选。我一般会组合使用:系统提示和任务状态永远保留,近期对话保留最近N轮,历史对话做摘要,需要细节的时候从向量数据库检索。
4.2 我实际用的上下文管理方案
我们现在的方案是这样的:每个会话维护一个上下文对象,里面包含几个部分。
系统提示是固定的,包含Agent的角色定义、能力边界、输出格式要求。这部分永远不压缩。
任务状态是结构化的,包含当前任务的目标、已完成步骤、待完成步骤、关键中间结果。这部分用JSON存储,每次更新只改变化的部分,不重复塞历史。
近期对话保留最近10轮,每轮包含用户输入和Agent输出。超过10轮的对话,做摘要后存入历史摘要区。
历史摘要区保留最近5条摘要,每条摘要对应一段对话。摘要用一个小模型生成,成本很低。
向量检索区存储所有历史对话的embedding,需要的时候检索top-3相关片段。
这套方案跑下来,上下文窗口的利用率大概在60%到70%之间,留了足够的余量给工具返回结果。关键是每一层都有明确的职责,不会互相干扰。
4.3 一个反直觉的经验:上下文不是越长越好
很多人觉得上下文越长,Agent越聪明。实际恰恰相反。上下文太长会导致两个问题:一是模型注意力被分散,关键信息被淹没;二是成本直线上升,延迟也增加。
我做过一个对比测试,同一个任务,上下文长度分别是2K、8K、32K。结果8K的效果最好,2K信息不够,32K反而因为噪声太多导致效果下降。成本方面,32K的token消耗是8K的四倍,延迟也增加了两倍多。
所以上下文管理的目标不是“塞满”,而是“精准”。该保留的保留,该丢的丢,该摘要的摘要。面试的时候如果能说出这个观点,面试官会觉得你是有实战经验的。
5. 第四个问题:你怎么评估Agent的效果
5.1 Agent评估比模型评估难在哪
模型评估有标准答案,Agent评估没有。同一个任务,Agent可以用不同的步骤、不同的工具、不同的路径完成,你很难说哪条路径是“正确”的。而且Agent的效果往往需要多轮交互才能体现,单轮评估没有意义。
面试官问评估,是在看你有没有一套系统化的方法来衡量Agent的好坏。我一般从四个维度来评估:
- 任务完成率:Agent最终有没有完成用户的任务。这是最核心的指标。
- 步骤效率:完成同一个任务,Agent用了多少步。步数越少越好。
- 工具调用准确率:Agent调用的工具是否恰当,参数是否正确。
- 用户满意度:用户对Agent的回复是否满意。可以用点赞点踩、追问率、会话时长等间接指标。
这四个维度里,任务完成率是结果指标,后面三个是过程指标。结果指标告诉你Agent行不行,过程指标告诉你哪里不行。
5.2 构建评估集的实操方法
评估Agent效果的前提是有一个评估集。评估集怎么来?我的做法是分三步。
第一步,从真实日志里采样。上线之后把用户的真实请求记录下来,按任务类型分层采样,每个类型采100到200条。这些是真实分布,最有代表性。
第二步,人工标注期望结果。对于每条请求,标注出期望的任务完成状态、期望调用的工具、期望的输出格式。这一步最费时间,但必不可少。
第三步,定期更新。用户的行为会变化,评估集也要跟着更新。我一般每个月更新一次,把新的任务类型加进去,把过时的去掉。
有了评估集之后,每次Agent有改动,都跑一遍评估集,看四个维度的指标有没有变化。这比凭感觉判断靠谱得多。
5.3 线上监控:评估不能只在离线做
离线评估集只能覆盖已知的任务类型,线上还会出现各种意想不到的情况。所以线上监控同样重要。
我一般会监控这几个指标:任务完成率的实时曲线、工具调用的成功率、平均步骤数、P99延迟、单次调用成本。这些指标异常的时候触发告警。
另外我还会做一件事:定期从线上采样,人工review Agent的回复质量。离线评估集是标准化的,线上采样能发现新的问题模式。两者结合,才能全面掌握Agent的效果。
6. 第五个问题:成本和延迟怎么优化
6.1 Agent的成本结构:不只是模型调用
很多人算Agent成本的时候只算模型调用的token费用。实际上Agent的成本结构复杂得多:
- 模型调用成本:每次推理的token费用,包括输入和输出。
- 工具调用成本:每次调用外部API的费用,有些API是按次收费的。
- 向量检索成本:如果用了向量数据库,每次检索都有成本。
- 存储成本:会话状态、任务状态、日志的存储费用。
- 计算成本:Agent本身的运行需要CPU和内存,高并发下这部分成本不小。
面试的时候如果能把这五项都说出来,面试官会觉得你算过账。大部分人只算第一项。
6.2 我实际用过的成本优化手段
成本优化我一般从三个方向入手:减少调用次数、降低单次成本、缓存复用。
减少调用次数方面,最有效的是优化Agent的决策逻辑。很多Agent会做不必要的工具调用,比如明明上下文里已经有答案了还要去查。通过优化提示词和加一些规则判断,可以把工具调用次数降低30%到50%。
降低单次成本方面,主要是模型选型。不是所有步骤都需要用大模型。简单的意图识别、参数提取可以用小模型,复杂的推理再用大模型。我们现在的方案是大小模型混合,成本比全用大模型降低了60%左右。
缓存复用方面,主要是对重复的请求做缓存。很多用户的请求是相似的,比如“今天天气怎么样”,完全可以缓存结果。我们做了一个语义缓存,相似度超过阈值的请求直接返回缓存结果,命中率大概在20%左右。
6.3 延迟优化:用户等不了太久
Agent的延迟比普通API高得多,因为要经过多轮推理和工具调用。用户能接受的延迟大概是3到5秒,超过这个时间就会觉得卡。
延迟优化我一般做这几件事:并行化工具调用、流式输出、预加载。
并行化工具调用是最有效的。如果Agent需要调用多个工具,而且这些工具之间没有依赖关系,就并行调用。我们有一个场景需要查三个数据源,串行调用要3秒,并行调用只要1.2秒。
流式输出是体验优化。Agent的推理过程可以流式返回给用户,让用户看到Agent在“思考”,感知延迟会低很多。虽然总延迟没变,但用户体验好很多。
预加载是针对可预测的场景。比如用户打开客服Agent的时候,预加载常见问题的答案。用户真正提问的时候,直接返回预加载的结果。
6.4 一个容易忽略的点:成本要按会话算,不是按请求算
很多人算成本的时候是按单次请求算的。但Agent的一个会话可能包含多轮请求,成本要按会话算才有意义。
我见过一个案例,单次请求的成本看起来很低,但一个会话平均有8轮对话,实际成本是单次请求的8倍。按会话算下来,成本远超预期。
所以面试的时候如果被问到成本,一定要说清楚是按会话算还是按请求算。这个细节能体现你有没有真正算过账。
7. 面试中如何把这5个问题串成一个完整的故事
单独回答这5个问题不难,难的是把它们串成一个完整的故事,让面试官觉得你是一个有全局观的工程师。
我的建议是:用一个你真实做过的Agent项目作为主线,把这5个问题串起来。比如你可以说:“我之前做过一个XX场景的Agent,开发阶段很顺利,但上线之后遇到了状态管理、工具失败、上下文爆炸、效果评估、成本延迟这五个方面的问题,我一个个解决了。”
然后每个问题讲一个具体的踩坑经历和解决方案。这样讲下来,面试官会觉得你不仅有技术深度,还有实战经验。
另外要注意的是,这5个问题的顺序不是固定的。面试官可能从任何一个问题切入,你要能灵活地把其他问题带出来。比如聊到成本的时候,可以顺带提一下上下文管理对成本的影响;聊到评估的时候,可以提一下评估结果如何指导成本和延迟优化。
最后说一个我自己的体会:Agent工程化面试,面试官真正想考察的不是你知不知道某个技术点,而是你有没有把Agent当成一个生产系统来对待。开发阶段你可以只关注功能,部署阶段你必须关注稳定性、成本、延迟、可观测性。这个思维的转变,才是工程化的核心。