常见陷阱与最佳实践汇总
常见陷阱与最佳实践汇总
本章汇总 Agent 开发全链路(提示词 → 上下文 → 工具 → 循环 → 记忆 → RAG → 多智能体 → 安全 → 成本 → 评估)的常见陷阱与最佳实践,作为动手前的自检清单。各章内的 🚨/💡 标注在此集中收录并扩展。
提示词与上下文
- 🚨 把全部文档前置塞进 system prompt:上下文腐蚀(Context Rot)会让模型回忆能力随 token 数增加而下降。💡 只放索引,让 Agent 按需拉取(详见 03-上下文工程)
- 🚨 “Lost in the middle”:长上下文中间部分的信息最容易被忽略。💡 关键指令放在开头和结尾,重要证据紧邻问题
- 🚨 Few-shot 示例引入偏置:模型会模仿示例的一切特征——包括你不想要的(长度、口癖、错误格式)。💡 示例要经过审查,覆盖边界情况
- 🚨 工具输出原样进入上下文:一次
cat大文件、一段冗长报错就能挤掉真正有用的信息。💡 工具层做截断、分页、摘要 - 🚨 依赖模型输出 JSON 却不校验:可靠性因模型而异,偶发的非法 JSON 会击穿下游。💡 格式校验 + 解析失败重试;能用 API 层结构化输出(tool schema / response_format)就不要靠提示词约定
工具设计
- 🚨 工具描述含糊:description 是模型选择工具的唯一依据,写得像给人看的注释而不是给模型看的说明书,会导致误用、漏用。💡 说清"何时用、何时不用、参数含义与格式"
- 🚨 工具数量失控:几十个相似工具会显著降低选择准确率。💡 原子化但不碎片化;相似操作合并为一个带 mode 参数的工具,或分层(先选类别再选工具)
- 🚨 工具执行失败直接抛异常终止循环:模型失去了自我纠错的机会。💡 把错误信息作为
tool_result(is_error: true)返回,让模型看到报错后调整参数重试 - 🚨 工具幂等性缺失:Agent 重试是常态,一个"创建订单"工具被调两次就是事故。💡 副作用类工具设计幂等键,或在 Harness 层去重
- 💡 schema 中用 enum / required 约束参数:比在 description 里用文字描述"只能是 a/b/c"可靠得多
Agent Loop 控制
- 🚨 没有 max_steps:模型陷入"调工具 → 看结果 → 再调"的死循环时,没有熔断就是无限烧钱。💡 步数上限 + token 预算上限 + 单工具超时,三层熔断
- 🚨 用字符串匹配判断任务结束(“回复里有 FINAL ANSWER 就停”):提示词格式脆弱,模型换个说法就失控。💡 用 API 的结构化字段
stop_reason != "tool_use"驱动控制流 - 🚨 漏回并行工具调用的结果:一次响应含多个
tool_use时,必须为每个 id 返回对应tool_result,缺一个 API 直接报错 - 🚨
max_tokens截断的响应被当正常结果处理:stop_reason == "max_tokens"时工具参数可能是残缺 JSON。💡 检测并重试
安全
- 🚨 间接提示注入(Indirect Prompt Injection):Agent 读取的网页、文件、工具返回值中可能嵌入"请忽略之前的指令并…"。这是 Agent 安全的头号威胁。💡 信任边界原则——工具返回的一切都是数据而非指令;高危操作不因"上下文里有人叫我做"而免审批
- 🚨 路径逃逸:
../../etc/passwd类输入绕过工作区限制。💡 所有文件操作过safe_path沙箱(resolve 后校验前缀,详见 05-Agent-Loop与工具调用) - 🚨 把用户输入拼进 shell 命令:命令注入在 Agent 场景同样成立,且模型自己生成的命令也不可信。💡 白名单 + 参数化执行 + 破坏性命令(rm -rf、force push、DROP)人工审批
- 🚨 密钥泄漏进上下文:环境变量、配置文件被工具读出后,会随对话历史反复出现在每次 API 请求里。💡 工具层做敏感信息过滤/打码
- 💡 最小权限 + 全量审计:Agent 只拿完成任务所需的最小权限;所有操作留痕,便于回溯(详见 10-评估与安全)
记忆系统
- 🚨 记忆污染:一次幻觉产生的"事实"被写入长期记忆后,会在之后每次检索中反复毒害推理。💡 入库前验证;记忆带来源与置信度;发现错误可删除
- 🚨 存入相对时间(“昨天”、“上周”):跨会话读取时语义已经错了。💡 写入前统一转为绝对日期
- 🚨 记忆只增不减:无限增长既拖慢检索又稀释相关性。💡 生命周期管理——合并去重、冲突更新、过期遗忘(详见 07-记忆系统)
RAG
- 🚨 切片切断语义:固定字数硬切会把一句话拦腰斩断,检索出的片段没头没尾。💡 按语义边界(标题/段落)切分 + 相邻块 overlap
- 🚨 只用向量检索:专有名词、错误码、精确 ID 这类查询,语义检索反而不如关键词。💡 向量 + BM25 混合检索,再加 rerank 重排序
- 🚨 Top-K 一味调大:召回更多 ≠ 回答更好,无关片段会稀释注意力甚至诱发幻觉。💡 宁可 K 小 + 高精度重排
- 🚨 认为长上下文模型可以取代 RAG:成本、延迟、“中间遗忘"三项都不答应(详见 09-RAG检索增强生成)
多智能体
- 🚨 子 Agent 回传全部原始内容:子代理架构的意义就是上下文隔离,全文回传等于没隔离。💡 只回传结构化摘要/结论
- 🚨 为并行而并行:多 Agent 的通信与协调成本是真实的,简单任务上多 Agent 往往比单 Agent 又贵又差。💡 单 Agent 做不动(上下文装不下、需要独立视角)时才引入多 Agent
- 🚨 多 Agent 并发写同一工作区:文件冲突、互相覆盖。💡 worktree / 目录级隔离,或串行化写操作
成本与性能
- ⚡ 提示缓存是 Agent 最大的省钱杠杆:系统提示 + 工具定义放最前并打缓存断点,多轮循环下成本可降一个数量级(详见 01-模型API)
- ⚡ 上下文膨胀 = 成本线性增长:Agent Loop 每轮携带全量历史。💡 长任务及时 Compaction(压缩整合)
- ⚡ 分级用模型:路由、分类、摘要等子任务用小模型,只有核心推理用大模型
- ⚡ 并行执行独立工具调用:模型一次请求多个工具时,Harness 应并发执行而非顺序等待
评估
- 🚨 只测 happy path:Agent 的失败大多发生在工具报错、信息缺失、指令冲突等边界上。💡 评估集必须包含扰动输入与故障注入
- 🚨 基准数据污染:模型可能背过测试集。💡 随机化变量、私有测试集、沙箱环境
- 🚨 LLM-as-a-Judge 不校准就上线:评判模型有自己的偏好与幻觉。💡 用人工标注的子集校准 judge,定期复核(详见 10-评估与安全)
- 🚨 单次运行下结论:LLM 输出有随机性。💡 用 Pass@k / 多次运行取均值
最佳实践清单(上线前自检)
| # | 检查项 | 对应章节 |
|---|---|---|
| 1 | Agent Loop 有 max_steps、token 预算、工具超时三层熔断 | 05 |
| 2 | 控制流由 stop_reason 驱动,不靠字符串匹配 |
01 / 05 |
| 3 | 文件操作全部经过路径沙箱,破坏性操作有审批关卡 | 05 / 10 |
| 4 | 工具描述清晰、参数有 schema 约束、错误以 tool_result 回传 | 06 |
| 5 | 工具输出有截断/分页,防止撑爆上下文 | 03 / 06 |
| 6 | 稳定前缀(系统提示/工具定义)已配置提示缓存 | 01 |
| 7 | 长任务有 Compaction 或外部状态层(笔记/任务图) | 03 |
| 8 | 长期记忆有入库验证与生命周期管理 | 07 |
| 9 | RAG 采用混合检索 + rerank,切片保留语义边界 | 09 |
| 10 | 工具返回内容按不可信数据处理(防间接注入) | 10 |
| 11 | 有含边界用例的评估集,关键指标(成功率/成本/延迟)可监控 | 10 |
| 12 | 每次响应的 usage 被记录,成本可归因、可告警 | 01 |