Skip to content

A2A 中的扩展

Agent2Agent (A2A) 协议为智能体间通信提供了坚实的基础。然而,特定领域或高级用例通常需要超出通用方法的额外结构、自定义数据或新的交互模式。扩展是 A2A 在基础协议上叠加新功能的强大机制。

扩展允许通过新数据、需求、RPC 方法和状态机来扩展 A2A 协议。智能体在其 Agent Card 中声明对特定扩展的支持,然后客户端可以在向智能体发出的请求中选择使用扩展提供的行为。扩展通过 URI 标识,并由其自己的规范定义。任何人都可以定义、发布和实现扩展。

扩展的灵活性允许在不分割核心标准的情况下定制 A2A,促进创新和领域特定的优化。

扩展的范围

扩展的可能使用方式的确切集合是有意广泛的,便于将 A2A 扩展到已知用例之外。然而,一些可预见的应用包括:

  • 纯数据扩展:在 Agent Card 中暴露新的结构化信息,不影响请求 - 响应流程。例如,扩展可以添加关于智能体 GDPR 合规性的结构化数据。
  • 配置文件扩展:在核心请求 - 响应消息上叠加额外的结构和状态更改要求。这种类型实际上作为核心 A2A 协议的配置文件,缩小允许值的空间(例如,要求所有消息使用符合特定模式的 DataParts)。这还可以包括通过使用元数据来增强任务状态机中的现有状态。例如,当 TaskStatus.state 为 'working' 且 TaskStatus.message.metadata["generating-image"] 为 true 时,扩展可以定义 'generating-image' 子状态。
  • 方法扩展(扩展技能):在协议定义的核心方法集之外添加全新的 RPC 方法。扩展技能是指智能体通过实现定义新 RPC 方法的扩展而获得或暴露的特定能力或功能。例如,task-history 扩展可能会添加 tasks/search RPC 方法来检索以前任务的列表,有效地为智能体提供新的扩展技能。
  • 状态机扩展:向任务状态机添加新状态或转换。

限制

有些协议更改是扩展不允许的,主要是为了防止破坏核心类型验证:

  • 更改核心数据结构的定义:例如,向协议定义的数据结构添加新字段或删除必需字段。扩展应将自定义属性放置在核心数据结构上的 metadata 映射中。
  • 向枚举类型添加新值:扩展应使用现有枚举值并在 metadata 字段中注释额外的语义含义。

扩展声明

智能体通过在 AgentCapabilities 对象中包含 AgentExtension 对象来在其 Agent Card 中声明对扩展的支持。

/**
 * A declaration of a protocol extension supported by an Agent.
 *
 * @TJS-examples [{"uri": "https://developers.google.com/identity/protocols/oauth2", "description": "Google OAuth 2.0 authentication", "required": false}]
 */
export interface AgentExtension {
  /** The unique URI identifying the extension. */
  uri: string;
  /** A human-readable description of how this agent uses the extension. */
  description?: string;
  /**
   * If true, the client must understand and comply with the extension's requirements
   * to interact with the agent.
   */
  required?: boolean;
  /** Optional, extension-specific configuration parameters. */
  params?: { [key: string]: any };
}

以下是带有扩展的 Agent Card 示例:

{
  "name": "Magic 8-ball",
  "description": "An agent that can tell your future... maybe.",
  "version": "0.1.0",
  "url": "https://example.com/agents/eightball",
  "capabilities": {
    "streaming": true,
    "extensions": [
      {
        "uri": "https://example.com/ext/konami-code/v1",
        "description": "Provide cheat codes to unlock new fortunes",
        "required": false,
        "params": {
          "hints": [
            "When your sims need extra cash fast",
            "You might deny it, but we've seen the evidence of those cows."
          ]
        }
      }
    ]
  },
  "defaultInputModes": ["text/plain"],
  "defaultOutputModes": ["text/plain"],
  "skills": [
    {
      "id": "fortune",
      "name": "Fortune teller",
      "description": "Seek advice from the mystical magic 8-ball",
      "tags": ["mystical", "untrustworthy"]
    }
  ]
}

必需扩展

虽然扩展通常提供可选功能,但一些智能体可能有更严格的要求。当 Agent Card 将扩展声明为 required: true 时,它向客户端发出信号,表示扩展的某些方面会影响请求的结构或处理方式,客户端必须遵守它。智能体不应将纯数据扩展标记为必需。如果客户端不请求激活必需扩展,或未能遵循其协议,智能体应拒绝传入请求并返回适当错误。

扩展规范

