构建可互操作的智能体

P7
深入解析 · 协议与互操作

构建可互操作的智能体:选择并组合协议。

本文综合整个系列。它在"各自实际为何而设、在哪里重叠又在哪里不重叠"上比较各路方案——原生厂商工具调用、MCP,以及 A2A 这类智能体间协议——并给出一条实用决策规则,以及一个必须与一切对话的智能体的集成架构。

STEP 1

三层、三个职责——而非三个竞争者。

最常见的困惑是把工具调用、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。

STEP 2

重叠、缺口,以及一条决策规则。

在一道接缝处确有真实重叠:"调用另一个智能体"可被建模为单个厂商工具、一个 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 服务器都可以合规却暴露不兼容的工具词汇;一张智能体卡片告诉你对端的技能存在,而非它们意味着你所假设的东西。信封层的互操作买不来任务层的互操作——那仍是集成工作,只是你不必再重新铺管的集成工作。

STEP 3

一个参考集成架构。

把整个系列收拢成一个形状。智能体有单一的内部工具注册表;每个来源——本地函数、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 对端),在运行时被发现,并通过单一归一化注册表和"工具调用标准"一文的薄厂商适配器呈现给模型。增加一个系统是增加一个来源,而非循环里的一个分支。更换模型只更换渲染器。

STEP 4

协议之后你仍欠下什么。

协议交付形状、发现与统一循环。它们不交付正确性、安全或信任——这些仍是你的责任,凌驾于上述一切之上。

  • 校验。在你拥有的边界处重新校验输入(先结构后语义/授权),并为一致性、节省与可操作错误设计输出——无论是否有厂商严格模式。见结构化工具 I/O。
  • 凌驾于发现之上的策略。发现列举什么是可能的;你决定连接哪些服务器/对端、呈现哪些能力、哪些需要同意。"它被公布过"不是授权。见能力发现。
  • 信任边界。每个被连接的服务器、每个被委派的对端都能返回操纵你模型并在所授权限下行动的内容。威胁模型——经由工具输出的提示注入、被混淆的代理、范围、来源溯源、对高影响动作引入人类把关——在"安全、对齐与智能体安全"深入探讨系列中展开。本系列有意推迟其深度,只标记接缝。

本系列一句话:优先选择带版本、可发现的协议,而非 M × N 套手写桥接;挑能表达该交互的最薄层(厂商工具调用 → MCP → A2A);把每个来源在一个接口之后归一化进一个注册表;并记住协议给你信封,而校验、策略与信任仍是你要强制执行的。

如此构建,智能体通过增加来源而非重写循环获得新工具、数据与对端智能体,通过更换渲染器而非更换集成切换其底层模型——这从一开始就是拥有协议层的全部意义。