大模型服务中断这件事,我一直想找个机会好好聊聊。前两天某大模型API突然不可用,我们这边多个智能客服Agent同时广播断联告警,线上即时响应率从99.2%一路掉到61%,值班手机直接被打爆。排查下来不是带宽问题、不是防火墙策略,就是上游大模型服务侧出现大规模波动——而我们的Agent架构里,所有推理请求都被硬编码指向这一条通路。
这不是个例。把大模型当成普通HTTP接口调用,却不考虑它本质上是一个“高延迟、高波动、不可预测的远程依赖”,是企业级Agent最常见的架构事故源头。很多团队在做Agent平台化的时候,把绝大多数精力花在指令编排、工具调用、数据接入这些上层能力上,真正到了稳定性层面,往往只剩下“失败重试三次”这种粗糙处理。这篇文章就结合我自己在多个Agent项目里的实战经验,讲讲企业级Agent的稳定性基石到底该怎么搭。
1. 一次大模型服务中断,暴露了什么
1.1 断联事件复盘:我们到底输在哪
当时的情况是这样的:我们有两个独立部署的Agent服务集群,一个面向内部员工的知识助手,一个面向客户的外部智能客服,流量峰值都不算高。故障爆发前没有任何预兆,监控面板上突然出现大面积“429限流”和“500错误”,紧接着链路跟踪里出现大量“等待上游响应”的调用栈。
第一波冲击其实是雪崩式的。Agent在处理一个用户请求时,往往需要多轮大模型调用——先理解意图,再规划步骤,然后调用工具,最后生成答案。一轮对话背后可能是3到5次推理请求,每次推理的响应时间从2秒到30秒不等。当上游服务不可用时,我们同步请求的HTTP客户端默认超时是60秒,这就导致一个用户请求会挂住60秒,而线程池里的线程数量是有限的,很快新的请求直接进不来,表现为整个服务无响应。
第二波冲击是重试风暴。那个失败的“硬编码重试三次”逻辑,在流量高峰时段直接把同一个对话上下文塞回队列重试,每个请求试着二十几秒,重试之间还没有抖动退避。结果就是给本就异常的上游服务额外增加了两倍以上的请求压力,两边同时陷入恶性循环。
第三波冲击是数据面问题。很多Agent的状态信息都存在内存里,进程重启就丢。故障过程中我们有节点因为内存溢出被反复拉起,用户会话上下文频繁丢失,对话连续性彻底重建。
复盘下来,我们输在三个设计缺失上:没有多路容灾、没有智能熔断、没有完善的降级链路。
1.2 为什么企业级Agent比普通API服务更脆弱
普通后端服务调用数据库,数据库出问题有主从切换、有缓存降级,有比较成熟的一整套兜底方案。但Agent调用大模型的时候,很多人习惯性地把它当成“远程SQL查询”来设计,忽略了几个本质差异。
差异之一是时间尺度完全不同。普通API调用通常要求在100毫秒到1秒内返回,而大模型推理动辄几秒到几十秒,时间一长,整个同步调用链路的线程占用、连接资源占用都会异常显著。这决定了Agent不能简单套用普通API的容错策略——重试次数、超时阈值、并发控制都要重新设计。
差异之二是不确定性。数据库查询是确定的,同样的SQL出来同样的结果;大模型生成是概率性的,同一个Prompt每次返回可能都有变化,而且它会“一本正经地胡说八道”。当你把不稳定的生成能力组合进一个复杂的Agent工作流中,任何一个环节出现偏差都可能被下游放大,最终表现为行为异常。
差异之三是外部性。大模型服务是第三方依赖,你无法控制它的发布节奏、运维水平和故障恢复时间。这不是说问题都出在上游,而是说我们必须接受一个事实:上游一定会出问题,我们只能在系统设计上为它出问题做好充分准备。
1.3 稳定性设计是什么:三层视野
我在实际项目中,把企业级Agent的稳定性拆成了三层来看。
第一层是基础设施接入层,核心是多路接入、身份隔离、配额管理,解决的是“还能不能打电话”的问题。第二层是业务编排层,核心是超时控制、重试退避、熔断降级、上下文管理,解决的是“这个电话打得稳不稳”的问题。第三层是观测治理层,核心是链路追踪、质量评估、成本度量、多模型调度,解决的是“我怎么知道电话打得好不好”的问题。
很多团队其实只做了第一层的一部分——申请了一个API Key就完事了。第二层和第三层极度缺失,而这个恰恰是企业级Agent能否在真实业务场景中活下来的关键。
2. 稳定性基石解析:接入层需要怎样的架构思维
2.1 多模型接入不是简单加个Key
假设你手里只有一个大模型的API Key,你的Agent架构对上游服务就是单点依赖。这个API Key背后可能对应的是某一家公司的某一个服务集群,它发生故障时你没有任何备选路径。
我做过一个相对稳妥的多模型接入设计,核心是两层抽象。
第一层是模型网关层。把不同厂商的模型服务、不同规格的模型实例,统一封装成标准化的推理接口。网关负责把业务请求翻译成各模型厂商的调用格式,同时维护统一的超时、鉴权、限流策略。第二层是路由策略层。网关之上加一层智能路由,根据预设的优先级、可用性状态、业务场景、成本预算,决定每一个请求到底该走到哪个上游。
实际落地时,我见过很多人把“多模型接入”等同于“在配置中心里多写三个Key”。这是不够的,多模型接入必须和故障转移机制联动。具体来说,上游认知分为主用模型池和备用模型池,主用模型池的服务一旦连续失败达到阈值,网关自动将流量切到备用模型池。这个过程对上层业务应该是完全透明的。
这里还要提一个容易被忽略的点:不同模型的能力密度不一样。有的模型擅长长文本理解和复杂推理,有的模型响应速度极快适合简单问答,还有一些开源模型可以私有化部署作为特殊情况下的保底方案。在定义备用池的时候,不要只考虑“是否可用”,还要考虑“在任务上是否可用”。我在一个项目中遇到过备用模型能响应但逻辑能力较弱,最终智能客服的答非所问率翻了三倍,气得业务负责人直接打电话来问怎么回事。
2.2 单租户隔离:别让邻居的故障拖垮你
企业级Agent平台往往要服务多个内部业务线,甚至对外服务多个客户。如果所有业务线共用一个API账号、一个限流配额,那就是把整个平台的稳定性押在了一个公共池子上。
我们曾上线过一个内部Agent平台,同时服务市场部、HR、财务三条业务线。最初觉得大模型API配额充足,搞了个共享账号。结果市场部做活动时导入了大批量营销创意生成任务,短期内把共享配额全部耗尽,财务部和HR的Agent全部限流,他们的员工在系统里问问题得到的是“请稍后再试”。这件事在管理层会议上被点名批评了好几次。
后来我把每个业务线拆成独立账号,分配独立配额,并在网关层再做一次按业务线的流控。这个改造看起来像是运维琐事,但它定义了故障边界:市场部的活动冲击不会波及其他业务线,除非整个平台级配额都被打满,而这种极端情况下我们还有更上游的预案。
2.3 接入层的成本治理:稳定性的一部分
很多人一听到成本治理就觉得这是财务的事,和稳定性没关系。其实在Agent场景下,成本失控本身就是一种稳定性问题。
大模型的API计费通常按token或按调用次数,而Agent的一次任务可能产生大量token消耗。我遇到过业务方说“用户只是问了一个简单问题,为什么账单这么贵?”——因为Agent在后台跑了意图识别、多步规划、知识库检索、答案生成好几轮调用,每一轮都有对应的token消耗。如果配置不对,甚至会因为循环调用陷入“无限对话”消耗大量配额。
接入层应该内置一套预算控制机制,比如单用户单日最大token消耗、单任务最大调用轮数、单请求最大输入长度。超限后的策略不是硬失败,而是降级处理——把复杂的多轮Agent任务降级为单轮问答。这样可以确保成本在可控范围内,同时保证核心功能不抛异常。
3. 编排层实操:Agent怎么设计才能扛住故障
3.1 超时控制:从硬编码到分级超时
超时是Agent稳定性里最基本也最容易被忽视的环节。很多团队的代码里,大模型调用就是requests.post(url, data=payload, timeout=60),整个链路一个超时值走天下。这在企业级场景是远远不够的。
大模型服务的特点是延迟波动极大。同一个API,低峰期2秒返回,高峰或上游抖动时可能30秒才返回。如果你统一设置60秒超时,大多数请求会在20秒左右返回,线程池被占满是因为那一小部分慢请求拖住了线程,而不是因为正常流量。但如果统一设置10秒超时,又会有很多正常请求因偶发延迟被判失败,造成不必要的重试。
我的做法是分级超时。根据Agent的不同任务阶段设置不同超时:意图识别这类简单任务给15秒,知识库检索和工具调用给20秒,长文本生成给60秒;同时把请求分类为“用户实时交互型”和“后台任务型”,前者超时严格,宁可失败也要给用户快速反馈,后者超时可以放宽,追求任务完成率。
3.2 重试机制:盲目的三次重试只会制造雪崩
重试是故障处理的第一反应,但盲目的重试会让情况更糟。原因很简单:当上游服务已经过载或故障时,你重试的每一个请求都在增加它的压力,而且大量重试请求堆积在自己的队列里,会让整个服务进程内存膨胀、线程池耗尽。
我在设计重试策略时遵循几条原则。
一是必须带抖动退避。固定间隔重试会导致同步重试风暴——所有失败的请求在同一时刻发起重试,形成新的峰值。抖动退避的常见实现是:第一次重试等待1到2秒之间的随机时长,第二次重试等待2到4秒,第三次4到8秒,呈指数递增再加随机扰动。
二是必须限制最大重试次数。正常情况下不超过3次,并且要区分“可重试错误”和“不可重试错误”。限流(429)、超时(408)、服务不可用(503)这类错误可以重试;参数错误(400)、鉴权失败(401)这类错误重试一万次也没用,直接失败并上报就行了。
三是大模型调用必须有上下文感知的重试策略。Agent的任务里,有些步骤是有状态的——比如已经调用了外部工具拿到了中间结果,此时重新发起大模型请求时,要确保这些中间结果不丢、不会被重复执行。我们在实现时会给每个步骤生成唯一的task_id,重试时会带上对应的上下文快照ID,保证每一步的执行上下文是一致的。
3.3 熔断与降级:断臂求生不是美学是必须
熔断的核心思路很简单:当一个依赖持续失败时,不去调用它,而是快速失败或走备选路径。就像电路里的保险丝,电流过大时熔断,保护整个系统不被烧毁。
我在Agent系统里实现的是一个变种的熔断器,核心参数有三个:
- 失败阈值:连续失败次数达到5次,或错误率达到50%以上,触发熔断。
- 熔断窗口:熔断后进入半开状态前的等待时间,默认60秒。
- 半开尝试:半开状态下游离出少量试探请求,成功率达到阈值则恢复,否则继续熔断。
熔断真正难落地的地方在降级策略。因为Agent不像普通服务,不能简单地返回一个“服务暂不可用”。你要想清楚:如果大模型不可用,Agent还能不能给用户提供一个有价值的回应?
我在客服Agent中设计了三级降级链路。第一级是模型池切换,上游主用模型熔断后自动切到备用模型。第二级是知识库直答降级:当所有大模型都不可用时,Agent直接检索知识库中最匹配的FAQ条目,不做语义生成,直接返回预设答案。第三级是人工接管通道:所有无法自动处理的会话,自动转接人工客服,并且把用户意图、上下文、已尝试的工具调用过程整理成摘要,让人工客服不用从头看对话记录。
这里想特别强调一下:降级方案一定要提前设计、提前测试。平时没有故障的时候看不出来,等到真出问题时再临时写降级代码,基本等于裸奔。
3.4 上下文管理:如何保证对话不因故障中断
Agent与传统API的另一个关键差异,是它有状态。一轮对话的上下文保存在哪里,直接决定了故障恢复后对话能否接续。
我们踩过一个坑:最初把对话上下文存在服务进程的内存Map里,节点重启丢失,用户重新咨询时Agent完全不记得之前聊过什么,体验极其割裂。后来我们改成了外部缓存存储,用会话ID作为键,保存该会话的完整消息序列、变量状态、已执行的工具结果,key设置了TTL,默认保存24小时。
但这个设计也带来了并发一致性问题。Agent在多轮交互中,同一会话可能被多个工作线程同时处理——比如用户发了新消息,同时后台有一个工具调用结果回调正在更新上下文。如果不同时更新,容易出现上下文错乱、Agent“失忆”甚至重复回答。
我们的解决方案是:在上下文更新入口加基于会话ID的分布式锁,锁的粒度尽量小,只保护“状态变更期”;同时上下文快照采用版本号机制,后写入的版本号大,旧版本过期数据直接丢弃。这些看起来都是很工程化的细节,但恰恰是这些细节决定了Agent在故障场景下的行为是否符合预期。
4. 观测治理层:看不见的故障最致命
4.1 可观测性:不止是监控“通没通”
传统监控关心的是“通没通”和“快不快”,比如HTTP状态码、响应时间。但Agent系统多了一层黑盒——大模型生成的内容质量怎么样,是监控很难回答的问题。
我在实际项目里给Agent系统设计了四类可观测指标。
- 调用链指标:每次Agent任务从开始到结束的完整调用链路,包括大模型调用次数、工具调用次数、每步耗时。通过链路追踪可以看到“哪一步最慢”“哪一步在反复重试”。
- 状态指标:会话状态机的流转情况,比如多少会话处于“规划中”、多少处于“等待工具结果”、多少处于“生成中”。状态指标能帮助我们发现哪个环节卡住了。
- 质量指标:这需要引入额外的评估模型或规则引擎,对Agent的每次回答做一些质量打分,比如是否回答、是否答非所问、是否包含负面情绪。质量指标是成本最贵的一类,但价值也最大。
- 成本指标:每次会话消耗了多少token、调用了多少次模型、每次调用的费用是多少。成本指标可以帮助业务方发现异常损耗。
4.2 全链路追踪:从用户请求到模型调用的每一跳
Agent链路追踪和微服务链路追踪本质原理一样——通过traceId把一次用户请求涉及的所有内部调用串起来。但Agent场景有个特殊难点:一次用户请求往往不是一个流水线,而是一棵复杂的调用树,里面还有循环、条件分支、并行分支。
比如一个用户问“帮我对比一下这两个方案的优劣”,Agent可能需要先检索知识库,再调用多个工具获取数据,然后分多轮大模型推理,这些步骤之间可能有并行、有串行、有循环。传统的Span树模型表达起来很吃力,需要配合事件时间轴来看。
我们实践的方案是:在每个Agent运行的关键节点打上带有traceId和spanId的结构化日志,记录节点类型(规划/工具调用/模型调用)、输入输出摘要、状态(成功/失败/重试)、耗时。所有日志汇聚到统一的日志平台,配合链路追踪面板进行可视化。这样在做故障复盘时,能看到“到底是哪一步出了错”“出错后又重试了几次”“重试时用户等了多久”。
4.3 多模型调度:在稳定性和效果之间的动态权衡
多模型接入之上,如果能再往前一步,就可以做一个动态的多模型调度器,根据实时状态决定请求发往哪个模型。这个调度器解决的不只是“可用性”,还兼顾效果与成本。
我在一个文档处理Agent中做过一类实践:依据输入长度和任务复杂度,调度器自动选择不同模型。简单的关键词抽取任务,走小模型的快车道;复杂的合同条款对比,走大模型的高质量车道。系统运行一段时间后,发现有超过35%的请求降到了低成本模型上,整体调用成本下降了接近四成,而业务指标基本没有回退。
调度器本身要有一个独立的健康检查模块,定期对每个上游模型发起轻量级的探测请求,得到实时延迟和可用性状态。这样,调度器在决定路由时就可以直接避开已经不健康的模型池,而不是等调用失败后才被动切换。
5. 实战经验:一次大模型断联的完整应对过程
5.1 故障前:我们做的演练
在正式的稳定性改造之前,我们团队内部做过一次大模型不可用的应急演练。演练方案很简单:把网关层配置成所有大模型API都不可达,模拟最坏情况,看整个Agent系统会怎么表现。
结果相当难看。业务侧大量请求超时,线程池被打满;重试风暴导致网关层CPU接近100%;知识库检索模块因为依赖链路上的模型调用失败,连带着把知识库也拖进了故障范围;最糟糕的是,客服Agent在无法调用模型后返回了“系统出错,请稍后再试”的默认异常提示,完全没有走我们设计的FAQ直答降级链路——因为降级代码写是写了,但从来没有在真实流量下测过。
那次演练让团队达成一个共识:稳定性设计不是“上有余力时做的优化”,而是Agent系统上线前的必选项。
5.2 故障中:我们的处置时间线
按时间线复盘一次真实故障的处理过程。
第0分钟:监控警报告警,大模型API错误率超过20%。值班工程师启动应急预案,第一时间在网关层将主用模型池标记为“不健康”,流量切换到备用模型池。此时用户体验无感知。
第3分钟:备用模型池也开始出现偶发延迟。熔断器触发,系统自动进入降级模式。客服Agent开始走知识库直答链路,FAQ匹配率尚可,但生成式对话质量显著下降。
第7分钟:业务方反馈客服应答质量下降明显,我们评估后决定将高价值客户会话转人工客服,接线员使用的不是传统客服工作台,而是一个带有Agent上下文摘要的辅助面板,人工可以在短时间内了解用户诉求。
第18分钟:上游服务基本恢复,我们开始将流量逐步回切到主用模型池。注意这里是“逐步”——我们用了10分钟时间,按照5%、20%、50%、100%的比例慢慢放流量,每一档都观察错误率和延迟,确认稳定后再继续切。这个“逐步回切”的细节很重要,直接回切可能导致二次故障。
第40分钟:故障正式解除,整个过程用户完全不可用的时间非常短,核心业务没有出现长时间中断。
事后我们做了复盘,发现虽然整体处置节奏还可以,但备用池的降级质量和主用池相比有明显差距,这提示我们要么在备用模型选择上多花精力,要么引入更强的路由策略,确保备用池在效果上尽量接近主用。
5.3 我们的稳定性改造清单
如果你也想做企业级Agent的稳定性改造,以下是我实践下来最有价值的几项清单。
- 多模型网关:所有大模型请求统一走网关层,实现鉴权、流控、路由、熔断。
- 分级超时与抖动重试:根据不同任务阶段和业务等级,设置差异化的超时与重试参数。
- 上下文外置存储:会话上下文存Redis等外部缓存,不依赖进程内存。
- 降级链路设计:至少设计一级无模型依赖的保底方案,比如知识库直答、规则匹配。
- 全链路追踪与告警:确保任何一次异常都能追溯到具体的调用链和Agent节点。
- 容量与配额治理:按业务线隔离配额,设置每日预算上限,防止一个业务线拖垮整个平台。
- 定期故障演练:至少每季度做一次大模型断联演练,验证降级链路真实可用。
6. 常见问题与排查技巧实录
6.1 Agent突然变慢但没报错,怎么查
最常见的情况是:大模型API本身没有报错,但响应时间大幅增加,导致用户感知整体变慢。排查步骤一般是:先看网关层的P99延迟是否升高,确认是上游变慢还是内部逻辑变慢;然后看调用链中的“等待上游响应”耗时占比;接着看并发请求数,确认是否因为线程池被打满导致请求排队。
如果确认是某个模型池整体变慢,可以在网关层直接将该池的熔断阈值调低——比如错误率阈值从50%降到20%,这样系统会更早触发熔断,保护其他链路。
6.2 重试时重复调用了外部工具,怎么解决
这是一个典型问题:Agent调用大模型失败后重试,但重试之前已经执行过一步“查询订单状态”的工具,重试时又把查询动作执行了一遍。订单类、交易类场景下,这会直接导致业务事故。
我们的解法是:给每个Agent任务定义一个“幂等键”,工具调用时把幂等键传到外部服务,外部服务根据幂等键实现幂等处理。同时在上层,把工具执行结果和步骤ID绑定,重试时先检查这个步骤ID的结果是否已存在,存在就直接复用,不再重新执行。
6.3 模型回复质量下降怎么监控
质量下降不像服务不可用那样会立刻触发告警,它更像是一种“慢性病”。我们的做法是:每轮Agent生成后,将用户的反馈(点赞、踩、追问、放弃)作为质量信号,结合评估模型做抽样打分,定期输出质量趋势。如果发现某个模型池的质量评分持续低于阈值,调度器会在路由时降低该池的优先级。
6.4 成本突然暴涨怎么定位
先按业务线维度看消耗分布,定位是哪个业务线消耗异常;再按会话维度看,定位是哪些会话产生了海量调用或长token输出;最后审查这批会话的Prompt和上下文大小——很多时候成本暴涨是因为上下文越滚越大,每次调用都重复携带了全部历史消息,token消耗随轮次线性甚至指数增长。解决办法是引入上下文裁剪策略,只保留最近N轮有效信息,或在长对话中做摘要压缩。
7. 写在最后:稳定性的本质是承认不确定性
经历了几次大模型断联的洗礼,我越来越觉得,企业级Agent稳定性设计的本质,不是“让大模型永不故障”,而是“在大模型故障时,Agent的行为依然可预期、可管理、可恢复”。这和传统的分布式系统容错设计思路一脉相承,但因为大模型独有的延迟高、结果不确定、消耗不可控等特性,执行起来需要很多场景化的取舍。
如果只让我留一条经验给后面做Agent的团队,我会说:千万不要把稳定性当成上线后的补丁,而是从第一行架构代码开始就写进去。第一版就把多网关、超时控制、降级链路设计好,后面会省去无数个手忙脚乱的深夜。在这些问题上踩过的坑,一个都少不了,越早面对,越早从容。