Agent上线后账单暴涨?我用三层熔断,把无限循环调用这个炸弹拦在了门外|可写简历
前面两篇我们把 Agent 压测最容易踩的两个坑讲透了第一篇告诉你只压 HTTP 接口不算压 Agent第二篇告诉你真实模型烧钱压测不如先做 Model 层仿真。这一篇我们来解决一个更隐蔽、也更致命的问题Agent 无限循环调用。很多团队上线 Agent 后账单不是线性增长而是突然翻倍、甚至几倍。一开始大家会怀疑是不是用户量涨了是不是 Prompt 写得太长是不是模型太贵查下来往往不是。真正的原因经常是 Agent 在某些输入下反复进入“思考—调用工具—再思考—再调用工具”的循环。循环本身不一定报错。接口可能一直返回 200LLM 网关也可能没有明显异常但 Token、工具调用次数、向量库查询量一直在涨。等账单告警出来损失已经发生了。 框架迁移提示本文熔断与上下文裁剪思路是通用方案示例基于 Spring AI 实现如果你使用 LangChain4j、AgentScope 等其他 Java Agent 框架核心思路一致只替换为对应框架的中断条件与上下文管理扩展点即可。一、先搞清楚Agent 为什么会无限循环Agent 和普通接口最大的区别是它的执行路径不确定。普通接口输入固定逻辑固定结束条件明确。Agent输入同一个问题可能一轮结束也可能多轮推理如果工具返回结果不收敛模型就可能一直要求继续调用。常见循环场景有三类1. 工具结果无法满足模型预期比如模型要求“查到结果再回答”但工具每次都返回“未查到”“请补充条件”。模型理解为条件不足于是继续调用同一个工具进入死循环。2. 输出格式不稳定模型第一次调用工具失败第二次换参数重试第三次换说法再试。如果没有次数限制重试会被不断放大。3. 上下文越来越长模型越来越难收敛每一轮工具结果都塞回上下文Token 越来越多模型注意力下降。到后面模型可能已经分不清自己有没有查过、有没有回答过只能继续调用工具。所以要治 Agent 循环不能只靠模型“自觉结束”必须在工程上加三层边界第一层限制推理轮次第二层限制工具调用次数第三层限制上下文长度二、第一层熔断限制 Agent 最大推理轮次最有效的第一道防线是给 Agent 设置一个明确的最大轮次。很多人觉得“设轮次限制会影响正常能力”。实际上绝大多数业务 Agent正常回答都不需要几十轮。真正异常的请求往往会在第 5 轮、第 8 轮还不收敛。我们可以维护一个轮次计数器每完成一轮推理就加 1超过阈值后主动终止执行。代码实现RoundLimitAdvisorpackage com.agent.demo.advisor; import org.springframework.ai.chat.client.advisor.api.AdvisedRequest; import org.springframework.ai.chat.client.advisor.api.AdvisedResponse; import org.springframework.ai.chat.client.advisor.api.CallAroundAdvisor; import org.springframework.ai.chat.client.advisor.api.CallAroundAdvisorChain; import org.springframework.stereotype.Component; Component public class RoundLimitAdvisor implements CallAroundAdvisor { private static final int MAX_ROUNDS 5; Override public AdvisedResponse aroundCall(AdvisedRequest advisedRequest, CallAroundAdvisorChain chain) { Integer round (Integer) advisedRequest.chatOptions().getMetadata().getOrDefault(round, 1); if (round MAX_ROUNDS) { throw new IllegalStateException(Agent 超过最大推理轮次已终止执行); } advisedRequest.chatOptions().getMetadata().put(round, round 1); return chain.nextAroundCall(advisedRequest); } Override public String getName() { return roundLimitAdvisor; } Override public int getOrder() { return 0; } }设计说明round存在 metadata 里跟随整个 Agent 会话传递。每调用一次aroundCall代表一轮交互。超过MAX_ROUNDS后直接抛异常不再继续调用模型。异常会被全局异常处理器捕获返回明确错误而不是继续消耗 Token。推荐阈值不同业务阈值不同但建议普通问答 Agent35 轮工具型 Agent58 轮复杂任务 Agent815 轮不要一上来就设 20 轮、30 轮。阈值越高成本风险越大。先从保守值开始再根据真实业务观察放开。三、第二层熔断限制工具调用次数有些场景下Agent 推理轮次还没到上限但工具调用已经失控。比如反复调用同一个检索工具、数据库工具、计算工具。所以第二层熔断要单独统计工具调用次数。代码实现ToolCallLimitAdvisorpackage com.agent.demo.advisor; import org.springframework.ai.chat.client.advisor.api.AdvisedRequest; import org.springframework.ai.chat.client.advisor.api.AdvisedResponse; import org.springframework.ai.chat.client.advisor.api.CallAroundAdvisor; import org.springframework.ai.chat.client.advisor.api.CallAroundAdvisorChain; import org.springframework.stereotype.Component; Component public class ToolCallLimitAdvisor implements CallAroundAdvisor { private static final int MAX_TOOL_CALLS 4; Override public AdvisedResponse aroundCall(AdvisedRequest advisedRequest, CallAroundAdvisorChain chain) { Integer toolCallCount (Integer) advisedRequest.chatOptions().getMetadata() .getOrDefault(toolCallCount, 0); if (toolCallCount MAX_TOOL_CALLS) { throw new IllegalStateException(Agent 超过最大工具调用次数已终止执行); } AdvisedResponse response chain.nextAroundCall(advisedRequest); boolean hasToolCall response.response().getResults().stream() .anyMatch(result - result.getMetadata().containsKey(toolCalls)); if (hasToolCall) { toolCallCount; advisedRequest.chatOptions().getMetadata().put(toolCallCount, toolCallCount); } return response; } Override public String getName() { return toolCallLimitAdvisor; } Override public int getOrder() { return 1; } }设计说明工具调用次数单独统计不与推理轮次混在一起。每轮响应里如果包含toolCalls计数加 1。超过阈值后终止避免 Agent 一直查库、一直检索。更细一点按工具类型隔离如果业务里工具很多建议不只统计总次数还要按工具名隔离。比如查询类工具最多 3 次计算类工具最多 2 次写入类工具最多 1 次这样能防止某一个工具被无限打爆。四、第三层熔断上下文长度裁剪Agent 循环调用的另一个放大器是上下文越来越长。工具结果、历史对话、中间推理步骤如果全部保留Token 会迅速膨胀。上下文越长模型越容易分心越容易继续调用工具。所以第三层不是等循环发生再拦而是主动把上下文“瘦身”。策略 1只保留必要上下文不要把所有历史都塞进每一轮。很多业务只需要保留用户原始问题当前任务目标最近一次工具结果必要的约束条件中间过程、调试信息、重复描述能不保留就不保留。策略 2超过长度自动裁剪可以设置上下文窗口超过后只保留最近 N 轮或保留关键结果。代码实现ContextTruncationAdvisorpackage com.agent.demo.advisor; import org.springframework.ai.chat.client.advisor.api.AdvisedRequest; import org.springframework.ai.chat.client.advisor.api.AdvisedResponse; import org.springframework.ai.chat.client.advisor.api.CallAroundAdvisor; import org.springframework.ai.chat.client.advisor.api.CallAroundAdvisorChain; import org.springframework.ai.chat.messages.Message; import org.springframework.stereotype.Component; import java.util.List; Component public class ContextTruncationAdvisor implements CallAroundAdvisor { private static final int MAX_HISTORY_ROUNDS 6; Override public AdvisedResponse aroundCall(AdvisedRequest advisedRequest, CallAroundAdvisorChain chain) { ListMessage messages advisedRequest.messages(); if (messages.size() MAX_HISTORY_ROUNDS) { ListMessage truncated messages.subList(messages.size() - MAX_HISTORY_ROUNDS, messages.size()); return chain.nextAroundCall(new AdvisedRequest( advisedRequest.userText(), advisedRequest.systemText(), advisedRequest.advisors(), advisedRequest.chatOptions(), advisedRequest.functionNames(), advisedRequest.memoryId(), truncated, advisedRequest.advisorParams() )); } return chain.nextAroundCall(advisedRequest); } Override public String getName() { return contextTruncationAdvisor; } Override public int getOrder() { return 2; } }设计说明只保留最近MAX_HISTORY_ROUNDS条消息。减少无效上下文堆积降低 Token 消耗也降低模型“反复纠结”的概率。裁剪策略要按业务调整不能机械一刀切。策略 3工具结果摘要如果工具返回结果很长不要原样塞回上下文。先做摘要再送入模型。例如数据库返回 100 条记录只保留关键字段和统计结果检索返回 20 个片段只保留 Top 5 相关片段计算结果很大只返回最终结论工具结果摘要是很多团队容易忽略的成本优化点。五、三层熔断怎么配合使用这三层不是选一个而是要同时开。推荐执行顺序第一步先限制轮次和工具次数这是最快见效的两道硬边界。只要 Agent 出现异常循环先被拦在这两层。第二步再做上下文裁剪上下文短了模型出错概率下降轮次和工具调用自然也会下降。第三步最后加监控告警配合前两篇的 Agent 可观测体系监控这几个指标平均推理轮次P95 推理轮次工具调用次数单请求 Token 消耗异常终止率如果这些指标突然上涨说明 Agent 正在进入异常模式需要立刻排查。六、生产避坑清单❌ 不要只靠 Prompt 要求模型“结束后不要继续调用工具”模型不可靠必须工程兜底。❌ 不要只做全局异常捕获异常捕获只能止损不能阻止循环发生。❌ 不要把上下文全量保留上下文越长成本越高模型越容易失控。❌ 不要阈值设置过大轮次、工具次数、上下文长度都要从保守值开始。✅ 必须设置最大推理轮次✅ 必须设置最大工具调用次数✅ 必须做上下文裁剪或摘要✅ 必须配合监控观察指标变化✅ 异常终止后记录输入、上下文、工具结果方便复盘七、简历描述片段基于 Spring AI 搭建 Agent 生产稳定性治理体系通过多层 Advisor 扩展实现最大推理轮次熔断、最大工具调用次数限制与上下文动态裁剪有效防止 Agent 无限循环调用配合 Agent 可观测指标监控推理轮次、工具调用频次与 Token 消耗在保证业务能力的前提下显著降低大模型成本异常波动提升多 Agent 生产稳定性。 落地资源推荐跑Agent的应用尤其是做压力测试更吃服务器资源通常本机是不够用的建议使用云服务器能大大减少我们做其他事的精力提高学习代码的专注力和学习AI的效率免除后顾之忧新用户首年特惠专属渠道https://www.aliyun.com/daily-act/ecs/activity_selection?userCodefzoabro9领取完整工程找到图片上的水印即Java-AI工程师然后在Java-AI工程师中练习打字【agent-metric】即可本篇完整熔断与上下文裁剪源码下期预告下一篇我们继续把成本治理往前推一步前面解决了“异常循环”下一篇解决“正常请求也很贵”的问题。我们会把缓存、工具结果摘要、模型降级、Token统计归因放到一个方案里做一套可直接上线的 Agent成本控制清单。