Source: https://aiprimetech.io/zh/blog/agent-cost-control/ 2026 年 25 日,六月 · 6 分钟 · 智能体 # 避免智能体循环耗尽你的 API 预算 A 作者 [AI Prime Tech](https://aiprimetech.io/zh/) · AI 辅助撰写 我会直接起草这篇文章,加入具体的工程策略、对比表和实用示例。内容会围绕真实的循环行为和成本控制展开,并确保以可执行的建议收尾。## 耗尽 API 预算的最快方式 我曾亲眼看到,一个“简单”的编程智能体在不到两分钟内,把一条 400 词元的用户请求变成了账单上一笔 28,000 词元的费用。 这种模式熟悉得令人痛心:智能体调用搜索工具,总结结果,重新阅读自己的总结,换个略有不同的说法再次调用同一个工具,然后不断扩充上下文,直到每一轮都带上整段对话、半个代码仓库,以及一连串失败的计划。模型本身没有问题,出问题的是循环设计。 这就是智能体系统的核心问题:成本并不随用户提示词增长,而是随 循环行为增长。一个糟糕的循环就能成倍增加: - 持续膨胀的上下文带来的输入词元, - 冗长“思考”带来的输出词元, - 重复调用带来的工具费用, - 以及串行重试带来的延迟。 如果你正在构建生产环境中的智能体,真正的任务并不是“让模型更聪明”,而是“让循环成本更低、流程更短、更难失控”。 ## 为什么智能体循环会让成本暴涨 普通聊天的一轮交互只有一次输入和一次输出。智能体循环则包含如下序列: - 用户提出问题, - 模型制定计划, - 模型调用工具, - 工具返回数据, - 模型读取数据, - 模型决定下一步, - 重复上述过程。 每次迭代都会为下一次迭代的提示词增加新的词元。如果你不断追加完整的工具输出和先前的思考内容,提示词就会大致呈阶梯式增长。 在实际运行中,这会产生三种成本放大因素: - 上下文累积:每一步都带上此前各步的内容。 - 工具调用冗余:使用略有不同的参数反复调用同一个工具。 - 失控的重试:模型已经做得足够多,却仍不断“再试一种办法”。 一个常见的坑是,词元浪费通常很难察觉,直到你查看每次运行的追踪记录。最终答案可能很简洁,但隐藏的执行链可能比用户可见的输出大 10x。 ### 一个简单的成本模型 如果一个循环运行 N 步,每步包含: - C 词元的携带上下文, - I 词元的工具输出重新注入上下文, - O 词元的模型输出, 那么总量可粗略估算为: ``` total_tokens ≈ N * (C + I + O) ``` 这个估算偏乐观,因为 C 通常会随着循环继续而增长。在真实的智能体中,后面的轮次往往成本最高。 ## 真正重要的控制手段 你可以从几个地方着手施加控制。关键在于将它们结合起来。 | 控制手段 | 减少的内容 | 最佳适用场景 | 权衡 | 步数上限 | 失控循环 | 任何使用工具的智能体 | 处理困难任务时可能提前停止 | 上下文裁剪 | 输入词元 | 长程任务 | 可能丢失有用的历史信息 | 成本更低的子智能体 | 常规工作的费用 | 搜索、提取、分类 | 协调开销 | 工具结果缓存 | 重复的工具费用 | 稳定的数据源、重复查询 | 数据过时与缓存失效 | 费用可观测性 | 意外的高额账单 | 生产系统 | 需要埋点工作 | 循环停止条件 | 无限或近乎无限的循环 | 不可靠的智能体 | 必须定义“足够好”的标准 最有效的生产环境配置会使用所有这些手段。 ## 1) 严格限制步数 这是最简单、也最被低估的解决办法:如果你不设定硬性上限,就等于相信模型会自行停止。 我通常从以下设置开始: - 3–5 步,用于范围较小的任务, - 6–8 步,用于中等复杂度的任务, - 只有在理由充分时才增加步数。 合理的上限不仅是安全阀,还会促使任务得到更好的拆解。如果智能体只能行动四次,它往往会: - 更早请求使用正确的工具, - 避免探索性的绕路, - 并更快收敛到可用的答案。 ### 循环控制器示例 ``` MAX_STEPS = 5 for step in range(MAX_STEPS): action = model.next_action(state) if action.type == "final": return action.final_answer observation = run_tool(action.tool_name, action.arguments) state = update_state(state, action, observation) raise RuntimeError("Agent stopped after step cap") ``` 一个常见的坑:步数上限应适用于 整个计划,而不是分别对每个子程序独立生效。否则,你只是把失控增长从顶层智能体转移到了嵌套的辅助程序中。 ## 2) 每轮都裁剪上下文 大多数智能体携带了过多的历史信息。它们不需要此前每一次工具响应,尤其是当响应很长、却只有一个细节有用时。 在实践中,分层记忆策略给我带来了最好的效果: - 原样保留:用户请求、当前目标、最终决策、尚未解决的约束。 - 总结:先前的推理、分支尝试、冗长的工具输出。 - 丢弃:走入死胡同的假设、重复的工具结果、旧的中间草稿。 ### 应保留哪些内容 紧凑的状态对象比直接回放原始对话记录更有效: ``` { "goal": "Find the failing endpoint and propose a fix", "constraints": [ "No schema changes", "Must preserve backward compatibility" ], "known_facts": [ "500s started after deploy 1842", "Only /v1/search is affected" ], "open_questions": [ "Is the new cache layer returning stale payloads?" ], "step": 3 } ``` 这比向模型输入 20 轮“边想边说”的内容便宜得多。 ### 实用的裁剪模式 使用三个缓冲区: - working_set:当前轮次、工具输出、当前执行中的计划。 - summary_memory:压缩后的历史记录。 - archive:审计时可能需要、但不必放入提示词上下文的内容。 智能体只能看到 working_set + summary_memory。当 working_set 变得过大时,将其总结到 summary_memory. 这里的陷阱是摘要漂移。如果摘要生成过程会丢失信息,就可能抹去约束,导致智能体重蹈覆辙。我倾向于将结构化事实与自由形式的摘要分开保留,这样模型就不必从文字描述中推断这些事实。 ## 3) 用更便宜的子智能体处理简单工作 并非每一步都值得动用你最好的模型。 如果任务是: - 从 JSON 中提取字段, - 对工单进行分类, - 检查文件是否发生变化, - 或生成简短的搜索查询, 那么更小、更便宜的模型通常就够用了。将昂贵的模型留给规划、综合分析和处理歧义。 ### 常见分工 - 主智能体:对任务进行推理,决定何时停止。 - 子智能体:执行搜索、提取或规范化等范围明确的工作。 - 验证器:检查输出的格式、完整性或明显错误。 一种实用架构: ``` User -> Orchestrator (strong model) -> Search agent (cheap model) -> Extract agent (cheap model) -> Final synthesis (strong model) ``` ### 为什么这样有效 主模型可以专注于控制流程,而不是亲自处理所有事情。子智能体则可以通过提示词限定任务范围,并严格限制 token 用量。 搜索子智能体的提示词示例: ``` Return only: 1. the best search query, 2. 3 likely source categories, 3. no explanation. ``` 这种范围明确的约定能让输出保持简短且可预测。 如果你的平台提供价格实惠的多模型访问能力,这正是它发挥价值的地方:用一个强大的模型负责协调,用一个更便宜的模型处理重复性子任务,没有理由把高价 token 消耗在常规解析上。 ## 4) 认真做好工具结果缓存 智能体循环经常为同一份信息重复付费: - 重复读取文件, - 重复查询数据库, - 重复进行网页搜索, - 重复调用嵌入或检索功能。 缓存工具输出是你能做出的投资回报率最高的改进之一。 ### 使用语义键缓存,而不是原始文本 只要措辞稍有变化,原始提示词缓存就无法命中。更好的缓存键应基于规范化后的意图: ``` def cache_key(tool_name, args): normalized = normalize_args(args) return f"{tool_name}:{hash(normalized)}" ``` 缓存条目示例: ``` { "tool": "repo_search", "query": "auth middleware rate limit bug", "result": { "files": ["src/middleware/auth.py", "src/api/routes.py"], "ts": 1710001123 } } ``` ### 缓存在哪些场景下最有帮助 - 代码仓库检查智能体, - 文档搜索, - 内容稳定的知识库, - 确定性转换, - 多轮工作流中的重复检索。 ### 缓存可能带来问题的场景 - 快速变化的数据, - 因用户而异的结果, - 任何对数据时效性有严格要求的内容。 常见的陷阱是缓存了工具输出,却没有向智能体说明数据的新鲜程度。如果模型拿到的是缓存数据,却以为是实时数据,就可能做出错误决策。应在工具元数据中包含时间戳或有效期。 ## 5) 在仪表板上展示支出 如果你只跟踪延迟和成功率,就会漏掉真正的失败模式:代价高昂的成功。 你需要在每次运行中观测以下指标: - 输入 token 数, - 输出 token 数, - 工具调用次数, - 工具延迟, - 总支出, - 步骤数, - 停止原因。 ### 最简事件结构 ``` { "run_id": "r_8f2c", "step": 4, "model": "gpt-5.5", "input_tokens": 1842, "output_tokens": 221, "tool_name": "repo_search", "tool_latency_ms": 312, "estimated_cost_usd": 0.087, "stop_reason": "step_cap" } ``` ### 实际运行中应关注什么 - 每个成功任务的 token 用量:最直接的成本指标。 - 每一步的 token 用量:用于发现提示词膨胀。 - 重复的工具调用:通常意味着规划存在缺陷。 - 停止原因分布:如果大量运行因达到上限而结束,说明智能体的规划不够充分。 按任务类型统计成本是最有用的图表之一。有些类别自然会比较昂贵,这没有问题。你要找出的是那些本应便宜、实际却不便宜的任务。 ## 6) 尽早终止失控循环 循环的停止理由不应只有“我已达到步骤上限”。 有用的停止条件包括: - 模型已生成最终答案, - 同一工具调用不断重复,却没有带来新信息, - 置信度或效用的增量低于阈值, - 验证器判定任务已解决, - 计划已停滞。 ### 循环中断器示例 ``` seen_calls = set() for step in range(MAX_STEPS): action = model.next_action(state) signature = (action.tool_name, canonicalize(action.arguments)) if signature in seen_calls: return fail("repeated tool call with no new information") seen_calls.add(signature) observation = run_tool(action.tool_name, action.arguments) state = update_state(state, action, observation) if verifier_says_done(state): return finalize(state) ``` 这可以发现一种非常常见的失败模式:模型“想要帮上忙”,却只是在改写同一个查询。 ### 另一项有用的防护措施:效用门控 如果某一步没有让状态发生足够大的变化,就不要继续。判断依据可以很简单,例如: - 没有找到新文件, - 没有提取出新实体, - 答案的置信度没有提升, - 没有加入新的证据。 具体指标取决于任务,但必须以某种方式衡量边际收益。 ## 调优到位后,实际会发生什么 收紧循环之后,智能体通常会在一些起初容易被忽略的方面变得更好: - 它会少说废话,决策更果断。 - 它会更早请求合适的工具。 - 它会减少“我还在调查”的循环。 - 它的成本会更低, 和 速度也会更快,因为轮次减少意味着上下文更少、延迟更低。 需要注意的权衡是,硬性上限和激进裁剪可能让系统在处理真正困难的任务时变得脆弱。因此,不要把智能体实际上因超时而终止的问题说成已经“解决”。应在日志和面向用户的消息中如实说明。 我的经验法则是:优化目标应是 有边界的胜任能力 而非无休止的探索。 ## 实用的生产环境配置 如果明天就要上线一个智能体,我会从以下配置开始: - MAX_STEPS = 5 - 使用结构化状态,而非重放完整对话记录 - 每轮结束后生成摘要记忆 - 用低成本子智能体执行搜索和提取 - 为工具结果建立缓存,并附带数据新鲜度元数据 - 记录每次运行的 token 用量和成本 - 重复调用检测器 - 明确的停止原因 这套配置并不亮眼,但它能防止账单增长速度超过产品增长速度。 ## 实践要点 - 首先限制步骤数;这是防止循环失控的最低成本防护措施。 - 大幅精简上下文,并将结构化状态与摘要分开保存。 - 让更便宜的子智能体处理范围明确的任务,避免处处消耗高价 token。 - 缓存可重复使用的工具输出,但要明确呈现数据新鲜度,避免模型盲目信任过时数据。 - 按每次运行、每个步骤和每次工具调用记录支出,让成本恶化立即显现。 - 在出现重复、进展停滞或确认完成时停止循环,而不是只在资源耗尽时停止。 - 围绕有边界的胜任能力进行设计:足够好、快速且可预测,始终胜过聪明但昂贵。 [智能体](/zh/blog/tag/agents/)[工程](/zh/blog/tag/engineering/)[API](/zh/blog/tag/api/) A [AI Prime Tech](https://aiprimetech.io/zh/) 本博客由 AI Prime Tech 发布。文章借助 AI 辅助起草;在据此采取行动前,请对照官方文档核实模型 ID、价格和限额等特定版本的细节。 以更低价格接入 Claude API 一个 API 密钥即可使用 Claude Opus 5.5、Sonnet 5、Haiku 4.5 和 Fable 5.1,以及 GPT-6 个模型。按量付费,无需订阅。 [获取 API 密钥 →](/register) AI Prime Tech 是独立的第三方 API 网关。Claude™ 和 Anthropic® 是 Anthropic, PBC 的商标。此处不暗示任何关联或背书。