能力发现与协商

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

能力发现与协商:在运行时得知对端能做什么。

硬编码工具或智能体能做什么,会把你绑死在构建时,并在每次变更时失效。成熟的互操作协议让能力在连接时可发现、可版本协商。本文泛化发现模式、为什么版本协商不可或缺,以及为什么发现与信任是分开的关注点。

STEP 1

构建时掌握能力知识的代价。

朴素的集成做法是把对端能力编进客户端:这个服务器有这三个工具、这些模式;这个智能体接受这种请求形状。它能工作,直到第一次变更。加一个工具、改一个参数名、弃用一个技能——每个硬编码了旧假设的客户端现在都错了,且没有任何东西通知它。在"互操作问题"一文的 M+N 图里,"没有任何东西通知它"会跨每个被改服务器的每个客户端成倍放大。

运行时发现把这反转。客户端不假设;它询问。能力成为连接时获取的数据,而非编进调用方的常量。服务器可以长出新工具,合规客户端无需重新部署就能拾取它们,因为客户端的行为由发现返回的内容驱动,而非由其作者编写时的信念驱动。

STEP 2

发现模式,抽象化。

纵观本系列的协议,发现这步是同样的三步,只是拼写不同:

  • 宣告。每一方陈述自己是谁、支持哪些大类能力。MCP:initialize 能力对象。A2A:智能体卡片。工具调用:随每个请求发送的所声明工具数组。
  • 枚举。客户端列举具体能力。MCP:tools/listresources/listprompts/list。A2A:卡片中的 skills 数组。
  • 绑定。客户端按名使用某能力,参数由发现返回的模式塑形——tools/callmessage/send
announce   ── who am I, what classes do I support ──>
enumerate  ── list the concrete tools/skills/resources ──>
bind       ── call one by name, args per its schema ──>
(re-enumerate on a listChanged notification)

关键特性是枚举返回模式,而不只是名称。发现产出足以在无先验知识下构造一次有效调用的内容:工具名、其描述、其输入 JSON Schema。这正是让客户端通用的原因——它能呈现并调用一个从未见过的工具,因为描述是机器与模型可读的。

发现与模型是耦合的。tools/list 返回的描述或智能体卡片技能携带的描述,不仅供客户端 UI——它们被喂给模型,使其能决定是否以及如何使用该能力。发现元数据就是提示材料,这也是"工具调用标准"一文称 description 为杠杆最高字段的原因。

STEP 3

版本协商不可选。

M 个客户端与 N 个服务器共享一个接口的那一刻,该接口就必须在没有同步升级的情况下变化。开放生态里没有"统一切换日"。所以发现与协商配对:双方交换协议版本与一个能力集,当对方不支持某物时,各自必须优雅降级。

# Negotiation: agree a version, advertise optional features
# client → {"protocolVersion": "2025-06-18",
              "capabilities": {"sampling": {}}}
# server → {"protocolVersion": "2025-06-18",
              "capabilities": {"tools": {"listChanged": true},
                               "resources": {}}}
# Outcome: tools + resources usable; prompts absent;
# client must NOT call prompts/* — it was never offered.

由此直接得出两条纪律。特性探测,而非版本嗅探:基于"对端是否公布了 listChanged?"分支,而非"版本是否 ≥ X?"——能力标志正是为此设计且能挺过未来版本。未公布即视为缺失:若某能力未被宣告,调用它就是协议违规;要么降级要么拒绝,绝不假设。这正是让 M+N 图能一次升级一个节点而非一次性全量的原因。

A2A 在智能体卡片中体现同一原则:一个 capabilities 块(例如 streamingpushNotifications)在调用方承诺某种请求形状之前就告诉它哪些交互模式可用,于是它可以对不支持流式的对端选择同步调用。

STEP 4

发现描述的是能力,不是许可。

这整个领域里最有后果的概念错误:把"对端说它能做 X"与"对端在此处应被允许做 X"混为一谈。发现回答什么是可能的。它对什么是被授权的只字不提。

一份被发现的工具列表是一则广告,而广告主可能错误、过时或敌对。服务器可以列出一个 delete_all 工具;发现它并不意味着你的宿主应把它暴露给模型,更不应在无同意的情况下如此。宿主仍掌握发现无法替它做的三个决定:到底连接哪些被发现的服务器/智能体、把它们的哪些能力呈现给模型、以及哪些在运行前需要显式用户批准。

能力发现是一项策略决定的输入,绝非决定本身。"它在 tools/list 里"不是授权。白名单、范围与同意门禁位于发现之上且强制;威胁模型与范围机制见"安全、对齐与智能体安全"深入探讨系列。协议的贡献是让选项集显式,从而策略有具体可作用之物。

主线:发现加协商,是把 M × N 套硬编码耦合变成一张能演进的 M + N 图的关键——宣告、枚举(带模式)、绑定、特性探测、优雅降级。它告诉你什么是可能的;决定什么是被许可的是另一个不可商量、凌驾于此处所述一切之上的层。