ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

大模型协议演进:函数调用、MCP与A2A协同实战指南

大模型协议演进:函数调用、MCP与A2A协同实战指南 1. 大模型协议演进的底层逻辑1.1 从单点智能到系统协作的必然路径大模型刚出来那会儿大家最直观的体验就是“你问它答”本质上是一个高级的文本补全器。但真正把它塞进业务系统里跑一圈就会发现光会聊天远远不够。模型需要查数据库、调接口、读文件、发消息甚至要跟另一个模型协同干活。这时候函数调用、MCP、A2A这三层协议就依次登场了。我习惯把这三者比作一个公司的运作方式。函数调用是“员工手册”规定了每个岗位能干什么、需要什么材料MCP 是“内部OA系统”把公司里所有资源统一编目让任何人按同一套规则取用A2A 则是“跨部门协作流程”解决的是两个独立团队之间怎么对接任务、怎么同步进度的问题。三者不是替代关系而是层层递进、各管一段。从技术演进的视角看这个顺序不是拍脑袋定的。最早大家用 Prompt Engineering 硬编码工具描述模型输出一段 JSON 再去解析极其脆弱。后来 OpenAI 在 2023 年推出 Function Calling把工具描述结构化模型直接输出符合 schema 的调用请求这才算有了正式协议。但 Function Calling 只解决了“模型到工具”这一跳工具本身怎么注册、怎么发现、怎么复用还是各写各的。于是 Anthropic 在 2024 年推出 MCP把工具、资源、提示词统一成标准接口任何支持 MCP 的客户端都能即插即用。再往后当多个 Agent 需要互相委托任务时Google 在 2025 年牵头搞了 A2A定义了 Agent 之间的能力发现、任务生命周期和消息格式。理解这条脉络比死记每个协议的字段重要得多。因为实际落地时你往往需要同时用到三者用 MCP 管理本地工具用函数调用触发具体动作用 A2A 跟外部 Agent 交换结果。1.2 三个协议各自解决什么问题先把这个说清楚后面展开才不会乱。函数调用解决的是“模型如何表达它想调用某个工具”。它定义了一套 JSON Schema 格式让模型在对话中输出结构化的调用意图而不是自由文本。核心价值在于确定性——你拿到的是一个可解析的对象不是一段需要正则匹配的字符串。MCP解决的是“工具和资源如何被标准化地暴露和发现”。它把外部能力抽象成 Server客户端通过标准协议连接支持工具列表查询、资源读取、提示词模板获取。核心价值在于复用性——写一次 MCP ServerClaude Desktop、Cursor、各种 IDE 都能直接用。A2A解决的是“多个 Agent 之间如何协作”。它定义了 Agent Card 来描述能力用 Task 来管理任务状态支持流式更新和推送通知。核心价值在于互操作性——不同厂商、不同框架的 Agent 可以互相调用不用为每个组合写适配层。这三者的关系我用一个实际场景串一下你在 IDE 里让 AI 帮你修一个 bug。IDE 通过 MCP 连接到本地文件系统 Server 和 Git Server模型通过函数调用决定读取哪个文件、执行什么命令修完之后如果需要部署再通过 A2A 把部署任务委托给运维 Agent。整条链路里三个协议各司其职缺一不可。1.3 为什么现在必须关注这三者有个很现实的原因生态已经起来了。Claude Desktop、Cursor、Windsurf、Cline 这些工具都原生支持 MCPLangChain、LlamaIndex 这些框架都在适配 A2AOpenAI 的函数调用格式几乎成了事实标准。你现在不学过半年再入场光是各种 Server 的配置和调试就够喝一壶。另一个原因是本地部署的普及。以前大家用 API工具调用在云端完成感知不强。现在 Ollama、vLLM 本地跑模型越来越普遍模型本身不具备联网能力所有外部交互都得靠协议层来补。我见过太多人本地部署完模型发现它连查个天气都不会就是因为没配工具调用链路。还有一点多 Agent 协作正在从 demo 走向生产。单 Agent 能做的事有上限复杂任务必须拆解。A2A 的出现让拆解后的任务有了标准交接格式不用再自己造轮子。虽然现在 A2A 的落地案例还不如 MCP 多但趋势已经很明显了。2. 函数调用模型与工具之间的第一座桥2.1 函数调用的本质与工作流程很多人以为函数调用是模型真的去执行了某个函数其实不是。模型做的事情只有一件根据对话上下文和工具描述输出一个 JSON 对象表明它想调用哪个函数、传什么参数。真正的执行发生在你的代码里。完整流程分四步定义工具你用 JSON Schema 描述每个函数的名称、用途、参数类型和是否必填。模型决策用户提问后模型判断是否需要调用工具如果需要输出tool_calls字段。本地执行你的代码解析tool_calls找到对应函数传入参数执行拿到结果。结果回传把执行结果以tool角色消息追加到对话历史再次请求模型模型基于结果生成最终回复。这个流程里模型始终是“决策者”而非“执行者”。理解这一点非常关键因为它决定了你的安全边界——所有实际动作都在你的代码控制之下模型只是建议。我刚开始用的时候犯过一个错把工具描述写得太模糊模型经常在不该调用的时候调用。后来学乖了每个工具的description必须写清楚“什么时候用”和“什么时候不用”参数描述也要具体到格式。比如date参数要写“格式为 YYYY-MM-DD”不然模型可能传“明天”这种自然语言。2.2 工具定义的实战要点工具定义的质量直接决定调用准确率。我总结了几条硬经验命名要动词开头语义明确。get_weather比weather好search_orders比order_query好。模型对动词的敏感度更高能更快判断意图。描述要包含使用场景和反例。比如{ name: get_user_balance, description: 查询用户账户余额。仅在用户明确询问余额、账户资金时使用。不要用于查询订单状态或物流信息。, parameters: { type: object, properties: { user_id: { type: string, description: 用户唯一标识格式为 U 开头加 8 位数字例如 U12345678 } }, required: [user_id] } }参数尽量扁平避免嵌套。嵌套对象虽然 JSON Schema 支持但模型解析时容易出错。如果确实需要复杂结构拆成多个工具比塞一个复杂参数更稳。枚举值要列全。如果参数是有限选项用enum明确列出比让模型自由发挥靠谱得多。我见过模型把status传成已完成而 schema 定义的是completed就是没写 enum 的锅。必填项要克制。只把真正必需的参数设为required其他都给默认值。模型面对太多必填项时容易编造参数值来满足要求。2.3 多轮调用与并行调用的处理实际场景里一次对话往往需要多次调用。比如用户问“帮我查一下北京和上海明天的天气”模型可能一次输出两个tool_calls这就是并行调用。你的代码需要遍历所有调用分别执行然后把所有结果一起回传。并行调用的好处是快但要注意结果顺序。回传时每个结果都要带上对应的tool_call_id模型靠这个 ID 匹配请求和结果。如果 ID 对不上模型会懵。多轮调用则是串行的第一次调用拿到结果模型发现还需要更多信息再发起第二次调用。这种情况在需要链式操作的场景很常见比如先查用户 ID再用 ID 查订单。你的代码要能循环处理直到模型不再输出tool_calls为止。有个坑我踩过循环没有终止条件。模型有时候会反复调用同一个工具陷入死循环。后来我加了一个最大轮次限制比如 10 轮超过就强制让模型基于现有信息回答。这个保护在生产环境是必须的。2.4 函数调用的局限与常见误区函数调用最大的局限是工具描述占用上下文。每个工具的定义都要塞进 system prompt 或 tools 参数里工具一多token 消耗直线上升。我见过一个项目定义了 50 多个工具光工具描述就占了 8000 多 token还没开始对话上下文就快满了。另一个局限是模型可能编造参数。尤其是当用户请求模糊时模型会“猜”一个参数值。比如用户说“查一下我的订单”模型可能编一个user_id出来。解决办法是在工具描述里强调“如果缺少必要参数先向用户询问不要猜测”。常见误区还有把工具当万能钥匙不是所有功能都要做成工具。简单的文本处理、格式转换模型自己就能做没必要绕一圈。忽略错误处理工具执行失败时要把错误信息回传给模型让它决定是重试还是告知用户。直接抛异常会让整个对话中断。工具粒度太细get_user_name、get_user_age、get_user_email不如一个get_user_info来得高效。粒度太细会导致调用次数暴增。3. MCP让工具和资源标准化接入3.1 MCP 的核心架构与设计哲学MCP 全称 Model Context Protocol是 Anthropic 在 2024 年底开源的协议。它的核心思想很简单把模型需要的外部能力抽象成 Server通过标准协议暴露给 Client。Client 可以是 Claude Desktop、IDE 插件、或者你自己写的 Agent 框架。架构上分三层MCP Host运行模型的应用比如 Claude Desktop、Cursor。它负责管理多个 Client。MCP ClientHost 内部与 Server 通信的组件一个 Client 对应一个 Server 连接。MCP Server实际提供能力的一方可以是本地进程也可以是远程服务。Server 能暴露三种东西Tools可调用的函数跟函数调用的工具类似但通过 MCP 协议标准化了。Resources可读取的数据比如文件内容、数据库记录、API 响应。Prompts预定义的提示词模板方便用户快速调用常用指令。这个设计的精妙之处在于解耦。工具提供方不用关心谁在用使用方不用关心工具怎么实现。只要双方都遵守 MCP 协议就能自由组合。我本地写了一个查股票数据的 MCP ServerClaude Desktop 和 Cursor 都能直接用不用改一行代码。3.2 MCP Server 的开发与配置实操写一个 MCP Server 没有想象中复杂。官方提供了 Python 和 TypeScript 的 SDK基本就是定义工具、注册、启动三步。以 Python 为例一个最简单的天气查询 Serverfrom mcp.server import Server from mcp.server.stdio import stdio_server from mcp.types import Tool, TextContent app Server(weather-server) app.list_tools() async def list_tools(): return [ Tool( nameget_weather, description查询指定城市的天气, inputSchema{ type: object, properties: { city: {type: string, description: 城市名称} }, required: [city] } ) ] app.call_tool() async def call_tool(name: str, arguments: dict): if name get_weather: city arguments[city] # 实际查询逻辑 result f{city}今天晴25度 return [TextContent(typetext, textresult)] async def main(): async with stdio_server() as (read, write): await app.run(read, write, app.create_initialization_options()) if __name__ __main__: import asyncio asyncio.run(main())配置到 Claude Desktop 里只需要在claude_desktop_config.json加一段{ mcpServers: { weather: { command: python, args: [/path/to/weather_server.py] } } }重启 Claude Desktop就能在对话里直接问天气了。整个过程不需要写任何胶水代码这就是标准化的力量。3.3 MCP 的资源与提示词机制Tools 之外Resources 和 Prompts 是 MCP 容易被忽略但很有用的部分。Resources适合暴露只读数据。比如你把项目文档目录注册为 Resource模型就能按需读取文件内容不用你手动粘贴。Resource 用 URI 标识比如file:///project/docs/readme.mdClient 可以列出所有可用 Resource也可以直接读取指定 URI。Prompts适合固化常用指令。比如你经常让模型“按照代码规范审查这段代码”可以把这段指令做成 Prompt 模板带参数。用户选择模板、填参数就能生成完整提示词。这在团队协作里特别有用保证每个人用的指令一致。我自己的做法是把项目里常用的查询封装成 Tools把配置文件和文档注册成 Resources把代码审查、提交信息生成这类固定指令做成 Prompts。一套配下来日常开发效率提升很明显。3.4 MCP 落地中的坑与排查思路MCP 虽然设计得好但实际用起来坑不少。我整理了几个高频问题Server 启动失败。最常见的原因是路径不对或依赖没装。Claude Desktop 的日志在~/Library/Logs/Claude/mcp.logMacWindows 在%APPDATA%\Claude\logs。先看日志大部分问题都能定位。工具列表为空。检查list_tools是否正确定义以及 Server 是否成功初始化。有时候是 SDK 版本不匹配升级到最新版通常能解决。调用超时。MCP 默认有超时限制如果工具执行时间较长需要在 Client 端调整超时配置。另外长时间运行的任务建议改成异步先返回任务 ID再通过 Resource 查询进度。中文乱码。stdio 传输时编码问题比较常见确保 Server 和 Client 都用 UTF-8。Python 里可以在启动时设置PYTHONIOENCODINGutf-8。权限问题。Server 访问本地文件时要注意运行账户的权限。特别是 Windows 上如果 Claude Desktop 以普通用户运行Server 也继承这个权限访问系统目录会失败。提示调试 MCP Server 时可以先用官方提供的 Inspector 工具单独测试确认 Server 本身没问题再接入 Client。这样能快速区分是 Server 的问题还是配置的问题。4. A2A多 Agent 协作的通信标准4.1 A2A 要解决的核心问题当你有多个 Agent每个负责不同领域它们之间怎么配合没有标准之前只能点对点写适配代码。A Agent 要调 B Agent得知道 B 的接口格式要调 C Agent又得写一套。Agent 数量一多适配成本指数级上升。A2A 的思路是定义一套所有 Agent 都遵守的通信规范。每个 Agent 发布一个 Agent Card描述自己叫什么、能做什么、怎么调用。其他 Agent 拿到 Card 就能发起任务不用关心对方内部怎么实现。核心概念有三个Agent CardAgent 的能力说明书包含名称、描述、技能列表、认证方式、通信端点。Task任务单元有唯一 ID 和生命周期状态提交、处理中、完成、失败。Message任务过程中的消息交换支持文本、文件、结构化数据。这套机制让 Agent 之间可以动态发现和调用。你新加一个 Agent只要它发布了标准 Card其他 Agent 就能自动识别并委托任务不需要改任何现有代码。4.2 Agent Card 与任务生命周期管理Agent Card 通常是一个 JSON 文件放在/.well-known/agent.json路径下。一个典型的 Card{ name: 翻译助手, description: 提供中英互译服务, url: https://example.com/agent, version: 1.0.0, capabilities: { streaming: true, pushNotifications: false }, skills: [ { id: translate, name: 文本翻译, description: 将文本从一种语言翻译成另一种语言, inputModes: [text], outputModes: [text] } ] }任务生命周期是 A2A 的另一个核心。一个 Task 从创建到结束会经历多个状态状态含义触发方submitted任务已提交调用方working任务处理中被调方input-required需要补充输入被调方completed任务完成被调方failed任务失败被调方canceled任务取消调用方调用方通过tasks/get查询状态或者通过 SSE 订阅流式更新。被调方在需要更多信息时可以发input-required状态调用方补充后再继续。这个机制让长任务和交互式任务都能覆盖。4.3 A2A 与 MCP 的协同关系很多人搞不清 A2A 和 MCP 的关系觉得功能重叠。其实两者定位完全不同MCP 是纵向的解决 Agent 如何访问工具和资源是 Agent 到能力的连接。A2A 是横向的解决 Agent 之间如何协作是 Agent 到 Agent 的连接。一个 Agent 可以同时用 MCP 获取工具用 A2A 与其他 Agent 通信。比如一个客服 Agent通过 MCP 连接订单数据库和知识库通过 A2A 把退款请求委托给财务 Agent把技术问题委托给技术支持 Agent。实际部署时通常是一个 Host 管理多个 Agent每个 Agent 有自己的 MCP Client 连接工具 ServerAgent 之间通过 A2A 通信。这样分层清晰各司其职。4.4 A2A 当前落地的现实挑战A2A 虽然理念好但落地还处于早期。我实际尝试下来有几个现实问题生态支持不足。目前原生支持 A2A 的框架还不多很多场景需要自己实现 Agent Card 的发布和发现。LangChain 和 LlamaIndex 有社区适配但成熟度一般。认证和授权复杂。Agent 之间跨组织调用时认证是个大问题。A2A 定义了认证方式的声明但具体实现各家不同互操作时经常卡在认证环节。调试困难。多 Agent 协作的链路比单 Agent 长得多出问题时定位困难。我一般会在每个 Agent 加详细日志记录收到的 Task、发出的 Message、状态变更方便回溯。性能开销。Agent 之间的通信有网络延迟任务拆得越细开销越大。不是所有任务都适合拆成多 Agent简单任务单 Agent 反而更快。注意A2A 目前更适合作为架构设计时的参考实际生产落地建议先从单 Agent MCP 做起等业务确实需要多 Agent 协作了再引入 A2A。过早引入会增加不必要的复杂度。5. 三协议协同的实战架构5.1 一个完整的本地 AI 开发环境搭建把三个协议串起来我搭了一个本地开发助手能查代码、跑测试、生成提交信息。架构是这样的HostClineVS Code 插件MCP Servers文件系统 Server、Git Server、终端 Server函数调用Cline 内置支持模型用本地 Ollama 跑的 Qwen2.5-CoderA2A暂时没用上单 Agent 够用配置步骤安装 Ollama拉取模型ollama pull qwen2.5-coder:7b安装 Cline 插件在设置里选择 Ollama 作为 Provider配置 MCP Server在 Cline 的 MCP 设置里添加{ mcpServers: { filesystem: { command: npx, args: [-y, modelcontextprotocol/server-filesystem, /path/to/project] }, git: { command: uvx, args: [mcp-server-git, --repository, /path/to/project] } } }重启 Cline在对话里就能让 AI 读文件、查 Git 历史、执行命令。这套环境跑下来日常的代码问答、重构建议、提交信息生成都能覆盖。模型虽然只有 7B但配合工具调用实际能力远超纯对话。5.2 协议选型决策表实际项目里怎么选我整理了一个决策表场景推荐方案理由单模型调用少量固定工具函数调用最简单无需额外依赖工具需要跨应用复用MCP标准化一次开发多处使用需要访问本地文件和数据库MCPResources 机制天然适合多个 Agent 分工协作A2A标准化任务交接跨组织 Agent 调用A2AAgent Card 支持能力发现快速原型验证函数调用改起来最快选型原则是从简到繁。能用函数调用解决就不上 MCP能用单 Agent 解决就不上 A2A。每引入一层协议调试复杂度和运维成本都会增加。5.3 性能与安全的关键考量三个协议都涉及外部调用性能和安全必须提前考虑。性能方面工具描述会占用上下文工具越多 token 消耗越大。建议按需加载不要一次性把所有工具都塞进去。MCP Server 如果是本地进程启动有开销。常驻 Server 比每次启动快但要注意资源占用。A2A 的网络调用延迟不可忽略任务拆分要合理避免过度拆分。安全方面函数调用的参数要校验不能直接拼 SQL 或执行 shell。模型可能被诱导传入恶意参数。MCP Server 的权限要最小化只开放必要的目录和操作。不要用 root 跑 Server。A2A 的 Agent Card 要认证防止恶意 Agent 冒充。跨组织调用要用 HTTPS 和 token 验证。我自己的做法是所有工具执行前都过一层参数校验敏感操作加二次确认MCP Server 用独立低权限账户运行。这些措施看起来麻烦但出一次安全事故的代价更大。5.4 从单 Agent 到多 Agent 的演进路线如果你现在还在单 Agent 阶段想往多 Agent 走我建议这个路线第一阶段单 Agent 函数调用。把核心工具用函数调用接进来跑通基本流程。第二阶段引入 MCP。把工具改造成 MCP Server实现跨应用复用。这个阶段重点是标准化把散落的工具统一管理。第三阶段拆分 Agent。当单 Agent 的工具太多、提示词太长、决策准确率下降时按领域拆成多个 Agent。每个 Agent 有自己的 MCP 工具集。第四阶段引入 A2A。Agent 之间需要协作时用 A2A 定义通信。先从简单的任务委托开始逐步扩展到复杂的工作流。每个阶段都要有明确的触发条件不要为了用新技术而用。我见过太多项目一上来就搞多 Agent结果调试成本远超收益最后又退回单 Agent。6. 常见问题与排查技巧实录6.1 函数调用高频问题速查问题可能原因解决方法模型不调用工具工具描述不清晰补充使用场景和反例调用参数错误参数描述不具体加格式说明和示例反复调用同一工具缺少终止条件加最大轮次限制工具结果被忽略结果格式不对确保回传格式符合协议中文参数乱码编码不一致统一用 UTF-86.2 MCP 调试的实用技巧MCP 出问题时我一般按这个顺序排查单独测试 Server用 Inspector 工具直接连 Server确认工具列表和调用都正常。检查配置文件路径、命令、参数是否正确JSON 格式有没有错。看日志Client 和 Server 的日志都要看错误信息通常很明确。简化环境把其他 Server 先禁用只留出问题的一个排除干扰。升级版本SDK 和 Client 都升到最新很多问题是版本不匹配导致的。有个小技巧在 Server 里加详细的日志输出记录每次请求和响应。MCP 的 stdio 传输看不到中间过程加日志是最直接的调试手段。6.3 A2A 落地的避坑指南A2A 目前还在早期坑比较多。我踩过的几个Agent Card 发现失败确保 Card 放在标准路径且 Content-Type 是application/json。有些框架对路径大小写敏感统一用小写。任务状态不同步调用方和被调方对状态的理解要一致。建议在 Card 里明确状态机定义避免歧义。流式更新中断SSE 连接不稳定时要有重连机制。同时保留轮询作为兜底方案。认证失败跨组织调用时先确认双方的认证方式是否兼容。OAuth2 和 API Key 混用时容易出问题。提示A2A 的调试建议先用本地两个 Agent 互调跑通后再扩展到远程。本地调试可以用 HTTP生产必须上 HTTPS。6.4 我个人的经验总结折腾这三个协议大半年最大的体会是协议是手段不是目的。不要为了用协议而用协议先想清楚要解决什么问题。函数调用是最成熟的几乎没坑放心用。MCP 生态在快速完善现在入场正是时候但要注意 Server 的质量参差不齐用之前先测试。A2A 理念很好但落地还早建议先关注等生态成熟再大规模投入。另一个体会是日志和监控不能省。协议层出问题时没有日志基本抓瞎。我在每个关键节点都加了日志虽然前期麻烦但排查问题时省了大量时间。最后保持简单。能用简单方案解决的不要引入复杂协议。技术选型的第一原则是够用就好过度设计是给自己挖坑。
返回列表