当前位置: 首页 > news >正文

LLM工具调用面试篇4

10. MCP 和 Agent Skill 的区别是什么?

MCP 和 Agent Skill 不是同类概念,不是竞争关系,而是互补的。

MCP 解决的是「Agent 怎么获得外部能力」,它把数据库、API、文件系统这些外部工具标准化封装成服务,Agent 通过 MCP 就能查数据、调接口、读写文件。

Skill 解决的是「Agent 拿到这些能力之后,该按什么步骤、什么标准来完成任务」,它把完成某类工作的知识和流程打包成可复用的模块。

简单记:MCP 是给 Agent 配的电脑和软件,Skill 是给 Agent 发的操作手册和 SOP。在实际系统里,两者经常同时工作,Skill 定义流程,流程中调用 MCP 提供的工具。

从定位说起:两者解决的不是同一个问题

很多人第一次接触这两个概念会觉得它们都跟「Agent 能做什么」有关,但仔细一想会发现,两者的目的和工作层次完全不同。

MCP 解决的是「Agent 怎么获得外部能力」。没有 MCP 之前,Agent 就是一个只会说话的语言模型,你让它查数据库它查不了,让它读文件它读不了,让它调 API 它也调不了。MCP 把这些外部工具标准化封装成独立的服务,Agent 连上 MCP Server 就能用这些工具了。所以 MCP 解决的是「从无到有」的问题,让 Agent 有能力去操作外部世界。

Skill 解决的是另一类问题:「Agent 有了这些能力之后,该怎么用」。你想,Agent 现在能查数据库了、能读文件了、能调 API 了,但面对一个「帮我做代码审查」的任务,它该先做什么后做什么?检查哪些维度?用什么格式输出?这些「知识和流程」,就是 Skill 要提供的。

用一个类比就很好理解。MCP 就像给新员工配电脑、装软件、开各种系统权限,这些是他「能做事」的前提。但光有电脑和权限是不够的,你还得给他一份操作手册,告诉他做代码审查的时候先检查什么、后检查什么、用什么标准判断、最后用什么模板写报告。这份操作手册就是 Skill。

MCP:让 Agent 有「手」

理解了两者的定位差异,先来展开看看 MCP。为什么说它是 Agent 的「手」?因为如果没有 MCP,Agent 就只会「说话」,不会「做事」。

MCP Server 暴露的 Tools、Resources、Prompts 就是 Agent 操作外部世界的手段。模型通过 Function Calling 触发这些工具,工具执行完把结果喂回对话。MCP 的粒度是「原子操作」,read_file(path)是一个 Tool,query_database(sql)是一个 Tool,每次调用做一件明确完整的事,执行结果立刻返回。模型能看到每个 Tool 的完整 schema,包括它叫什么名字、接受什么参数、返回什么格式。这种精确的可见性正是模型能准确判断「这个问题该调哪个工具」的基础。

简单说,MCP 让 Agent 从「只会聊天」进化成了「能真正干活」,这是一切上层能力的前提。

Skill:给 Agent 一份「操作手册」

有了 MCP 之后,Agent 确实能查数据、调 API 了,但面对一个复杂任务,它怎么知道该按什么顺序用这些工具?该关注哪些维度?该用什么标准判断质量?这就是 Skill 要解决的问题。

Agent Skill 是 Anthropic 在 2025 年 10 月推出的概念,同年 12 月把规范作为开放标准发布,目标是让这套能力模块格式能在不同 Agent 平台之间通用。每个 Skill 是一个文件夹,核心是一份 SKILL.md 文件,用 YAML frontmatter 声明名字和描述,正文写具体的执行指令和步骤。除了指令文件,Skill 还可以带上脚本(比如一个安全检查的 Python 脚本)、参考文档(比如团队的审查标准)、模板(比如报告的输出格式)。这些东西打包在一起,就构成了一个完整的「操作手册」。

