很多团队做 AI 应用,第一反应是:
模型不知道业务知识,那就上 RAG。
这当然没错。
如果模型没有看到公司文档、产品手册、历史工单、代码说明,它不可能稳定回答这些问题。但问题在于,很多系统上了 RAG 之后,效果还是不稳定。
表现通常是这样:
检索结果看起来相关。
模型回答却漏掉关键条件。
同一问题换个说法,引用来源就变了。
旧文档和新文档冲突,模型自己编一个折中答案。
用户追问时,系统忘了上一轮已经确认过的事实。
这时候继续调 embedding、换向量库、改 top_k,不一定能解决问题。
因为真正的问题可能不是"有没有检索到"。
而是:
检索结果如何进入当前推理步骤?
这就是为什么我说:
RAG 只是 Context Engineering 的一小块。

一、RAG 解决什么,不解决什么
RAG 的核心动作很简单:
Retrieval-Augmented Generation
先检索,再生成。它解决的是模型知识边界问题。
比如:
模型训练时不知道你的内部文档。
模型不知道你昨天刚改的 API。
模型不知道客户合同里的特殊条款。
模型不知道某个项目里的真实代码结构。
RAG 可以把这些外部信息找回来。但它不自动解决后面的事。检索回来之后,系统还要回答一串更细的问题:
哪些片段可信?
哪些片段过期?
哪些片段互相冲突?
哪些片段应该进入上下文?
哪些只应该作为引用留在外部?
哪些需要进一步查证?
哪些应该更新任务状态?
哪些不应该让模型看到?
这些不是 retrieval 的问题,这是 context assembly 的问题,即上下文装配。
二、很多失败发生在装配层
一个典型的 RAG 管道长这样:
User Query
-> Rewrite Query
-> Retrieve Chunks
-> Rerank
-> Assemble Context
-> Generate Answer
-> Cite Sources
很多团队会把精力放在前半段。怎么切块,用什么 embedding,top_k 设多少、要不要 hybrid search、要不要 rerank。
这些都重要,但真正进入模型的,不是"检索系统",而是装配后的上下文。如果装配层粗糙,再好的检索也会被浪费。
常见粗糙做法是:
取 top 10。
拼成一段。
塞进 prompt。
让模型回答。
这在 demo 里可以跑。进生产就容易出事。因为 top 10 不代表当前步骤都需要。
排名靠前不代表可信。语义相关不代表能回答问题。同一主题下,不同版本的文档可能互相冲突。内部文档、网页、用户输入、数据库记录的可信等级也不一样。
如果这些边界没有进入上下文装配,模型只能自己猜。
三、RAG、MCP、File Search、Memory 不是一回事
做 Context Engineering,先要把几个概念分开。
3.1 RAG。
它主要解决:
从知识库中找相关文本片段。
3.2 File Search。
它更像一个托管检索能力,帮助你从文件集合里找内容。它仍然属于 retrieval。
3.3 MCP。
MCP 不是 RAG,它是让 Agent 连接外部数据源和工具的协议层。
通过 MCP,Agent 可以访问:
文件系统
数据库
代码仓库
业务 API
设计系统
工单系统
浏览器
这些连接里,有些是检索,有些是工具调用,有些会产生副作用,不能混成一个"知识库"。
3.4Memory。
Memory 也不是 RAG。
Memory 解决的是跨步骤、跨任务保留状态。
比如:
用户偏好
项目约定
历史决策
失败案例
长期画像
这些信息可以被检索出来,但它们的生命周期和普通文档不同。长期记忆必须支持更新、过期、删除和审计。
3.5 Database Query。
数据库查询不是"相似内容搜索"。它通常要求精确、可解释、可权限控制。
比如:
查询订单状态
查询某个客户的合同条款
统计过去 7 天错误率
这种场景用向量检索硬凑,往往会制造不确定性。

