Agent 慢的时候很多人第一反应就是砍 Prompt。把 system prompt 从两千字砍到三百字删掉角色设定去掉输出格式重新跑一次发现该慢还是慢。这不是个别现象。Agent 这类应用的响应延迟本质上是一条完整链路的累积结果Prompt 只是其中一个环节。把慢全部归因到 Prompt甚至指望靠“精简提示词”解决性能问题基本属于隔靴搔痒。如果你正在做 Agent 开发或者已经部署了基于大模型的智能体发现系统响应慢、批量任务排队严重、单次任务动不动几十秒这篇文章会帮你重新建立排查顺序先定位慢在哪一层再决定要不要动 Prompt。真正的性能瓶颈往往藏在上下文膨胀、工具调用往返、模型推理时间和重试策略里。我会按实际落地顺序把 Agent 性能排查的思路、步骤和判断标准拆开讲一遍。1. 先搞清楚 Agent 慢到底慢在哪一层1.1 一慢就砍 Prompt为什么经常是瞎忙先看一个典型场景。你封装了一个 Agent用来做资料整理和报表生成。用户输入一个查询后后端要把任务拆成几步读取历史记录、调用检索工具、让模型推理、生成最终答案。整条链路跑完花了 28 秒。你的第一反应是是不是 Prompt 写得太长模型读得太慢于是你把 system prompt 里的背景说明删掉把工具说明压缩成几行把输出模板精简。结果跑完还是 25 秒。为什么因为一次 Agent 请求的耗时往往不是由 Prompt 字符串长短决定的而是由下面这些因素叠加出来的输入 token 总量。Prompt 只是输入 token 的一部分真正占大头的是历史消息、工具返回结果、上下文文档。模型推理时间。同样的输入不同模型的速度差异可能达到数倍。工具调用次数。Agent 每调用一次外部工具就多一次网络往返和结果解析。重试和失败处理。工具超时、模型报错、解析失败都会让任务从头再来。并发和排队。同一时刻任务多了请求只在队列里等着也会产生明显延迟。如果这些问题没排查只盯着 Prompt 字数基本就是白忙。1.2 分段计时把一次 Agent 任务拆成可观测的环节要解决慢第一步不是优化而是测量。建议先把一次 Agent 任务拆成下面几个阶段输入预处理文本清洗、格式转换、权限校验。任务规划模型判断要调用哪些工具、按什么顺序执行。工具调用外部 API 请求、数据库查询、文件读取。模型推理多轮对话或单轮生成。输出后处理解析 JSON、格式化、落库。重试和补偿逻辑异常情况下额外增加的耗时。拆完之后给每个阶段打点计时。最简单的做法是在代码里埋时间戳import time def run_agent_task(task_input): result {} start time.perf_counter() task_input preprocess(task_input) result[preprocess_ms] (time.perf_counter() - start) * 1000 start time.perf_counter() tool_results call_tools(task_input) result[tool_call_ms] (time.perf_counter() - start) * 1000 start time.perf_counter() model_output call_llm(task_input, tool_results) result[llm_ms] (time.perf_counter() - start) * 1000 start time.perf_counter() final_output postprocess(model_output) result[postprocess_ms] (time.perf_counter() - start) * 1000 return final_output, result这只是示意真实项目里可以把它接进日志框架。关键是你要有一份数据知道 28 秒到底花在哪个环节。如果 tool_call_ms 占了 20 秒那问题根本不在 Prompt而在工具接口。如果 llm_ms 占了 20 秒你该考虑模型选择、上下文长度或推理参数而不是 Prompt 字数。判断标准很简单单环节耗时占比超过 50%优先处理这个环节。优化前和优化后必须对比同一组测试样本。不要只看一次结果至少跑 5 次取中位数。没有数据所有优化都是猜。2. 上下文膨胀和重复推理才是最常见的隐形拖累2.1 上下文越长推理成本不是线性增长很多 Agent 框架会把聊天历史、工具返回结果、系统指令全部拼在一起作为下一轮模型的输入。每轮对话都会把之前的 token 再重新发送一遍。任务跑得越深历史越长后续每一轮请求的输入 token 就越大。这里有个容易被忽略的点输入 token 增加模型处理时间不是简单线性增长。尤其在基于 Transformer 架构的模型里长上下文的注意力计算开销会明显上升。多轮 Agent 任务跑到十几步之后每步都在处理越来越长的上下文整体延迟自然被放大。有一个经验很值得记住Agent 慢经常不是因为第一次请求慢而是因为第 N 次请求慢。第一次请求 prompt 写得好不好可能只影响一两秒第十次请求之前累积的历史和工具结果可能一次就多出几万 token。2.2 简化 Prompt 不等于压缩上下文理解了上下文膨胀再回头看“砍 Prompt”这个动作就会发现它有多局限。假设 system prompt 从 2000 字砍到 500 字省下 1500 字。但每一次请求仍然要携带前 20 轮对话历史每轮可能 500 到 2000 token最近 5 个工具返回的 JSON有的返回结果几千字用户上传的文档切片一个切片就可能覆盖几千 token。砍掉 1500 字的 system prompt能影响多少总耗时很小。真正需要做的是上下文管理历史裁剪只保留最近几轮的关键信息。历史摘要用模型把前面的对话压缩成摘要而不是全量保留。工具结果截断工具返回结果只保留核心字段不要把整个 JSON 塞进去。关键文档检索用检索方式拿相关片段而不是把长文档全文塞进上下文。这些操作都属于上下文工程不是 Prompt 工程。上下文压缩之后每轮请求的输入 token 会显著下降延迟也会跟着降。这才是治本方向之一。3. 让 Agent 真正变快的几条实用路径3.1 优化任务拆解和工具调用而不是先精简 PromptAgent 和普通单轮补全最大的区别是会自主决定调用工具。这个能力带来灵活性的同时也带来了大量额外延迟。举个例子。一个 Agent 要回答“最近一周各渠道的销售数据”。如果它的设计是先查渠道列表再逐个渠道查数据最后再汇总生成结论那它可能需要 4 到 5 次模型推理中间还夹着多次工具调用。每一步都有网络延迟和模型推理延迟整体会非常慢。如果能把“查渠道列表”和“查各渠道数据”合并成一个工具接口或者提前在代码层把渠道列表注入让模型一次拿到所有数据那整个任务可能只需要两次模型推理。所以遇到 Agent 慢先做减法但这个减法不是减 Prompt而是减步骤。检查一下能不能减少工具调用次数能不能把多个独立查询合并成一个能不能在代码里预设规则避免让模型做不必要的规划能不能让工具调用超时更快不要傻等另外要单独关注失败重试。工具超时默认 30 秒如果还允许重试 3 次最坏情况下一个工具就要 120 秒。这类问题和你写多少 Prompt 一点关系都没有。3.2 引入缓存、跳步、并行和分批优化链路之后再看吞吐层面。常见手段有四类第一缓存。对于同样或高度相似的请求不要再完整调用模型。可以在两个层面缓存工具结果缓存和模型输出缓存。工具结果缓存尤其有效因为很多 Agent 会反复查询相同的数据。模型输出缓存需要评估效果一致性和业务风险适合那些结果可复用、对时效性不敏感的场景。第二跳步。如果 Agent 在某一步已经拿到明确答案就不需要再走后续流程。可以在代码里加状态判断提前结束任务。不要为了“规划完整”而让模型做多余的推断。第三并行。当一次任务需要调用多个互不依赖的工具时尽量并发执行而不是串行等待。很多 Agent 框架默认是按顺序调用工具时间被简单相加。你可以用 asyncio 或线程池把独立调用并行化。import asyncio async def fetch_sales_data(channel_ids): tasks [query_channel(channel_id) for channel_id in channel_ids] results await asyncio.gather(*tasks, return_exceptionsTrue) return results第四分批。如果是批量任务比如处理 100 个文件不要让每个文件都完整跑一遍流程。应该用任务队列控制并发数处理失败重试并保存断点进度。这里有个常见误区低配置环境也能跑一个文件不代表能同时跑 100 个文件。并发太高会让模型服务直接排队反而更慢。注意不要把并行数直接拉到最大。先小批量验证接口和资源占用再逐步提高。3.3 模型选择和参数设置同样影响延迟很多人调 Prompt 时从来没想过换模型。但模型本身的推理速度是决定延迟最大的变量之一。同一个任务用大参数模型可能跑 8 秒用更快的小模型可能跑 2 秒。如果你的业务对结果质量要求不是极端苛刻完全可以在 Agent 的不同环节用不同模型简单分类、意图识别、格式提取用小模型复杂规划和最终生成用大模型。这类策略叫模型路由效果通常比死磕 Prompt 明显得多。参数设置也要检查max_tokens。有些框架默认给很大模型会尽量生成到上限附近。如果你的任务只需要几百字把 max_tokens 调低。temperature。不直接决定速度但过高的随机性可能导致输出不稳定增加重试成本。timeout。给每一次模型调用和工具调用设置合理超时不要默认无限等待。stream。如果用户只需要最终结果可以不开流式如果需要“感知速度”就开流式输出让首字尽快到达。判断标准要分开看端到端耗时、首 token 耗时、单步耗时、成功率和 token 消耗。只盯其中一个指标很容易被误导。4. 从“能用”到“稳定快”日志、追踪和压测怎么落地4.1 给 Agent 加可观测性比反复改 Prompt 更值钱聊到 Agent 性能优化很多开发者最缺的不是技巧而是数据。问题在于 Agent 任务链路太长中间状态又多光靠肉眼观察根本定位不了瓶颈。建议至少记录以下字段字段说明task_id每一次任务的唯一标识step_name当前链路步骤model_name实际使用的模型input_tokens输入 token 数output_tokens输出 token 数duration_ms该步骤耗时tool_name调用的工具名称status成功、失败、超时、重试可以用 LangSmith、Langfuse 这类追踪工具也可以自己打结构化日志。关键是数据能串成一条完整的调用链能够回答三个问题慢在哪一步每次请求发送了多少 token失败和重试占了多少时间我一般会先看“错误率”和“重试次数”。很多 Agent 慢不是正常处理慢而是失败之后一遍遍重试。这时候优化 Prompt 没有意义先处理异常路径才对。4.2 用一份最小基准测试判断优化是否有效没有基准你没法判断改动是变好还是变差。建议维护一组固定的测试样本规模不用大10 到 20 条就够。测试样本要覆盖正常短任务长上下文任务需要多次工具调用的任务工具返回异常或超时的任务用户输入含糊、容易触发误判的任务。固定模型、参数和并发数。每条样本跑 5 次取中位数。记录三个核心指标端到端耗时、成功率、平均 token 消耗。优化前先跑一轮基线。之后每做一次改动就在同一组样本上重跑。如果改动之后端到端耗时下降 20%且成功率没有下降说明这个改动有效。如果只是某个环节数据变好但整体没有改善说明瓶颈不在那里。注意不要只测“最好走”的路径。长上下文和失败重试路径往往是拖垮整体性能的隐藏点。5. Prompt 该不该调该调但要分清优先级5.1 Prompt 质量影响结果质量不等于速度写到这里不是说要完全放弃 Prompt 工程。Prompt 当然重要但它的核心价值是控制模型行为不是控制系统性能。一段写得很好的 Prompt可以让模型更准确地理解任务减少格式错误减少无效工具调用。这些能力间接会降低重试率从而让系统看起来更快。但这里有一个前提你必须先确定慢的根因是模型行为异常而不是链路本身太重。如果模型每一步都给出错误格式导致解析失败重试三次那确实该改 Prompt。如果模型输出很稳定只是每一步都要处理几万 token那改 Prompt 解决不了问题应该去改上下文和链路结构。有个很实用的判断方法看日志里失败原因分布。如果大量失败来自“输出格式不符合预期”或“JSON 解析失败”Prompt 是优化重点。如果失败来自“工具超时”“接口限流”“模型排队”那就别在 Prompt 上浪费时间。5.2 什么时候该调 Prompt什么时候别只改它按优先级排序我的建议是先看链路耗时分布再看上下文 token 是否有压缩空间再看工具调用是否过多、超时和重试是否合理再看模型选择是否匹配任务难度最后才 review Prompt。换句话说Prompt 是排查顺序里的最后一项不是第一项。即使要调 Prompt也要注意边界不要把 Prompt 砍到不可读。太简略会导致模型理解错误反而提高重试率。不要只删不补。如果系统指令里有必要的安全限制、输出格式、工具使用规范删掉会引入新的行为问题。不要反复堆 Prompt。遇到问题就加一句“请务必准确”“不要瞎编”这类话对性能没有任何帮助。正确做法是把 Prompt 当成代码来维护结构化、版本化、可测试。每次修改 Prompt都当成一次功能变更记录变更原因、影响范围和测试结果。6. 写在最后处理慢问题先按链路排查不要凭感觉动刀我见过太多 Agent 项目性能一慢就进入“调 Prompt 循环”今天删一段明天加一段后天又改回来始终没解决真正的问题。如果让我给一个最直接的建议那就是在动手之前先跑一轮完整的数据埋点。把任务拆成步骤给每一步计时记录输入 token、输出 token、工具调用耗时和重试次数。拿到数据之后你自然会知道该动哪里。这个方案真正落地时最该盯住的不是 Prompt 写得好不好而是上下文管理、工具调用效率和失败重试策略。把这三件事做好Agent 慢的问题基本能解决一大半。等到链路干净了、日志完整了再回头优化 Prompt你会发现自己不再靠猜每一步都看得见效果。