扩展的详细行为和结构由其规范定义。虽然未强制要求确切格式,但至少应包含:

  • 标识扩展的特定 URI。
  • AgentExtension 对象的 params 字段中指定的对象的模式和含义。
  • 客户端和智能体之间通信的任何附加数据结构的模式。
  • 新请求 - 响应流、附加端点或实现扩展所需的任何其他逻辑的详细信息。

扩展依赖

扩展可能依赖于其他扩展。这可以是必需依赖(扩展没有依赖项就无法运行)或可选依赖(如果存在另一个扩展则启用附加功能)。扩展规范应记录这些依赖关系。客户端有责任激活扩展及其规范中列出的所有必需依赖项。

扩展激活

扩展默认为非活动状态,为不了解扩展的客户端提供基线体验。客户端和智能体进行协商以确定哪些扩展对特定请求处于活动状态。

  1. 客户端请求:客户端通过在向智能体的 HTTP 请求中包含 X-A2A-Extensions 头来请求扩展激活。该值是客户端打算激活的扩展 URI 的逗号分隔列表。
  2. 智能体处理:智能体负责识别请求中支持的扩展并执行激活。智能体不支持的任何请求扩展都可以被忽略。
  3. 响应:智能体识别出所有激活的扩展后,响应应包含 X-A2A-Extensions 头,列出该请求成功激活的所有扩展。

显示扩展激活的示例请求:

POST /agents/eightball HTTP/1.1
Host: example.com
Content-Type: application/json
X-A2A-Extensions: https://example.com/ext/konami-code/v1
Content-Length: 519
{
  "jsonrpc": "2.0",
  "method": "message/send",
  "id": "1",
  "params": {
    "message": {
      "kind": "message",
      "messageId": "1",
      "role": "user",
      "parts": [{"kind": "text", "text": "Oh magic 8-ball, will it rain today?"}]
    },
    "metadata": {
      "https://example.com/ext/konami-code/v1/code": "motherlode"
    }
  }
}

响应激活扩展的对应响应:

HTTP/1.1 200 OK
Content-Type: application/json
X-A2A-Extensions: https://example.com/ext/konami-code/v1
Content-Length: 338
{
  "jsonrpc": "2.0",
  "id": "1",
  "result": {
    "kind": "message",
    "messageId": "2",
    "role": "agent",
    "parts": [{"kind": "text", "text": "That's a bingo!"}]
  }
}

实现注意事项

虽然 A2A 协议定义了扩展的功能,但本节提供了关于其实现的指导——关于编写、版本控制和分发扩展实现的最佳实践。

  • 版本控制:扩展规范不断发展。拥有清晰的版本控制策略至关重要,以确保客户端和智能体能够协商兼容的实现。
    • 建议:使用扩展的 URI 作为主要版本标识符,理想情况下包括版本号(例如,https://example.com/ext/my-extension/v1)。
    • 破坏性更改:当对扩展的逻辑、数据结构或必需参数引入破坏性更改时,必须使用新 URI。
    • 处理不匹配:如果客户端请求智能体不支持的版本,智能体应忽略该扩展的激活请求;不得回退到不同版本。
  • 可发现性和发布
    • 规范托管:扩展规范文档应该托管在扩展的 URI 上。
    • 永久标识符:鼓励作者使用永久标识符服务(如 w3id.org)作为其扩展 URI,以防止链接失效。
    • 社区注册表(未来):A2A 社区可能会建立一个中央注册表,用于发现和浏览可用扩展。
  • 打包和可重用性(A2A SDK 和库): 为了促进采用,扩展逻辑应打包成可重用的库,可以集成到现有的 A2A 客户端和服务器应用程序中。

    • 扩展实现应作为其语言生态系统的标准包分发(例如,Python 的 PyPI 包,TypeScript/JavaScript 的 npm 包)。
    • 目标是为开发者提供简化的集成体验。设计良好的扩展包应允许开发者以最少的代码将其添加到服务器中,例如:

      
      

      此示例展示了 A2A SDK 或库(如 Python 中的 a2a.server)如何促进 A2A 智能体和扩展的实现。

  • 安全性:扩展修改 A2A 协议的核心行为,因此引入了新的安全考虑:

    • 输入验证:扩展引入的任何新数据字段、参数或方法都必须严格验证。将来自外部方的所有扩展相关数据视为不受信任的输入。
    • 必需扩展的范围:在 Agent Card 中标记扩展为 required: true 时要小心。这为所有客户端创建了硬依赖,应仅用于对智能体的核心功能和安全至关重要的扩展(例如,消息签名扩展)。
    • 身份验证和授权:如果扩展添加新方法,实现必须确保这些方法受到与核心 A2A 方法相同的身份验证和授权检查。扩展不得提供绕过智能体主要安全控制的方法。