很多团队上线 AI Agent 后会发现一个反直觉现象:前几轮对话成本正常,聊到第十轮、第二十轮后,单次请求越来越贵,延迟也越来越高。

原因通常不是用户的新问题变长了,而是应用把完整聊天历史、系统提示、知识库片段和工具结果一起重新发送给模型。用户只输入一句“继续”,后台可能再次处理前面几万 Token。

因此,多轮 Agent 的成本不能只按“新增消息长度”估算,而应该观察每一轮实际发送的完整上下文。

一、为什么第十轮比第一轮贵

一次典型 Agent 请求可能包含:

  • 系统提示与安全规则;
  • 历史用户消息和模型回复;
  • RAG 检索结果;
  • 工具参数与工具返回值;
  • 当前用户问题;
  • 输出预留 Token。

如果每轮都携带完整历史,累计输入量接近:

总输入 Token ≈ 第1轮上下文 + 第2轮上下文 + … + 第N轮上下文

假设每轮新增 800 Token,同时把所有旧内容继续发送,第 1 轮约 800 Token,第 10 轮约 8000 Token。十轮累计处理的输入不是 8000,而可能接近 44000 Token。

工具调用会进一步放大问题。搜索接口返回的网页正文、数据库查询结果和调试日志如果原样留在历史中,后面的每一次模型调用都会再次为它们付费。

二、先给上下文做“身份分类”

不要直接按照“最旧的先删除”。建议把消息分成四类:

  1. 必须保留:用户目标、关键限制、最终确认和安全边界;
  2. 可以摘要:早期讨论、已完成步骤和中间推理结果;
  3. 可以外置:长文档、工具原始返回和可重新查询的数据;
  4. 可以删除:重复寒暄、失败尝试、无效检索和旧版本内容。

这比简单设置“只保留最近 10 条消息”更稳。因为一条早期的预算限制可能比最近几轮闲聊更重要。

三、滑动窗口适合短任务

最简单的方案是保留系统提示、关键状态和最近若干轮:

def build_context(system_message, memory, recent_messages, keep_last=8):
    return [
        system_message,
        {"role": "system", "content": f"Known state: {memory}"},
        *recent_messages[-keep_last:],
    ]

滑动窗口实现简单,适合客服问答、短任务助手和状态变化不复杂的流程。但如果用户目标跨越几十轮,仅保留最近消息可能让 Agent 忘记关键约束。

四、长任务使用结构化摘要

长任务不要只生成一段自然语言总结。更稳妥的是把记忆整理成固定结构:

{
  "goal": "用户最终目标",
  "confirmed_constraints": ["预算", "格式", "截止时间"],
  "completed_steps": ["已完成内容"],
  "open_questions": ["仍需处理内容"],
  "important_ids": ["workflow_id"],
  "last_updated_at": "ISO-8601"
}

只有达到阈值时才重新摘要,例如上下文超过 12k Token,或者已完成一个明确阶段。每轮都调用模型做摘要,可能省下输入费用,却增加一笔新的摘要费用。

摘要完成后仍要保留最近几轮原文,避免摘要遗漏最新细节。比较常见的组合是“结构化长期记忆 + 最近 4~8 轮原文”。

五、工具结果只保留结论和引用

工具原始返回往往是上下文中最肥的一块。推荐把它拆成三层:

  • 模型上下文:只放结论、关键字段和引用 ID;
  • 外部存储:保存完整返回值;
  • 审计日志:记录时间、工具名、参数摘要和结果哈希。

例如网页抓取返回 20k Token,不必把全文永久留在消息历史中。可以保存文档 ID,只把相关段落和来源链接交给模型。后续需要时再按 ID 检索。

六、Prompt Cache 只能缓存稳定前缀

支持 Prompt Cache 的模型或线路可以减少重复处理稳定前缀的成本和延迟,但前提是内容顺序稳定。

适合放在前缀的内容包括:

  • 固定系统提示;
  • 长期不变的工具说明;
  • 稳定的输出格式;
  • 版本固定的参考文档。

用户输入、时间戳、随机 ID 和不断变化的工具结果应放在后面。把当前时间写在系统提示第一行,会让几乎整个前缀每次都变化,缓存命中率自然很低。

监控时不要只看“是否开启缓存”,还要记录缓存命中 Token、未命中 Token 和实际折扣。

七、给上下文设置三层预算

建议同时设置:

  1. per-call:单次上下文、输出 Token 和超时上限;
  2. per-workflow:整个 Agent 任务的调用次数和总费用;
  3. per-user/day:单用户每日用量,防止异常循环。

在构建请求前先做预算预估:

def should_compact(input_tokens, output_reserve, context_limit, soft_ratio=0.75):
    projected = input_tokens + output_reserve
    return projected >= context_limit * soft_ratio

不要等模型返回“context length exceeded”才处理。达到 70%~80% 的软阈值时就应摘要、裁剪或外置内容,并给输出保留足够空间。

八、用“成功工作流成本”验证优化

上下文变短不等于效果更好。如果裁剪掉关键约束,重试和人工返工可能抵消节省的 Token。

建议同时比较:

单个成功工作流成本 =
(输入费用 + 输出费用 + 重试费用 + 工具费用)÷ 成功工作流数

固定同一批真实任务,对比优化前后的成功率、P95、输入 Token、缓存命中、重试率和成功工作流成本。

在线测试、价格与接入入口:https://woofapi.com

Python、Node.js 最小接入示例:https://github.com/zcl97630815-cpu/woofapi-openai-compatible-starter

上线检查清单

  • 不把完整聊天历史无限追加;
  • 为消息标记必须保留、可摘要、可外置、可删除;
  • 长工具结果只保留结论、引用 ID 和必要片段;
  • 稳定提示放在前缀,提高 Prompt Cache 命中率;
  • 在上下文达到 70%~80% 时主动压缩;
  • 同时监控质量、延迟、缓存和成功工作流成本。

WoofAPI 提供 OpenAI-compatible 多模型路线,适合开发者、Dify、RAG 和 AI Agent 工作流测试。部分 GPT 路线在特定官方输入价格比较中最高可低约 95%;不同模型、输入/输出计费和实时线路会变化,最终以价格页和实际压测为准。

本文由 WoofAPI 团队整理,公开关系披露如下:

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