四、只读知识库和可执行工具要分开
这是生产 Agent 里非常重要的一条边界。
知识库是只读的。
工具可能会行动。
比如:
查文档:只读
查数据库:通常只读,但要看权限
创建工单:有副作用
修改配置:有副作用
发送邮件:有副作用
执行 shell:高风险副作用
如果系统把所有外部能力都叫"上下文",就会失去风险分层。
模型看到一个结果片段,和模型能调用一个工具,不是同一件事。
前者影响回答,后者影响世界。
所以上下文系统至少要标记:
source_type: document / memory / database / tool_result / user_input
trust_level: high / medium / low
freshness: timestamp or version
permission: read / write / execute
side_effect: none / reversible / irreversible
这些元数据不是给人看的装饰,它们应该影响上下文装配。
比如用户输入和网页内容,默认不能覆盖系统规则。
比如低可信来源可以参与参考,但不能独立支撑结论。
比如过期文档需要提示模型"可能失效"。
比如有副作用的工具结果要进入执行日志,而不是混进长期知识库。
五、Agentic Retrieval:让 Agent 决定查什么
传统 RAG 更像一次检索:
用户问一句。
系统查一次。
模型答一次。
Agentic retrieval 更像一个小循环。
Agent 会判断:
现在缺什么事实?
应该查哪个源?
关键词要不要改写?
第一轮结果是否足够?
是否需要查原文?
是否需要查数据库验证?
是否需要停止检索并回答?
这和人做研究更像:你不会只搜一次就下结论,你会先扫一批资料,发现关键概念,再换关键词查。看到冲突时查源头。最后只把真正能支撑结论的证据放进报告。
Agentic retrieval 的关键不是"让模型无限查"。
而是给它一个检索预算和停止条件:
最多查几轮?
必须找到什么类型的证据?
什么时候认为信息不足?
什么时候必须引用来源?
什么时候应该问用户澄清?
没有这些约束,Agentic retrieval 会变成"看起来很努力的搜索循环"。
六、引用不是装饰,是验证接口
很多 RAG 系统会在回答末尾放几个引用。
但引用经常只是装饰。
真正有用的引用应该满足三个条件。
6.1 答案里的关键结论能映射到具体来源。
不是整篇文章附在后面。
而是:
这个判断来自哪一段?
这个数字来自哪个表?
这个限制来自哪条政策?
6.2 引用要保留版本和时间。尤其是政策、价格、接口文档、法律条款、产品说明。
-
3 引用要参与验证。生成答案后,系统应该能检查:
每个关键事实是否有来源?
来源是否真的支持这个结论?
来源之间是否冲突?
模型是否把来源没有说的话补出来了?
这就是证据链。

七、常见反模式
7.1 一次塞入过多片段。
top_k 设得越大,不一定越安全;片段越多,冲突越多,噪声越多,模型越容易失焦。
7.2 没有来源引用。
没有引用的 RAG,很难调试;你不知道是没检索到,还是模型没用,还是模型用了但理解错了。
7.3 检索结果不参与验证。
检索只是回答前的一步,验证应该发生在回答后。
7.4 混淆长期记忆和临时上下文。
一次任务里的临时偏好,不应该自动写入长期记忆;长期记忆里的旧偏好,也不应该无条件覆盖当前用户指令。
7.5 把工具结果当知识库。
工具结果是某次执行的事实它需要记录,但不一定应该成为长期知识。
7.6 把用户输入当可信资料。
用户上传的文档、网页内容、PR 描述,都可能包含不可信指令。它们是数据,不是系统规则。
八、一个更健康的 RAG 上下文管道
我建议把 RAG 放进完整上下文管道里:
User Goal
-> Query Planning
-> Source Selection
-> Retrieval
-> Rerank
-> Evidence Selection
-> Context Assembly
-> Answer Generation
-> Citation Check
-> Memory / State Update
注意这里有三个关键变化。
8.1 先选 source,再检索。
不是所有问题都查同一个向量库。产品问题查产品文档,客户问题查 CRM 和合同,代码问题查仓库和测试,历史偏好查 memory。
8.2 先选 evidence,再装配 context。
检索结果是候选,不是所有候选都进上下文。
8.3 回答后再更新状态。
如果本轮确认了新事实,要写入任务状态;如果发现文档冲突,要记录 open issue;如果用户纠正了偏好,要考虑是否更新长期记忆。
九、实践 checklist
设计 RAG 系统前,先问这些问题:
[ ] 用户问题应该查哪些来源?
[ ] 每个来源的可信等级是什么?
[ ] 检索结果是否带版本、时间和来源?
[ ] top_k 之后是否有 rerank 或 evidence selection?
[ ] 片段之间冲突时怎么处理?
[ ] 回答里的关键结论是否必须引用?
[ ] 引用是否参与自动或人工验证?
[ ] 临时上下文和长期记忆是否分开?
[ ] 工具结果是否进入执行日志,而不是直接进知识库?
[ ] 信息不足时,系统是承认不足,还是强行回答?
这张表比"用哪个向量数据库"更重要:向量数据库是基础设施,上下文装配才决定模型到底看见什么。
十、从 RAG 到 Context Engineering
RAG 不是过时,恰恰相反,它仍然是很多 AI 系统最重要的基础能力之一。但它不是完整答案。在生产系统里,RAG 应该被放进更大的 Context Engineering 框架:
Retrieve 是取回候选材料。
Assemble 是决定当前步骤看什么。
Verify 是确认材料支撑结论。
Update 是把新状态写回系统。
下一篇,我们继续 Context Engineering 的另一个核心问题:
长上下文时代的压缩、缓存与遗忘。
窗口变大以后,很多人以为可以不再管理上下文。实际正好相反:能放更多,意味着更需要知道什么时候压缩,什么时候缓存,什么时候忘掉。
参考资料
- Effective context engineering for AI agents | Anthropic Engineering
- Context engineering for agents | LangChain
- Model Context Protocol
- OpenAI Agents and Responses API docs
参考文献: