构建可互操作的智能体:选择并组合协议。
本文综合整个系列。它在"各自实际为何而设、在哪里重叠又在哪里不重叠"上比较各路方案——原生厂商工具调用、MCP,以及 A2A 这类智能体间协议——并给出一条实用决策规则,以及一个必须与一切对话的智能体的集成架构。
三层、三个职责——而非三个竞争者。
最常见的困惑是把工具调用、MCP 与 A2A 当作互斥替代。它们工作在同一栈的不同层:
- 厂商工具调用是模型到函数的契约:单个模型如何对一份 JSON Schema 发出结构化调用并取回结果。它是进程内的、厂商形状的,是其余一切构建其上的底层。
- MCP 是智能体到工具/资源的契约:宿主如何通过一个经协商的 JSON-RPC 会话触达可复用、独立构建的工具/资源/提示服务器。它把集成标准化并外化,使其无需按智能体重写。
- A2A 是智能体到智能体的契约:智能体如何把不透明、可能长时间运行、多轮的工作委派给一个不归它所有的对端智能体。
user
└─ Host / Agent
├─ provider tool calling → model ⇄ functions (in-process)
├─ MCP client(s) → tools/resources (your systems)
└─ A2A client → peer agents (others' agents)
the same program is often an MCP host AND an A2A server
它们纵向组合。一个典型的生产智能体把厂商工具调用当作其内层机制,用 MCP 在无定制客户端的情况下取得其大部分工具与数据,并在部分工作属于他人运营的智能体时使用 A2A。
重叠、缺口,以及一条决策规则。
在一道接缝处确有真实重叠:"调用另一个智能体"可被建模为单个厂商工具、一个 MCP 工具,或一个真正的 A2A 任务。它们并不等价——它们在能表达什么上不同:
- 作为厂商工具 / MCP 工具:同步、单次、字符串或 JSON 进出。最便宜。当对端实际上是无状态函数且调用在一次请求内完成时,正确。
- 作为 A2A 任务:长时间运行、多轮(对端可向你提问)、类型化产物、不透明内部状态。当工作超越单次请求、需要澄清或返回丰富输出时,必需。
一条实用决策规则:
# Pick the thinnest layer that expresses the interaction. if capability lives in your process and is provider-shaped: use provider tool calling directly elif it wraps a system, is reusable, may serve other agents: use MCP (write/adopt a server once) elif it is another team's agent, or work is long / multi-turn / richly-typed: use A2A (task, messages, artifacts) else: # do not invent a protocol; reuse one of the above
诚实的缺口:这些方案没有一个标准化语义。两个 MCP 服务器都可以合规却暴露不兼容的工具词汇;一张智能体卡片告诉你对端的技能存在,而非它们意味着你所假设的东西。信封层的互操作买不来任务层的互操作——那仍是集成工作,只是你不必再重新铺管的集成工作。
一个参考集成架构。
把整个系列收拢成一个形状。智能体有单一的内部工具注册表;每个来源——本地函数、MCP 服务器、A2A 对端——都在一个接口之后被归一化进它,于是智能体循环从不为某个集成分支。
# One registry; sources normalised behind one shape class Capability: name: str description: str # model-facing; highest leverage schema: dict # interoperable JSON Schema core invoke: Callable # hides local | MCP | A2A registry = [] registry += [wrap(fn) for fn in LOCAL_TOOLS] registry += mcp_client.tools_list() # discovered registry += a2a.skills_as_tools(agent_card) # discovered # Agent loop sees ONE uniform list, renders it per # provider with the thin adapter from essay P2. tools = [provider_render(c) for c in registry]
这个架构是把 M+N 论证落到实处:每个系统被包装一次(作为本地处理器、MCP 服务器或 A2A 对端),在运行时被发现,并通过单一归一化注册表和"工具调用标准"一文的薄厂商适配器呈现给模型。增加一个系统是增加一个来源,而非循环里的一个分支。更换模型只更换渲染器。
协议之后你仍欠下什么。
协议交付形状、发现与统一循环。它们不交付正确性、安全或信任——这些仍是你的责任,凌驾于上述一切之上。
- 校验。在你拥有的边界处重新校验输入(先结构后语义/授权),并为一致性、节省与可操作错误设计输出——无论是否有厂商严格模式。见结构化工具 I/O。
- 凌驾于发现之上的策略。发现列举什么是可能的;你决定连接哪些服务器/对端、呈现哪些能力、哪些需要同意。"它被公布过"不是授权。见能力发现。
- 信任边界。每个被连接的服务器、每个被委派的对端都能返回操纵你模型并在所授权限下行动的内容。威胁模型——经由工具输出的提示注入、被混淆的代理、范围、来源溯源、对高影响动作引入人类把关——在"安全、对齐与智能体安全"深入探讨系列中展开。本系列有意推迟其深度,只标记接缝。
本系列一句话:优先选择带版本、可发现的协议,而非 M × N 套手写桥接;挑能表达该交互的最薄层(厂商工具调用 → MCP → A2A);把每个来源在一个接口之后归一化进一个注册表;并记住协议给你信封,而校验、策略与信任仍是你要强制执行的。
如此构建,智能体通过增加来源而非重写循环获得新工具、数据与对端智能体,通过更换渲染器而非更换集成切换其底层模型——这从一开始就是拥有协议层的全部意义。