这是近几年 Agent 面试最高频的“送命题”
如果你最近面过 Agent 相关岗位,大概率遇到过这个问题:Function Calling、MCP、A2A 到底有什么区别?
很多人的第一反应是把三个词并列在一起背定义:“Function Calling 是大模型调用函数的机制,MCP 是大模型连接外部工具的标准,A2A 是智能体之间通信的协议。”背完之后,面试官如果再追问一句“那它们在工程上分别解决了什么痛点”,很多人就卡住了。
这个问题的杀伤力在于:它看起来是考概念背诵,实际上是在考察你有没有完整经历过 Agent 工程的工具调用链路。
只调用一个函数、接入一个外部 API、协调多个智能体协同,这三件事的复杂度完全不同。对应到技术上,它们分别指向 Function Calling、MCP 和 A2A。如果你只是见过 Demo、读过文档,没有真正区分过它们的边界,很容易把三个概念混成一团。本文就站在工程落地的角度,把这层关系拆开讲清楚。
1. 先说结论:这三个东西根本不在同一个层次
先把核心判断放在前面。
Function Calling 是“模型按约束调用函数”的推理机制;MCP 是“模型按标准协议调用工具”的接入规范;A2A 是“智能体之间互相通信和协作”的交互协议。
这三者不是同义词,也不是前后替代关系,而是 Agent 能力分层中的不同环节。打一个不算太精确的类比:
- Function Calling 相当于“本地函数签名约定”,解决的是模型如何把自己的意图映射成一次程序调用;
- MCP 相当于“RESTful API 标准”,解决的是不同工具如何被统一接入、发现、调用;
- A2A 相当于“服务间的通信协议”,解决的是一个 Agent 如何把任务委托给另一个 Agent。
从演进关系看,它们是一条链上逐渐外扩的过程:模型先要学会调用单个函数,再要对接多种外部工具,最后还要和别的智能体协作。每一层解决的都是上一层做不了的事。
理解了这一点,面试官那个问题的答题框架就有了:不是背定义,而是讲清楚每一层解决什么问题、由什么机制承载、在实际工程里怎么落地。
2. Function Calling:把“模型想要做的事”翻译成“程序能执行的调用”
2.1 它解决的最原始痛点
先回到最早的场景。在没有 Function Calling 之前,你想让大模型完成一个需要程序介入的任务,比如查询天气、计算运费、写数据库,流程非常别扭。
模型只会生成文本,它不会真的去调用你的代码。传统做法是:你让模型输出一段 JSON,再写一套正则或关键词匹配逻辑去解析这段 JSON,最后手动拿着解析结果去调用对应函数。模型可能答非所问,可能格式跑偏,整个链路既脆弱又难维护。
Function Calling(也叫工具调用、函数调用、Tool Use)的出现,把“从自然语言到函数参数”这件事变成了模型原生支持的标准动作。你在请求里声明有哪些函数,模型在生成回复时,会先推理出应该调用哪个函数、参数填什么,然后以结构化格式返回调用信息,由你的程序真正执行。
2.2 一个最小的 Function Calling 示例
以 OpenAI 风格接口为例,核心就是在请求里声明一个functions或tools列表:
{ "model": "gpt-4o-mini", "messages": [ { "role": "user", "content": "北京明天天气怎么样?" } ], "tools": [ { "type": "function", "function": { "name": "get_weather", "description": "查询指定城市和日期的天气", "parameters": { "type": "object", "properties": { "city": { "type": "string", "description": "城市名" }, "date": { "type": "string", "description": "日期,格式 YYYY-MM-DD" } }, "required": ["city", "date"] } } } ] }模型返回时不会直接说“北京明天晴”,而是返回类似下面的结构:
{ "tool_calls": [ { "id": "call_abc123", "type": "function", "function": { "name": "get_weather", "arguments": "{\"city\":\"北京\",\"date\":\"2025-01-20\"}" } } ] }然后你的程序负责真正执行get_weather("北京", "2025-01-20"),再把结果作为新的消息回传给模型,让模型基于真实温度数据生成答案。
你可以把 Function Calling 理解为“大模型参与了一次合同谈判”:模型根据用户需求,输出一份结构化的“调用合同”,程序拿这份合同去执行,执行结果就是“履约证据”,模型再依据证据组织最终回复。
2.3 Function Calling 的天花板在哪里
Function Calling 很实用,但它有一个明显局限:它是面向单模型的编程接口。
每个模型厂商都有自己的实现细节。OpenAI 有tools参数,Anthropic 有tools和tool_use块,国产模型有的叫functions、有的叫tools,参数描述语法也各不相同。如果你针对 OpenAI 写了一套函数调用逻辑,换一个模型再接入时,通信格式基本要重写一遍。
更麻烦的是,工具本身也是“焊死”的。你声明了get_weather,代码里就必须有对应的get_weather实现,调用逻辑、参数校验、异常处理都写在你的业务代码里。工具多了以后,你会在工程里看到大量散落的函数声明、参数校验和调用分发代码。
这就像早期分布式系统里,每个服务都自己定义 RPC 接口,服务之间能通信但没法互操作。于是,标准化的问题来了。
3. MCP:把“一堆零散工具”变成“一套标准接口”
3.1 MCP 在解决什么
MCP(Model Context Protocol,模型上下文协议)最早由 Anthropic 提出,现在已经成为 Agent 工具接入的事实标准之一。它的设计目标和 REST API 有点类似:定义一套统一的客户端/服务端协议,让模型能够通过同一套规范发现、连接和调用任意工具。
在没有 MCP 之前,你每接一个新工具,都要为它写一套自定义封装。接数据库要写一个查询封装,接 Git 要写一个命令封装,接 Figma 要写一个设计稿读取封装。这些封装里的鉴权、格式转换、错误处理逻辑大量重复。
有了 MCP 之后,工具提供方只需要实现一个“MCP Server”,把能力声明为工具;Agent 应用作为“MCP Client”去连接这些 Server,并通过统一协议调用工具。工具不需要知道模型是什么,模型也不需要知道工具内部怎么实现。
3.2 MCP 的三个核心角色
MCP 体系里通常有三个角色:
| 角色 | 作用 | 类比 |
|---|---|---|
| MCP Host | 承载 Agent 运行的应用,比如 Claude Desktop、Cursor、Codex | 浏览器 |
| MCP Client | Host 内部负责与 Server 建立连接的协议客户端 | HTTP Client |
| MCP Server | 暴露一个或多个工具的外部能力服务 | 后端 API 服务 |
整个调用链路大致是:用户的自然语言请求进入 Host,Host 里的 Agent 判断需要调用某个工具,MCP Client 按协议找到对应 MCP Server,Server 执行真实逻辑,把结果返回给模型。对模型来说,MCP 工具和本地 Function Calling 在“函数调用”这个层面感受是一致的;差别在于,MCP 把工具的声明、发现、连接、鉴权、调用、返回都标准化了。
3.3 一个 MCP Server 的轻量示例
MCP 官方提供了 Python SDK,用FastMCP可以很快写一个内置工具。下面是一个查询“城市温度”的最小 Server 示例,文件命名weather_server.py:
from mcp.server.fastmcp import FastMCP mcp = FastMCP("weather-demo") # 内置一个模拟的温度查询工具 @mcp.tool() def get_temperature(city: str) -> str: """根据城市名返回模拟温度""" data = {"北京": "5℃", "上海": "12℃", "广州": "20℃"} return data.get(city, "暂不支持该城市") if __name__ == "__main__": mcp.run()运行:
pip install mcp python weather_server.py然后,在支持 MCP 的客户端(比如 Claude Desktop、Cursor、Codex)里配置该 Server 的地址,客户端就能自动发现get_temperature这个工具,并在 Agent 推理需要时自动调用。
完整配置方式取决于客户端,这里只演示 MCP Server 侧的核心逻辑。如果你在 Cursor 或 Codex 里接入过 MCP,你会发现流程基本一致:安装 SDK、写 Server、暴露工具、客户端填入配置、授权后即可对话使用。
3.4 MCP 的价值与边界
MCP 真正的价值不是取代 Function Calling,而是让工具接入从“点对点集成”变成了“一次接入、到处使用”。工具开发者只需要维护一个 MCP Server,就能被多个支持 MCP 的 Agent 客户端复用;Agent 开发者也不需要为每个外部系统写专属适配器。
但它不是万能的。MCP 解决的只是“工具调用标准化”问题,它不负责“多个智能体如何配合完成任务”。你可以把 MCP 理解成给 Agent 配了更多“手脚”,但“多个 Agent 之间如何对话、如何分工、如何交付结果”,是 MCP 管不到的上层问题。
4. A2A:从“一个人干活”到“一整个团队协作”
4.1 为什么需要 Agent 和 Agent 之间通信
当 Agent 的能力越来越强、场景越来越复杂时,一种新的需求冒出来了:一个 Agent 搞不定的任务,能不能让多个专长不同的 Agent 协作完成?比如,一个前端 Agent 负责生成页面,一个后端 Agent 负责生成接口,一个测试 Agent 负责自动审查。每个 Agent 跑在各自环境里,使用各自的工具链和模型。如果它们之间不能通信,任务就只能由一个超大 Agent 全包,或者靠外部流程编排硬串,这两种方式在复杂任务下都会变得笨重。
谷歌在 2025 年发布的 A2A(Agent2Agent)协议,就是为了解决这个问题。它的定位是:定义一套智能体之间互相发现、通信、协商和任务协作的开放协议。
4.2 A2A 的核心设计思想
A2A 在设计上借鉴了 HTTP、JSON-RPC 等成熟协议的经验。它有几个核心概念:
| 概念 | 作用 |
|---|---|
| Agent Card | 智能体的“名片”,描述能力、端点和认证方式 |
| Agent 间消息 | 基于 JSON-RPC 的标准化消息,用于任务分发和状态同步 |
| A2A Client/Server | 每个 Agent 既可以作为 Client 发起协作,也可以作为 Server 接收任务 |
两个 Agent 协作的基本流程是:发起方通过 Agent Card 发现目标 Agent 的能力和入口,然后发送任务请求,接收方确认后异步执行,通过消息不断同步进度,最终返回结构化结果。因为通信协议是标准化的,不同框架、不同模型底座训练的 Agent 理论上可以互相协作。
从目前公开材料看,A2A 强调的不是“让模型更聪明”,而是“让不同团队开发的独立 Agent 能以开放方式见面、协商、分工”。它更像是在 Agent 之间建立了一层“外交渠道”。
4.3 A2A 与 MCP 的关系
A2A 和 MCP 不是替代关系,而是互补关系。
一个常用的比喻是:MCP 是给 Agent 接“工具库”,A2A 是给 Agent 找“合作伙伴”。一个 Agent 内部要用 Function Calling 调用本地方能,用 MCP 接入外部工具;当它发现自己搞不定整个任务时,再通过 A2A 把子任务委托给其他 Agent。
因此,A2A 通常处于更上层。在实际工程中,一个大型任务可能由 Agent A 通过 A2A 协议拆给 Agent B、Agent C,每个 Agent 内部再用 MCP 调用各自的工具,整个体系形成一种“协作层 + 工具层 + 函数层”的三级结构。
5. 一张表看懂三者区别
面试中如果能画出这张对比表,基本就赢了一半:
| 维度 | Function Calling | MCP | A2A |
|---|---|---|---|
| 核心定位 | 模型调用函数的推理机制 | 模型调用工具的接入标准 | 智能体之间的通信协议 |
| 解决层次 | 单模型内部 | 单 Agent 对接外部工具 | 多 Agent 协同 |
| 主要提出方 | OpenAI 等模型厂商 | Anthropic | 谷歌 |
| 通信方向 | 模型 → 函数 | Agent 客户端 → MCP Server | Agent → Agent |
| 类比 | 本地函数签名 | RPC / REST 标准 | 服务间通信 / 外交协议 |
| 主要承载格式 | 模型 API 的 tools/tool_calls | JSON-RPC 2.0 等通道的命令交互 | JSON-RPC 消息 + Agent Card |
| 典型场景 | 模型需要按结构调用一个函数 | 接数据库、Git、Figma 等各种外部工具 | 多 Agent 分工完成复杂任务 |
从字面看,三个词都有“调用”或“交互”的味道,但抽象层级完全不同。Function Calling 是单点能力,MCP 是点对面的接入标准,A2A 是面对面(Agent 对 Agent)的协作协议。
进一步说,三者也不是互斥的,工程上经常组合使用。比如一个 Agent 用 Function Calling 调用内部函数,通过 MCP 连接外部工具,再通过 A2A 把任务委托给另一个 Agent。这个组合关系也是面试官常爱追问的“联系”。
6. 一次完整的工程调用链路:从 Function Calling 到 MCP
为了把“联系”讲清楚,这里给一个相对完整的工程假设。假设你在写一个会议安排 Agent,用户说“帮我查一下明天下午两点有没有空会议室,有的话订一间,并把会议邀请发给参会人”。
如果不用任何协议,你需要在代码里硬写查询会议室、预定会议室、发送邀请三个函数,再写一堆判断逻辑让模型选择、调用。用了 Function Calling,流程变成了:
# 伪代码:Function Calling 的标准调用循环 tools = [ {"type": "function", "function": {"name": "query_meeting_rooms", ...}}, {"type": "function", "function": {"name": "book_meeting_room", ...}}, {"type": "function", "function": {"name": "send_invite", ...}}, ] while True: response = model.chat(messages, tools=tools) if response.tool_calls: for call in response.tool_calls: result = execute_local_function(call.function.name, call.function.arguments) messages.append(tool_result_message(call.id, result)) else: return response.content这段代码展示了核心机制:模型根据用户问题判断该调用哪个函数,程序拿到函数名和参数后执行,再把执行结果回填给模型。模型继续推理是否还需要调用更多函数,直到没有新的工具调用请求,才生成最终回复。
如果进一步把查询会议室、预定会议室、发送邀请三个操作都做成 MCP Server,那么上面的循环就变成了通用的 MCP 调用循环:
from mcp import ClientSession # 连接到 MCP Server,自动发现可用工具 async with ClientSession(transport) as session: tools = await session.list_tools() # 把 tools 映射给模型 response = await model.chat(..., tools=tools) for call in response.tool_calls: result = await session.call_tool(call.function.name, call.function.arguments) messages.append(tool_result_message(call.id, result))区别非常明显:前者需要你自己写execute_local_function,并且每增加一个工具就要改一次分发逻辑;后者通过 MCP Client 自动发现工具、统一调用,业务代码里不再出现散落的函数映射。这就是 MCP 的工程价值。
7. 面试回答参考:这三层怎么组织语言
回答这类问题时,建议不要一上来就背定义,而是先给判断框架:“这三者不是同一维度的东西,而是 Agent 技术栈不同层级的能力。”接着可以这样展开:
- Function Calling 是模型侧的能力机制。它定义了模型如何在推理时选择函数、生成参数、返回结构化调用结果。属于单模型内部的行为约束。
- MCP 是工具接入侧的标准化协议。它解决的是 Agent 与外部工具之间的互通问题,让工具实现一次、被多个 Agent 复用。属于单 Agent 向外扩展能力的通道。
- A2A 是智能体与智能体之间的通信协议。它解决的是多个独立 Agent 如何发现彼此、拆分任务、同步状态和返回结果。属于多 Agent 协作的编排层问题。
然后再补一句连接点:实际工程中它们是叠加关系,一个 Agent 内部可以用 Function Calling 处理模型推理,用 MCP 接入外部系统,需要时再用 A2A 把子任务委托给其他 Agent。这样回答既有层次感,又有工程视角,比单纯背概念强很多。
8. 常见误区与面试追问
8.1 “MCP 是不是取代了 Function Calling?”
不是。MCP 是工具接入规范,Function Calling 是模型推理机制。MCP 让工具更容易被模型调用,但底层仍然需要模型按照调用约定输出函数名和参数。换句话说,MCP 里的工具调用成功,基础仍然落在了正确的函数参数生成上。如果模型不具备稳定的函数参数输出能力,MCP 也帮不上忙。
8.2 “A2A 出现后,是不是不用学 MCP 了?”
不是。A2A 面向 Agent 与 Agent 协作,不解决单个 Agent 如何连接数据库、读取文件、调用 Web API 的问题。即使所有 Agent 都能通过 A2A 互相通信,每个 Agent 内部还是要有工具执行能力。MCP 仍然是单 Agent 工具接入的重要方案。
8.3 “本地模型支持 Function Calling 吗?支持 MCP 吗?”
越来越多的本地模型支持 Function Calling,但表现差异较大。小参数模型在参数约束、工具选择准确率上明显弱于大模型。MCP 本质上是客户端与服务端之间的协议,本地模型能不能用 MCP,取决于承载模型的 Host 是否实现了 MCP Client。换句话说,模型本身不直接“支持 MCP”,MCP 是客户端侧的标准化能力。
8.4 “MCP 和 Computer Use 有什么区别?”
Computer Use 是模型直接操作图形界面,理解屏幕截图、点击按钮、键入文字,相当于让模型“用鼠标键盘操作软件”。MCP 是让模型通过结构化协议调用工具接口,不依赖图形界面。前者适合没有 API 的旧系统,后者适合有明确接口的场景。二者可以互补,但不是同一类技术。
8.5 “需要自己实现 MCP Server 吗?”
看场景。如果是接一个已有 API,并且社区已经有人写好了 MCP Server,直接配置使用即可,不用重复造轮子。如果是对接内部系统,或者现有 Server 不满足需求,再自己写。当前各大 Agent 产品都在支持 MCP,社区生态里已经有不少常用系统的现成 Server,搜索相关关键词即能找到。
8.6 “A2A 落地了吗?”
A2A 是比较新的协议,目前更多处于生态建设和框架适配阶段。部分 Agent 框架已开始引入 A2A 模式支持多智能体协作,但大规模生产环境落地还需要时间。面试中谈到这一点时,可以表达“关注其生态成熟度,同时并行建设内部的多 Agent 应用基础设施”。
9. 工程实践建议
9.1 面向面试:答题要有分层结构
不要背三个孤立定义。核心是“分层”判断:Function Calling 是模型侧推理机制,MCP 是工具接入标准,A2A 是 Agent 间协作协议。每一层给出一个类比、一个工程痛点、一个典型落地场景即可。
9.2 面向项目:优先从 Function Calling 起步
如果你的项目刚起步,不要一上来就引入 MCP 和 A2A。先在模型对话能力基础上,把 Function Calling 跑通,写清楚函数声明、参数校验、执行分发、错误处理这四个环节。等工具数量明显增加、每次接入新工具都产生重复劳动时,再抽象出 MCP Server 层。过早引入协议会让小项目变得复杂。
9.3 面向架构:工具定义与实现分离
无论用不用 MCP,都建议把“工具声明”和“工具实现”分开。工具声明描述函数名、参数、用途,是给模型看的;工具实现是真实执行逻辑。两者分离后,从 Function Calling 迁移到 MCP 时只需改造声明层的接入方式,不用动业务实现,重构成本会低很多。
9.4 面向多 Agent:先想清楚边界再上 A2A
多 Agent 协作不是锦上添花,而是复杂度放大器。如果你的任务可以被单一 Agent 完成,不要为了“上 A2A”而上 A2A。只有当任务确实存在明确领域边界、多个 Agent 各自独立维护、且协作价值大于通信开销时,再引入 A2A 层。先定义好 Agent Card 和能力边界,再谈通信协议,避免出现“协作五分钟,通信两小时”。
10. 总结与延伸思考
把三个概念放在一张时间线上看,其实是一条清晰的技术演进路径:Function Calling 让模型有了“调用函数”的基础能力;MCP 让工具的接入和复用不再各自为战;A2A 则试图让智能体之间找到统一的“外交语言”。它们不是竞争关系,而是不同层级的配套能力。
对于开发者来说,最重要的不是记住这三者的名词定义,而是理解它们分别处在 Agent 技术栈的哪一层、各解决什么工程痛点。如果你能把“函数层、工具层、协作层”这个框架讲清楚,再配合一两个自己实践过的调用链路或接入案例,这个面试题基本就稳了。
如果面试官继续追问“给你一个项目,你会怎么选型”,可以考虑这样回答:先看项目是否需要大模型,再看是否需要大模型主动调用外部工具,然后评估工具数量与复杂度,最后才考虑是否需要多 Agent 协作。这个决策顺序本身,就是对概念边界最好的证明。