Skill 和普通 prompt 最大的区别在于两点。

  • 第一,Skill 能被 Agent 自动发现。Agent 启动的时候会扫描可用的 Skill 列表,当用户提了一个任务,Agent 自己判断哪个 Skill 和这个任务相关,主动去加载,不需要你手动告诉它「用 code-review 这个 Skill」。
  • 第二,Skill 用了一套「渐进式加载」的机制来节省 context window。启动时只加载每个 Skill 的名字和一句话描述,大概每个 Skill 只占 30 到 50 个 token;只有当 Agent 判断某个 Skill 和当前任务相关时,才会加载完整的指令正文;执行过程中需要用到模板或参考文档时,才会进一步加载这些资源文件。这样就避免了把所有 Skill 的内容一股脑塞进上下文,浪费宝贵的 context window 空间。

所以 Skill 的粒度比 MCP 工具粗得多。MCP 的粒度是单个函数调用,比如read_filequery_database;Skill 的粒度是一个完整的工作流程,比如「代码审查」「数据分析报告」,内部可能涉及好几个步骤、调用好几个工具。

两者怎么配合工作

看到这里你可能会想,既然 MCP 提供工具、Skill 提供流程,那它们在实际系统里是怎么配合的?咱们用一个代码审查的场景走一遍就清楚了。

用户对 Agent 说「帮我审查一下这次提交的代码」。Agent 收到任务后,先扫描自己可用的 Skill 列表,发现有一个叫 code-review 的 Skill 和这个任务匹配度很高。于是 Agent 加载它的 SKILL.md 正文,读取里面的执行流程。这份 SKILL.md 长这个样子:

--- name: code-review description: "对代码进行全面审查,识别 bug、安全漏洞和性能问题" --- # 代码审查 ## 第一步:读取待审查的代码文件 读取用户指定的代码文件,理解功能和修改范围。 ## 第二步:执行安全检查 运行 scripts/check_security.py 对代码做自动化安全扫描。 ## 第三步:输出审查报告 使用 assets/report_template.md 的模板格式,输出结构化审查报告。

你看,SKILL.md 的作用就是告诉 Agent「做什么、按什么顺序做」,它就是一份操作手册。

但 Skill 只定义了流程,真正「动手」的时候还是得靠 MCP。Agent 执行第一步「读取代码文件」,需要调用文件系统 MCP Server 提供的工具:

# Skill 第一步说:读取待审查的代码文件 # Agent 发现 MCP 有 read_file 工具,于是调用它 code = mcp_client.call_tool("read_file", { "path": "src/auth.py" # 要审查的文件路径 })

执行第二步「安全检查」时,Agent 加载 Skill 自带的脚本scripts/check_security.py并执行。这就是 Skill 比普通 prompt 强的地方,它不只有文字指令,还能带可执行的脚本。

执行第三步「输出报告」时,Agent 加载 Skill 的assets/report_template.md模板,按照里面定义的格式把审查结果整理成结构化报告返回给用户。

整个流程的分工非常清晰:Skill 扮演「编排者」,定义了做什么、按什么顺序做、用什么标准做;MCP 扮演「执行者」,提供了每一步需要调用的具体工具。两者配合起来,Agent 才能既知道「该怎么做」,又有能力「真正去做」。

再看一个稍复杂的场景,你就能感觉到这种分工的威力。假设 Skill 定义的流程里有一步「如果改动涉及数据库表结构,额外执行权限合规检查」,这就是条件分支。

Agent 读到这条指令时,会先调用一个 MCP Tool 去扫描这次提交有没有改数据库 schema,拿到结果(布尔值)之后再决定要不要走那条分支;如果要走,就再调另一个 MCP Tool(比如query_permission_policy)去查合规规则,最后根据结果决定审查报告里是否要加一条严重级警告。

整个过程里,Skill 就像项目经理,拿着流程图和判断标准指挥执行;MCP 提供的每个 Tool 就像专业工人,各自只管做好一件小事。

缺了 Skill,Agent 拿着一堆工具不知道该什么时候用;缺了 MCP,Skill 再详细的流程也只是纸上谈兵。

面试回答这道题,第一个必须说清楚的是两者的定位差异:MCP 提供工具和数据的访问能力,解决的是「Agent 怎么做事」;Skill 提供完成任务的知识和流程,解决的是「Agent 该怎么做事」。一个是能力,一个是知识。

第二个关键点是粒度差异。MCP 的粒度是原子操作,每次调用做一件明确的事,schema 对模型完全可见;Skill 的粒度是工作流程,定义的是完成某类任务的完整步骤和标准,还可以附带脚本、模板等资源,通过渐进式加载按需使用。

