在AI技术社区里泡久了你会发现凡是自己动手做过Agent项目的开发者多少都能给你讲几个“经典事故”。我自己的经历从最早的提示词包装开始到后来一步步接入工具调用、多轮规划、甚至多Agent协作踩过的坑加起来能写满一张表。今天这篇不聊框架选型也不吹哪个模型更强就实打实地把Agent开发中最常遇到的经典问题总结一遍讲清楚问题长什么样、根子出在哪里、我在实际项目里是怎么解决的。这篇内容适合两类人。一类是正准备从普通大模型接口调用转向Agent开发的开发者想提前绕开别人已经踩烂的坑另一类是已经写了几天Agent代码、总觉得结果“时好时坏不太可控”的工程师需要一份系统性的排查清单。全文以我自己的实操经历为主线尽量少讲虚的多讲能落地的东西。1. 先把Agent的核心问题归归类Agent和普通模型接口调用最大的区别在于它把模型从“单次问答工具”变成了“能自主执行任务的工作流引擎”。这个转变带来一个本质变化不确定性从单点扩散到了整条链路。普通调用的错误顶多是输出内容不对Agent的错误却往往是一连串错误叠加后的连锁反应而且每个环节的错误还会被后面的步骤放大。我在经历了好几个项目的毒打之后习惯把Agent的问题归成六类指令跟随、上下文与记忆、工具调用、多步规划、幻觉、调试可观测性。这六类问题几乎覆盖了我线上遇到的90%以上的故障场景。它们之间不是完全孤立的比如工具调用出错往往源于指令约束不到位多步规划跑偏又常常是因为上下文管理失效。但分开看更容易对症下药排查的时候也更有条理。需要说明的是这六类问题不会因为模型升级而自动消失。模型能力在提升新的问题也在不断冒出来但底层规律是相对稳定的。你理解了这些规律之后无论以后换什么模型、用什么开发框架都会知道问题大概出在哪个环节不至于面对一个异常结果完全无从下手。2. 六大经典问题拆解与根治思路2.1 指令不听话Prompt链路上的第一个坑所谓指令不听话就是模型不按你的要求执行。典型表现包括要求输出JSON却给你一段散文要求只调用查询工具却自作主张调用了写入接口要求分三步处理结果却一步全做完。这种问题在Agent场景里格外致命因为Agent的下一步行动往往依赖上一步的解析结果输出格式一乱整个链路就直接断掉了。我遇到过一个非常典型的案例。当时做一个信息收集Agent要求模型最后输出一个结构化表格我自认为Prompt写得够清楚了还专门给了JSON示例。结果模型在真实运行时偶尔会往JSON里塞一段解释性文字导致解析器直接抛异常。最诡异的是这类问题不是必现的同样的输入上一轮正常下一轮就翻车。这种不确定性是最让人头疼的地方。根因要从两个层面看。第一是Prompt本身的设计问题比如指令表述模糊、正反例不足、系统提示和用户输入之间有潜在冲突。第二是模型本身的概率特性同样的Prompt每次推理在词元分布上都有细微差别温度参数设得越高输出漂移的概率就越大。我的解决思路是三层保险。第一层在Prompt层面把约束写死用“必须”“禁止”“只能”这类强约束词并且给一到两个完整的输入输出示例少用抽象描述。比如你要JSON就直接给出JSON结构定义和一段合法的示例输出不要写“请以合适的格式返回”这种模棱两可的话。第二层在解析层面做容错不依赖模型的“自觉”解析器要能处理常见变体比如允许JSON前后有额外文本时自动剥离、容忍部分字段缺失时给默认值。第三层在运行层面做矫正解析失败就自动让模型基于报错信息重新生成一次。这个“犯错后纠正”的重试机制能救回很大一部分偶发故障。2.2 记忆和上下文永远在丢与塞之间摇摆上下文窗口再大也装不下无限的历史这是Agent开发里最现实的一条约束。经典问题有两个方向一是token量不够用多轮对话加上工具返回结果几轮下来窗口就满了二是信息被粗暴丢掉之后Agent开始“失忆”对用户前面说过的话毫无反应。我做一个客服类Agent的时候这个问题体现得特别明显。用户和Agent来回聊了十几轮前面已经确认过收货地址后面Agent又一本正经地问“请问您的收货地址是”。用户当场就炸了体验极差。问题不在模型而在于我把早期轮次的细节压缩掉了压缩逻辑又没有做到关键信息无损。这里要分清两种记忆需求。一种是短期工作记忆就是当前任务执行过程中必须保留的上下文比如用户刚提供的订单号、正在处理的问题类型。另一种是长期记忆比如用户的历史偏好、之前处理过的事件记录。两者的管理策略完全不同。短期记忆适合用滑动窗口加关键信息抽取长期记忆适合用外部存储加检索召回。我目前验证过比较稳的方案是“三层记忆”。第一层是原始对话窗口只保留最近N轮原文保证短期内的完整对话语境。第二层是结构化摘要每隔几轮用模型把关键上下文压缩成一个简短摘要固定塞进系统提示里。第三层是外部记忆存储把用户身份、订单状态这类强结构化信息落到独立的存储里需要时精准读取而不是靠模型自己回忆。这套组合下来既控制住了token消耗又保住了关键信息。实现的时候要注意摘要把关摘要生成这一步本身也可能丢细节所以关键字段要单独抽取出来存结构化副本。2.3 工具调用模型自作主张就是不听安排工具调用是Agent区别于普通对话的核心能力也是最容易翻车的环节。经典症状包括该调工具的时候不调不该调的时候乱调参数填错把字符串塞进数字字段同一个意图连续调用好几个不必要的工具白白浪费时间和成本。我印象很深的一次事故是一个数据分析Agent用户问“上个月销售额是多少”模型没有调用查询工具而是直接基于自己编造的数字给出了答案。那个数字和真实数据差了整整一个数量级。这类“跳过工具直接编造”的问题比参数填错更可怕因为结果看起来特别自然不校验根本发现不了。工具调用不稳定的原因有几层。一是模型对工具的理解依赖工具描述的自然语言质量描述写得含糊模型就容易误判适用场景。二是参数定义不严谨类型、取值范围、枚举值没有约束清楚给了模型自由发挥的空间。三是工具数量一多模型的选择难度呈指数级上升十几个工具摆在面前选错的概率会明显增加。针对这些问题我的做法是给每个工具写“使用说明书式”的描述什么场景用、什么场景坚决不能用、每个参数的含义和取值范围全部写清楚。写完之后还要做一轮“模拟对抗测试”故意拿边缘case去试看模型会不会误调用、会不会漏调用。另一个关键点是启用工具选择约束机制把关键步骤的调用锁定为必须执行不给模型跳过或自由发挥的余地。还有一点容易被忽略工具返回的结果要强制格式化让模型把原始返回先做摘要再交给下一步决策能显著降低无关信息对后续判断的干扰。2.4 多步规划计划完不成还容易原地打转多步Agent最怕的不是任务本身难而是Agent自己规划出来的路线走到一半发现走不通然后陷入无限重试或循环。我见过一个Agent在某个步骤解析失败后一直重复同一个调用每一轮都报同样的错接着又发起同样的调用白白烧掉了几十万token最后是我手动杀掉进程才停下来的。这种死循环的根因是Agent缺少全局视角和退出机制。每一步模型只能看到当前窗口里的局部信息一旦当前动作失败模型没有能力对比“我已经尝试了几次”“我是否应该换一种方案”于是只能在原地重复。我后来给所有多步Agent都加了三样东西。第一是最大重试次数限制任何单一步骤失败重试超过两次就直接进入降级流程比如放弃该步骤并报告失败原因而不是继续硬试。第二是思路切换提示当检测到连续两次相同动作时在下一轮提示词里显式告诉模型“你已经尝试过这个方法两次结果相同请选择完全不同的方案”。第三是任务分解前置不在运行时让模型自由发挥规划而是先用一次独立的规划步骤把大任务拆成子任务清单执行阶段就围绕这个清单逐项推进。加了这三样之后循环类故障率下降非常明显。说到规划还要提一个反直觉的经验任务越复杂越不应该让Agent自由探索。自由探索适合探索性任务但生产环境里的Agent绝大多数任务都适合“确定性优先、灵活性补充”的模式。先固定主干流程再允许模型在分支环节里发挥可控性会好很多。特别是涉及真实数据操作的任务比如改配置、发消息、记状态主干流程的每一步都应该有明确的校验点。2.5 幻觉说得越流畅错得越离谱幻觉在Agent里不只是“信息不准确”更危险的是“过程性幻觉”——模型编造出根本不存在的工具返回值、编造中间计算步骤、甚至编造一次看似合理的执行结果。因为Agent的决策链条建立在模型自己生成的中间结果上一步幻觉就可能污染后续所有决策。有个财务分析Agent的案例教训特别深刻。模型在回答里引用了一组数据看起来有理有据还带表格、带小数点后两位实际上那组数据在原始数据源里根本不存在。我后来逐条核对了它的推理链才发现它在一个中间步骤里把某个数“推算”了出来后面所有计算都基于这个编造的数字最后得出来的结论自然错得离谱。对付幻觉我有一套“防编造护栏”。第一凡是涉及真实数据的回答必须让模型引用数据源标识没有引用标识的回答直接判定不合格。第二关键数字在返回前用代码层面的规则校验比如和原始数据源做数值比对不一致就触发重新生成。第三在Prompt里显式声明“禁止编造工具调用结果如果未获得返回数据请如实说明”。别小看这句话模型在没有明确禁令的时候默认倾向就是补全信息给它一句硬约束能挡掉相当一部分编造行为。第四有条件的话引入外部检索让模型先检索后回答而不是凭参数知识硬答。检索加引用这套组合虽然不能做到百分百消除幻觉但能把风险压到可以接受的范围。2.6 调试黑洞出了问题根本不知道发生在哪一步Agent是天然的黑盒系统。一次任务可能经历模型推理、工具调用、结果解析、再次推理等多个环节任何一个环节出错都可能导致最终结果不对但日志里往往只有一个“最终回答异常”的模糊记录你根本不知道问题出在哪里。我调试一个Agent的时候经常陷入这种困境用户报障说回答不对我把完整对话翻一遍看不出是哪一步出了问题。因为没有分步日志没有中间状态记录模型每一步到底看到了什么语境、输出了什么内容、工具实际返回了什么全部没有留存。这种情况下排查全凭猜效率极低。后来我把可观测性当成了和功能开发同等重要的事情来对待。核心做三件事第一完整记录每一步的事件日志包括模型输入输出、工具调用参数、工具返回结果、token消耗、耗时全部落库。第二给每一次会话生成唯一的追踪标识从用户提问到最终回答全链路串起来出问题的时候可以随时回放每一步当时发生了什么。第三记录中间状态快照尤其是每轮生成的摘要、临时决策这类影响后续流程的关键状态单独存一份。做完这些之后线上再出问题我基本可以在几分钟内定位到具体环节排查效率提升了一个量级。3. 实操方案可以直接抄的配置思路3.1 用结构化输出把不确定性按住结构化输出是控制Agent输出质量最有效的手段之一。我的做法是所有关键输出都绑定固定的输出结构定义要求模型返回严格符合定义的JSON并且在解析层做双重校验。这里有个容易踩坑的细节光在Prompt里贴结构定义不够因为模型偶尔还是会给无效JSON。要启用模型接口自带的强制结构化能力这类能力通常能把无效输出的概率压到极低。即使如此我还是会在解析层保留兜底逻辑。推荐的做法是解析失败时把解析错误信息拼进Prompt让模型“基于这个错误修正你的输出”并重试一次。实测下来这种“报错后纠正”的重试策略比单纯重试的成功率高很多因为模型明确知道了自己错在哪里。3.2 记忆方案选型参考记忆方案没有银弹我在实际项目中根据业务特点做选择。如果是单轮问答为主的场景滑动窗口就够用不需要过度设计。如果是多轮对话且需要长期用户画像的场景必须引入外部存储加检索。如果是复杂任务执行型场景建议用分层记忆就是前面说的原始窗口、结构化摘要、外部存储三层组合。选型时还要考虑一个隐性成本记忆检索本身的延迟和token消耗。我见过有人给每个用户请求都做向量检索结果延迟增加了几百毫秒成本也翻了一倍收益却微乎其微。合理做法是给记忆检索加触发条件比如检测到当前对话涉及历史偏好或用户身份信息时再检索而不是每次无脑召回。另外摘要更新的频率也要控制好频繁压缩反而会在摘要里累积误差。3.3 工具定义的写法要点工具定义写得好不好直接决定工具调用成功率。我的核心心得是描述要写“模型视角”而不是“开发者视角”。开发者知道这个工具是干什么的模型不知道所以描述里必须包含适用场景、禁用场景、参数的实际语义。举个例子。一个查询订单状态的工具开发者的第一反应是写“获取订单状态”但靠这条描述模型很容易在用户问物流进度时误用。更好的写法是“仅当用户询问已下单订单的状态、进度、物流信息时使用。不要用于查询商品信息或售后服务。参数order_id为用户下单后得到的唯一订单编号格式为18位数字。”这种写法看起来啰嗦但实测能把误调用的概率降低一大半。工具数量超过十个后建议按领域分组成命名空间进一步降低模型的选择难度。4. 高频故障排查速查表把这一年多遇到的高频故障整理成表格排查的时候可以直接对照。故障现象可能的根因排查思路解决方案输出JSON经常解析失败Prompt约束不足或温度过高查看原始输出判断是格式问题还是内容问题启用强制结构化输出解析层做容错和重试Agent忘记用户早期说过的话上下文压缩丢失关键信息检查摘要生成逻辑确认关键字段是否保留关键信息抽取到结构化存储需要时精准读取该调工具时不调工具描述不明确或工具选择未锁定查看模型决策日志确认模型对工具的理解重写工具描述增加适用和禁用场景说明死循环重复调用同一个工具缺少失败退出机制查看追踪日志里的连续动作序列加重试上限、思路切换提示、降级流程回答里的数据是编造的模型幻觉且无引用校验核对推理链和引用标识强制引用溯源、关键数据代码校验、检索增强同样输入结果时好时坏模型概率特性或上下文差异对比正常轮和异常轮的上下文差异降低温度、增加输出校验、重试纠错多轮后token消耗暴涨上下文无限累积分析每轮token构成滑动窗口加摘要压缩控制上下文规模调用了多余的不必要工具工具选择逻辑过于宽松检查是否启用了工具选择约束锁定关键步骤必须调用的工具放宽非关键步骤计划走到一半推不动子任务依赖关系未理清查看规划阶段的输出完整性任务分解前置明确子任务顺序和依赖线上故障无法定位缺少分步日志和追踪标识检查事件日志是否完整落库完善可观测性记录中间状态快照这张表是我日常排查的起点但不是终点。每个项目的Agent链路都有自己的特殊故障模式建议你维护一份属于自己项目的排查文档每踩一个新坑就补一条慢慢就会变成团队里最有价值的资料。5. 项目落地后的几点个人体会文章最后说几句实在话。Agent开发最大的错觉是以为把Prompt写漂亮了就能得到稳定的Agent。实际上Prompt只是整个系统里的一环结构化输出、记忆管理、工具约束、失败重试、可观测性每一环都是决定Agent能不能真正上线的重要因素。我在做第一个Agent项目时也是天真的“Prompt迷信者”被现实教育过几次之后才开始老老实实搭全套方案。另一个体会是别指望一次上线就完美Agent产品天生是迭代型的。上线前用边界case做一轮覆盖测试上线后保持对错误日志的持续关注把每一次线上故障都当成优化Prompt和流程的机会。随着项目越跑越久Agent会从“时好时坏”慢慢变成“稳得一批”这个过程靠的就是一轮轮真实故障的打磨而不是一次性的完美设计。最后分享一个小技巧给Agent加一个“认错”机制。在系统提示里明确告诉模型如果发现自己拿不到需要的数据、或者某个步骤执行失败直接向用户说明“这个问题暂时无法完成”而不是强行生成一个看似合理的答案。这个机制对我来说是所有护栏里最简单、也最管用的一个它不能提升Agent的上限但能守住体验的下限值得每个项目都加上。