Agent 的脑和手——把 SOP 塞进知识库不等于 Agent 能做事|Agentic AI 落地方法论(六)

《Agentic AI 落地方法论》系列第六篇。 前五篇拆「方案能不能上线 + 上线后怎么不放养 + 北极星指标怎么定」——L0-L3 定级、L2 vs L3 的 5 个架构决策、Critic fail-closed、上线即放养、接住率 vs 解决率。这一篇换一个角度——为什么 90% 的「我们 Agent 落地了」其实只是「我们 RAG 上线了」,和怎么把这条线划清楚。English version: Brain and Hands — Why Stuffing SOPs Into a Knowledge Base Doesn't Make Your Agent Capable.
「我们把 SOP 都写进知识库了」——这句话是评审会上最常见的伪 Agent
某零售客户客服 Agent 项目验收会,乙方 PPT 翻到第 12 页:
「目前已沉淀 SOP 文档 320 篇 / 政策条款 1,400 条 / FAQ 8,000 条 / 商品话术 6 万条——全部入知识库,召回率 92%,RAG 准确率 87%。」
老板点头。然后随口问了一句:「那现在客户问『帮我把昨天那笔退一下』,能直接退吗?」
PPT 翻完没有这一页。乙方答:「这个我们后面会加退货流程的 Skill。」——意思是没有。
那一刻在场的所有人都意识到一件事:320 篇 SOP + 1,400 条政策 + 92% 召回率,只是让 Agent 知道退货政策长什么样。它没有让 Agent 能给客户办退货。
这一年我跟的所有客服 / 补调 / 工单 类 Agent 项目,技术评审最大的盲区都不在算法、不在模型选型、不在向量库选哪家——是在这一条:没人把「知道」和「能做」分清楚。
知识库塞满了,就当能力齐了。检索准确率上去了,就当 Agent 落地了。第一次客户来个写操作请求,整个项目原地翻车。
这一篇拆三件事:(1)脑 vs 手 在工程上到底差在哪、(2)一个 3 行的测试把你方案里的假 Skill 揪出来、(3)「为什么没有像 MCP 那样的 Skill 协议」这个问题为什么问反了。
知识库是脑,Skill 是手——一张表分清
先把结论摆桌面上:知识库(Knowledge Base)和 Skill 不是同一类东西的两种实现,是 Agent 架构里两个完全不同的层。混淆这两个,方案从第 1 天就建错了。
| 知识库 | Skill | |
|---|---|---|
| 回答的问题 | Agent 知道什么 | Agent 能做什么 |
| 内容形态 | 事实、政策、SOP、产品信息、对话语料 | 触发条件 + 工具调用 + 约束 + 输出契约 |
| 怎么被触发 | 被检索(RAG,问题进来就召回) | 被调用(Agent 判断需要执行某个动作) |
| 关键失败模式 | 召回错了 → 答错 / 漏答 | 调用错了 → 给客户多退 980 元 / 给错的人发优惠券 |
| 维护者 | 业务 / 运营 | 工程 |
| 更新触发 | 政策变了 / 产品上新 | 系统接口变了 / 业务规则变了 |
| 审计粒度 | 文档版本 | 调用日志 + 入参 + 出参 + 决策依据 |
| 可逆性 | 召回错了 → 改文档重新嵌入 | 写操作错了 → 退款已发出 / 工单已关 / 库存已扣 |
| 测试方法 | 召回精度、Recall@K | 端到端流程对账、幂等性、Critic 漏放率 |
最后两行特别重要:写操作出错不可逆。知识库召回错了,下次问换个 prompt 还能补救;Skill 调错了,钱已经退出去了。所以 Skill 必须有 Critic(系列三整篇在讲),知识库不一定要。
一句话压缩——知识库回答「客户为什么生气」,Skill 决定「我要不要给他退钱」。前者 RAG 召回就够了,后者要 trigger / tool / constraint / critic 全栈一起上。
同一份退货政策,在知识库里是「Agent 能告诉客户 7 天无理由可退」,在 Skill 里是「Agent 能真的把退款发起、对账、留审计、Critic 兜底」——这道分界决定 L2 项目能不能上线。一个 3 行的测试:你方案里的「Skill」是真 Skill 还是知识库别名?
下面这个测试是这一年我反复在评审会上用的。任何被标为「Skill」的能力点,用这 3 行问回去:
Test-1:触发它的不是用户问句,而是 Agent 的判断?
- 知识库典型触发:用户问「退货怎么办」→ embedding 检索 → 召回政策段 → LLM 抽取关键事实 → 答用户。
- Skill 典型触发:用户说「帮我退一下昨天那笔」→ Agent 判断(这是 write op + 涉及订单 ID + 涉及金额)→ 决定调用
refund_orderSkill。
如果你的「Skill」本质上是「问题进来 → 检索 → 把检索结果说出来」,那不是 Skill,是知识库的别名。
Test-2:它有写操作 / 副作用 / 调外部系统?
- 调订单 API 改状态 = 有副作用
- 调 IM 给客户发消息 = 有副作用
- 调 CRM 写客户标签 = 有副作用
- 召回退货政策段告诉客户 = 没有副作用(只是读)
任何「能力」只读不写、不调外部系统、不改任何状态,本质都是知识库的延伸表达。把这类东西命名成 Skill 是营销话术,不是工程区分。
Test-3:失败模式是「答错了」还是「做错了」?
- 答错 → 用户看到错的回复 → 一般可以再问一次纠正 → 损失:客户体验
- 做错 → 系统状态被改了 → 不能"再问一次"撤销 → 损失:钱 / 工单 / 库存 / 合规
写操作错了不可回头——这是 Skill 真正的工程特征。如果失败模式是「答错」,那它是知识库;如果失败模式是「做错」,那才是 Skill,那才需要 Critic + 灰度 + 审计链路。
3 个 test 任何一个答「不」,那个「Skill」就是知识库别名。这一招放到下次评审会上,乙方 PPT 上自称的 5-8 个 Skill,多半剩下 2-3 个是真的。
把 CLAUDE.md 写满规则不等于这些规则会执行——一个博客项目里的同构问题
这件事我自己做这个博客 18 个月也踩了一遍。
CLAUDE.md 现在有 2 万多字,里头写满了规则:「跑 npm run build 之前要确认 dev server 没开」、「写公众号 markdown 时 **X**:description 要写成 **X:** description 避免冒号撞行首」、「DB-backed 的页面要 export const revalidate = N」、「不要给 next.config 加显式 distDir」。
每一条规则都是踩坑后写下来的——文字、清楚、附带原因和反例。问题是:下一次新对话开始,Claude(或者我自己半年后回来)会不会自动遵守?
答案:看是不是变成了执行。
| 规则 | 留在 CLAUDE.md(知识库) | 写成代码(Skill) | 状态 |
|---|---|---|---|
| 跑 build 前不能让 dev server 在 :3002 | 「Gotchas」里写了 | scripts/check-dev-server.js prebuild hook,跑 build 前自动检测、阻断 | ✅ Skill 化 |
公众号 **X**: 冒号撞行首 | notes/2026-05-18-wechat-colon-orphan.md 写了 | scripts/mdx-to-wechat-html.mjs 在 marked.parse 之前一行 regex 自动修 | ✅ Skill 化 |
API 端点动 Post 表前要 ensurePostInDB(slug) 自动 seed | CLAUDE.md 里写了 | lib/db.ts 提供 ensurePostInDB 函数 + view/clap 端点都调了 | ✅ Skill 化 |
| 不要给 next.config 加显式 distDir | 「Gotchas」里写了,附 burn site reference | 没有 lint / hook 强制 | ⚠️ 还是知识 |
MDX 里不要写 <2%(会被 JSX 解析) | CLAUDE.md 案例里写了 | 没有 pre-commit 检查 | ⚠️ 还是知识 |
| ZH-first ship 时要去掉 alternateLang frontmatter | 系列产出指南里写了 | 没有脚本检查 | ⚠️ 还是知识 |
前 3 条变成了脚本之后,它们不再依赖我或 Claude 记得。第 4-6 条只要还是文字,每次重开对话都有概率漏。
这个博客 18 个月里 CLAUDE.md 写了 2 万多字。每条规则下次重开对话都有概率漏——直到把它变成 prebuild hook、变成 marked 的 pre-processor、变成 ensurePostInDB 函数。这件事和客服 Agent 完全同构。这是 Skill 的工程定义:一条规则只要还停留在文档里,它就是「希望」;它一旦能在系统执行流里被强制走到,才是「能力」。
这件事和客服 Agent 完全同构:
- 「7 天无理由退换」写在客服培训手册里 → 知识库
- 「7 天无理由退换」走到下单页底部 + 退货按钮点开自动判断时间 + 超 7 天直接灰掉退货选项 → Skill 化
前者是「客服都知道这条政策」,后者是「这条政策被流程强制执行了」。两者之间隔着是不是被代码(或确定性流程)兜底。Agent 也是同一道分界。
「为什么没有 MCP 那样的 Skill 协议」——这个问题问反了
每隔两周就有人在评审会上问这个。措辞略不同——「行业有没有统一的 Skill 标准」、「我们要不要等 OpenAI 出一个协议」、「Anthropic 的 Skills 算不算工业标准」——本质都同一个问题:我们是不是该等一个标准出来再开始?
不是。这个问题问反了,原因有 3 条:
原因 1:MCP 和 Skill 不在同一层。 MCP 解决的是 transport——Agent 怎么调外部工具,工具怎么暴露能力,鉴权 / 通道 / 序列化怎么走。它是协议层的东西,所以可以标准化。
Skill 是 policy——这个工具在你这家公司客服场景里允不允许调、调之前要不要先查会员等级、调失败要不要主动补偿、超过多少金额要转人工。这是业务规则的封装,不是传输标准。
行业不会出一个统一协议告诉你「客服 Agent 退款金额超过 500 元应该转人工」,因为这件事每家公司都不一样。你公司的客单价 300 元,门槛可能是 500;你竞品的客单价 3000 元,门槛是 5000。统一协议在这一层不存在,也不应该存在。
原因 2:MCP 已经在你想要的那一层做完了。 你担心的是「我接 5 个 SaaS 系统,每个都自己的 API,没法复用」——这件事 MCP 已经解决了。订单系统、工单系统、物流系统、CRM 系统、IM 系统,全部按 MCP server 暴露能力,Agent 用统一调用方式接所有这些。这是真的 protocol-level 标准化。
剩下的「这个 tool 在这个场景下怎么用、什么时候调、调之前要先做什么」,那部分本来就该是你公司自己的资产,不应该等一个外部标准告诉你。
原因 3:等就是不开始。 行业里凡是说「等 Skill 标准出来再上 Agent」的公司,6 个月后看,全部什么都没做。等的人不是在等协议,是在用「等协议」当不动手的理由。
行业的真实状态——
| 层 | 标准 | 状态 |
|---|---|---|
| 工具传输层 | MCP / OpenAPI / function calling schema | 成熟,照着接就行 |
| 知识检索层 | embedding + RAG + rerank | 成熟,开源闭源方案一抓一把 |
| Skill 定义层 | YAML + Prompt + 工具引用 + Critic | 没有外部统一标准,也不需要 |
| 多 Agent 编排层 | A2A / OpenAI Swarm / LangGraph | 早期,方案在收敛 |
中间两层是你自己企业的内功,没有外部协议能替你定义你公司的客服 Agent 该怎么退款。这件事跟 ERP / OMS 时代是一样的——SAP 不会出一个协议告诉你 SKU 怎么打标,它给你字段和工作流,标怎么打你自己定。Skill 在 Agent 时代是同一个位置。
一个 Skill 真正长什么样——比 YAML 多三块
很多人看到「Skill 用 YAML 定义」就觉得够了。不够。一个真正能落地的 Skill 至少要 5 块。下面是我跟过的项目里收敛出来的最小 Skill 规范:
skill:
name: "refund_order"
description: "对未发货 / 7 天内的订单发起退款"
# 1. 触发:谁来调,怎么知道该调
trigger:
intents: ["refund_request", "cancel_order"]
required_entities: ["order_id"]
optional_entities: ["refund_amount", "reason"]
# Critical: trigger 不止是 intent 匹配,还要 entity 齐
# 没有 order_id 就不能调,应该转去「澄清意图」分支
# 2. 知识引用:调之前 / 调之间要查哪些政策
knowledge:
must_check:
- "refund_policy.7day_no_reason" # 7 天无理由条款
- "refund_policy.shipped_status" # 已发货 vs 未发货
- "member_tier.refund_priority" # 会员等级影响优先级
# 3. 工具调用:调什么、参数怎么填、失败怎么处理
tools:
- server: "order-service"
action: "query_order_status"
timeout_ms: 1500
on_failure: "escalate_to_human"
- server: "order-service"
action: "initiate_refund"
idempotency_key: "refund:{order_id}:{timestamp}"
timeout_ms: 3000
on_failure: "rollback_and_escalate" # 失败必须能回滚
# 4. 约束:在这个公司这个场景,这个 Skill 不允许做什么
constraints:
- "refund_amount 必须 ≤ order_total_paid"
- "refund_amount > 500 → 必须转人工二次确认"
- "同一订单 24h 内不允许重复调用"
- "用户未实名 → 不允许调用"
- "凌晨 02:00-08:00 → 转人工(风控时段)"
# 5. Critic:调用前 + 调用后 双层审查
critic:
pre_call:
- check: "金额对账:amount == queried_order_total"
- check: "状态对账:order_status in ['paid','shipped_not_delivered']"
- check: "时间窗:now - order_create_time <= 7 days"
timeout_action: "fail_closed" # 超时即升级(系列三讲过)
post_call:
- verify: "refund record 已写入"
- verify: "用户已收到确认通知"
- verify: "三方对账接口返回一致"
timeout_action: "alert_human"
# 6. 输出契约:调用结果怎么回给上层
output:
success:
template: "已为您发起退款,预计 X 个工作日到账,订单号:{order_id}"
failure:
template: "[转人工] 我帮您接入人工客服跟进退款,请稍等"
attach_context: true # 工单系统能看到 Agent 之前的判断链路
最关键的是 4、5、6 三块——constraints + critic + output 契约。
constraints 是这家公司这个场景的业务规则封装。「金额 > 500 转人工」是这家公司的风控阈值,下家公司是 5000。这部分只能你自己定,没有外部标准。
critic 是写操作的兜底审查。pre_call 检查参数对得上,post_call 检查调完了状态对。任何一关 fail → 升级人工(系列三 fail-closed)。一个没有 critic 的 Skill 上线就出事故,时间问题而已。
output 契约决定 Agent 调完 Skill 之后能不能跟上下游对话。包括失败时的话术、人工接管时附带的上下文——这件事乙方默认会跳,因为 demo 阶段只演示 happy path,failure path 的输出契约没人写。
少了这三块,剩下的 YAML 只是「调 API 的薄壳」,谈不上 Skill。
5 个失败模式:「我们只用 RAG 也能做」的方案为什么 6 个月后翻车
这一年我跟过的几个项目,乙方一开始的方案就是「我们把 SOP 入知识库,加上 LLM,就能解决」。6 个月后翻车的 5 个典型模式——
模式 1:知识漂移——政策变了,知识库没更新,Agent 照念老政策。客服领域这件事每周发生:商品下架了、活动结束了、规则改了。这件事 RAG 系统结构上没办法管,因为它不知道知识过期。Skill 化的对应做法:每次调用前 pre_call critic 查最新政策接口,不依赖 embedding 副本。
模式 2:幻觉执行——Agent 看了「7 天无理由退换」的政策文档,自己脑补出退款已经发起的话术回给用户。用户以为退完了,过两天发现钱没到账,回头投诉。这一年至少在 3 个项目里见过。RAG 模式下根本拦不住——只读不写的链路里,LLM 编一句「退款已发起」零成本。Skill 化后这件事调不了 initiate_refund API 就根本说不出口。
模式 3:没有审计链路——客户投诉「为什么给我多退了 200」,公司想查是谁批的、为什么批,RAG 模式只能查到 Agent 当时检索了哪几段政策,查不到为什么决定退这个数。Skill 模式下整个调用链有日志:trigger → critic → tool call → response,每一步入参出参都在。出事故时这件事决定能不能定责。
模式 4:prompt-only 治理——所有约束都写在 prompt 里:「金额超过 500 一定要转人工」、「凌晨不要做退款」、「记得查会员等级」。LLM 听 70-80% 的话,剩下 20-30% 该听不听。prompt 越长这个比例越糟。Skill 模式下 constraints 是代码 if-then,确定性走通,不依赖 LLM 自觉。
模式 5:版本回滚不可能——RAG 系统里调整一段政策文档的描述,整个 embedding 索引重建一次,效果上不上不知道,回滚也只能再重建一次。Skill 模式下 YAML 走 git,每次改动 diff 可见、灰度可控、一键回滚。
5 个模式有一条共性:纯 RAG 方案在「写操作」这件事上没有任何工程兜底。所有兜底都靠 prompt 提醒 LLM 自觉。LLM 不自觉时,问题直接打到生产用户。
这就是为什么 L1 场景可以 RAG-only,L2 / L3 不行(L0-L3 定级)——级别越高,写操作越多,对工程兜底依赖越重,对 Skill 化的需求越硬。
落地路径:从 5 个 Skill 开始,3 个月建起企业 Skill 库
不要等协议。也不要一口气定 50 个 Skill。从最痛的 5 个开始:
第 1 个月:盘点你现在客服 Agent 真正在做的写操作。一个 L2 客服 Agent 一般是 5-8 个:查订单 / 发起退款 / 创工单 / 改地址 / 发优惠券 / 标记投诉 / 转人工。每一个写一份完整的 YAML(5 块齐:trigger / knowledge / tools / constraints / critic)。
第 2 个月:把这 5 份 YAML 放进 git,建一个 skills/ 目录,每个 Skill 一份 PR、走 code review。重点 review 两个地方:(1)constraints 业务侧签字,(2)critic 工程侧签字。任何一边没签 → 这个 Skill 不上线。
第 3 个月:把同样的格式复制到非客服场景。补调(智能补货)、滞销预警、排班——同一份 YAML 模板填新场景的 trigger / tool。3 个月跑完,你公司的内部 Skill 规范就建起来了。
这个东西完全不依赖外部协议。等的所有公司,3 个月后还在等。
5 个评审问题:下次乙方说「我们有 N 个 Skill」时问回去
下次乙方 PPT 翻到「我们已沉淀 X 个 Skill」时,问这 5 个。任何一个答不上 = 那不是 Skill。
问题 1:把你们 5 个 Skill 的 YAML 定义发我一眼。 真 Skill 至少有 trigger + tools + constraints + critic 4 块。乙方拿出来的如果只是「我们做了 skill_refund.py」+ 一段调 API 的代码,那叫 wrapper,不叫 Skill。
问题 2:每个 Skill 的 critic 在哪里?pre_call 检查什么,post_call 检查什么,超时怎么办? 答「我们没有 critic,LLM 自己判断」= 直接终止评审(系列三专门讲为什么)。
问题 3:constraints 谁定的、改 constraints 要走什么流程? 合格答案:业务方和工程方双签 + PR 走 code review + 灰度上线 + 一键回滚。不合格答案:「都在 prompt 里写了」。Prompt 里写约束 = 没约束。
问题 4:Skill 调用失败时,上下文怎么交给人工? 合格答案:人工座席能看到 Agent 之前 trigger 了哪个 Skill、检索了哪些知识、试图调用什么 tool、为什么失败。不合格答案:「失败了就转人工」(剥离上下文,等于让人工从零开始)。
问题 5:5 个 Skill 里,写操作 Skill 占几个?纯读 Skill 占几个? 帮乙方分清这件事。如果他们 PPT 上的 8 个 Skill,6 个其实是「查 + 答」,2 个是真写操作——那意味着方案只解决 L1 + L1.5。L2 部分基本没做。
10 件这周可以做的事
- 把团队现在 Agent 方案里所有「能力点」列出来,用文章里的 3 行 test 走一遍,标出哪些是真 Skill / 哪些是知识库别名
- 抓一个最容易翻车的写操作(一般是「退款」「改地址」「发优惠券」),照着上面 6 块的 YAML 模板补全
- 把 constraints 单独拉出来给业务方签字——这是治理签字,不是技术签字
- 把 critic 的 pre_call / post_call 检查项单独列一张表给工程方签字
- 上线前跑一遍漏放率测试:故意构造 100 个边界 case(金额刚好 500 / 订单刚好第 8 天 / 凌晨 02:01),看 critic 拦下多少
- 写一份 Skill review checklist 挂工位墙——下次新 Skill PR 必走这张表
- 把知识库内容和 Skill 的 constraints 做一次对账——任何在知识库里出现「不能 / 必须 / 超过 X 要 Y」类语句,对应 Skill constraints 里要有等价 if-then
- 在你的 CLAUDE.md / 团队 SOP 里挑 1 条最常忘的规则,把它写成脚本 / hook,让它不能被忘
- 给所有写操作 Skill 加 idempotency key(典型格式
<action>:<entity_id>:<timestamp>)防重复触发 - 下次评审会拿这一篇的 5 个问题问乙方
写在最后:脑可以背 SOP,手要被流程兜住
知识库和 Skill 的区分不是一个名词游戏。它决定的是你的方案在第一次写操作出事故时,有没有兜底。
「我们 SOP 都入库了」=「客服都背过那条政策」。这是真的,但和「公司退货流程能跑通」是两件事。后者要按钮按下去后系统真的能退、退完了对账对得上、出错了能追责——这是 Skill 工程化解决的事。
行业还会有人继续问「为什么没有像 MCP 那样的 Skill 协议」。等的人继续等。这一年开始动手定义自己 5-8 个 Skill 的公司,3 个月后就有真 L2 Agent 在跑了,他们不会再问这个问题。
如果你公司方案里乙方自称的 Skill 数量 ≥ 5、但真写操作 Skill ≤ 2、且没有一个有完整 critic——这是个伪 Agent 方案。从今天起把上面那张 5 块 YAML 拿过去对一遍。一个对不上的 Skill 比 10 个对得上的容易补,先盯一个补到能跑。
工具包领取
如果你想把这一篇里的工具立刻用到下次评审会 / 团队 Skill 定义,我整理了一个 PDF 工具包:
回复关键词「SKILL 模板」,我把工具包发给你:
- Skill 定义 6 块 YAML 完整模板(refund / cancel / address-change / coupon-grant 4 个填好的示例)
- 「真 Skill vs 知识库别名」3 行测试表(评审会 + 内部 review 都能用)
- Skill review checklist(PR 必经的 9 项检查 + 双签字段)
- 乙方评审 5 问 + 合格 / 不合格答案样本
这一年跟项目里收敛出来的工程模板,送给读到这里的你。
回复渠道见页脚(公众号 / X)。不方便回复的,评论区留邮箱也行。
系列接下来排期
A4 系列下一篇——
- 3 级 intent 级联调参:规则 + embedding + LLM 三级 fallback 的阈值怎么调(系列二决策 2 深挖)
- LLM 接入企业 SaaS 生态:25 API → 5 tool 的契约和幂等性(系列二决策 4 深挖)
- AI 系统怎么测:双轨架构 + 7 质量维度 + SSE Spike
- 企业 LLM Agent 踩坑合集:async ES 阻塞事件循环 / Critic timeout fallback 误用 / proxy 拦 localhost / intent rename 跨 7+ 文件 / KB-ES 不同步
如果团队正在做 L2 客服 Agent 或别的写操作类 Agent,这 4 篇接下来一篇一篇出。
Subscribe for updates
Get the latest AI engineering posts delivered to your inbox.