第三个加分点是讲清楚两者的配合方式。Skill 编排流程,MCP 提供工具,Skill 指令里经常会调用 MCP 的工具来完成具体操作。如果能用代码审查这样的完整场景把两者的配合串起来,面试官能看出你不只是背了概念,而是真正理解了它们在系统里怎么协作的。

11. Function Calling、Skill、MCP 这三个有什么区别?

Function Calling 是最底层的调用协议,解决的是「模型怎么调函数」,模型输出结构化 JSON 告诉程序该调哪个函数、传什么参数。

MCP 在 Function Calling 之上做工具标准化,解决的是「工具怎么暴露给模型」,把数据库、API 这些外部能力封装成标准化服务,一次实现到处复用。

Agent Skill 在最上层做知识和流程的封装,解决的是「拿到工具之后按什么流程完成任务」,把执行步骤、标准、脚本、模板打包成可复用模块。

简单记就是:Function Calling 是语言,MCP 是工具箱,Skill 是操作手册。

为什么会有三个概念

这三个概念放在一起确实很容易让人迷惑,但其实它们各自解决的是完全不同层次的问题,是三层架构,不是三个竞争方案。

怎么理解呢?咱们先建立一个直觉感受:Function Calling 是「模型说:我要调这个函数」,MCP 是「工具服务说:我能提供这些函数」,Skill 是「操作手册说:用这些工具按这个流程做」。你看,三句话的主语不一样,说话对象不一样,粒度也不一样,这就是三者的本质差异。

再从时间线来看就更清楚了。

Function Calling 是最先出现的,当时的核心问题是「模型只会生成文本,怎么让它能触发外部调用」,所以 Function Calling 解决的是最基础的调用协议问题。

后来 Function Calling 普及了,大家发现一个新的痛点:每个应用都要自己写代码对接各种工具,数据库一套、文件系统一套、API 又一套,重复劳动太多了。MCP 就是在这个背景下出现的,它把工具的接入标准化了,一次实现到处复用。

再后来,工具有了、接入也标准化了,又冒出了新问题:Agent 有了一堆工具,但面对一个复杂任务,它不知道该按什么流程、什么标准来用这些工具。Skill 就是为了解决这个「知识和流程复用」的问题才诞生的。

三者的出现背景不同,自然解决的是不同层次的东西。

从「谁和谁通信」来看三者位置

理解三者最清晰的切入点是:每个机制发生在哪两个角色之间。

Function Calling发生在模型和函数之间,是单次调用的格式规范。模型生成tool_callsJSON 告诉宿主程序「调这个函数、参数是这个」,宿主程序执行完把结果以 tool 消息形式喂回去。这一切发生在单个 Agent 内部,是最底层的「调用语言」,整个系统靠这个让模型触发实际动作。

理解了 Function Calling 是最底层的通信语言,往上一层就是MCP。它发生在 AI 客户端(MCP Client)和工具服务(MCP Server)之间,是工具的标准化封装协议。Client 连上 Server 后自动发现工具列表,把工具定义转换成 Function Calling 格式喂给模型。所以 MCP 本质上是对 Function Calling 的封装和管理,它让工具从「应用内的代码片段」变成「独立的标准化服务」,一次实现到处复用。

再往上一层就到了Skill,它发生在 Agent 和知识模块之间。Agent 启动的时候会扫描可用的 Skill 列表,当用户提了一个任务,Agent 自己判断哪个 Skill 和这个任务相关,主动去加载 SKILL.md 里的执行指令、脚本和模板。Skill 的粒度比 MCP 工具粗得多,「代码审查」是一个 Skill,「数据分析报告」是一个 Skill,每个 Skill 内部可能涉及好几个步骤、调用好几个 MCP 工具。

三者的层级依赖关系

搞清楚了三者各自的位置,接下来一个很自然的问题是:它们之间有没有上下级关系?答案是有的,而且层级非常明确。

为什么 Function Calling 在最底层?

因为它是模型触发工具调用的「语言」,没有这套语言,模型就没办法告诉外部「我要调哪个函数、传什么参数」,一切上层能力都无从谈起。

