带着症状来查,比从头读一遍快。下面按「现象 → 根因 → 修复 → 预防」组织,覆盖最常见的 16 类问题。
快速对照表
| 症状 | 最可能根因 | 先做什么 |
|---|---|---|
| 反复调用同一个工具 | 错误信息没用 / 无进展检测 | 看 trace,改错误语义 |
| 一直不结束 | 终止条件缺失 | 加步数/预算硬上限 |
| 编造事实 | 无检索 / 无引用要求 | 加接地与拒答 |
| 答非所问 | 上下文污染 / 提示含糊 | 看实际输入,裁剪上下文 |
| 工具选错 | 工具描述重叠 / 太多 | 合并工具,写清场景 |
| 参数填错 | Schema 含糊 / 缺示例 | 收紧枚举,加校验 |
| 成本暴涨 | 步数或上下文增长 | 按任务统计,设预算 |
| 延迟高 | 串行工具 / 大模型 / 重排 | 并行、路由、缓存 |
| 过度拒答 | 安全提示过强 | 分级、给正例 |
| 格式不稳定 | 只靠提示 | 严格 Schema + 校验 |
| 忘记目标 | 上下文压缩丢信息 | 状态显式化 |
| 越权操作 | 权限过宽 / 身份由模型填 | 服务端注入 + 最小权限 |
| 记忆串用户 | 检索无 scope 过滤 | 加 tenant/user 过滤 |
| 多 Agent 丢信息 | 交接无契约 | 结构化 handoff |
| 检索不到 | 切分/召回/过滤问题 | 看 Recall@k |
| 重复副作用 | 非幂等 | 幂等键 + 去重 |
1. 死循环 / 反复调用
症状:trace 里相同的工具、相同的参数连续出现,观察结果也一样。
根因:
- 没有最大步数或预算;
- 错误信息只说「失败」,模型不知道该怎么改;
- 工具返回空结果,但描述没说「空意味着什么」;
- 模型陷入「再查一次就齐了」的错觉。
修复:
- 加
max_steps、总超时、token 预算; - 对
(tool, args)做指纹,连续 2 次相同就注入提醒或终止; - 错误返回
code、message、retryable、suggestion; - 空结果明确写「未找到,建议换关键词或停止」。
预防:评估集加入「工具持续失败」的案例,验证 Agent 会停。
2. 幻觉 / 编造
症状:答案包含资料中没有的数字、日期、引用;引用链接打不开或与结论无关。
根因:
- 没有检索,或检索没命中;
- 提示没有要求引用;
- 模型被要求「必须回答」,没有「不知道」的出口;
- 上下文里混入了旧版本/错误资料。
修复:
- 要求每个事实附来源,输出后校验引用是否存在、是否支持结论;
- 允许
null/insufficient_info; - 检索结果带版本与生效日期;
- 关键数字用代码核对,不靠模型。
预防:专门构造「资料不足」测试集,统计拒答准确率。
3. 工具误用
症状:该查订单却查了文档;该用只读工具却调用了写工具;参数张冠李戴。
根因:
- 工具有重叠,描述没有区分场景;
- 工具太多,选择空间过大;
- 参数名相似(
order_idvsuser_id); - 模型不知道当前用户/租户,编造 ID。
修复:
- 合并重叠工具,名称用「动词 + 名词」;
- 描述写「何时不用」;
- 身份由服务端注入;
- 工具数量控制在 5–15 个,超出则分组/动态加载;
- 加工具选择测试,统计混淆矩阵。
4. 上下文溢出 / 质量下降
症状:长对话后开始忽略早期约束;工具结果很长时答非所问;成本随轮数平方增长。
根因:
- 所有历史原样保留;
- 检索结果未裁剪;
- 工具返回原始 JSON/HTML;
- 压缩策略丢失关键决策。
修复:
- 显式预算:系统、历史、检索、输出各设上限;
- 工具层裁剪,返回
summary+ 必要字段; - 历史摘要保留目标、事实、决策、失败、未决;
- 子 Agent 隔离长文档;
- 把稳定前缀放前面,提升缓存命中。
5. 成本失控
症状:账单远超预期;单任务 token 分布长尾严重。
根因:
- 按平均步数估算,忽略 P95;
- 每步都带完整历史和全部工具;
- 所有步骤用最贵模型;
- 没有预算上限;
- 重试没有计数。
修复:
- 按「每任务成本」统计,按租户/功能归因;
- 模型路由:分类/抽取用小模型;
- 提示缓存、工具结果裁剪、输出限制;
- 单任务硬预算,超限降级;
- 监控 P95 步数与 token。
6. 延迟高
症状:用户等 30 秒以上;P95 远高于平均。
根因:
- 工具串行;
- 每次调用都重新检索/重排;
- 大模型 + 长输出;
- 重试风暴;
- 同步跑长任务。
修复:
- 并行独立工具;
- 流式输出,先给反馈;
- 缓存检索/重排/前缀;
- 路由到更快模型;
- 超过 30 秒改异步 + 进度。
7. 过度拒答
症状:大量本可回答的问题被拒绝;用户觉得「不好用」。
根因:
- 安全提示过于保守;
- 没有正例,模型只学会「拒绝」;
- 检索没命中时直接拒答,而不是换查询;
- 分类器把正常请求判为高风险。
修复:
- 分级:哪些必须拒、哪些可答但需谨慎;
- 给正例与边界示例;
- 检索失败先改写/重试一次;
- 评估「正确回答率」与「误拒率」两个指标。
8. 格式不稳定
症状:JSON 多字段/少引号;枚举拼错;有时输出 Markdown 包裹。
根因:
- 只靠提示要求 JSON;
- Schema 太深/太复杂;
- 没有严格模式;
- 没有校验与修复。
修复:
- 使用严格结构化输出;
- 扁平 Schema、枚举、
additionalProperties: false; - 服务端校验 + 一次修复;
- 记录字段级失败率。
9. 忘记目标 / 跑偏
症状:做到一半开始做别的事;最终输出没有回答原问题。
根因:
- 目标只在第一条消息里,后续被淹没;
- 没有显式待办列表;
- 压缩时丢了目标;
- 工具结果把注意力带偏。
修复:
- 每轮上下文都带「目标 + 当前步骤 + 剩余待办」;
- 用状态机/计划约束;
- 关键节点后做「是否仍服务于目标」检查;
- 压缩摘要必须保留目标。
10. 过度修改 / 回归
症状:修一个 bug,弄坏三个功能;diff 巨大。
根因:
- 没有最小修改约束;
- 上下文不足,模型「猜」着改;
- 没有回归测试;
- 一次性重写。
修复:
- 要求最小 diff,限制变更行数;
- 先读相关测试与调用方;
- 每轮跑相关测试 + 最终全量;
- 保留回滚。
11. 越权 / 注入
症状:Agent 调用了不该调用的工具;访问了其他租户数据;把内容发到外部。
根因:
- 工具权限过宽;
- 身份由模型填;
- 外部内容被当成指令;
- 出站无白名单;
- 高危动作无审批。
修复:见〈安全〉:最小权限、服务端注入身份、出站白名单、沙箱、人工审批、审计。
12. 记忆污染 / 串数据
症状:Agent 记得别的用户偏好;用了过时信息;记忆越用越乱。
根因:
- 检索没有
user_id/tenant_id过滤; - 写入没有去重/冲突解决;
- 没有 TTL 与删除;
- 把原始对话直接灌入。
修复:
- scope 过滤必须在检索前;
- 原子事实 + key + 来源 + 时间;
- 冲突时保留新值并记录;
- TTL、容量上限、用户删除;
- 定期抽检记忆质量。
13. 多 Agent 交接丢信息
症状:下游重复上游做过的事;最终报告缺少关键事实;错误被放大。
根因:
- 只传自然语言摘要;
- 没有「已完成/未决/约束」;
- 共享状态过大或没有;
- 没有独立 trace。
修复:
- 结构化 handoff:目标、已完成、发现(带来源)、未决、约束;
- 共享事实表,原始材料放外部;
- 每个子 Agent 独立 trace;
- 限制协调轮数。
14. 检索失败
症状:明明有资料却答「没有」;引用不相关;多文档问题只答一半。
根因:
- 切分切断语义;
- 只做向量,缺关键词;
- 过滤过严;
- top-k 太小或太大;
- 没有重排。
修复:
- 按标题/句子切分,保留元数据;
- 混合检索 + RRF;
- 先看 Recall@k,再调生成;
- 重排后取 4–8 条;
- 多文档问题保证来源多样性。
15. 限流 / 429
症状:高峰期大量失败;重试后更糟。
根因:
- 没有客户端限流;
- 重试没有退避/抖动;
- 单租户占用全部配额;
- 并发估算错误。
修复:
- 令牌桶限流;
- 指数退避 + 抖动;
- 租户级配额与隔离;
- 队列削峰;
- 监控 429 率与排队时间。
16. 状态损坏 / 恢复失败
症状:恢复后重复执行副作用;状态字段缺失;旧检查点无法加载。
根因:
- 状态存在内存;
- 写操作非幂等;
- Schema 变更无迁移;
- 检查点与副作用不一致。
修复:
- 状态外部化、可序列化;
- 幂等键 + 对账;
- Schema 版本与迁移;
- 「意图—执行—确认」两阶段记录;
- 恢复演练。
排查顺序
遇到问题,按这个顺序看:
- Trace:哪一步开始错?
- 输入:模型当时看到了什么?检索对吗?工具返回完整吗?
- 决策:为什么选这个工具/参数?
- 校验:输出是否通过了 Schema/规则?
- 环境:模型版本、提示版本、工具版本是否变了?
- 复现:固定输入能否重现?
- 修复:改一个变量,跑评估。
- 回归:加入测试集。
小结
- 先分类症状,再定位根因,不要盲目改提示词。
- 大多数问题出在上下文、工具、权限与控制平面,而不是模型不够强。
- 修复后必须加入评估集,否则会复发。
- Trace 是排查的起点,没有 trace 就只能猜。
下一篇是面试题,可以用来检验自己是否真的理解。