做 Agent 的朋友多半都经历过这种循环:任务一复杂,Prompt 就忍不住往长了写,各种角色设定、背景知识、输出格式、边界约束全塞进去,结果 token 账单一路飙升,响应也越来越慢。于是开始压缩 Prompt,删掉“冗余”描述,缩写指令,把长句改短句,好不容易把 token 省下来了,Agent 却开始频繁犯错——漏了关键词、忽略约束条件、甚至自作主张改变输出格式。再往后就是无穷无尽的调试,改一句加一句,Prompt 又不知不觉涨回去了。这不是个别现象,而是 Agent 开发里最常见的资源错配。我在好几个真实项目里都踩过这个坑,结论很一致:让 Agent 少踩坑,比压缩 Prompt 更省钱。这里的“省钱”不只是省 token 费,还包括省调试时间、省人工介入成本、省重试带来的模型调用开销。一味压缩 Prompt 是在省小钱、花大钱,真正的成本优化应该放在降低失败率上。1. 为什么“压缩 Prompt”常常是错误的方向1.1 Token 成本只是冰山上的一角先算一笔最直观的账。假设一个 Agent 的单轮调用中,系统 Prompt 占了 2000 个 token,用户输入占 500 个 token,模型输出占 800 个 token。用某主流模型按输入 20 美元/百万 token、输出 80 美元/百万 token 计费,一次调用的成本大概是:输入成本:(2000 + 500) / 1,000,000 × 20 = 0.05 美元输出成本:800 / 1,000,000 × 80 = 0.064 美元单次成本约 0.114 美元如果把 Prompt 从 2000 token 压缩到 1000 token,单次调用成本变成 (1000 + 500) / 1,000,000 × 20 + 0.064 = 0.094 美元。看起来每次省了 0.02 美元,约 18%。问题在于,这个计算只考虑了正常路径。Agent 实际运行时的开销大头从来不是单次成功的调用,而是失败后的重试、纠偏、人工介入,以及为了排查问题花掉的工程师时间。Prompt 压缩带来的精度下降,会直接推高这些隐形成本。我在一个智能客服 Agents 项目里做过一次对照测试。原始 Prompt 大约 2800 token,经过两轮压缩后变成 1100 token,token 成本确实降了约 35%,意图识别准确率却从 94% 掉到了 87%。遇到识别错误的对话,用户通常要重复表达两三次,客服人工介入率直接从 5% 跳到 14%。算下来综合成本反而涨了 20% 以上,还不算用户体验的损失。Prompt 压缩的真正风险在于:它破坏了系统容错能力。长 Prompt 里有相当一部分内容不是在“讲故事”,而是在给模型设定清晰的边界和兜底策略,这些一旦被压缩掉,模型就更倾向于自由发挥。自由发挥在单个任务上可能看不出大问题,但在真实业务里就是故障源。1.2 压缩动作本身也有隐性成本很多人忽略了一个事实:Prompt 压缩不是一劳永逸的,它往往伴随着长时间的调试回归。在压缩 Prompt 之后,你必须重新验证所有历史功能是否正常。原本测试好的流程,因为措辞变化可能导致模型输出风格改变、JSON 格式丢失、工具调用参数出错。我在一个文档自动化项目里就吃过这个亏——只是把“请以 JSON 格式输出”改成了“输出 JSON”,模型就开始偶尔把 JSON 直接包在 markdown 代码块里,下游解析器直接报错。排查了一下午,最后加了个预处理函数才解决。这种回归测试的时间成本,往往比省下的 token 费用高出一个数量级。按一个工程师时薪折算,一次两小时的回归测试就是几百元的成本,而 Prompt 压缩省下来的 token 费用在低并发场景下可能一个月也就省个几十元。这个账怎么算都不划算。所以我的基本判断是:当你的 Agent 频繁出错时,优先关注的不是 Prompt 长短,而是系统架构是否给了 Agent 足够的容错空间。真正有效的成本优化,应该从“降低失败率”和“降低每次调用的冗余度”两个方向同时下手。2. Agent 踩坑的真实成本模型2.1 一次重试的代价远高于想象要理解“少踩坑比压缩 Prompt 更省钱”,得先建立一个准确的成本模型。Agent 任务失败后的重试流程通常是这样的:模型第一次输出结果或工具调用失败Agent 系统判断需要重试,将错误信息和前一轮的完整对话重新发送给模型模型基于新的错误信息重新规划,可能重新调用部分工具如果第二次仍然失败,可能触发降级策略或人工介入我实测过一组数据:一个正常的检索型 Agent 任务,单次成功率在 90% 时的平均 token 消耗是 1800 token。如果失败一次再重试成功,总消耗会跳到 3600 token 左右,因为重试时要发送上一轮的完整上下文、工具返回的错误信息,再加上新一轮的推理和输出。如果失败两次,消耗直接超过 5400 token。也就是说,一次额外重试的成本,等于多跑 2-3 次正常任务。当一个 Agent 的失败率从 5% 降到 2%,节省的成本不是 3% 的调用量,而是系统整体 token 消耗中至少 6%-10% 的重试冗余。让我用一个简化的公式表达:系统总成本 ≈ 正常路径成本 + 失败重试成本 + 人工介入成本 + 回归调试成本其中失败重试成本占总成本的比例,往往和失败率呈非线性关系。失败率越高,每一次额外的失败带来的重试成本越被放大,因为重试本身也可能失败,形成递归式消耗。2.2 各类成本的对比与拆解我把 Agent 系统的常见成本拆成了四类,做了一个对比:成本类型主要来源量级特征可控手段Token 调用费输入、输出、上下文累积线性增长,容易预估上下文裁剪、减少无效轮次失败重试费任务失败后的多次重建非线性,随失败率上升工具设计、结构化约束、兜底策略人工介入成本客服接管、人工修正输出单次极高提高首次成功率、降级路径调试回归成本排查问题、改 Prompt、重新验证工程师时间,容易被忽略日志观测、可复现实验这里最值得关注的是“失败重试费”和“人工介入成本”这两列。它们都不是直接体现在模型账单里的,但对总成本的影响最大。我做过的项目里,某个月 Agent 账单账单显示 token 消耗约 400 美元,但排查日志后发现其中约 120 美元来自重试消耗,占比接近三分之一。这还是在业务量不算大的情况下。所以,如果你的 Agent 系统 token 成本高,第一反应不应该是在 Prompt 上做减法,而是先去看失败日志。失败率高,才是真正的“成本漏斗”。3. 让 Agent 少踩坑的五个关键实践3.1 用“窄接口”替代“万能接口”Agent 调用工具的方式,决定了它犯错的概率。很多团队设计工具时喜欢做一个“万能接口”——比如一个 ExecuteRequest 函数,参数里挂一个 action 字符串,让模型自己决定执行什么操作。这种设计的最大问题是自由度过高。模型对 action 的理解不一定符合你的业务预期,它可能把 search 写成了 select,把 query 写成了 scan。这种低级错误在 Prompt 里写多少遍“请谨慎选择 action”都难以根治,因为问题不出在理解上,而出在接口设计本身给了模型太多犯错空间。推荐的替代方案是把每个动作拆成独立函数,函数名就是动作名,入参尽量单一和明确。比如某项目里,把“按关键词搜索资料”和“按分类筛选资料”拆成两个不同的工具,而不是在同一个工具里靠参数区分。这样模型选择工具时就是在做选择题,而不是做填空题,错误率大幅度下降。我在设计工具时还加了一层“入参预校验”。如果模型调用工具的入参类型不对、缺少必要字段,系统不是直接返回错误让模型重试,而是自动补齐缺失字段、修正类型,并给模型返回一条“修正提示”。看起来只是多了一步,实际上把重试率降了一半。3.2 用结构化约束代替“请输出规范格式”让模型自由输出再靠下游解析容错,是另一大踩坑来源。最典型的例子是:让模型输出 JSON,模型却在开头加了一句“为你找到以下结果”,导致JSON.parse直接报错。我见过补救方案是写一个非常复杂的解析函数,去处理各种格式污染。但这是在治标。真正有效的做法是在 Prompt 之外,用结构化的方式约束输出,并且在上层做运行时校验。目前比较可靠的方式是用 JSON Schema 加功能调用式输出。把输出定义成结构化对象,每个字段指定类型和取值范围,模型生成前就确认了这个 schema。很多模型的原生能力已经能很好地支持这种输出模式,不需要额外用 Prompt 去描述输出格式。我之前做的一个日程规划 Agent 里,输出 schema 大概长的这样:{ "type": "object", "properties": { "tasks": { "type": "array", "items": { "type": "object", "properties": { "title": { "type": "string" }, "start_time": { "type": "string", "format": "date-time" }, "duration_minutes": { "type": "integer", "minimum": 5 } }, "required": ["title", "start_time", "duration_minutes"] } }, "reminders": { "type": "array", "items": { "type": "string" } } }, "required": ["tasks"] }加上运行时校验之后,凡是 schema 不匹配的输出都会被自动拒绝并触发一次修正重试。听起来会增加重试,但实际上因为模型已经知道输出必须匹配 schema,首次合规率非常高,整体重试次数反而下降。3.3 把“记忆”显式化,不要全塞进上下文Agent 和模型的本质区别在于有状态和记忆,但实现记忆的方式往往非常粗暴——把所有历史对话、工具返回、中间结果全部塞进上下文。这种做法有两个问题:一是 token 消耗呈现线性增长,随着对话轮次变多,上下文变得臃肿;二是模型会被冗余信息干扰,想象一下你让一个助手记住昨天的任务,却把三个月前的不相关聊天记录也一起发过去,它分心是必然的。我实践下来的经验是,显式维护一个“记忆存储”,只保留对当前任务有作用的信息,并在每次调用前把记忆压缩成摘要。具体做法有几种:按会话维度维护一个结构化的记忆对象,包含用户意图、关键事实、当前状态在每次任务完成后,把历史对话总结成一段话存入记忆,而不是保留原始日志调用工具时,把上一轮工具返回的关键结果抽取成结构化字段,避免原文重新进入上下文这样做的直接效果是,当对话轮次从 5 轮延伸到 20 轮时,输入 token 从 5000 涨到 6000 左右,而不是涨到 15000 以上。上下文压缩不是靠减少 Prompt 内容,而是靠重建上下文结构,这个思路比语义压缩更可扩展。3.4 给每个关键步骤准备降级路径Agent 踩坑最致命的场景不是出错,而是出错后没有下一步动作。用户问了个问题,Agent 调用工具失败,系统返回空白,用户只能干瞪眼。对用户来说,这次交互就是失败。对系统来说,这次调用就是纯浪费。我在系统设计里增加了一个强制要求:每个关键工具调用步骤都必须配置一个降级路径。比如:检索工具失败时,从本地缓存里返回历史结果,并提示“内容可能不是最新”模型生成结果超时后,使用上一轮成功结果或预设模板回复,不让对话中断工具入参校验不通过时,给模型返回一组候选参数,引导二次选择而不是直接重试降级路径的存在让 Agent 即使踩坑,也能够优雅地绕过去,而不是原地打转。这部分逻辑的代码量通常不大,但对用户体验的整体提升非常明显。某项目里加了降级路径后,用户反馈“对话中断”的数量直接降到了零。3.5 观测优先:让每一次失败可复现最后这个是工程习惯问题,但恰恰是被忽略最多的。很多团队调试 Agent 时靠改 Prompt 碰运气,来回改,来回试,完全凭感觉。正确的方式是提前设计好观测系统。我自己的习惯是每一轮 Agent 调用都会输出一个结构化的日志,包含:输入的原始请求和经过处理后的实际请求模型当时的完整输出(包括中间思考痕迹,如果可获取)工具调用的入参、返回值、状态码上下文里实际包含了哪些信息,各占多少 token最终输出和用户反馈有了完整的日志,排查问题时不需要瞎猜,直接搜索失败样本就能定位是哪一步出了错。在一次事件排查中,我靠日志发现某次失败是由于缓存中的旧数据格式和新工具不兼容导致的,而这个问题在只靠 Prompt 调试时完全发现不了。观测系统的另一个好处是能做回归验证。每次修改工具或结构时,跑一遍相同的测试集,对比前后的成功率和 token 消耗,随时发现劣化点。这个习惯成本不高,但长期受益巨大。4. 一次真实项目里的对比测试4.1 三个阶段的测试设计为了验证“让 Agent 少踩坑比压缩 Prompt 更省钱”这个判断,我在一个模拟项目里做了系统的对比测试。项目背景是做一个跨平台的智能日程与资料助手,功能包括日程创建、冲突检查、资料检索。测试分三个阶段:阶段 A(基线版):Prompt 较长,包含大量角色设定、步骤说明、输出格式样例,工具设计采用大而全的万能接口,上下文全部保留。阶段 B(压缩版):在阶段 A 基础上压缩 Prompt,保留核心指令,删减场景描述和格式样例,工具和上下文设计不变。阶段 C(架构优化版):保持 Prompt 中等长度,但采用窄接口工具、结构化输出约束、显式记忆管理和降级路径。每个阶段跑同样的 200 个测试任务,统计 token 消耗、任务成功率、人工介入率、重试次数这四个指标。4.2 数据对比与结论指标阶段 A(长 Prompt)阶段 B(压缩 Prompt)阶段 C(架构优化)平均每次任务 token 消耗460032002900任务首次成功率88%78%95%重试占比12%22%5%人工介入率6%15%2%总 token 消耗(200 任务)约 920K约 810K约 610K数据里的信息量很大。从“压缩 Prompt”这个方向看,阶段 B 确实降低了单任务的平均 token(从 4600 降到 3200),但首次成功率反而下降到了 78%。这意味着更多任务要走重试路径,最终 200 个任务的总 token 消耗只比阶段 A 少了约 12%,远没有单次节省看起来那么可观。更麻烦的是,人工介入率从 6% 翻倍到了 15%,这部分成本没有体现在 token 账单里,但实际消耗了很多人力。阶段 C 的架构优化版,单次消耗反而进一步降到了 2900,比压缩版还低。关键原因在于重试占比大幅下降,上下文也被结构性裁剪了。首次成功率 95%,绝大多数任务一次搞定,总 token 消耗约 610K,比阶段 A 节省了约 33%,比阶段 B 节省了约 25%。这个结果再次验证了那个判断:token 消耗的浪费主要来自重试和上下文冗余,而不是 Prompt 本身的长度。4.3 额外观察:压缩 Prompt 后调试成本也更高测试过程中还有一个很实际的感受:阶段 B 的调试时间远高于另外两个阶段。因为压缩后的 Prompt 行为不稳定,同一个测试用例在不同轮次可能表现不一致。有时候同一段 Prompt 第一次输出正确,第二次就开始加多余的话。为了找出规律,不得不反复跑很多轮,每次都要人工确认输出是否符合预期。阶段 C 的表现则稳定得多。因为工具设计清晰、输出有 schema 约束、日志完整,出了问题可以直接定位到具体环节。一次结构化校验失败,看日志就知道是哪个字段不合法,改起来很快。这也说明了一个事情:压缩 Prompt 节省的是确定成本,消耗的是不确定性,而不确定性在工程上往往更昂贵。5. 常见问题与排查技巧实录5.1 Agent 反复调用同一个工具,陷入死循环现象:某 Agent 在检索资料时,反复调用同一个检索工具,每次结果不同,但都不满足需求,导致流程无法推进。排查思路:先看日志里工具返回的结果和模型的判断逻辑。我遇到过一种情况:工具返回了结果,但没有返回“结果质量评分”或“匹配度”信息,模型无法判断当前结果是否可接受,只能一次次重试。解决方案:给工具返回值增加置信度字段或空结果标记。当模型发现结果为空或质量不达标时,能够明确知道应该结束、请求用户补充条件,而不是原地打转。同时给循环调用设置最大次数限制,超过时触发降级路径,直接向用户说明情况。这个坑的教训是:工具不仅要返回“有什么”,还要返回“够不够好”。Agent 需要足够的信号来判断下一步动作,否则就会在同一个地方反复撞墙。5.2 压缩 Prompt 之后,意图识别开始错乱现象:某团队把系统 Prompt 从 2000 token 压到 800 token 后,Agent 频繁把“创建日程”理解成“查找日程”,功能入口选错。排查思路:对照压缩前后的 Prompt 差异,我发现被删掉的部分恰好包含了一些关键的语义区分词和“否定示例”。“否定示例”看起来像是冗余——它们不直接描述正确行为,但也在告诉模型哪些边缘情况不应归入此类。删掉之后,模型对边界情况的判断失去了参照。解决方案:把语义区分的关键词重新加回来,但用更精简的方式。比如在工具描述里直接把易混淆意图的差别写明。架构层面同时收紧意图识别的后处理逻辑,加入关键词匹配和置信度阈值,当模型输出的意图置信度偏低时,向用户确认而不是直接行动。我这里多说一句,压缩 Prompt 时最不该动的部分,就是“否定示例”和“边界条件”。这些内容在正常情况下用不到,但不是无用信息,它们是模型的纠偏锚点。5.3 上下文越塞越多,幻觉也开始变多现象:一个多轮对话项目里,随着对话长度增加,模型开始编造一些不存在的数据,把不同用户的资料混在一起输出。排查思路:这是典型的上下文污染。当历史对话超过一定长度,早期信息与当前任务无关却在持续影响生成结果。模型难以区分哪些上下文是“当前必须参考的”,哪些只是“历史残留”。解决方案:引入独立的记忆存储机制。把对话过程中的关键事实(用户偏好、已完成的操作、待办事项)提取出来,存成结构化数据。每次调用时只把与当前任务相关的记忆放进上下文,历史对话原文不再整体带入。这个改动之后,幻觉出现的次数明显减少,上下文 token 消耗也降下来了。5.4 判断优化效果的三个高频指标最后分享一个我在不同项目里反复使用的参照体系。判断一个 Agent 系统是否在“变好”,不要只盯单次 token,要看这三个指标:首次成功率:同样一批测试任务,不经过任何修正和重试就正确完成的比例。这个指标直接决定重试成本高度。重试占比:总调用次数中重试次数的比例。重试占比超过 20% 时,系统一定存在结构性问题,优先排查工具和输出约束。单位有效产出成本:用总 token 消耗除以有效完成的任务数。这个指标把上下文冗余和失败消耗都纳入了衡量范围,比单看平均 token 更准确。我个人实际使用中的体会是,把这三个指标放到每周的版本对比里,比任何 Prompt 优化套路都更有指导意义。很多团队把精力花在“让 Prompt 更精炼”上,却没有建立“失败成本”的度量,最终收入下降了看不出来,成本上升了也找不到根因。Agent 工程的成本优化是一个系统工程。与其反复压缩 Prompt 去省那十几个百分点的 token,不如花时间把工具边界、输出约束、状态管理和观测体系做扎实,让 Agent 每一步都走得稳。稳了之后你会发现,成本自然就降下来了,而且是那种不反弹的下降。
做 Agent 的朋友多半都经历过这种循环:任务一复杂,Prompt 就忍不住往长了写,各种角色设定、背景知识、输出格式、边界约束全塞进去,结果 token 账单一路飙升,响应也越来越慢。于是开始压缩 Prompt,删掉“冗余”描述,缩写指令,把长句改短句,好不容易把 token 省下来了,Agent 却开始频繁犯错——漏了关键词、忽略约束条件、甚至自作主张改变输出格式。再往后就是无穷无尽的调试,改一句加一句,Prompt 又不知不觉涨回去了。这不是个别现象,而是 Agent 开发里最常见的资源错配。我在好几个真实项目里都踩过这个坑,结论很一致:让 Agent 少踩坑,比压缩 Prompt 更省钱。这里的“省钱”不只是省 token 费,还包括省调试时间、省人工介入成本、省重试带来的模型调用开销。一味压缩 Prompt 是在省小钱、花大钱,真正的成本优化应该放在降低失败率上。1. 为什么“压缩 Prompt”常常是错误的方向1.1 Token 成本只是冰山上的一角先算一笔最直观的账。假设一个 Agent 的单轮调用中,系统 Prompt 占了 2000 个 token,用户输入占 500 个 token,模型输出占 800 个 token。用某主流模型按输入 20 美元/百万 token、输出 80 美元/百万 token 计费,一次调用的成本大概是:输入成本:(2000 + 500) / 1,000,000 × 20 = 0.05 美元输出成本:800 / 1,000,000 × 80 = 0.064 美元单次成本约 0.114 美元如果把 Prompt 从 2000 token 压缩到 1000 token,单次调用成本变成 (1000 + 500) / 1,000,000 × 20 + 0.064 = 0.094 美元。看起来每次省了 0.02 美元,约 18%。问题在于,这个计算只考虑了正常路径。Agent 实际运行时的开销大头从来不是单次成功的调用,而是失败后的重试、纠偏、人工介入,以及为了排查问题花掉的工程师时间。Prompt 压缩带来的精度下降,会直接推高这些隐形成本。我在一个智能客服 Agents 项目里做过一次对照测试。原始 Prompt 大约 2800 token,经过两轮压缩后变成 1100 token,token 成本确实降了约 35%,意图识别准确率却从 94% 掉到了 87%。遇到识别错误的对话,用户通常要重复表达两三次,客服人工介入率直接从 5% 跳到 14%。算下来综合成本反而涨了 20% 以上,还不算用户体验的损失。Prompt 压缩的真正风险在于:它破坏了系统容错能力。长 Prompt 里有相当一部分内容不是在“讲故事”,而是在给模型设定清晰的边界和兜底策略,这些一旦被压缩掉,模型就更倾向于自由发挥。自由发挥在单个任务上可能看不出大问题,但在真实业务里就是故障源。1.2 压缩动作本身也有隐性成本很多人忽略了一个事实:Prompt 压缩不是一劳永逸的,它往往伴随着长时间的调试回归。在压缩 Prompt 之后,你必须重新验证所有历史功能是否正常。原本测试好的流程,因为措辞变化可能导致模型输出风格改变、JSON 格式丢失、工具调用参数出错。我在一个文档自动化项目里就吃过这个亏——只是把“请以 JSON 格式输出”改成了“输出 JSON”,模型就开始偶尔把 JSON 直接包在 markdown 代码块里,下游解析器直接报错。排查了一下午,最后加了个预处理函数才解决。这种回归测试的时间成本,往往比省下的 token 费用高出一个数量级。按一个工程师时薪折算,一次两小时的回归测试就是几百元的成本,而 Prompt 压缩省下来的 token 费用在低并发场景下可能一个月也就省个几十元。这个账怎么算都不划算。所以我的基本判断是:当你的 Agent 频繁出错时,优先关注的不是 Prompt 长短,而是系统架构是否给了 Agent 足够的容错空间。真正有效的成本优化,应该从“降低失败率”和“降低每次调用的冗余度”两个方向同时下手。2. Agent 踩坑的真实成本模型2.1 一次重试的代价远高于想象要理解“少踩坑比压缩 Prompt 更省钱”,得先建立一个准确的成本模型。Agent 任务失败后的重试流程通常是这样的:模型第一次输出结果或工具调用失败Agent 系统判断需要重试,将错误信息和前一轮的完整对话重新发送给模型模型基于新的错误信息重新规划,可能重新调用部分工具如果第二次仍然失败,可能触发降级策略或人工介入我实测过一组数据:一个正常的检索型 Agent 任务,单次成功率在 90% 时的平均 token 消耗是 1800 token。如果失败一次再重试成功,总消耗会跳到 3600 token 左右,因为重试时要发送上一轮的完整上下文、工具返回的错误信息,再加上新一轮的推理和输出。如果失败两次,消耗直接超过 5400 token。也就是说,一次额外重试的成本,等于多跑 2-3 次正常任务。当一个 Agent 的失败率从 5% 降到 2%,节省的成本不是 3% 的调用量,而是系统整体 token 消耗中至少 6%-10% 的重试冗余。让我用一个简化的公式表达:系统总成本 ≈ 正常路径成本 + 失败重试成本 + 人工介入成本 + 回归调试成本其中失败重试成本占总成本的比例,往往和失败率呈非线性关系。失败率越高,每一次额外的失败带来的重试成本越被放大,因为重试本身也可能失败,形成递归式消耗。2.2 各类成本的对比与拆解我把 Agent 系统的常见成本拆成了四类,做了一个对比:成本类型主要来源量级特征可控手段Token 调用费输入、输出、上下文累积线性增长,容易预估上下文裁剪、减少无效轮次失败重试费任务失败后的多次重建非线性,随失败率上升工具设计、结构化约束、兜底策略人工介入成本客服接管、人工修正输出单次极高提高首次成功率、降级路径调试回归成本排查问题、改 Prompt、重新验证工程师时间,容易被忽略日志观测、可复现实验这里最值得关注的是“失败重试费”和“人工介入成本”这两列。它们都不是直接体现在模型账单里的,但对总成本的影响最大。我做过的项目里,某个月 Agent 账单账单显示 token 消耗约 400 美元,但排查日志后发现其中约 120 美元来自重试消耗,占比接近三分之一。这还是在业务量不算大的情况下。所以,如果你的 Agent 系统 token 成本高,第一反应不应该是在 Prompt 上做减法,而是先去看失败日志。失败率高,才是真正的“成本漏斗”。3. 让 Agent 少踩坑的五个关键实践3.1 用“窄接口”替代“万能接口”Agent 调用工具的方式,决定了它犯错的概率。很多团队设计工具时喜欢做一个“万能接口”——比如一个 ExecuteRequest 函数,参数里挂一个 action 字符串,让模型自己决定执行什么操作。这种设计的最大问题是自由度过高。模型对 action 的理解不一定符合你的业务预期,它可能把 search 写成了 select,把 query 写成了 scan。这种低级错误在 Prompt 里写多少遍“请谨慎选择 action”都难以根治,因为问题不出在理解上,而出在接口设计本身给了模型太多犯错空间。推荐的替代方案是把每个动作拆成独立函数,函数名就是动作名,入参尽量单一和明确。比如某项目里,把“按关键词搜索资料”和“按分类筛选资料”拆成两个不同的工具,而不是在同一个工具里靠参数区分。这样模型选择工具时就是在做选择题,而不是做填空题,错误率大幅度下降。我在设计工具时还加了一层“入参预校验”。如果模型调用工具的入参类型不对、缺少必要字段,系统不是直接返回错误让模型重试,而是自动补齐缺失字段、修正类型,并给模型返回一条“修正提示”。看起来只是多了一步,实际上把重试率降了一半。3.2 用结构化约束代替“请输出规范格式”让模型自由输出再靠下游解析容错,是另一大踩坑来源。最典型的例子是:让模型输出 JSON,模型却在开头加了一句“为你找到以下结果”,导致JSON.parse直接报错。我见过补救方案是写一个非常复杂的解析函数,去处理各种格式污染。但这是在治标。真正有效的做法是在 Prompt 之外,用结构化的方式约束输出,并且在上层做运行时校验。目前比较可靠的方式是用 JSON Schema 加功能调用式输出。把输出定义成结构化对象,每个字段指定类型和取值范围,模型生成前就确认了这个 schema。很多模型的原生能力已经能很好地支持这种输出模式,不需要额外用 Prompt 去描述输出格式。我之前做的一个日程规划 Agent 里,输出 schema 大概长的这样:{ "type": "object", "properties": { "tasks": { "type": "array", "items": { "type": "object", "properties": { "title": { "type": "string" }, "start_time": { "type": "string", "format": "date-time" }, "duration_minutes": { "type": "integer", "minimum": 5 } }, "required": ["title", "start_time", "duration_minutes"] } }, "reminders": { "type": "array", "items": { "type": "string" } } }, "required": ["tasks"] }加上运行时校验之后,凡是 schema 不匹配的输出都会被自动拒绝并触发一次修正重试。听起来会增加重试,但实际上因为模型已经知道输出必须匹配 schema,首次合规率非常高,整体重试次数反而下降。3.3 把“记忆”显式化,不要全塞进上下文Agent 和模型的本质区别在于有状态和记忆,但实现记忆的方式往往非常粗暴——把所有历史对话、工具返回、中间结果全部塞进上下文。这种做法有两个问题:一是 token 消耗呈现线性增长,随着对话轮次变多,上下文变得臃肿;二是模型会被冗余信息干扰,想象一下你让一个助手记住昨天的任务,却把三个月前的不相关聊天记录也一起发过去,它分心是必然的。我实践下来的经验是,显式维护一个“记忆存储”,只保留对当前任务有作用的信息,并在每次调用前把记忆压缩成摘要。具体做法有几种:按会话维度维护一个结构化的记忆对象,包含用户意图、关键事实、当前状态在每次任务完成后,把历史对话总结成一段话存入记忆,而不是保留原始日志调用工具时,把上一轮工具返回的关键结果抽取成结构化字段,避免原文重新进入上下文这样做的直接效果是,当对话轮次从 5 轮延伸到 20 轮时,输入 token 从 5000 涨到 6000 左右,而不是涨到 15000 以上。上下文压缩不是靠减少 Prompt 内容,而是靠重建上下文结构,这个思路比语义压缩更可扩展。3.4 给每个关键步骤准备降级路径Agent 踩坑最致命的场景不是出错,而是出错后没有下一步动作。用户问了个问题,Agent 调用工具失败,系统返回空白,用户只能干瞪眼。对用户来说,这次交互就是失败。对系统来说,这次调用就是纯浪费。我在系统设计里增加了一个强制要求:每个关键工具调用步骤都必须配置一个降级路径。比如:检索工具失败时,从本地缓存里返回历史结果,并提示“内容可能不是最新”模型生成结果超时后,使用上一轮成功结果或预设模板回复,不让对话中断工具入参校验不通过时,给模型返回一组候选参数,引导二次选择而不是直接重试降级路径的存在让 Agent 即使踩坑,也能够优雅地绕过去,而不是原地打转。这部分逻辑的代码量通常不大,但对用户体验的整体提升非常明显。某项目里加了降级路径后,用户反馈“对话中断”的数量直接降到了零。3.5 观测优先:让每一次失败可复现最后这个是工程习惯问题,但恰恰是被忽略最多的。很多团队调试 Agent 时靠改 Prompt 碰运气,来回改,来回试,完全凭感觉。正确的方式是提前设计好观测系统。我自己的习惯是每一轮 Agent 调用都会输出一个结构化的日志,包含:输入的原始请求和经过处理后的实际请求模型当时的完整输出(包括中间思考痕迹,如果可获取)工具调用的入参、返回值、状态码上下文里实际包含了哪些信息,各占多少 token最终输出和用户反馈有了完整的日志,排查问题时不需要瞎猜,直接搜索失败样本就能定位是哪一步出了错。在一次事件排查中,我靠日志发现某次失败是由于缓存中的旧数据格式和新工具不兼容导致的,而这个问题在只靠 Prompt 调试时完全发现不了。观测系统的另一个好处是能做回归验证。每次修改工具或结构时,跑一遍相同的测试集,对比前后的成功率和 token 消耗,随时发现劣化点。这个习惯成本不高,但长期受益巨大。4. 一次真实项目里的对比测试4.1 三个阶段的测试设计为了验证“让 Agent 少踩坑比压缩 Prompt 更省钱”这个判断,我在一个模拟项目里做了系统的对比测试。项目背景是做一个跨平台的智能日程与资料助手,功能包括日程创建、冲突检查、资料检索。测试分三个阶段:阶段 A(基线版):Prompt 较长,包含大量角色设定、步骤说明、输出格式样例,工具设计采用大而全的万能接口,上下文全部保留。阶段 B(压缩版):在阶段 A 基础上压缩 Prompt,保留核心指令,删减场景描述和格式样例,工具和上下文设计不变。阶段 C(架构优化版):保持 Prompt 中等长度,但采用窄接口工具、结构化输出约束、显式记忆管理和降级路径。每个阶段跑同样的 200 个测试任务,统计 token 消耗、任务成功率、人工介入率、重试次数这四个指标。4.2 数据对比与结论指标阶段 A(长 Prompt)阶段 B(压缩 Prompt)阶段 C(架构优化)平均每次任务 token 消耗460032002900任务首次成功率88%78%95%重试占比12%22%5%人工介入率6%15%2%总 token 消耗(200 任务)约 920K约 810K约 610K数据里的信息量很大。从“压缩 Prompt”这个方向看,阶段 B 确实降低了单任务的平均 token(从 4600 降到 3200),但首次成功率反而下降到了 78%。这意味着更多任务要走重试路径,最终 200 个任务的总 token 消耗只比阶段 A 少了约 12%,远没有单次节省看起来那么可观。更麻烦的是,人工介入率从 6% 翻倍到了 15%,这部分成本没有体现在 token 账单里,但实际消耗了很多人力。阶段 C 的架构优化版,单次消耗反而进一步降到了 2900,比压缩版还低。关键原因在于重试占比大幅下降,上下文也被结构性裁剪了。首次成功率 95%,绝大多数任务一次搞定,总 token 消耗约 610K,比阶段 A 节省了约 33%,比阶段 B 节省了约 25%。这个结果再次验证了那个判断:token 消耗的浪费主要来自重试和上下文冗余,而不是 Prompt 本身的长度。4.3 额外观察:压缩 Prompt 后调试成本也更高测试过程中还有一个很实际的感受:阶段 B 的调试时间远高于另外两个阶段。因为压缩后的 Prompt 行为不稳定,同一个测试用例在不同轮次可能表现不一致。有时候同一段 Prompt 第一次输出正确,第二次就开始加多余的话。为了找出规律,不得不反复跑很多轮,每次都要人工确认输出是否符合预期。阶段 C 的表现则稳定得多。因为工具设计清晰、输出有 schema 约束、日志完整,出了问题可以直接定位到具体环节。一次结构化校验失败,看日志就知道是哪个字段不合法,改起来很快。这也说明了一个事情:压缩 Prompt 节省的是确定成本,消耗的是不确定性,而不确定性在工程上往往更昂贵。5. 常见问题与排查技巧实录5.1 Agent 反复调用同一个工具,陷入死循环现象:某 Agent 在检索资料时,反复调用同一个检索工具,每次结果不同,但都不满足需求,导致流程无法推进。排查思路:先看日志里工具返回的结果和模型的判断逻辑。我遇到过一种情况:工具返回了结果,但没有返回“结果质量评分”或“匹配度”信息,模型无法判断当前结果是否可接受,只能一次次重试。解决方案:给工具返回值增加置信度字段或空结果标记。当模型发现结果为空或质量不达标时,能够明确知道应该结束、请求用户补充条件,而不是原地打转。同时给循环调用设置最大次数限制,超过时触发降级路径,直接向用户说明情况。这个坑的教训是:工具不仅要返回“有什么”,还要返回“够不够好”。Agent 需要足够的信号来判断下一步动作,否则就会在同一个地方反复撞墙。5.2 压缩 Prompt 之后,意图识别开始错乱现象:某团队把系统 Prompt 从 2000 token 压到 800 token 后,Agent 频繁把“创建日程”理解成“查找日程”,功能入口选错。排查思路:对照压缩前后的 Prompt 差异,我发现被删掉的部分恰好包含了一些关键的语义区分词和“否定示例”。“否定示例”看起来像是冗余——它们不直接描述正确行为,但也在告诉模型哪些边缘情况不应归入此类。删掉之后,模型对边界情况的判断失去了参照。解决方案:把语义区分的关键词重新加回来,但用更精简的方式。比如在工具描述里直接把易混淆意图的差别写明。架构层面同时收紧意图识别的后处理逻辑,加入关键词匹配和置信度阈值,当模型输出的意图置信度偏低时,向用户确认而不是直接行动。我这里多说一句,压缩 Prompt 时最不该动的部分,就是“否定示例”和“边界条件”。这些内容在正常情况下用不到,但不是无用信息,它们是模型的纠偏锚点。5.3 上下文越塞越多,幻觉也开始变多现象:一个多轮对话项目里,随着对话长度增加,模型开始编造一些不存在的数据,把不同用户的资料混在一起输出。排查思路:这是典型的上下文污染。当历史对话超过一定长度,早期信息与当前任务无关却在持续影响生成结果。模型难以区分哪些上下文是“当前必须参考的”,哪些只是“历史残留”。解决方案:引入独立的记忆存储机制。把对话过程中的关键事实(用户偏好、已完成的操作、待办事项)提取出来,存成结构化数据。每次调用时只把与当前任务相关的记忆放进上下文,历史对话原文不再整体带入。这个改动之后,幻觉出现的次数明显减少,上下文 token 消耗也降下来了。5.4 判断优化效果的三个高频指标最后分享一个我在不同项目里反复使用的参照体系。判断一个 Agent 系统是否在“变好”,不要只盯单次 token,要看这三个指标:首次成功率:同样一批测试任务,不经过任何修正和重试就正确完成的比例。这个指标直接决定重试成本高度。重试占比:总调用次数中重试次数的比例。重试占比超过 20% 时,系统一定存在结构性问题,优先排查工具和输出约束。单位有效产出成本:用总 token 消耗除以有效完成的任务数。这个指标把上下文冗余和失败消耗都纳入了衡量范围,比单看平均 token 更准确。我个人实际使用中的体会是,把这三个指标放到每周的版本对比里,比任何 Prompt 优化套路都更有指导意义。很多团队把精力花在“让 Prompt 更精炼”上,却没有建立“失败成本”的度量,最终收入下降了看不出来,成本上升了也找不到根因。Agent 工程的成本优化是一个系统工程。与其反复压缩 Prompt 去省那十几个百分点的 token,不如花时间把工具边界、输出约束、状态管理和观测体系做扎实,让 Agent 每一步都走得稳。稳了之后你会发现,成本自然就降下来了,而且是那种不反弹的下降。