MCP 为什么在它之上?因为 MCP 做的是工具管理和标准化封装,但归根到底,MCP Server 暴露的工具最终还是要通过 Function Calling 的格式传给模型、让模型来触发,所以 MCP 天然依赖 Function Calling。

那 Skill 为什么在最上面?因为 Skill 定义的是使用工具完成任务的流程和标准,Agent 按照 Skill 里的指令去执行,每一步需要调工具的时候,还是得靠 MCP 发现工具、靠 Function Calling 触发调用。

所以完整的链条是:Skill(定义流程)-> MCP(提供工具)-> Function Calling(模型触发调用),从上到下三层,每一层都建立在下一层的基础之上,各司其职。

用一个完整故事串联三者

把三者放在同一个场景里感受一下各层分工。用户对 Agent 说「帮我分析最近三个月的销售数据,找出下滑的产品线,给改进建议」。

首先是Skill 层在起作用。Agent 收到任务后,扫描自己可用的 Skill 列表,发现有一个叫「数据分析报告」的 Skill 和这个任务高度匹配。于是 Agent 加载这个 Skill 的 SKILL.md 正文,读取里面定义的分析流程:第一步从数据库取数据,第二步用 Python 做趋势分析,第三步按模板写分析报告。Skill 就像一份菜谱,把整个任务的步骤和标准安排得明明白白。

然后是MCP 层在起作用。执行第一步「从数据库取数据」的时候,Agent 的 MCP Client 已经连着数据库 MCP Server 和 Python 执行器 MCP Server,自动知道有query_databaserun_python这些工具可用。MCP 就像厨房,里面的厨具和食材随时可以取用,不需要任何手动配置。

最底层是Function Calling在起作用。模型判断需要查数据库,输出tool_calls: query_database(sql="SELECT product, revenue FROM sales WHERE date >= '2026-01-01'"),MCP Client 把这个请求路由到数据库 Server 执行,拿到结果后模型继续处理。接着模型输出调用 Python 执行器的 Function Calling,对数据做趋势分析。最后 Agent 按 Skill 里定义的报告模板把结果整理成结构化的分析报告返回给用户。

整个流程里 Skill 做流程编排、MCP 做工具管理、Function Calling 做模型和工具的通信,三层分工明确,缺哪层都不完整。

12. 什么是 A2A 协议?它和 MCP 协议的区别是什么?

A2A 是 Google 发布的开放协议,专门解决多个 AI Agent 之间怎么互相通信协作的问题。

我理解它和 MCP 的区别是这样的:MCP 解决的是「单个 Agent 怎么连工具和数据」,A2A 解决的是「多个 Agent 之间怎么分工协作」。

一个 Agent 通过 A2A 可以把子任务委托给另一个专业 Agent,接收方按自己的 Skill 声明承接,支持异步长任务和流式推送结果。

两者是互补的,不冲突:MCP 向下连工具,A2A 向上连 Agent,在复杂的多 Agent 系统里这两个通常都要用到。

为什么单个 Agent 不够用,上下文和专业边界

要理解 A2A 是干什么的,得先把「单 Agent 的天花板」搞清楚。

一个 Agent 的本质是:一个 LLM + 一组工具 + 一段上下文窗口。这三个维度都有自己的天花板。

首先是工具数量的限制,你不可能给一个 Agent 装 100 个工具,模型处理起来效率极低,容易混乱。

其次是上下文窗口的限制,128K tokens 听起来很多,但复杂任务积累的中间产物,搜索结果、草稿、反思记录,会很快把窗口塞满,后面的生成根本顾不上前面写了什么。

最后是专业能力的限制,同一个 Agent 既做代码审查又做市场分析,不如专门为各自任务配置或微调的 Agent 效果好。

举一个具体任务:「帮我做一份 AI 编程工具的竞品分析报告,要有行业趋势、技术对比、商业模式分析和 SWOT」。让单个 Agent 做这件事,问题是:搜索结果和草稿会把上下文撑满,等到写 SWOT 时,前面的行业趋势分析早就被挤出了有效注意力范围;而且市场调研和技术分析需要不同的知识侧重,一个 Agent 很难全面兼顾。

你可能会问,拆成多个 Agent 协作,上下文压力就真的变小了吗?

