一句话 — RAG 从文档里找答案。Agent 去做事。真实系统几乎都是两者结合:RAG 提供上下文,Agent 基于上下文行动。难点不是选哪个,而是分清楚你问题的哪一层属于哪种模式。
为什么这个对比在现在很重要
过去半年发生了两件事,让 RAG vs Agent 不再是纸上谈兵。
第一:coding agent 在 2025 年 11 月跨过了质量门槛。Simon Willison 在 PyCon 闪电演讲里把这个时刻总结为 agent 从"经常能用"到"基本都能用"——可以作为日常生产力工具了,不再只是 demo。同一个月里 Anthropic、OpenAI、Google 之间的"最强模型"头衔换手了 5 次。
第二:模型实验室自己在转型。Greg Brockman 直说:“模型本身已经不再是产品。” AI21 关闭了模型团队转去做 agent。DeepSeek 第一次组建了 “Harness 团队”。Latent Space 把这个趋势总结为 “所有模型实验室现在都是 agent 实验室”。
当训练模型的人都开始说"模型不是产品"的时候,怎么把模型接到系统里就成了真正的工程问题。RAG 和 Agent 是两个主流答案,解决的问题不一样,选错了会浪费大量 token。
心智模型
RAG:先检索,再生成
RAG 是固定的四步流水线:
用户提问
│
▼
Embedding 模型 → 向量
│
▼
向量库 / 搜索索引 → 取最相关的 top-K 片段
│
▼
片段拼进 LLM prompt 作为上下文
│
▼
LLM 基于检索内容写一次答案
一次检索,一次生成。便宜、确定性高、易于 debug。
Agent:推理 → 行动 → 再推理
Agent 是一个推理循环:
用户目标
│
▼
┌──────────────────────────────────────────┐
│ LLM 读取目标 │
│ ↓ │
│ 选择工具 (Read / Edit / Bash / ...) │
│ ↓ │
│ Runtime 执行工具 │
│ ↓ │
│ 结果反馈给 LLM │
│ ↓ │
│ LLM 推理下一步该做什么 │
│ ↓ │
│ 选下一个工具 │
│ ↓ │
│ ... 循环直到任务完成 │
└──────────────────────────────────────────┘
每一轮都烧 token,每一步都可能失败,错误会沿着循环逐步累积。
两个具体例子
RAG 实战:Wiki 语义搜索
我们本地跑了一个知识库——大概 60 篇 markdown,覆盖项目笔记、设计决策、对话记录。直接 grep 行不通,因为问题和答案很少共享关键词。
解决方案是封装了一个 MCP server:
MCP server: wiki-search
Backend: bge-m3 embedding 模型
存储: 60+ 篇 markdown 的余弦相似度索引
输入: 自然语言查询(中英文都行)
输出: 文件路径 + 章节标题 + 相似度分数
当我问 Claude Code “上个月我们对自动管道是怎么决策的?",会发生这些事:
- Claude Code 识别需要搜 wiki,调用
search_wiki("自动管道 决策") - 查询被嵌入成 1024 维向量
- 余弦相似度返回 top 5 相关章节
- 匹配片段被注入 Claude 的上下文
- Claude 基于实际文件回答——不会瞎编
这是端到端的 RAG。Wiki 是被动的,它被查询,不主动做事。
Agent 实战:Claude Code 改文件
同一个 Claude Code 实例,换一个问题:“把 mybrew/hugo.yaml 的 baseURL 改成 aibrew.ai,并在 TODO.md 里记一笔。”
第 1 轮:
LLM 推理: "得先看现有配置"
工具: Read("mybrew/hugo.yaml")
结果: 文件内容
第 2 轮:
LLM 推理: "baseURL 在第一行,改它"
工具: Edit(old="https://mybrew.cc/", new="https://aibrew.ai/")
结果: 编辑成功
第 3 轮:
LLM 推理: "现在更新 TODO.md 标记完成"
工具: Read("hugo/TODO.md")
结果: 文件内容
第 4 轮:
LLM 推理: "得加在 '域名配置' 段下面"
工具: Edit(...)
结果: 编辑成功
任务完成。
四轮迭代,四次工具调用,多次推理。Agent 自己决定做什么、怎么做、什么时候算完成。
一个更刺激的 Agent:游戏服务器控制
我们还接了一个 Terraria 游戏服务器的 MCP bridge——大约 40 个工具(给道具、传送、ban 玩家、刷 Boss、重启服务器)。
玩家在聊天: "@ai 给我一把天顶剑"
→ terra_item_lookup("Zenith") → 解析到 ID 4956
→ terra_give_item(player="kali", item="Zenith") → SUCCESS
→ 道具出现在玩家背包里
对比一下破坏性操作:
玩家: "@ai 把世界结束掉"
→ terra_world_hardmode(confirm=true) 要求显式授权
→ 没确认就拒绝
→ 一旦确认:世界永久进入困难模式(不可逆)
这就是 Agent 模式开始变危险的地方。LLM 拿到了真实系统的方向盘。一次错误工具调用的影响不再是"答错了”,而是"世界毁了"。权限边界变成了一等公民的设计问题。
决策框架
一句话规则:
答案在文档里用 RAG。需要执行动作用 Agent。
更详细的版本:
| 维度 | RAG | Agent |
|---|---|---|
| 目标 | 回答问题 | 完成任务 |
| 交互模式 | 一次性 | 多轮循环 |
| Token 成本 | 低(1× 检索 + 1× 生成) | 高(N× 推理 + N× 工具调用) |
| 延迟 | 约 1–3 秒 | 几秒到几分钟 |
| 确定性 | 高——同一问题答案相似 | 低——同一目标路径各异 |
| 可调试性 | 看检索结果即可 | 得追踪每一步推理 |
| 失败模式 | 上下文错或缺 → 答得差 | 工具错误累积 → 跑偏 |
| 影响范围 | 答错就答错 | 触碰真实系统 |
| 最适合 | 问答、搜索、摘要 | 编码、运维、自动化、工作流 |
什么时候必须用 RAG
- “我们的内部 API 文档对限流是怎么写的?”
- “总结一下上周的客户反馈。”
- “那次认证设计讨论的结论是什么?”
什么时候必须用 Agent
- “跑一下测试套件,把失败的修了。”
- “把昨天 RSS 未读里最有意思的三篇挑出来,写成一篇 roundup。”
- “把这个目录重构成新的 logging API。”
大部分真实系统:两个都要
- “找到相关的设计文档,提个符合它思路的代码改动。” → RAG 拉文档,Agent 写代码。
- “看一下 Pinterest 怎么做 MCP 认证的,然后设计我们的认证层。” → RAG 收集参考,Agent 动手写。
混合模式:RAG 驱动的 Agent
大部分 “RAG vs Agent” 对比都忽略了一件事:任何真实的 Agent 内部,RAG 都在多个层面同时发生。
一个 Claude Code session 简化后是这样:
会话启动:
└─ 加载 CLAUDE.md 进上下文 ................ 启动时 RAG
└─ 加载相关的 MEMORY.md ................... 启动时 RAG
用户提问:
└─ Agent 推理目标
│
├─ 工具调用: search_wiki("...") ....... 按需 RAG
├─ 工具调用: searxng_web_search("...") . 按需 RAG
├─ 工具调用: Read("config.yaml") ...... 确定性检索
└─ 工具调用: Edit(...) ................ 行动
Agent 循环是外壳。RAG 调用发生在循环内部,按需进行,Agent 觉得需要更多依据时就调一次。
这跟 Pinterest 工程师描述的 MCP 部署完全一致:所有 Agent 界面(chat、IDE、CLI)都连同一组 MCP server,其中一部分是纯检索(Presto 查询、文档搜索),一部分是行动(提工单、重启任务)。Agent 在运行时自己决定调哪个。
生产案例:Pinterest 的 MCP 生态
ByteByteGo 对 Pinterest MCP 部署的写作是少数公开的生产实践之一。
N×M 问题
Pinterest 工程师每天要跨多个系统工作——Presto 查数据、Spark 调批处理、Airflow 跑工作流、查内部文档、追 ticket。他们想让 AI agent 能直接进到这些系统里。
直接做的话:
5 个 agent 界面 × 10 个内部工具 = 50 个定制集成
每加一个界面或工具就乘出更多工作量。还有 50 套 OAuth 流程、50 套 token 生命周期、50 套管道。
MCP 的赌注
Model Context Protocol(MCP)的承诺是把乘法变加法:
5 个 client + 10 个 server = 15 个标准化集成
一个协议两端用。每个界面写一个 client。每个工具包一个 server。它们都说同一种"语言"。
MCP 解决不了的问题
Pinterest 的教训:协议本身是最容易的部分。真正的工程量在协议周围的基础设施:
| 关注点 | Pinterest 的方案 |
|---|---|
| 发现机制 | MCP server 中央注册中心——名字、版本、负责人、endpoint |
| 认证(第一层) | 服务身份——是哪个 agent runtime 在发起调用 |
| 认证(第二层) | 用户身份——agent 是以谁的权限在操作 |
| 部署 | 所有 MCP server 走同一条 CI/CD 管线 |
| 可观测性 | 从第一天就埋点——调用频次、延迟、错误率 |
结论:Agent 越能干,权限和可观测性层就越重要。一个让任何 agent 都能调任何工具的协议,也是让任何被攻陷的 agent 都能调任何工具的协议。
这也是为什么我们更小的部署(3 个 MCP server:searxng / wiki-search / terra_llm_bridge)在破坏性操作上加了硬性的 confirm=true 门——比如 ban 玩家、重启世界、开启 hardmode。三个 server 不需要注册中心,但需要授权。
架构对比:Claude Code vs OpenClaw
两个主流 Agent harness 在设计上立场截然不同。ByteByteGo EP214 从 5 个维度拆解:
1. 系统范围
| Claude Code | OpenClaw | |
|---|---|---|
| 生命周期 | 短命进程 | 常驻 daemon |
| 触发方式 | 用户跑 CLI | WebSocket 从 Discord/Slack/WhatsApp 进来 |
| 退出 | 任务完成后 | 永不退出 |
Claude Code 是你召唤来干活的工人。OpenClaw 是永远在听的管家。
2. Agent 运行时
- Claude Code:单线程异步循环——
Think → Tool Call → Observe → Repeat。一个进程一次只做一件事。 - OpenClaw:每个 session 独立队列。Gateway 把入站消息分发到各自的队列。
3. 扩展模型
- Claude Code:四个扩展原语,全都接进同一个 Agent 循环:
- MCP(外部工具服务)
- Plugin(打包的工具集)
- Skill(模型可调用的命名流程)
- Hook(事件驱动的 shell 命令)
- OpenClaw:manifest-first 插件系统。所有插件先经过中央 Registry 才进入 Agent。
4. 记忆机制
- Claude Code:
CLAUDE.md在会话启动时加载进上下文。子目录有自己的CLAUDE.md,cd进去时追加加载。 - OpenClaw:
MEMORY.md和日常笔记分离存储。结构化片段上做向量 + 关键词的混合搜索。
5. 多 Agent 拓扑
- Claude Code:主 Agent → 子 Agent 模式。主 Agent 派遣子 Agent 干活。
- OpenClaw:路由分发模式。入站频道路由到专门的 Agent,再交给共享的子 Agent。
更深的规律:Claude Code 优化的是"一个会话做一件事"。OpenClaw 优化的是"多个对话并发,环境感知存在"。两个都是对的,看你的用例。别选错了。
失败模式与反模式
RAG 失败模式
1. 检索没命中相关片段。 Embedding 模型觉得问题和答案语义距离很远,其实并不远。缓解:混合搜索(向量 + 关键词)、重排序、查询扩展。
2. 检索返回太多无关片段。 上下文窗口被噪音填满。缓解:更严格的 top-K、相似度阈值、检索后过滤。
3. 答案根本不在语料库里。 RAG 无中生有不出来——不在索引里的知识,模型还是不知道。缓解:置信度检查,或者 fallback 到 web 搜索。
4. 分块切碎了结构。 你把一个 markdown 文件从表格中间、代码块中间、论证中间切开了。缓解:结构感知分块(按 heading / paragraph / 语义单元)。
Agent 失败模式
1. 推理跑偏。 Agent 陷在循环里,反复尝试同一个失败方法的变体。缓解:最大步数限制、tool call 去重约束、显式的"我试过什么"记忆。
2. 权限越界。 Agent 做得太多。被要求修一个测试,结果重构了半个文件。缓解:prompt 里写明 scope,工具权限收窄,破坏性操作上 human-in-the-loop。
3. Tool call 级联失败。 一次错误的工具调用(比如路径写错),后面跟着五步在"修补症状"而不是"找根因"。缓解:工具返回清晰的错误信息,“试一次失败就上报"的工具设计。
4. 在错的地方烧钱。 20 步 Agent 循环的成本是单次 LLM 调用的 20 倍。如果 RAG 能回答的问题用 Agent 做,你就花了 20 倍的钱拿到更差的答案。缓解:先问自己"这能不能一次检索搞定?“再决定上不上 Agent。
最糟的反模式:RAG 够用却上了 Agent
团队最贵的错误,是给搜索问题做了个 Agent。
如果用户问的是 “文档里哪里写了……?",你不需要 Agent。你需要一个搜索框接上向量索引。停止用多步推理烧 token 去找一次检索就能浮上来的东西。
给开发者的实战清单
如果你正在做新的 AI 功能,按这个顺序问自己:
- 把问题用动词描述。 “回答关于 X 的问题” → RAG。“代替用户做 X” → Agent。
- 如果一次检索能搞定,就一次检索。 更便宜、更快、更可预测。
- 上 Agent 就在第一天设计权限。 不是第 50 天。Pinterest 的双层认证不是 feature,是生存必需。
- 为混合模式留接口。 真实 Agent 内部一定会需要 RAG 式检索。挑一个协议(MCP 是显然的默认)一直用。
- 全链路埋点。 Tool call 次数、检索命中率、跑偏指标。看不到就调不好。
- 每个任务设预算。 Token 和迭代步数都要设。没有预算的 Agent 会创造性地永远花在错的地方。
收尾
RAG vs Agent 的对立框架在 2023 年合理——那时它们是两个抢同一个工作的范式。到了 2026 年,它们是同一个系统的互补层。
真正有意思的问题不是选哪个,而是 你问题的哪一层属于哪一层。分对了就能交付。分错了就要花一个季度重做。
对大多数现在在落地的团队来说,答案长这样:
┌───────────────────────────────┐
│ Agent 循环(外层) │
│ 推理 + 工具选择 │
└──────────┬────────────────────┘
│
┌──────────────────┼──────────────────┐
│ │ │
▼ ▼ ▼
RAG 检索 操作类工具 计算
(知识) (修改状态) (数学、代码)
Agent 做决策。RAG 提供信息。工具执行动作。这就是全栈。
参考来源