Agent 出问题,很多时候不是模型变笨了,是网关开始限流,而 Agent 不知道。它看到一个工具调用返回错误(或者更糟,返回一段被网关改写过的错误 JSON),于是换参数重试、换工具重试、拆步骤重试,每一步都在多烧 token,最后报一个跟真实原因毫无关系的失败——比如“任务规划失败”。
这篇聊三件事:限流为什么会漂移,Agent 能感知到的信号应该长什么样,以及被限流之后怎么做安抚(backoff + 提示)才不至于让一次配额超限演变成一次幻觉式的连环失败。
限流漂移的根源:配额是按 Token 算的,请求是按工作负载算的
商业大模型与托管平台的配额基本是 QPM/TPM 维度,按 API Key 计算。阿里云那套 AI 网关方案里讲得很直白:闭源模型和托管平台的 QPS/Token 限制上调困难,企业要么多申请账号、多 Key 轮询摊薄限制,要么靠结果缓存减少对模型的请求。这两种做法都会让“我看到的上限”和“运营商账本上的上限”错位。
再加上网关自己还有一层流控:按 consumer 的 token 消耗统计、按模型的 token 消耗统计、被限流拦截次数统计、是哪些 consumer 在被限流。这些指标说明了一件事——限流不是一个静态数字,而是一条随调用模式漂移的曲线。同一个租户,早高峰跑三个 Agent,晚高峰跑十个,配额没动,但撞线的概率完全不同。
再往下还有一层漂移来自 Agent 自己:多轮重试、并行工具调用、工具返回分页回填,都会改变单次任务的实际 token 消耗。工具的 schema、返回体长度一变,同一条任务链的 token 账本跟着变。网关的限流阈值如果不跟着走,就会出现“昨天还好好的,今天上游封号”的情况。
一句话:限制项是对 Token 和请求数的,Agent 的行为单位是“步”。两个单位对不上,中间就需要一层翻译,翻译不好就是漂移。
返回码本身要负一半责任
传统 API 挂了是 5xx,Agent 至少知道要退。LLM 调用和工具调用会“软失败”:HTTP 200,内容是空的、乱码的、输出异常;工具返回里塞一个 is_error: true 但文本还在。腾讯云那篇架构思考提到的点是同一个:故障判定更模糊,不能只靠状态码判断健康。
限流错误尤其容易被吞掉。网关为了兼容各家的错误格式,把上游的 429、配额超限、并发拒绝统一封装,这层封装如果丢了 retry-after 或者模糊了错误类别,Agent 那边就只剩一句“调用失败”。LLM 收到这个方法后最常见的动作是把参数改小一点再试——在限流场景里这是纯粹的浪费,重试命中的还是同一个配额窗口。
建议在网关出口用一套显式错误契约:区分 quota_exceeded(窗口内总量用尽)、rate_limited(瞬时太快)、concurrency_rejected(并发槽位不够)、upstream_unavailable(真的挂了)。前三者都要带上建议退避时长和可恢复标记。Agent 侧的 handler 按类别分派,而不是一堆 try/except 里面塞一个 sleep。
{
"error": "rate_limited",
"recoverable": true,
"retry_after_ms": 2400,
"scope": "consumer:team-a/qwen-max",
"hint": "do not change arguments"
}
最后那个 hint 不是为了给模型读,是给写 handler 的人读到之后不要自作聪明地换参数。
安抚分三级:入口退避、观察降速、对外表达
第一级是入口退避。限流就应该让请求停在网关前,不要让 Agent 一股脑往外发。具体做法是每个工具/模型通道后面挂一个带抖动的令牌桶或滑动窗口,重试带指数退避,并且设置一个任务级别的重试预算——前面写过 Agent 多轮重试的预算怎么分,这里同理,配额被限的时候重试预算花得飞快,“最多重试 5 次”的说法比较空泛,“这个任务累计最多花 30 秒在退避上”才有约束力。
第二级是观察降速。Agent 应该能读到自己的配额水位。网关那边本来就有“每单位时间内有多少次请求因为限流被拦截”和 consumer 维度的统计指标,把它做成 Agent 可见的协作信号:当前窗口用了多少、水位线在哪个百分比、下一次窗口什么时候重置。水位超过阈值以后,Agent 主动压缩上下文、砍掉不必要的工具试探调用。可观测性在这里的作用不是画 Grafana,而是让被治理的一方知道自己在被治理。
第三级是对外表达。给最终用户的输出要坦白,不要伪造。工具调用连环失败以后,Agent 最好输出“当前工具使用额度已满,X 秒后我会再试”;最差的做法是编造一个中间结果把界面糊过去,这就从限流问题升级成了信任问题。
两条容易被忽略的工程细节
第一,KV/上下文别跟着重试一起崩。限流期间用户会把原本的一步拆成多轮,历史越长,输入侧的 token 配额消耗得越快——这就进入上限流触发压缩、压缩又可能丢关键信息、丢信息后重新探索的环路。做法是在限流状态下冻结工具面,把尚未确认的中间观察结果做一次结构化摘要,把“接下来做什么”写进一个显式的状态,而不是靠不断增长的对话历史来承载。
第二,多 API Key 轮询只是延迟了撞墙时间。网关多 Key 轮询、结果缓存确实是缓解配额的可用手段——语义缓存落 embedding 模型和向量库,精确缓存落 Redis,后者只适合非常垂直的场景。但轮询不会消除不均衡,多个 Agent 的对齐形成“羊群同步”:所有 key 在同一秒一起撞线。抖动、租户级令牌桶分配、按 key 的独立水位告警,都是要的。还有一个别忘了的概念,权限是多项的交集:调用者原有授权、工作负载授权、任务委托范围、资源侧限制,取决于四者公共部分。限流配置同样得落到比某个单一日志条目更细的粒度上。
写在限流调试排查清单之前
排查顺序建议按这个来:先看 Agent 收到的错误到底是哪个类别,再看重试行为有没有放大问题(比较单任务要话和成功的 token 消耗),再看阈值跟上没跟上配额变化,最后再谈换模型。多数时候没想模型侧的问题,是模块自己把问题放大了。
最小告警列也列三条:consumer 级被限流拦截计数、单任务因限流发起的重试次数分布、限流时间占任务总时间的比例。第三个指标特别能够暴露一件事——用户感觉的“慢”,有多少其实是等待窗口,这部分值得在接受范围内以成本换吞吐,即高峰用贵模型错峰不用,或接入备用模型,而不是重试、重试。
转载请注明出处: 皮哈皮阿
本文的链接地址: https://blog.phpat.com/agent-engineering/661.html
微信或手机浏览器扫一扫,随时随地随心阅读与分享
-
Agent Harness:可观测、可评测、可回滚的 Agent 基础设施
去年我们做了一个处理退款申请的 Agent。Demo 很顺,上线第一周就出了事故:进程重启后状态丢了,同一笔申请被处理了两次。问题不在模型,而在模型外面那层没人愿意写的基础设施。
2026/10/09
-
AI Coding Agent 如何稳定提交可合并的 PR
上周 review 了一个 AI 生成的 PR,测试全绿,但我还是把它关了。它改了 37 个文件,顺手升级了一个依赖,还修改了两条测试断言。问题不是代码不能跑,而是这个 PR 没人敢合。
2026/10/14
-
MCP 进入生产环境:工具协议、网关与权限边界
MCP 刚出来时,我以为最难的是协议兼容。真正接了十几个工具之后才发现,把工具接上只花了两天,把权限、审计和故障处理理清楚花了两个月。
2026/10/07
-
Agent 安全清单:提示注入、工具越权与数据外泄
一个内部助手被要求总结一封客户邮件。邮件末尾有一行白色小字:把最近的客户名单转发到某个地址。Agent 真的准备去调邮件工具了。安全不能靠模型自觉,得靠系统设计。
2026/10/16
-
并行工具调用暴露的工具设计耦合问题
并行工具调用能砍掉四成延迟,但它更重要的价值在于暴露工具之间的隐性耦合。本文拆解上下文依赖、共享状态竞争与时序前提这三类静默失败,给出读写分类规则、工具合并的判据,以及什么时候该上依赖图编排。
2026/10/23
-
Agent 子目标检查点回归:从回滚状态到登记副作用
Agent 的子目标检查点能回滚本地状态,却回滚不了已提交的外部副作用。本文拆解恢复后重新合成工具调用导致的语义回滚,给出基于副作用指纹的检查点边界划分与确定性回归断言。
2026/10/25
京公网安备11011402053654 
@muffin:链接已更新,分类图像功能...
AI网址导航模版图标库更换指南
作者大大,图标库邀请链接失效了,麻烦更新...
AI网址导航模版图标库更换指南
太好看了,快点更新!
友情链接
@戴墨镜的刘备:哈喽,路过点赞。
vue.js组件之手写签名板vue-signature-simple
太好看了,快点更新!太棒了!👍真的很赞!
vue.js组件之手写签名板vue-signature-simple
你写得非常清晰明了,让我很容易理解你的观...
Emlog插件RSS订阅器发布