关键就在这里:调度 Agent 把「做行业趋势分析」委托给市场 Agent,市场 Agent 自己去搜几十个网页、写草稿、反复迭代,这些中间过程都在它自己的上下文里。任务做完,它只把最终结论(比如一份几百字的摘要)通过 A2A 返回给调度 Agent。

调度 Agent 的上下文里只多了一份摘要,而不是几十个网页的原文。这就把「调研过程」的上下文压力隔离在了市场 Agent 内部,调度 Agent 保持轻量,这是多 Agent 协作在上下文层面的核心收益。

解决方案很自然:把任务拆开,交给不同的专业 Agent 并行处理,最后汇总。一个「调度 Agent」负责任务拆分,「市场分析 Agent」专门做趋势调研,「技术研究 Agent」专门做工具对比,每个只需聚焦自己擅长的部分,整体效果远好于一个 Agent 包揽所有。

多 Agent 的基础问题,Agent 之间怎么互相认识?

多 Agent 系统有一个绕不开的基础问题:Agent A 要把任务委托给 Agent B,它得先知道 B 能做什么。但怎么知道呢?

最笨的方案是写死配置:A 的代码里硬编码「B 可以做竞品分析」。这样太脆了,B 的能力一变,A 的代码就得改,根本没法维护。

更好的方案是让 B 主动「发名片」,声明自己能做什么,A 来查。这就是 A2A 里Agent Card的设计思路。

每个 A2A Agent 都在一个约定位置发布一张 JSON 格式的名片(A2A 规范推荐的路径是/.well-known/agent-card.json,早期版本叫agent.json,两种路径在社区里都能看到),里面写清楚自己叫什么、能做哪类任务(Skill 列表)、支不支持流式返回、支不支持异步回调(push notification,任务完成后主动通知调用方)。任何想和它协作的 Agent,先去拿这张名片,再决定要不要把任务委托给它。

Agent Card 里最关键的是Skill 列表,每个 Skill 描述一类能力,比如「竞品分析」「行业趋势分析」,并带有示例输入。调度 Agent 用这些 Skill 描述来做任务路由决策,「这个任务和哪个 Agent 的哪个 Skill 最匹配?」。

这套机制让整个多 Agent 系统变得可插拔:新加一个 Agent,发布它的 Agent Card,调度 Agent 就能自动发现和利用它,完全不需要改调度 Agent 的代码。

Task,A2A 里的一等公民

A2A 里任务协作的基本单位是Task

调度 Agent 把一段任务委托给另一个 Agent,就是创建一个 Task;接收方执行这个 Task;完成后把结果作为 Task 的产出(artifacts,可以是文本、文件等)返回。

Task 有完整的生命周期状态管理。一个 Task 刚被创建时是 submitted 状态,表示已提交、等待处理。接收方开始执行后变为 working 状态,最终根据执行结果进入 completed(成功)或 failed(失败)状态。

为什么需要这么完整的状态机?因为 A2A 专门为长时间任务设计。

一个「竞品分析」任务可能要跑几分钟,先搜索、再整理、再写报告,不可能让调度 Agent 同步等着。

所以调度 Agent 提交任务后可以去处理其他事情,通过轮询状态或者 push notification(任务完成时接收方主动回调通知)来得知任务完成了。这套状态管理机制,正是为了支持这种异步长任务协作的。

调度 Agent 的视角很干净:给 Agent B 提交一个 Task,定期查一下状态,等到completed了去取 artifacts。整个过程不需要知道 B 内部用了什么工具、调了几次 LLM,完全黑盒。每个专业 Agent 自己的实现对外不可见,这正是解耦的意义所在。

A2A 的架构本质,Agent 的微服务化

如果你有后端开发经验,A2A 其实不陌生:它就是 Agent 世界里的微服务架构

在微服务架构里,每个服务是独立部署的 HTTP 服务,有自己的 API 文档,服务之间通过 HTTP 互相调用,支持异步消息队列处理耗时任务。A2A 的设计几乎照搬了这套思路,只不过把「服务」换成了「Agent」。

