一句话 — 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 “上个月我们对自动管道是怎么决策的?",会发生这些事:

  1. Claude Code 识别需要搜 wiki,调用 search_wiki("自动管道 决策")
  2. 查询被嵌入成 1024 维向量
  3. 余弦相似度返回 top 5 相关章节
  4. 匹配片段被注入 Claude 的上下文
  5. 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 CodeCLAUDE.md 在会话启动时加载进上下文。子目录有自己的 CLAUDE.mdcd 进去时追加加载。
  • OpenClawMEMORY.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 功能,按这个顺序问自己:

  1. 把问题用动词描述。 “回答关于 X 的问题” → RAG。“代替用户做 X” → Agent。
  2. 如果一次检索能搞定,就一次检索。 更便宜、更快、更可预测。
  3. 上 Agent 就在第一天设计权限。 不是第 50 天。Pinterest 的双层认证不是 feature,是生存必需。
  4. 为混合模式留接口。 真实 Agent 内部一定会需要 RAG 式检索。挑一个协议(MCP 是显然的默认)一直用。
  5. 全链路埋点。 Tool call 次数、检索命中率、跑偏指标。看不到就调不好。
  6. 每个任务设预算。 Token 和迭代步数都要设。没有预算的 Agent 会创造性地永远花在错的地方。

收尾

RAG vs Agent 的对立框架在 2023 年合理——那时它们是两个抢同一个工作的范式。到了 2026 年,它们是同一个系统的互补层。

真正有意思的问题不是选哪个,而是 你问题的哪一层属于哪一层。分对了就能交付。分错了就要花一个季度重做。

对大多数现在在落地的团队来说,答案长这样:

                ┌───────────────────────────────┐
                │   Agent 循环(外层)          │
                │   推理 + 工具选择              │
                └──────────┬────────────────────┘
                           │
        ┌──────────────────┼──────────────────┐
        │                  │                  │
        ▼                  ▼                  ▼
    RAG 检索        操作类工具           计算
    (知识)        (修改状态)        (数学、代码)

Agent 做决策。RAG 提供信息。工具执行动作。这就是全栈。


参考来源