本文整理自 CNB 上的开源课程 《Vibe Agent:从零搭建 Coding Agent》。课程讲义、示例代码与练习仓库均在 CNB 上公开,文中示例出自该仓库对应章节。

tool_calls 协议回答了两个问题:模型怎么决定调用哪个工具,执行结果怎么回传。它不回答另外三个:工具从哪来,一套复杂能力怎么打包,私有知识怎么送进模型。围绕这三个缺口,长出了三条延长线。

MCP:把工具搬出 Agent 进程

工具的常规做法是放在 Agent 仓库里,用装饰器注册,进程内调用。要接 GitHub、Slack、Notion 三个外部系统,就得读三套 API 文档、写三套 schema,任何一家改接口都要跟着改。

Model Context Protocol 是 Anthropic 在 2024 年底发布的开放协议,它把工具的实现方反过来:每个外部系统自己跑一个 MCP Server,声明自己有哪些工具、参数是什么;Agent 这边只需要一个 MCP 客户端,连上去拉取工具列表。tool_calls 的字段和流程一字不变,变化的只是工具来源从”进程内的函数”变成”远程服务的声明”。

接入成本随之改变。原来每接一个系统都要写一遍适配层,现在客户端实现一次,之后逐个挂载服务即可。协议只规定工具怎么描述和调用,工具内部怎么实现与 Agent 无关。服务端升级工具后,下次拉取时描述自动更新,客户端不必跟着发版。

Skill:把工具、提示词、资源一起发版

单个工具解决的是”能做什么动作”。一项可交付的能力往往不止于此:读 PDF 和写 docx 是两个工具,要让模型在正确的场景按正确的顺序调用它们,还需要一段说明;要让输出符合模板,还需要样例和字典。

Anthropic 在 2025 年提出的 Agent Skill 把这三类内容装进一个目录:

1
2
3
4
5
skills/
└── pdf-fill/
├── SKILL.md # 触发条件与调用约定,注入 system prompt
├── tools/ # 该能力专属的工具
└── assets/ # 模板、样例、字典

模型在 system prompt 里读到 SKILL.md 的描述,判断当前任务是否属于这个能力。判定命中后,Skill 内部的工具与资源进入可用范围,之后的调用仍然走标准 tool_calls。单看调用环节,Skill 没有引入新协议;它改变的是工具的组织方式和加载时机。

这种打包还有个实际好处:能力可以整体分发。目录拷贝过去,说明、工具、资源一起到位,不用在别人的 Agent 里重新讲一遍调用顺序。

RAG:检索结果当作工具返回值

检索增强生成的做法是先从私有知识库里取出若干段落,再把段落拼进 prompt,让模型基于这些内容回答。在 Agent 里,这一步通常被包装成一个工具:

1
2
3
4
@registry.tool("从公司内部知识库检索相关段落")
def search_kb(query: str, top_k: int = 5) -> str:
docs = vector_db.query(embed(query), top_k=top_k)
return "\n\n".join(d.content for d in docs)

模型判断这个问题自己答不了,于是调用 search_kb;拿到段落后再组织回答。它和”不知道现在几点,于是调用 current_time”是同一个动作。区别只在这个工具内部多了一层向量检索。

这意味着 RAG 的接入面就是 Tool Calling。剩下的工作是向量化、索引、召回排序,这些都在工具内部完成,对外仍然是一个函数签名加一段描述。模型不需要知道检索发生过。

参数也有工程含义。top_k 决定塞进 prompt 的段落数量,取多了挤占上下文,取少了可能漏掉该找的段落。这个值调多少,取决于知识库的段落粒度和任务对召回的要求。

四种来源,一份协议

把本地装饰器注册的工具、Skill 激活后的工具、MCP 拉取的工具、检索工具放在一起看,模型侧看到的都是 messages 里一条 role=tool 记录。

来源 解决什么 模型侧形态
本地 @tool 少量固定工具 role=tool
Skill 多工具加知识打包 role=tool
MCP 工具跨进程、跨服务 role=tool
RAG 私有知识检索 role=tool

Skill 的位置略有不同。它本身是一组工具的容器,在 system prompt 阶段注入说明,激活后内部工具照常调用。把它与另外三种并列,理由在于它同样提供了工具;它本身并不引入新的调用协议。

四种来源汇入同一个循环,说明那个五步循环的抽象是成立的。协议稳定之后,往上加工具不需要改循环,只需要多一个来源。

这对搭 Agent 意味着什么

三个方向对应三个工程问题:工具的供给方式、能力的封装粒度、知识的注入路径。它们都不改动 tool_calls,所以可以在循环定型之后逐个补上。

选择顺序也有实际含义。工具数量少,本地注册最省事;要接外部系统,MCP 免去重复适配;要把一套流程交给别人复用,Skill 的目录形式更容易分发;私有问答绕不开检索,RAG 是必选项。

协议解决的是模型怎么决定调谁,没有解决模型凭什么这么决定。下一篇换到第 3 章的视角:ReAct 用 Thought、Action、Observation 三段文字,把推理过程摊开在每一步里。