怎么理解这个对应关系呢?Agent Card 就像 API 文档,告诉别人「我能做什么、怎么调用我」。Task 状态机就像异步消息队列,支持提交任务后去做别的事、完成了再来取结果。而.well-known下的 Agent Card 就像微服务注册中心里的一条记录,让其他 Agent 能自动发现你。

所以每个 A2A Agent 对外其实就是一个 HTTP 服务,任何支持 A2A 的系统都可以发现它、向它发任务、接收结果,不绑定特定的 AI 框架,也不依赖特定的编程语言。这个设计理念和 MCP 是一脉相承的:MCP 让工具成为独立标准化服务,A2A 让 Agent 成为独立标准化服务。

A2A 和 MCP 的关系,一纵一横,各管一层

理清两者关系最简单的方式是看方向:MCP 是 Agent 向下连工具,A2A 是 Agent 向外连其他 Agent。

具体来说,一个专业 Agent 内部,用 MCP 连各种工具,比如数据库、浏览器、代码执行器,用 Function Calling 让 LLM 触发这些工具调用,这是「纵向」的连接。而多个 Agent 之间需要分工协作的时候,就用 A2A 来互相通信、委派任务、接收结果,这是「横向」的连接。两个协议解决的是完全不同维度的问题,不存在谁替代谁。

打个比方,MCP 就像公司里每个员工的「工具箱」,决定了这个人能用什么工具干活。A2A 就像公司里的「协作流程」,决定了不同岗位的人怎么分工、怎么交接任务。工具箱和协作流程是两回事,缺了哪个都不行。在一个复杂的多 Agent 系统里,这两者通常同时在用:MCP 负责每个 Agent 和工具之间的纵向连接,A2A 负责 Agent 之间的横向协作通信。两层协议各管一个维度,合在一起才能支撑起真正复杂的 Agent 系统。

http://www.jsqmd.com/news/710834/

相关文章:

  • Box86深度解析:ARM架构上的x86用户空间模拟器技术实现机制
  • 英语单词发音MP3音频批量下载方案:构建海量语音库的技术实现
  • 突破QQ音乐限制:高效QMCFLAC转MP3完整指南
  • HCLA第五次作业
  • 深度解析:如何通过三层架构设计实现Cursor Pro功能的技术实现方案
  • 5分钟解锁Windows桌面新美学:用TranslucentTB打造你的专属透明任务栏
  • 山东大学软件学院项目实训-基于语言大模型的智能居家养老健康守护系统-个人博客(三)
  • 5分钟搞定!魔兽争霸III WarcraftHelper插件完全指南:解锁300帧+宽屏完美体验
  • 告别调参玄学:用PANNs预训练模型搞定音频分类,附AudioSet实战代码
  • 第八届智源大会即将在6月12日-13日正式开启
  • SeanLib系列函数库-W25QXX
  • 从LeetCode到真实项目:DAG(有向无环图)在任务调度和依赖管理中的实战避坑指南
  • 人工海马网络(AHN)架构解析与长序列处理优化
  • 写给Ivy(我自己你信吗:))啊······
  • Bibata Gruvbox Yellow光标主题:Linux桌面美化与视觉统一方案
  • 2026降AI率工具实测:AI占比90%也能稳降到个位数
  • 终极指南:用Ryujinx模拟器在电脑上免费畅玩Switch游戏的完整攻略
  • Java 基础(十一)反射
  • SILENTTRINITY:基于Python异步架构的现代C2渗透测试框架解析
  • Windows电脑终极指南:如何用APK安装器直接运行安卓应用
  • 【Python】错误和异常
  • 亲测5款论文降AI工具:AIGC疑似度从90%降到4%实用指南
  • LycheeMemory:高效处理长上下文任务的创新解决方案
  • 星穹铁道跃迁记录分析工具:5分钟掌握抽卡数据可视化
  • Git 命令大全测试
  • 后端全栈轻松写前端!用 Vue,自动生成可维护 React
  • 终极RPG Maker解密工具:如何快速提取游戏资源与项目文件
  • 别再只用filter: blur()了!聊聊backdrop-filter在Vue3音乐播放器项目中的实战应用
  • RAG 工程实践:分块策略、Rerank、混合检索,这些细节决定效果上限
  • 手机电池寿命翻倍秘诀:BatteryChargeLimit智能充电限制器