前面的 Agent 系列,已经解决了几个大问题:
- 架构上:清楚地区分了意图解析、规划、工具层、状态与记忆、评估与控制;
- 工程上:用 Tool 抽象、安全网关、状态持久化、多 Agent 协作、LangGraph 工作流把东西串起来;
- 运维上:搭了监控、告警、灰度发布和安全权限治理。
但只要你一把 Agent 放进真实业务,迟早会面对两个现实问题:
- 这套多 Agent + 多工具 + 多模型的系统,是不是太贵了?
- 在高并发场景下,延迟和吞吐顶不顶得住?
这篇文章就专门讲一件事:
在不牺牲太多能力的前提下,
如何系统性地优化 Agent 的性能与成本 ,
让它从「能跑」走到「跑得起」「跑得久」。
一、先搞清楚:Agent 的成本都花在哪?
大部分团队一看账单,第一反应是"模型调用太贵了"。
实际上,Agent 的整体成本一般分成几块:
-
模型调用成本
- 大模型调用(主 LLM:3.5/4.0/Claude 等);
- 辅助模型(裁判模型、路由模型、Embedding 等)。
-
工具调用成本
- 访问内部服务 / 数据库 / 日志系统 / 监控系统;
- 访问第三方 API(搜索、支付、外部模型等)。
-
基础设施成本
- 向量库、缓存、数据库的读写;
- LangGraph / Agent Service 自身的计算与存储。
-
人为运维成本
- 调试与回放时间;
- 误调用、误策略造成的返工;
- 排障和回滚带来的隐性损耗。
优化的第一步,是把这些成本量化出来,然后再决定从哪一块切。
二、度量体系:没有度量就没有优化
要做性能和成本控制,建议先把以下指标打通到统一的日志 / 指标系统(比如 Prometheus + ClickHouse):
2.1 模型调用维度
每次模型调用(包括主模型和小模型),记录:
model_name/model_providertokens_prompt/tokens_completion/tokens_totallatency_mscost_estimated(根据定价表算出本次大致费用)agent_role(是 Planner / Worker / Evaluator / Router 之类)
后面就能算出:
- 单次任务平均 Token 消耗;
- 单任务平均 LLM 调用次数;
- 各类 Agent(Planner/Worker/Evaluator)的成本占比和延迟占比。
2.2 流程级别维度
对整条 Agent 流程(一次 episode)记录:
total_llm_calls/total_tokenstool_calls(分 Tool 统计)latency_ms_total(端到端延迟)steps_count(Graph 中实际走了几步)success/failed/fallback标记
这样你可以很直观地回答:
- 哪种类型的任务最贵?
- 是谁在"磨洋工"(Planner 太啰嗦、Evaluator 反复评估等)?
- 哪一步是延迟瓶颈?
三、策略一:优先用"小模型 + 明确约束",大模型留给"难活儿"
3.1 分层模型策略
一个常见的高性价比方案是:
- 主 LLM:负责复杂推理、生成最终答案(可以用 GPT-4/Claude 级);
- 裁判/评估 LLM:尽量用便宜/小一档的模型(如 GPT-4o-mini 或自家微调);
- Routing/Tool 选择/轻度信息抽取:优先用更小的模型或者规则引擎。
可以按这种映射划分:
| 任务类型 | 推荐模型层级 |
|---|---|
| Tool 选择/路由决策 | 小模型 / 规则 |
| JSON 结构化/字段抽取 | 小模型 / 模板 + 解析 |
| 复杂推理/报告生成 | 大模型 |
| 质量评估(简单场景) | 小模型 + 规则 |
3.2 Prompt 收紧,拒绝"流水账思考"
很多 ReAct/CoT 模式的 Prompt 会让模型输出大量"思考过程"(Thought),这些都是 Token 成本。
工程上可以做两件事:
- 区别"机器可读"和"人类可读"
- 大部分情况下,内部 Thought 只需要机器解析的 JSON 即可;
- 不需要自然语言长篇大论;
- 逐步压缩 Prompt
- 删除冗余说明;
- 把几个静态规则改为外部配置(不要每次复述给模型)。
示例对比:
-
低效 Prompt:
"请一步步详细解释你的想法,然后决定要调用哪个工具,解释每一步原因......"
-
高效 Prompt:
"只用 JSON 输出下一步动作和参数:
{\"tool\": ..., \"args\": ...}。不要解释。"
四、策略二:减少「无意义的步骤」和「过度协作」
多 Agent 协作带来的一个常见问题是:
为了"架构优雅",多拆了几个 Agent,结果每次多出好几轮模型调用。
4.1 复盘每一个节点是否"值回票价"
对每一个 Graph 节点问四个问题:
- 这个节点是否只是在做简单拼接/路由,是否可以用规则或小模型替代?
- 这个节点的输出是否对最终质量有可度量的贡献?
- 如果把这个节点去掉,整体错误率/用户满意度会不会显著变差?
- 这个节点是否可以合并进前一个/后一个节点?
如果某个节点:
- 每次都调用一次大模型;
- 但对最终质量和业务指标没有明显提升;
那它就是天然的"节省点"。
4.2 合并"轻量决策 + 工具规划"
在很多场景里,可以这样做合并优化:
- 不再单独搞一个重型 Planner Agent;
- 而是在 Worker 之前插一个轻量的"本地规划器" :
- 用规则判断要不要调某个 Tool;
- 用小模型决定是否需要多一步工具调用。
这样你可以把原本 "Planner LLM → Worker LLM → Evaluator LLM" 三次调用,压缩成:
- Worker 节点 → 小模型/规则 Decide → 工具调用 → 大模型生成最终答案。
五、策略三:缓存与重用------"同一问题不要问两遍"
对 Agent 来说,"缓存"不是简单的 HTTP 层缓存,而是多层缓存组合:
5.1 LLM 级别缓存
- 对常见问答 / 标准流程结果进行缓存(如 FAQ、标准诊断报告模版);
- 对典型的中间结果缓存,例如:
- 某种错误码 → 对应的根因解释(一天内变化不大);
- 某种日志模式 → 分类标签。
缓存键可以是:
- 问题归一化(去除无关部分后的指纹);
- 上下文关键字段组成的哈希(服务名 + 错误码 + 时间窗口)。
5.2 工具调用缓存
很多工具调用本身就支持幂等和缓存:
- 最近 5 分钟订单详情不必重复查;
- 最近 1 分钟的某个服务指标/健康检查可直接重用。
可以在工具层做一层简单的本地/Redis 缓存:
python
def cached_tool_call(key_builder, ttl_seconds=60):
def decorator(fn):
def wrapper(*args, **kwargs):
key = key_builder(*args, **kwargs)
cached = redis.get(key)
if cached:
return json.loads(cached)
result = fn(*args, **kwargs)
redis.setex(key, ttl_seconds, json.dumps(result))
return result
return wrapper
return decorator
5.3 可重用子任务
对于复杂任务(例如"告警诊断 + 报告生成"),可将流程拆为:
- 子任务 A:诊断根因;
- 子任务 B:生成报告。
在同一问题多次询问时,尽量重用子任务 A 的结果,只重新跑 B。
六、策略四:并发与异步------把等待时间"叠加成一份"
当一个 Agent 需要:
- 同时拉多个服务的指标、日志;
- 或并行调用多个领域的 Worker Agent;
就必须利用好并发/异步,把这些 IO 等待时间叠加成一份。
6.1 在 Tool 层做异步封装
如果你的 Tool 调用本身是 IO 密集(HTTP/DB),可以改为 async:
python
class GetServiceMetricsTool(AsyncTool):
async def run(self, service_name: str, window: int) -> Dict[str, Any]:
async with aiohttp.ClientSession() as session:
async with session.get(f"...?svc={service_name}&w={window}") as resp:
return await resp.json()
然后在 Worker 节点里使用 asyncio.gather 并发调用多个工具。
6.2 多 Agent 并行工作
例如,对同一告警:
- 一个 Agent 负责"拉指标+日志";
- 一个 Agent 负责"查最近变更几次发布";
- 一个 Agent 负责"分析业务指标波动"。
你可以在 LangGraph 里用并行节点(parallel)或在自研框架里用 gather,把三项工作并行做完,再汇总。
七、策略五:针对低价值请求"降级服务"
不是每个请求都值得跑一整套多 Agent 工作流。
可以在入口层做分级策略:
-
低价值请求(如随意性闲聊、探测性提问)
- 只用简单 Q&A Agent 或 FAQ;
- 不触发多 Agent 流程,也不调昂贵模型。
-
中价值请求(一般问题)
- 走单体 Agent + 工具;
- 限制最大步骤数、最大 Token 消耗。
-
高价值请求(高价值客户 / 高优先级告警 / 核心业务路径)
- 全量流程:多 Agent + 评估 + 报告;
- 可以使用更精度/更贵的模型与更长 CoT。
实现方式:
- 在入口处根据
user_tier/business_priority/alert_severity打标签; - 在
AgentContext里传入priority字段; - 各节点根据
priority决定:- 走哪条子图;
- 用哪个模型;
- 限制多少步数。
八、策略六:流程与配置分离,支持「线上调优」
把 Agent 流程的几个关键变量配置化:
- 使用哪个模型(model_name, temperature, max_tokens);
- 最大步骤数 / 最大重试次数;
- 启用哪些节点 / 哪些工具;
- 缓存 TTL、限流阈值。
并把这些配置挂到统一的配置中心(或环境变量/数据库),而不是写死在代码里。这样你可以:
- 在不发版的前提下调整"激进程度"(例如缩短最大步骤数、切换模型到便宜版);
- 做 A/B:线上部分流量使用不同配置,比较成本和效果。
九、实战落地方向建议
如果现在让你对现有 Agent 系统做一次「性能&成本优化」迭代,我建议按下面步骤来:
-
先度量,后优化
- 把"每次任务的总 Token / 总 LLM 调用次数 / 总 Tool 调用次数 / 总延迟"先打出来;
- 用 ClickHouse/SQL 做个按场景的 TopN,看看最贵、最慢的都是哪些流程。
-
先处理"无谓的浪费"
- 干掉或合并几个对质量贡献有限的节点;
- 减少不必要的 Evaluator 调用;
- 优先把简单决策下沉到规则或小模型。
-
再做结构性优化
- 为高 QPS/低价值路径做简化版单体 Agent;
- 为高价值路径保留多 Agent + 评估。
-
最后搞缓存与并发
- 针对高频工具调用加缓存;
- 对多源数据拉取、子任务执行做并行化。
-
持续评估
- 每周对比成本和关键指标:
- 单任务平均 Token/成本
- 单任务平均延迟
- 质量分数和业务指标有没有变糟
- 保证优化不会"省成本但把效果打穿"。
- 每周对比成本和关键指标:
十、小结:性能与成本,是 Agent 工程化的"后半程功课"
到这一步,你的 Agent 系列已经从:
-
能跑 Demo → 能跑生产 → 能被监控和回放 → 能被安全约束;
逐渐走到:
-
能在大规模、高并发场景下,稳定且可控地跑下去。
这一篇的核心结论可以压缩成几句:
- 先量化成本与延迟,再决定从哪一块下手;
- 大模型专注"难活儿",轻量任务交给小模型/规则/缓存;
- 不为"架构优雅"额外多堆节点,多 Agent 要为复杂需求服务;
- 缓存、并发、限流、分级服务,是把 Agent 体系"跑得起"的关键基础设施。