**异常处理与重试机制
1️⃣ 考察意图
面试官想考察你对Agent系统稳定性的工程化理解,而非单纯背概念。刁钻点在于:Agent的异常处理不同于传统后端——LLM调用是“黑盒”且高延迟,工具执行依赖外部系统,重试可能放大故障。答好了能展示你从“写代码”到“设计韧性系统”的硬实力,包括异常分类、退避策略、降级与监控完整流程。
2️⃣ 标准答
Agent系统的异常处理需分层设计,核心是“快速失败、优雅降级、可观测”。以下从异常分类、重试策略、降级方案、监控恢复四个层面展开。
1. 异常分类与优先级
- LLM调用失败:如OpenAI API返回429(限流)、500(服务端错误)、超时(默认30s)。需区分瞬时(可重试)与永久(如认证失败,直接降级)。
- 工具执行错误:如数据库连接超时、第三方API返回非200。需捕获具体异常类型(如
requests.ConnectionError),避免吞掉堆栈。 - 输入非法:Agent接收的JSON格式错误或参数越界。这类异常应直接返回错误提示,不重试。
- 业务逻辑异常:如工具返回“用户不存在”,需设计“语义重试”(如换参数重查),而非机械重试。
2. 重试策略:指数退避 + 随机抖动
- 实现:用
tenacity库,设置stop_max_attempt_number=3,wait_exponential(multiplier=1, min=2, max=60),加wait_jitter(max=5)。例如第一次失败后等2-5s,第二次等4-9s,第三次等8-13s。 - 为什么这么做:指数退避避免雪崩(所有Agent同时重试打垮API),随机抖动防止“惊群效应”(多个请求同时重试)。工程取舍:重试次数过多(>5)会累积延迟,对用户不可接受;过少(<2)则对瞬时故障不鲁棒。3次是经验值,需结合SLA调整。
- 实际落地的坑:幂等性。工具如“发送邮件”重试会导致重复发送。解法:为每个请求生成
request_id,工具端做去重(如数据库唯一索引),或重试前检查操作状态(如“订单已创建”则跳过)。
3. 降级方案
- 返回默认值:如天气查询失败,返回“天气未知,建议带伞”。需业务方确认默认值是否误导用户。
- 使用缓存结果:对非实时数据(如股票收盘价),用Redis缓存上次成功结果,TTL设为5分钟。取舍:缓存可能过时,适合“有比没有好”的场景。
- 切换模型:如GPT-4超时,降级到GPT-3.5-turbo(成本更低但质量下降)。需在Agent配置中声明
fallback_models列表,并记录切换日志。 - 静默失败:对非核心工具(如“推荐表情包”),直接返回空结果,不阻塞主流程。
4. 监控与自动化恢复
- 日志:用
structlog记录结构化日志,包含agent_id、tool_name、exception_type、retry_count、latency。避免打印敏感信息(如API key)。 - 告警:接入Sentry或Prometheus,设置阈值:单Agent连续失败3次触发P2告警,全局失败率>5%触发P1。告警需附带trace_id,方便回溯。
- 健康检查:Agent实例暴露
/health端点,返回LLM延迟、工具可用性。K8s配置livenessProbe,连续3次失败自动重启Pod。注意:重启前需优雅关闭(drain正在处理的请求),防止数据丢失。
3️⃣ 答题模板(30 秒电梯版)
“这个问题我从异常分类、重试策略、降级方案、监控恢复四个层面回答。首先,异常要区分LLM失败、工具错误、输入非法,分别处理;其次,重试用指数退避加随机抖动,最多3次,注意幂等性;降级包括返回默认值、用缓存、切模型;最后,用Sentry告警和K8s健康检查实现自动化恢复。总结一句:Agent稳定性是分层设计的,核心是快速失败、优雅降级、可观测。”
4️⃣ 高频追问 & 应对
追问 1:如果重试3次后仍然失败,你怎么办?
进入降级流程:先判断异常类型。如果是LLM超时,立即切到备用模型(如GPT-3.5),并记录切换原因;如果是工具执行错误,返回预定义默认值(如“服务暂时不可用”),同时将失败请求写入死信队列(DLQ),由离线Worker异步重试(最多再试5次,间隔1小时)。DLQ中的失败数据用于事后分析,比如发现某第三方API持续503,则触发熔断(10分钟内不再调用该工具)。
追问 2:如何设计重试的幂等性?
核心是给每个请求一个全局唯一ID(UUID),工具端在接收请求时检查该ID是否已处理。例如,支付工具在数据库建
request_id唯一索引,重复请求返回“已处理”状态。对于无法改动的第三方API,采用“先查询再操作”模式:重试前调用查询接口(如“订单状态”),若已成功则跳过。另外,重试策略中设置retry_on_result回调,检查响应是否包含“重复请求”标识。
追问 3:高并发下,所有Agent同时重试怎么办?
引入“断路器”模式:用Hystrix或Resilience4j,监控工具调用失败率。当失败率超过50%时,断路器打开,后续请求直接降级(不重试),避免打垮下游。断路器半开后,允许少量请求通过测试恢复情况。同时,重试的指数退避基数和抖动范围要随机化,防止所有Agent在同一时间点重试。还可以用分布式限流(如Redis滑动窗口),限制全局重试并发数。
5️⃣ 避坑 · 常见错误答法
- ❌ 说“所有异常都重试3次,用固定间隔1秒” → ✅ 正确做法:区分瞬时与永久异常,LLM限流用指数退避,输入非法不重试,固定间隔会导致雪崩。
- ❌ 说“重试时直接重新调用工具,不管幂等性” → ✅ 正确做法:为每个请求生成request_id,工具端做去重,或重试前检查操作状态,防止重复扣款/发邮件。
- ❌ 说“失败后直接返回空字符串,不记录日志” → ✅ 正确做法:记录结构化日志(含异常堆栈、上下文、重试次数),并触发告警,否则无法排查线上问题。
6️⃣ 简历呼应
- 如果你有Agent项目:从“实际踩过的坑”切入,比如“在XX项目中,工具调用重试导致重复下单,我通过引入request_id和去重表解决”,展示工程细节。
- 如果你只做过传统后端:用“微服务熔断”类比,比如“类似Spring Cloud的Hystrix,Agent的异常处理也需要断路器+降级”,强调迁移能力。
- 如果你是校招无项目:聚焦论文或开源库,比如“我读过tenacity源码,理解其重试策略设计”,或“用Python实现过一个简单Agent异常处理demo,集成Sentry监控”,展示学习深度。
- 《Building Resilient Microservices》by Sam Newman(熔断与重试模式)
- tenacity库官方文档(Python重试库,含指数退避和抖动示例)
- OpenAI API错误码文档(区分429/500/超时等异常类型)
- 《Designing Data-Intensive Applications》Chapter 8(分布式系统故障处理)
- Sentry官方博客:Error Monitoring for AI Agents(Agent日志最佳实践)