Agent2Agent (A2A) 协议规范¶
版本: 0.2.1
1. 简介¶
Agent2Agent (A2A) 协议是一个开放标准,旨在促进独立且可能不透明的 AI 智能体系统之间的通信和互操作性。在一个智能体可能使用不同框架、语言或由不同供应商构建的生态系统中,A2A 提供了一种通用语言和交互模型。
本文档提供了 A2A 协议的详细技术规范。其主要目标是使智能体能够:
- 互相发现的能力
- 约定交互模式(文本、文件、结构化数据)
- 管理协作任务
- 安全地交换信息以实现用户目标,而无需访问彼此的内部状态、内存(记忆)或工具
1.1. A2A 的主要目标¶
- 互操作性: 不同智能体系统之间建立通信
- 协作: 使智能体能够委派任务、交换上下文,并共同处理复杂的用户请求
- 发现: 允许智能体动态发现和理解其他智能体的能力
- 灵活性: 支持各种交互模式,包括同步请求/响应、实时更新的流式传输,以及长时间运行任务的异步推送通知
- 安全性: 依赖于标准 Web 安全实践,推动适合企业环境的安全通信模式
- 异步性: 原生支持长时间运行的任务和可能涉及人工干预场景的交互
1.2. 指导原则¶
- 简单: 重用现有的、易于理解的标准(HTTP、JSON-RPC 2.0、Server-Sent Events)
- 企业级: 通过遵循既定的企业实践,解决认证、授权、安全、隐私、追踪和监控问题
- 异步优先: 为(可能非常)长时间运行的任务和人工干预交互而设计
- 数据类型无关: 支持交换各种内容类型,包括文本、音频/视频(通过文件引用)、结构化数据/表单,以及潜在的嵌入式 UI 组件(例如,在部分中引用的 iframe)
- 不透明(隔离)执行: 智能体基于声明的能力和交换的信息进行协作,无需共享其内部算法、计划或工具实现
有关 A2A 目的和好处的更广泛理解,请参见什么是 A2A?。
2. 核心概念总结¶
A2A 围绕几个关键概念展开。有关详细说明,请参阅关键概念指南。
- A2A Client: 代表用户或其他系统向 A2A 服务器发起请求的应用或智能体
- A2A Server(远程智能体): 暴露符合 A2A 的 HTTP 端点的智能体或智能体系统,处理任务并提供响应
- 智能体卡片(AgentCard): 由 A2A 服务器发布的 JSON 元数据文档,描述其身份、能力、技能、服务端点和认证要求
- 消息(Message): 客户端和远程智能体之间的通信轮次,具有
role("user" 或 "agent")并包含一个或多个Parts - 任务(Task): A2A 管理的基本工作单元,由唯一 ID 标识。任务是有状态的,并按照定义的生命周期进行
- 部分(Part): 消息或工件(Artifact)中的最小内容单元(例如,
TextPart、FilePart、DataPart) - 工件(Artifact): 智能体作为任务结果生成的输出(例如,文档、图像、结构化数据),由
Parts组成 - 流式传输(SSE): 通过 Server-Sent Events 提供的任务实时增量更新(状态变化、工件块)
- 推送通知(Push Notifications): 通过服务器发起的 HTTP POST 请求发送到客户端提供的 webhook URL 的异步任务更新,用于长时间运行或断开连接的场景
- 上下文(Context): 一个可选的、服务器生成的标识符,用于逻辑上对相关任务进行区分
3. 传输和格式¶
3.1. 传输协议¶
- A2A 通信必须通过 HTTP(S) 进行
- A2A 服务器在其
AgentCard中定义的 URL 处暴露其服务
3.2. 数据格式¶
A2A 使用 JSON-RPC 2.0 作为所有请求和响应的有效载荷格式(不包括 SSE 流包装器)。
- 客户端请求和服务器响应必须遵守 JSON-RPC 2.0 规范
- 包含 JSON-RPC 有效载荷的 HTTP 请求和响应的
Content-Type头必须为application/json
3.3. 流式传输(Server-Sent Events)¶
当流式传输用于 message/stream 或 tasks/resubscribe 等方法时:
- 服务器响应 HTTP
200 OK状态和Content-Type头为text/event-stream - 此 HTTP 响应的主体包含由 W3C 定义的 Server-Sent Events (SSE) 流
- 每个 SSE
data字段包含一个完整的 JSON-RPC 2.0 响应对象(具体来说,是一个SendStreamingMessageResponse)
4. 认证和授权¶
A2A 将智能体视为标准企业应用程序,依赖于既定的 Web 安全实践。身份信息不会在 A2A JSON-RPC 有效载荷中传输;它在 HTTP 传输层处理。
有关企业安全方面的综合指南,请参见企业就绪功能。
4.1. 传输安全¶
如第 3.1 节所述,生产部署必须使用 HTTPS。实现应该使用现代 TLS 配置(推荐 TLS 1.2+)和强密码套件。
4.2. 服务器身份验证¶
A2A 客户端应该通过在 TLS 握手期间根据受信任的证书颁发机构(CA)验证其 TLS 证书来验证 A2A 服务器的身份。
4.3. 客户端/用户身份和认证过程¶
- 需求发现: 客户端通过
AgentCard中的authentication字段发现服务器所需的认证方案。方案名称通常与 OpenAPI 认证方法 一致(例如,"Bearer" 用于 OAuth 2.0 令牌,"Basic" 用于基本认证,"ApiKey" 用于 API 密钥) - 凭证获取(带外): 客户端通过特定于所需认证方案和身份提供商的带外过程获取必要的凭证(例如,API 密钥、OAuth 令牌、JWT)。此过程在 A2A 协议本身的范围之外
- 凭证传输: 客户端在每个发送到服务器的 A2A 请求的适当 HTTP 头 中包含这些凭证(例如,
Authorization: Bearer <token>,X-API-Key: <value>)
4.4. 服务器的认证责任¶
A2A 服务器:
- 必须根据提供的 HTTP 凭证和其 Agent Card 中声明的认证要求对每个传入请求进行认证
- 应该使用标准 HTTP 状态码,如
401 Unauthorized或403 Forbidden进行认证质询或拒绝 - 应该在
401 Unauthorized响应中包含相关的 HTTP 头(例如,WWW-Authenticate)以指示所需的认证方案,指导客户端
4.5. 任务内认证(次要凭证)¶
如果智能体在执行任务期间需要为_不同_的系统或资源提供_额外_的凭证(例如,代表用户访问需要自己认证的特定工具):
- 它应该将 A2A 任务转换到
auth-required状态(参见TaskState) - 随附的
TaskStatus.message(通常是DataPart)应该提供有关所需次要认证的详细信息,可能使用类似PushNotificationAuthenticationInfo的结构来描述需求 - A2A 客户端然后通过带外方式获取这些新凭证,并在后续的
message/send或message/stream请求中提供它们。这些凭证的使用方式(例如,如果智能体正在代理,则在 A2A 消息中作为数据传递,或由客户端直接与次要系统交互)取决于具体场景
4.6. 授权¶
一旦客户端通过认证,A2A 服务器负责根据已认证的客户端/用户身份及其自身策略对请求进行授权。授权逻辑是特定于实现的,可以基于以下因素强制执行:
- 请求的特定技能(例如,由 Agent Card 中的
AgentSkill.id标识) - 在任务中尝试的操作
- 与智能体管理的资源相关的数据访问策略
- 与所提供令牌关联的OAuth作用域(如果适用)。
服务器应该实施最小权限原则。
5. 智能体发现:智能体卡片¶
5.1. 目的¶
A2A 服务器必须提供智能体卡片。智能体卡片是一个 JSON 文档,描述服务器的身份、能力、技能、服务端点 URL,以及客户端应该如何进行认证和交互。客户端使用这些信息来发现合适的智能体并配置其交互。
有关发现策略的更多信息,请参见智能体发现指南。
5.2. 发现机制¶
客户端可以通过各种方法找到智能体卡片,包括但不限于:
- Well-Known URI: 访问智能体域上的预定义路径
- 注册表/目录: 查询智能体的精选目录或注册表(可能是企业特定的、公共的或特定领域的)
- 直接配置: 客户端可能预先配置了智能体卡片 URL 或卡片内容本身
5.3. 推荐位置¶
如果使用 well-known URI 策略,智能体卡片的推荐位置是: https://{server_domain}/.well-known/agent.json 这遵循 RFC 8615 关于 well-known URI 的原则。
5.4. 智能体卡片的安全性¶
智能体卡片本身可能包含被视为敏感的信息。
- 如果智能体卡片包含敏感信息,提供卡片的端点必须受到适当的访问控制保护(例如,mTLS、网络限制、获取卡片需要认证)
- 通常不建议在智能体卡片中直接包含明文密钥(如静态 API 密钥)。优先选择客户端通过带外方式获取动态凭证的认证方案
5.5. AgentCard 对象结构¶
/**
* An AgentCard conveys key information:
* - Overall details (version, name, description, uses)
* - Skills: A set of capabilities the agent can perform
* - Default modalities/content types supported by the agent.
* - Authentication requirements
*/
export interface AgentCard {
/**
* Human readable name of the agent.
* @example "Recipe Agent"
*/
name: string;
/**
* A human-readable description of the agent. Used to assist users and
* other agents in understanding what the agent can do.
* @example "Agent that helps users with recipes and cooking."
*/
description: string;
/** A URL to the address the agent is hosted at. */
url: string;
/** A URL to an icon for the agent. */
iconUrl?: string;
/** The service provider of the agent */
provider?: AgentProvider;
/**
* The version of the agent - format is up to the provider.
* @example "1.0.0"
*/
version: string;
/** A URL to documentation for the agent. */
documentationUrl?: string;
/** Optional capabilities supported by the agent. */
capabilities: AgentCapabilities;
/** Security scheme details used for authenticating with this agent. */
securitySchemes?: { [scheme: string]: SecurityScheme };
/** Security requirements for contacting the agent. */
security?: { [scheme: string]: string[] }[];
/**
* The set of interaction modes that the agent supports across all skills. This can be overridden per-skill.
* Supported media types for input.
*/
defaultInputModes: string[];
/** Supported media types for output. */
defaultOutputModes: string[];
/** Skills are a unit of capability that an agent can perform. */
skills: AgentSkill[];
/**
* true if the agent supports providing an extended agent card when the user is authenticated.
* Defaults to false if not specified.
*/
supportsAuthenticatedExtendedCard?: boolean;
}
| 字段名 | 类型 | 必需 | 描述 |
|---|---|---|---|
name | string | 是 | 智能体的人类可读名称 |
description | string | 是 | 人类可读描述。CommonMark 可以使用 |
url | string | 是 | 智能体 A2A 服务的基础 URL。必须是绝对路径。生产环境使用 HTTPS |
provider | AgentProvider | 否 | 关于智能体提供商的信息 |
iconUrl | string | 否 | 智能体图标的 URL |
version | string | 是 | 智能体或 A2A 实现版本字符串 |
documentationUrl | string | 否 | 智能体人类可读文档的 URL |
capabilities | AgentCapabilities | 是 | 指定支持的可选 A2A 协议功能(例如,流式传输、推送通知) |
securitySchemes | { [scheme: string]: SecurityScheme } | 否 | 用于与此智能体认证的安全方案详情。undefined 表示没有 A2A 广告的认证(不建议用于生产环境) |
security | { [scheme: string]: string[]; }[] | 否 | 智能体沟通的安全要求 |
defaultInputModes | string[] | 是 | 智能体接受的输入媒体类型 |
defaultOutputModes | string[] | 是 | 智能体产生的输出媒体类型 |
skills | AgentSkill[] | 是 | 技能数组。如果智能体执行操作,必须至少有一个 |
supportsAuthenticatedExtendedCard | boolean | 否 | 指示是否支持通过认证端点获取更详细的智能体卡片 |
5.5.1. AgentProvider 对象¶
关于提供智能体的组织或实体的信息。
/**
* Represents the service provider of an agent.
*/
export interface AgentProvider {
/** Agent provider's organization name. */
organization: string;
/** Agent provider's URL. */
url: string;
}
| 字段名 | 类型 | 必需 | 描述 |
|---|---|---|---|
organization | string | 是 | 组织/实体的名称 |
url | string | 是 | 提供商网站/联系的 URL |
5.5.2. AgentCapabilities 对象¶
指定智能体支持的可选 A2A 协议功能。
/**
* Defines optional capabilities supported by an agent.
*/
export interface AgentCapabilities {
/** true if the agent supports SSE. */
streaming?: boolean;
/** true if the agent can notify updates to client. */
pushNotifications?: boolean;
/** true if the agent exposes status change history for tasks. */
stateTransitionHistory?: boolean;
}
| 字段名 | 类型 | 必需 | 默认值 | 描述 |
|---|---|---|---|---|
streaming | boolean | 否 | false | 指示是否支持 SSE 流式传输方法(message/stream,tasks/resubscribe) |
pushNotifications | boolean | 否 | false | 指示是否支持推送通知方法(tasks/pushNotificationConfig/*) |
stateTransitionHistory | boolean | 否 | false | 未来功能的占位符:暴露详细的任务状态变更历史 |
5.5.3. SecurityScheme 对象¶
描述访问智能体 url 端点的认证要求。参考示例智能体卡片获取示例。
/**
* Mirrors the OpenAPI Security Scheme Object
* (https://swagger.io/specification/#security-scheme-object)
*/
export type SecurityScheme =
| APIKeySecurityScheme
| HTTPAuthSecurityScheme
| OAuth2SecurityScheme
| OpenIdConnectSecurityScheme;
5.5.4. AgentSkill 对象¶
描述智能体可以执行或处理的特定能力、功能或专业领域。
/**
* Represents a unit of capability that an agent can perform.
*/
export interface AgentSkill {
/** Unique identifier for the agent's skill. */
id: string;
/** Human readable name of the skill. */
name: string;
/**
* Description of the skill - will be used by the client or a human
* as a hint to understand what the skill does.
*/
description: string;
/**
* Set of tagwords describing classes of capabilities for this specific skill.
* @example ["cooking", "customer support", "billing"]
*/
tags: string[];
/**
* The set of example scenarios that the skill can perform.
* Will be used by the client as a hint to understand how the skill can be used.
* @example ["I need a recipe for bread"]
*/
examples?: string[]; // example prompts for tasks
/**
* The set of interaction modes that the skill supports
* (if different than the default).
* Supported media types for input.
*/
inputModes?: string[];
/** Supported media types for output. */
outputModes?: string[];
}
| 字段名 | 类型 | 必需 | 描述 |
|---|---|---|---|
id | string | 是 | 在此智能体中唯一的技能标识符 |
name | string | 是 | 人类可读的技能名称 |
description | string | 是 | 详细的技能描述。CommonMark 可以使用 |
tags | string[] | 是 | 用于可发现性的关键词/类别 |
examples | string[] | 否 | 展示技能使用的示例提示或用例 |
inputModes | string[] | 否 | 为此特定技能覆盖 defaultInputModes。接受的媒体类型 |
outputModes | string[] | 否 | 为此特定技能覆盖 defaultOutputModes。产生的媒体类型 |
5.6. 示例智能体卡片¶
{
"name": "地理空间路线规划智能体",
"description": "提供高级路线规划、交通分析和自定义地图生成服务。此智能体可以计算最佳路线、考虑实时交通估算旅行时间,并创建带有兴趣点的个性化地图。",
"url": "https://georoute-agent.example.com/a2a/v1",
"provider": {
"organization": "示例地理服务公司",
"url": "https://www.examplegeoservices.com"
},
"iconUrl": "https://georoute-agent.example.com/icon.png",
"version": "1.2.0",
"documentationUrl": "https://docs.examplegeoservices.com/georoute-agent/api",
"capabilities": {
"streaming": true,
"pushNotifications": true,
"stateTransitionHistory": false
},
"securitySchemes": {
"google": {
"type": "openIdConnect"
}
},
"security": [{ "google": ["openid", "profile", "email"] }],
"defaultInputModes": ["application/json", "text/plain"],
"defaultOutputModes": ["application/json", "image/png"],
"skills": [
{
"id": "route-optimizer-traffic",
"name": "Traffic-Aware Route Optimizer",
"description": "Calculates the optimal driving route between two or more locations, taking into account real-time traffic conditions, road closures, and user preferences (e.g., avoid tolls, prefer highways).",
"tags": ["maps", "routing", "navigation", "directions", "traffic"],
"examples": [
"Plan a route from '1600 Amphitheatre Parkway, Mountain View, CA' to 'San Francisco International Airport' avoiding tolls.",
"{\"origin\": {\"lat\": 37.422, \"lng\": -122.084}, \"destination\": {\"lat\": 37.7749, \"lng\": -122.4194}, \"preferences\": [\"avoid_ferries\"]}"
],
"inputModes": ["application/json", "text/plain"],
"outputModes": [
"application/json",
"application/vnd.geo+json",
"text/html"
]
},
{
"id": "custom-map-generator",
"name": "Personalized Map Generator",
"description": "Creates custom map images or interactive map views based on user-defined points of interest, routes, and style preferences. Can overlay data layers.",
"tags": ["maps", "customization", "visualization", "cartography"],
"examples": [
"Generate a map of my upcoming road trip with all planned stops highlighted.",
"Show me a map visualizing all coffee shops within a 1-mile radius of my current location."
],
"inputModes": ["application/json"],
"outputModes": [
"image/png",
"image/jpeg",
"application/json",
"text/html"
]
}
],
"supportsAuthenticatedExtendedCard": true
}
6. 协议数据对象¶
这些对象定义了在 A2A 协议的 JSON-RPC 方法中交换的数据结构。
6.1. Task 对象¶
表示 A2A 服务器为 A2A 客户端管理的有状态工作单元。任务封装了与特定目标或请求相关的整个交互。
export interface Task {
/** Unique identifier for the task */
id: string;
/** Server-generated id for contextual alignment across interactions */
contextId: string;
/** Current status of the task */
status: TaskStatus;
history?: Message[];
/** Collection of artifacts created by the agent. */
artifacts?: Artifact[];
/** Extension metadata. */
metadata?: {
[key: string]: any;
};
/** Event type */
kind: "task";
}
| 字段名 | 类型 | 必需 | 描述 |
|---|---|---|---|
id | string | 是 | 服务器生成的唯一任务标识符(例如,UUID) |
contextId | string | 是 | 服务器生成的 ID,用于跨交互的上下文对齐 |
status | TaskStatus | 是 | 任务的当前状态(状态、消息、时间戳)。 |
artifacts | Artifact[] | 否 | 智能体为该任务生成的输出数组。 |
history | Message[] | 否 | 可选的最近消息交换数组,如果请求了 historyLength。 |
metadata | Record<string, any> | 否 | 与任务相关的任意键值元数据。 |
6.2. TaskStatus 对象¶
表示 Task 的当前状态及其上下文(例如,智能体发送的消息)。
/** TaskState and accompanying message. */
export interface TaskStatus {
state: TaskState;
/** Additional status updates for client */
message?: Message;
/**
* ISO 8601 datetime string when the status was recorded.
* @example "2023-10-27T10:00:00Z"
* */
timestamp?: string;
}
| 字段名 | 类型 | 必需 | 描述 |
|---|---|---|---|
state | TaskState | 是 | 任务的当前生命周期状态。 |
message | Message | 否 | 可选的消息提供当前状态的上下文。 |
timestamp | string (ISO 8601) | 否 | 记录此状态的时间戳(推荐 UTC)。 |
6.3. TaskState Enum¶
定义了 Task 的可能生命周期状态。
/** Represents the possible states of a Task. */
export enum TaskState {
Submitted = "submitted",
Working = "working",
InputRequired = "input-required",
Completed = "completed",
Canceled = "canceled",
Failed = "failed",
Rejected = "rejected",
AuthRequired = "auth-required",
Unknown = "unknown",
}
| 值 | 描述 | 终端状态? |
|---|---|---|
submitted | 任务已由服务器接收并确认,但处理尚未积极开始。 | 否 |
working | 任务正在由智能体积极处理。客户端可能会期望进一步更新或终端状态。 | 否 |
input-required | 智能体需要客户端/用户提供额外输入才能继续。任务实际上已暂停。 | 否(暂停) |
completed | 任务成功完成。结果通常可在 Task.artifacts 或 TaskStatus.message 中找到。 | 是 |
canceled | 任务被取消(例如,通过 tasks/cancel 请求或服务器策略)。 | 是 |
failed | 任务因处理过程中出现错误而终止。TaskStatus.message 可能包含错误详情。 | 是 |
rejected | 任务因远程智能体拒绝而终止。TaskStatus.message 可能包含错误详情。 | 是 |
auth-required | 智能体需要客户端/用户提供额外认证才能继续。任务实际上已暂停。 | 否(暂停) |
unknown | 任务的状态无法确定(例如,任务 ID 无效、未知或已过期)。 | 是 |
6.4. Message 对象¶
表示客户端和智能体之间的单次通信轮次或一些上下文信息。消息用于指令、提示、回复和状态更新。
/** Represents a single message exchanged between user and agent. */
export interface Message {
/** Message sender's role */
role: "user" | "agent";
/** Message content */
parts: Part[];
/** Extension metadata. */
metadata?: {
[key: string]: any;
};
/** List of tasks referenced as context by this message.*/
referenceTaskIds?: string[];
/** Identifier created by the message creator*/
messageId: string;
/** Identifier of task the message is related to */
taskId?: string;
/** The context the message is associated with */
contextId?: string;
/** Event type */
kind: "message";
}
| 字段名 | 类型 | 必需 | 描述 |
|---|---|---|---|
role | "user" | "agent" | 是 | 指示发送者:"user"(来自 A2A 客户端)或 "agent"(来自 A2A 服务器)。 |
parts | Part[] | 是 | 内容部分的数组。必须包含至少一个部分。 |
metadata | Record<string, any> | 否 | 与该消息相关的任意键值元数据。 |
referenceTaskIds | string[] | 否 | 此消息引用的任务列表作为上下文提示。 |
messageId | string | 是 | 由消息发送者生成的消息标识符 |
taskId | string | 否 | 当前消息相关的任务 ID |
contextId | string | 否 | 消息关联的上下文标识符 |
kind | "message" | 是 | 类型鉴别器,文字值 |
6.5. Part Union Type¶
表示消息或工件(Artifact)中的不同内容。Part 是一个联合类型,表示导出内容为 TextPart、FilePart 或 DataPart。所有 Part 类型也包含一个可选的 metadata 字段(Record<string, any>)用于部分特定的元数据。
/** Represents a part of a message, which can be text, a file, or structured data. */
export type Part = TextPart | FilePart | DataPart;
它必须是以下之一:
6.5.1. TextPart Object¶
用于传达纯文本内容。
/** Represents a text segment within parts.*/
export interface TextPart extends PartBase {
/** Part type - text for TextParts*/
kind: "text";
/** Text content */
text: string;
}
| 字段名 | 类型 | 必需 | 描述 |
|---|---|---|---|
kind | "text" (literal) | 是 | 标识此部分为文本内容。 |
text | string | 是 | 部分中的文本内容。 |
metadata | Record<string, any> | 否 | 此文本部分的特定元数据(可选)。 |
6.5.2. FilePart Object¶
用于传达文件内容。
/** Represents a File segment within parts.*/
export interface FilePart extends PartBase {
/** Part type - file for FileParts */
kind: "file";
/** File content either as url or bytes */
file: FileWithBytes | FileWithUri;
}
| 字段名 | 类型 | 必需 | 描述 |
|---|---|---|---|
kind | "file" (literal) | 是 | 标识此部分为文件内容。 |
file | FileWithBytes | FileWithUri | 是 | 包含文件详细信息和数据/引用。 |
metadata | Record<string, any> | 否 | 此文件部分的特定元数据(可选)。 |
6.5.3. DataPart Object¶
用于传达结构化 JSON 数据。适用于表单、参数或任何机器可读信息。
/** Represents a structured data segment within a message part. */
export interface DataPart extends PartBase {
/** Part type - data for DataParts */
kind: "data";
/** Structured data content
*/
data: {
[key: string]: any;
};
}
| 字段名 | 类型 | 必需 | 描述 |
|---|---|---|---|
kind | "data" (literal) | 是 | 标识此部分为结构化数据。 |
data | Record<string, any> | 是 | 结构化 JSON 数据有效载荷(对象或数组)。 |
metadata | Record<string, any> | 否 | 此数据部分的特定元数据(例如,引用模式)。 |
6.6.1 FileWithBytes Object¶
表示文件的数据,用于 FilePart。
/** Define the variant where 'bytes' is present and 'uri' is absent */
export interface FileWithBytes extends FileBase {
/** base64 encoded content of the file*/
bytes: string;
uri?: never;
}
| 字段名 | 类型 | 必需 | 描述 |
|---|---|---|---|
name | string | 否 | 原始文件名(例如,"report.pdf")。 |
mimeType | string | 否 | 媒体类型 (例如,image/png)。强烈推荐。 |
bytes | string | 是 | Base64 编码的文件内容。 |
6.6.2 FileWithUri Object¶
表示文件的 URI,用于 FilePart。
/** Define the variant where 'uri' is present and 'bytes' is absent */
export interface FileWithUri extends FileBase {
/** URL for the File content */
uri: string;
bytes?: never;
}
| 字段名 | 类型 | 必需 | 描述 |
|---|---|---|---|
name | string | 否 | 原始文件名(例如,"report.pdf")。 |
mimeType | string | 否 | 媒体类型 (例如,image/png)。强烈推荐。 |
uri | string | 是 | URI(强烈推荐使用绝对 URL)到文件内容。可访问性取决于上下文。 |
6.7. Artifact Object¶
表示智能体在任务处理过程中生成的有形输出。工件是智能体工作的结果或产品。
/** Represents an artifact generated for a task. */
export interface Artifact {
/** Unique identifier for the artifact. */
artifactId: string;
/** Optional name for the artifact. */
name?: string;
/** Optional description for the artifact. */
description?: string;
/** Artifact parts. */
parts: Part[];
/** Extension metadata. */
metadata?: {
[key: string]: any;
};
}
| 字段名 | 类型 | 必需 | 描述 |
|---|---|---|---|
artifactId | string | 是 | 由智能体生成的工件的标识符。 |
name | string | 否 | 工件的描述性名称。 |
description | string | 否 | 人类可读的工件描述。 |
parts | Part[] | 是 | 工件的内容,作为一个或多个 Part 对象。必须至少有一个。 |
metadata | Record<string, any> | 否 | 与工件相关的任意键值元数据。 |
6.8. PushNotificationConfig Object¶
客户端提供给服务器,用于发送异步推送通知的任务更新配置。
/**Configuration for setting up push notifications for task updates. */
export interface PushNotificationConfig {
/** Push Notification ID - created by server to support multiple callbacks */
id?: string;
/** URL for sending the push notifications. */
url: string;
/** Token unique to this task/session. */
token?: string;
authentication?: PushNotificationAuthenticationInfo;
}
| 字段名 | 类型 | 必需 | 描述 |
|---|---|---|---|
url | string | 是 | 绝对 HTTPS webhook URL,用于 A2A 服务器向其发送任务更新。 |
token | string | 否 | 可选的客户端生成的不可见令牌,用于验证通知(例如,服务器在 X-A2A-Notification-Token 头中包含它)。 |
authentication | PushNotificationAuthenticationInfo | 否 | 当调用 url 时,A2A 服务器必须使用的身份验证详细信息。客户端的 webhook(接收者)定义这些要求。 |
6.9. PushNotificationAuthenticationInfo Object¶
用于指定身份验证要求的通用结构,通常在 PushNotificationConfig 中使用,以描述 A2A 服务器应该如何对客户端的 webhook 进行身份验证。
/** Defines authentication details for push notifications. */
export interface PushNotificationAuthenticationInfo {
/** Supported authentication schemes - e.g. Basic, Bearer */
schemes: string[];
/** Optional credentials */
credentials?: string;
}
| 字段名 | 类型 | 必需 | 描述 |
|---|---|---|---|
schemes | string[] | 是 | 数组包含 A2A 服务器必须使用的身份验证方案名称(例如,"Bearer"、"ApiKey")。 |
credentials | string | 否 | 可选的静态凭证或方案特定配置信息。如果涉及秘密,请极其小心。 优先选择服务器端动态凭证获取,如果可能的话。 |
6.10. TaskPushNotificationConfig Object¶
用于 tasks/pushNotificationConfig/set 方法和 tasks/pushNotificationConfig/get 方法的 params 对象,以及 result 对象。
/**Parameters for setting or getting push notification configuration for a task */
export interface TaskPushNotificationConfig {
/** Task id. */
taskId: string;
/** Push notification configuration. */
pushNotificationConfig: PushNotificationConfig;
}
| 字段名 | 类型 | 必需 | 描述 |
|---|---|---|---|
taskId | string | 是 | 要为其配置推送通知的任务 ID,或从其获取配置。 |
pushNotificationConfig | PushNotificationConfig | 是 | 推送通知配置。对于 set,所需的配置。对于 get,当前配置(服务器可能省略或屏蔽 authentication.credentials 字段中的敏感细节)。 |
6.11. JSON-RPC 结构¶
A2A 遵循标准 JSON-RPC 2.0 结构用于请求和响应。
6.11.1. JSONRPCRequest Object¶
所有 A2A 方法调用都包含在 JSON-RPC 请求对象中。
jsonrpc: 一个字符串,指定 JSON-RPC 协议的版本。必须为"2.0"。method: 一个字符串,包含要调用的方法的名称(例如,"message/send"、"tasks/get")。params: 一个结构化值,用于在调用方法时提供参数值。此成员可以省略,如果方法不需要参数。A2A 方法通常使用object作为params。id: 由客户端建立的标识符必须包含一个字符串、数字或NULL值。如果未包含,则假定为通知。此值不应为NULL用于期望响应的请求,且数字不应包含小数部分。服务器必须在响应对象中返回相同的值,如果包含的话。此成员用于在两个对象之间关联上下文。A2A 方法通常期望响应或流,因此id通常存在且不为空。
6.11.2. JSONRPCResponse Object¶
从 A2A 服务器返回的响应包含在 JSON-RPC 响应对象中。
jsonrpc: 一个字符串,指定 JSON-RPC 协议的版本。必须为"2.0"。id: 此成员必须与请求对象中的id成员值相同。如果请求对象中未检测到id(例如,解析错误/无效请求),则必须为null。- 要么
result: 此成员必须在成功时存在。如果方法调用时出错,则此成员不应存在。此成员的值由服务器上调用的方法确定。 - 或者
error: 此成员必须在失败时存在。如果未触发任何错误,则此成员不应存在。此成员的值必须是一个JSONRPCError对象。 result和error成员是互斥的:一个必须存在,另一个不应存在。
6.12. JSONRPCError Object¶
当 JSON-RPC 调用遇到错误时,响应对象将包含一个 error 成员,其值为该结构。
/**
* Represents a JSON-RPC 2.0 Error object.
* This is typically included in a JSONRPCErrorResponse when an error occurs.
*/
export interface JSONRPCError {
/**
* A Number that indicates the error type that occurred.
*/
code: number;
/**
* A String providing a short description of the error.
*/
message: string;
/**
* A Primitive or Structured value that contains additional information about the error.
* This may be omitted.
*/
data?: any;
}
| 字段名 | 类型 | 必需 | 描述 |
|---|---|---|---|
code | integer | 是 | 整数错误代码。请参见第 8 节(错误处理) 了解标准和 A2A 特定的代码。 |
message | string | 是 | 简短的人类可读错误摘要。 |
data | any | 否 | 可选的附加结构化错误信息。 |
7. 协议 RPC 方法¶
所有 A2A RPC 方法都通过向 A2A 服务器发送 HTTP POST 请求来调用。HTTP POST 请求的主体必须是 JSONRPCRequest 对象,并且 Content-Type 头必须为 application/json。
A2A 服务器返回的 HTTP 响应主体必须是 JSONRPCResponse 对象(或,对于流式方法,SSE 流,其中每个事件的数据是 JSONRPCResponse)。JSON-RPC 响应的 Content-Type 为 application/json。对于 SSE 流,它是 text/event-stream。
7.1. message/send¶
发送消息以启动新的交互或继续现有交互。此方法适用于同步请求/响应交互或当客户端侧轮询(使用 tasks/get)可以接受监控长时间运行的任务时。
- 请求
params类型:MessageSendParams - 响应
result类型(成功时):Task|Message(消息对象或处理消息后的任务当前或最终状态)。 - 响应
error类型(失败时):JSONRPCError。
7.1.1. MessageSendParams Object¶
/** Sent by the client to the agent as a request. May create, continue or restart a task. */
export interface MessageSendParams {
/** The message being sent to the server. */
message: Message;
/** Send message configuration. */
configuration?: MessageSendConfiguration;
/** Extension metadata. */
metadata?: {
[key: string]: any;
};
}
/**Configuration for the send message request. */
export interface MessageSendConfiguration {
/** Accepted output modalities by the client. */
acceptedOutputModes: string[];
/** Number of recent messages to be retrieved. */
historyLength?: number;
/** Where the server should send notifications when disconnected. */
pushNotificationConfig?: PushNotificationConfig;
/** If the server should treat the client as a blocking request. */
blocking?: boolean;
}
| 字段名 | 类型 | 必需 | 描述 |
|---|---|---|---|
message | Message | 是 | 要发送的消息内容。Message.role 通常为 "user"。 |
configuration | MessageSendConfiguration | 否 | 可选:额外的消息配置 |
metadata | Record<string, any> | 否 | 请求特定的元数据。 |
7.2. message/stream¶
发送消息以启动/继续任务,并订阅客户端以通过 Server-Sent Events (SSE) 实时更新该任务。此方法需要服务器具有 AgentCard.capabilities.streaming: true。
- 请求
params类型:MessageSendParams(与message/send相同)。 - 响应(成功订阅后):
- HTTP 状态:
200 OK。 - HTTP
Content-Type:text/event-stream。 - HTTP 主体:Server-Sent Events 流。每个 SSE
data字段包含一个SendStreamingMessageResponseJSON 对象。
- HTTP 状态:
- 响应(初始订阅失败):
- 标准 HTTP 错误代码(例如,4xx、5xx)。
- HTTP 主体可能包含标准
JSONRPCResponse和一个带有失败原因的error对象。
7.2.1. SendStreamingMessageResponse Object¶
这是在 message/stream 请求或 tasks/resubscribe 请求的 data 字段中找到的 JSON 对象结构。
/**
* JSON-RPC response model for the 'message/stream' method.
*/
export type SendStreamingMessageResponse =
| SendStreamingMessageSuccessResponse
| JSONRPCErrorResponse;
/**
* JSON-RPC success response model for the 'message/stream' method.
*/
export interface SendStreamingMessageSuccessResponse
extends JSONRPCSuccessResponse {
result: Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent;
}
| 字段名 | 类型 | 必需 | 描述 |
|---|---|---|---|
jsonrpc | "2.0" (literal) | 是 | JSON-RPC 版本字符串。 |
id | string | number | 是 | 与发起 message/stream 或 tasks/resubscribe 请求的 id 匹配。 |
result | 要么 Message 要么 Task 要么 TaskStatusUpdateEvent 要么 TaskArtifactUpdateEvent | 是 | 事件有效载荷 |
7.2.2. TaskStatusUpdateEvent Object¶
携带有关任务状态变化的流式传输信息。这是 SendStreamingMessageSuccessResponse 的可能结果之一。
/** Sent by server during sendStream or subscribe requests */
export interface TaskStatusUpdateEvent {
/** Task id */
taskId: string;
/** The context the task is associated with */
contextId: string;
/** Event type */
kind: "status-update";
/** Current status of the task */
status: TaskStatus;
/** Indicates the end of the event stream */
final: boolean;
/** Extension metadata. */
metadata?: {
[key: string]: any;
};
}
| 字段名 | 类型 | 必需 | 默认值 | 描述 |
|---|---|---|---|---|
taskId | string | 是 | 正在更新的任务 ID | |
contextId | string | 是 | 任务关联的上下文 ID | |
kind | string, literal | 是 | status-update | 类型鉴别器,文字值 |
status | TaskStatus | 是 | 新的 TaskStatus 对象。 | |
final | boolean | 否 | false | 如果为 true,表示这是当前流循环的终端状态更新。服务器通常在发送此事件后关闭 SSE 连接。 |
metadata | Record<string, any> | 否 | undefined | 事件特定的元数据。 |
7.2.3. TaskArtifactUpdateEvent Object¶
携带新或更新的工件(或工件块),由任务在流式传输过程中生成。这是 SendTaskStreamingResponse 的可能结果之一。
/** Sent by server during sendStream or subscribe requests */
export interface TaskArtifactUpdateEvent {
/** Task id */
taskId: string;
/** The context the task is associated with */
contextId: string;
/** Event type */
kind: "artifact-update";
/** Generated artifact */
artifact: Artifact;
/** Indicates if this artifact appends to a previous one */
append?: boolean;
/** Indicates if this is the last chunk of the artifact */
lastChunk?: boolean;
/** Extension metadata. */
metadata?: {
[key: string]: any;
};
}
| 字段名 | 类型 | 必需 | 默认值 | 描述 |
|---|---|---|---|---|
taskId | string | 是 | 与生成的工件部分关联的任务 ID | |
contextId | string | 是 | 任务关联的上下文 ID | |
kind | string, literal | 是 | artifact-update | 类型鉴别器,文字值 |
artifact | Artifact | 是 | 工件数据。可能是完整的工件或增量块。 | |
append | boolean | 否 | false | true 表示将部分附加到工件;false(默认)表示替换。 |
lastChunk | boolean | 否 | false | true 表示这是工件的最终更新。 |
metadata | Record<string, any> | 否 | undefined | 事件特定的元数据。 |
7.3. tasks/get¶
检索以前启动的任务的当前状态(包括状态、输出和可选的历史记录)。这通常用于轮询使用 message/send 启动的任务的状态,或用于在通过推送通知或 SSE 流结束通知后获取任务的最终状态。
- 请求
params类型:TaskQueryParams - 响应
result类型(成功时):Task(任务当前状态的快照)。 - 响应
error类型(失败时):JSONRPCError(例如,如果任务 ID 不存在,请参见TaskNotFoundError)。
7.3.1. TaskQueryParams Object¶
/** Parameters for querying a task, including optional history length. */
export interface TaskQueryParams extends TaskIdParams {
/** Number of recent messages to be retrieved. */
historyLength?: number;
}
| 字段名 | 类型 | 必需 | 描述 |
|---|---|---|---|
id | string | 是 | 要检索其当前状态的任务的 ID。 |
historyLength | integer | 否 | 如果为正数,请求服务器包含最多 N 个最近消息的 Task.history。 |
metadata | Record<string, any> | 否 | 请求特定的元数据。 |
7.4. tasks/cancel¶
请求取消正在进行中的任务。服务器将尝试取消任务,但成功与否无法保证(例如,任务可能已经完成或失败,或者在当前阶段不支持取消)。
- 请求
params类型:TaskIdParams - 响应
result类型(成功时):Task(任务取消尝试后的状态。理想情况下,Task.status.state将为"canceled"如果成功)。 - 响应
error类型(失败时):JSONRPCError(例如,TaskNotFoundError、TaskNotCancelableError)。
7.4.1. TaskIdParams Object (for tasks/cancel and tasks/pushNotificationConfig/get)¶
一个简单的对象,仅包含任务 ID 和可选的元数据。
/** Parameters containing only a task ID, used for simple task operations. */
export interface TaskIdParams {
/** Task id. */
id: string;
metadata?: {
[key: string]: any;
};
}
| 字段名 | 类型 | 必需 | 描述 |
|---|---|---|---|
id | string | 是 | 任务的 ID。 |
metadata | Record<string, any> | 否 | 请求特定的元数据。 |
7.5. tasks/pushNotificationConfig/set¶
设置或更新指定任务的推送通知配置。这允许客户端告诉服务器在哪里以及如何发送异步更新任务。需要服务器具有 AgentCard.capabilities.pushNotifications: true。
- 请求
params类型:TaskPushNotificationConfig - 响应
result类型(成功时):TaskPushNotificationConfig(确认设置了配置。服务器可能省略或屏蔽响应中的任何敏感细节,如authentication.credentials字段)。 - 响应
error类型(失败时):JSONRPCError(例如,PushNotificationNotSupportedError、TaskNotFoundError、与无效PushNotificationConfig相关的错误)。
7.6. tasks/pushNotificationConfig/get¶
检索指定任务的当前推送通知配置。需要服务器具有 AgentCard.capabilities.pushNotifications: true。
- 请求
params类型:TaskIdParams - 响应
result类型(成功时):TaskPushNotificationConfig(任务的当前推送通知配置。服务器可能会返回错误,如果任务没有关联的推送通知配置)。 - 响应
error类型(失败时):JSONRPCError(例如,PushNotificationNotSupportedError、TaskNotFoundError)。
7.7. tasks/resubscribe¶
允许客户端重新连接到 SSE 流以继续进行中的任务(从 message/stream 或之前的 tasks/resubscribe 中断)。需要服务器具有 AgentCard.capabilities.streaming: true。
目的是恢复接收后续更新。服务器在断开连接期间错过的事件的处理方式(例如,是否尝试回填一些错过的事件或仅从重新订阅点发送新事件)是特定于实现的,并且此规范没有严格定义。
- 请求
params类型:TaskIdParams - 响应(成功重新订阅后):
- HTTP 状态:
200 OK。 - HTTP
Content-Type:text/event-stream。 - HTTP 主体:Server-Sent Events 流,格式与
message/stream相同,携带后续的SendStreamingMessageResponse事件。
- HTTP 状态:
- 响应(重新订阅失败):
- 标准 HTTP 错误代码(例如,4xx、5xx)。
- HTTP 主体可能包含标准
JSONRPCResponse和一个带有失败原因的error对象。失败可能发生在任务不再活动、不存在或不支持/启用流式传输时。
7.8. agent/authenticatedExtendedCard¶
检索客户端通过认证后可能更详细的智能体卡片。此端点仅在 AgentCard.supportsAuthenticatedExtendedCard 为 true 时可用。这是一个 HTTP GET 端点,而不是 JSON-RPC 方法。
- 端点 URL:
{AgentCard.url}/../agent/authenticatedExtendedCard(相对于公共智能体卡片中指定的基础 URL)。 - HTTP 方法:
GET - 身份验证:客户端必须使用公共
AgentCard.securitySchemes和AgentCard.security字段中声明的方案之一对请求进行身份验证。 - 请求
params:无(HTTP GET 请求)。 - 响应
result类型(成功时):AgentCard(完整的智能体卡片对象,可能包含在公共卡片中未出现的其他细节或技能)。 - 响应
error类型(失败时):标准 HTTP 错误代码。401 Unauthorized:身份验证失败(缺少或无效的凭证)。服务器应该包含WWW-Authenticate头。403 Forbidden:身份验证成功,但客户端/用户无权访问扩展卡片。404 Not Found:声明了supportsAuthenticatedExtendedCard功能,但服务器未在指定的路径上实现此端点。5xx Server Error:服务器内部错误。
客户端检索此认证卡片后应该将其缓存的公共智能体卡片替换为从该端点接收到的内容,持续其认证会话或直到卡片版本更改。
7.8.1. AuthenticatedExtendedCardParams Object¶
此端点不使用 JSON-RPC params。如果需要,任何参数都可以作为 HTTP 查询参数包含(尽管标准中未定义任何参数)。
7.8.2. AuthenticatedExtendedCardResponse Object¶
成功的响应主体是一个符合 AgentCard 接口的 JSON 对象。
8. 错误处理¶
A2A 使用标准 JSON-RPC 2.0 错误代码和结构 报告错误。错误在 JSONRPCErrorResponse 对象的 error 成员中返回。请参见 JSONRPCError Object 定义。
8.1. 标准 JSON-RPC 错误¶
这些是 JSON-RPC 2.0 规范定义的标准代码。
| 代码 | JSON-RPC Spec 含义 | 典型的 A2A message | 描述 |
|---|---|---|---|
-32700 | Parse error | Invalid JSON payload | 服务器收到格式不正确的 JSON。 |
-32600 | Invalid Request | Invalid JSON-RPC Request | 提供的 JSON 有效载荷是有效的 JSON,但不是有效的 JSON-RPC Request 对象。 |
-32601 | Method not found | Method not found | 请求的 A2A RPC method(例如,"tasks/foo")不存在或不受支持。 |
-32602 | Invalid params | Invalid method parameters | 提供的 params 对于方法无效(例如,类型错误、缺少必需字段)。 |
-32603 | Internal error | Internal server error | 服务器在处理过程中遇到意外错误。 |
-32000 to -32099 | Server error | (Server-defined) | 保留用于实现定义的服务器错误。A2A 特定的错误使用此范围。 |
8.2. A2A 特定错误¶
这些是 JSON-RPC 服务器错误范围 (-32000 to -32099) 中定义的自定义错误代码,以提供有关 A2A 相关问题的更具体反馈。服务器应该在适用时使用这些代码。
| 代码 | 错误名称(概念) | 典型的 message 字符串 | 描述 |
|---|---|---|---|
-32001 | TaskNotFoundError | Task not found | 指定的任务 id 不对应于现有或活动的任务。它可能无效、过期或已完成并被清除。 |
-32002 | TaskNotCancelableError | Task cannot be canceled | 尝试取消任务时,任务不在可取消状态(例如,它已经达到终端状态,如 completed、failed 或 canceled)。 |
-32003 | PushNotificationNotSupportedError | Push Notification is not supported | 客户端尝试使用推送通知功能(例如,tasks/pushNotificationConfig/set),但服务器代理不支持它们(即,AgentCard.capabilities.pushNotifications 为 false)。 |
-32004 | UnsupportedOperationError | This operation is not supported | 请求的操作或特定方面(可能由参数暗示)不被此服务器代理实现支持。比方法不存在更广泛。 |
-32005 | ContentTypeNotSupportedError | Incompatible content types | 请求的 message.parts 中的 媒体类型(或对于工件隐含)不被代理或正在调用的特定技能支持。 |
-32006 | InvalidAgentResponseError | Invalid agent response type | 智能体为请求的方法生成无效响应 |
服务器可以在 -32000 到 -32099 范围内定义其他错误代码,以提供上述未涵盖的更具体场景,但它们应该清楚地记录这些错误。JSONRPCError 对象的 data 字段可以用于提供任何错误的更多结构化细节。
9. 常见工作流程和示例¶
本节提供了常见 A2A 交互的 JSON 示例。时间戳、上下文 ID 和请求/响应 ID 仅用于演示目的。为了简洁起见,如果示例不重要,某些可选字段可能会被省略。
9.1. 获取认证扩展智能体卡片¶
场景: 客户端发现公共智能体卡片,表示支持认证扩展卡片,并希望检索完整细节。
- 客户端获取公共智能体卡片:
服务器响应公共智能体卡片(如第 5.6 节中的示例),包括 supportsAuthenticatedExtendedCard: true(在根级别)和 securitySchemes。
-
客户端识别公共卡片中所需的认证:
-
客户端通过带外方式获取必要的凭证(例如,通过 Google 进行 OAuth 2.0 流程,生成访问令牌):
-
客户端获取认证扩展智能体卡片:
GET https://example.com/a2a/agent/authenticatedExtendedCard
Authorization: Bearer <obtained_access_token>
-
服务器认证并授权请求:
-
服务器响应完整智能体卡片:
9.2. 基本执行(同步/轮询风格)¶
场景: 客户端询问一个简单问题,智能体快速响应任务
- 客户端使用
message/send发送消息:
{
"jsonrpc": "2.0",
"id": 1,
"method": "message/send",
"params": {
"message": {
"role": "user",
"parts": [
{
"kind": "text",
"text": "tell me a joke"
}
],
"messageId": "9229e770-767c-417b-a0b0-f0741243c589"
},
"metadata": {}
}
}
- 服务器处理请求,创建任务并响应(任务快速完成)
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"id": "363422be-b0f9-4692-a24d-278670e7c7f1",
"contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4",
"status": {
"state": "completed"
},
"artifacts": [
{
"artifactId": "9b6934dd-37e3-4eb1-8766-962efaab63a1",
"name": "joke",
"parts": [
{
"kind": "text",
"text": "Why did the chicken cross the road? To get to the other side!"
}
]
}
],
"history": [
{
"role": "user",
"parts": [
{
"kind": "text",
"text": "tell me a joke"
}
],
"messageId": "9229e770-767c-417b-a0b0-f0741243c589",
"taskId": "363422be-b0f9-4692-a24d-278670e7c7f1",
"contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4"
}
],
"kind": "task",
"metadata": {}
}
}
场景: 客户端询问一个简单问题,智能体快速响应但没有任务
- 客户端使用
message/send发送消息:
{
"jsonrpc": "2.0",
"id": 1,
"method": "message/send",
"params": {
"message": {
"role": "user",
"parts": [
{
"kind": "text",
"text": "tell me a joke"
}
],
"messageId": "9229e770-767c-417b-a0b0-f0741243c589"
},
"metadata": {}
}
}
- 服务器处理请求,快速响应但没有任务
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"messageId": "363422be-b0f9-4692-a24d-278670e7c7f1",
"contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4",
"parts": [
{
"kind": "text",
"text": "Why did the chicken cross the road? To get to the other side!"
}
],
"kind": "message",
"metadata": {}
}
}
如果任务是长时间运行的,服务器可能会最初响应 status.state: "working"。客户端将定期使用 params: {"id": "363422be-b0f9-4692-a24d-278670e7c7f1"} 调用 tasks/get,直到任务达到终端状态。
9.3. 流式任务执行(SSE)¶
场景: 客户端要求智能体写一篇描述附件图片的长篇论文。
- 客户端发送消息并订阅使用
message/stream:
{
"method": "message/stream",
"params": {
"message": {
"role": "user",
"parts": [
{
"kind": "text",
"text": "write a long paper describing the attached pictures"
},
{
"kind": "file",
"file": {
"mimeType": "image/png",
"data": "<base64-encoded-content>"
}
}
],
"messageId": "bbb7dee1-cf5c-4683-8a6f-4114529da5eb"
},
"metadata": {}
}
}
- 服务器响应 HTTP 200 OK,
Content-Type: text/event-stream,并开始发送 SSE 事件:
事件 1:任务状态更新 - 工作
data: {
"jsonrpc": "2.0",
"id": 1,
"result": {
"id": "225d6247-06ba-4cda-a08b-33ae35c8dcfa",
"contextId": "05217e44-7e9f-473e-ab4f-2c2dde50a2b1",
"status": {
"state": "submitted",
"timestamp":"2025-04-02T16:59:25.331844"
},
"history": [
{
"role": "user",
"parts": [
{
"kind": "text",
"text": "write a long paper describing the attached pictures"
},
{
"kind": "file",
"file": {
"mimeType": "image/png",
"data": "<base64-encoded-content>"
}
}
],
"messageId": "bbb7dee1-cf5c-4683-8a6f-4114529da5eb",
"taskId": "225d6247-06ba-4cda-a08b-33ae35c8dcfa",
"contextId": "05217e44-7e9f-473e-ab4f-2c2dde50a2b1"
}
],
"kind": "task",
"metadata": {}
}
}
data: {
"jsonrpc": "2.0",
"id": 1,
"result": {
"taskId": "225d6247-06ba-4cda-a08b-33ae35c8dcfa",
"contextId": "05217e44-7e9f-473e-ab4f-2c2dde50a2b1",
"artifact": {
"artifactId": "9b6934dd-37e3-4eb1-8766-962efaab63a1",
"parts": [
{"type":"text", "text": "<section 1...>"}
]
},
"append": false,
"lastChunk": false,
"kind":"artifact-update"
}
}
data: {
"jsonrpc": "2.0",
"id": 1,
"result": {
"taskId": "225d6247-06ba-4cda-a08b-33ae35c8dcfa",
"contextId": "05217e44-7e9f-473e-ab4f-2c2dde50a2b1",
"artifact": {
"artifactId": "9b6934dd-37e3-4eb1-8766-962efaab63a1",
"parts": [
{"type":"text", "text": "<section 2...>"}
],
},
"append": true,
"lastChunk": false,
"kind":"artifact-update"
}
}
data: {
"jsonrpc": "2.0",
"id": 1,
"result": {
"taskId": "225d6247-06ba-4cda-a08b-33ae35c8dcfa",
"contextId": "05217e44-7e9f-473e-ab4f-2c2dde50a2b1",
"artifact": {
"artifactId": "9b6934dd-37e3-4eb1-8766-962efaab63a1",
"parts": [
{"type":"text", "text": "<section 3...>"}
]
},
"append": true,
"lastChunk": true,
"kind":"artifact-update"
}
}
data: {
"jsonrpc": "2.0",
"id": 1,
"result": {
"taskId": "225d6247-06ba-4cda-a08b-33ae35c8dcfa",
"contextId": "05217e44-7e9f-473e-ab4f-2c2dde50a2b1",
"status": {
"state": "completed",
"timestamp":"2025-04-02T16:59:35.331844"
},
"final": true,
"kind":"status-update"
}
}
(服务器在发送 final:true 事件后关闭 SSE 连接)。
9.4. 多轮交互(输入要求)¶
场景: 客户端想要预订航班,智能体需要更多信息。
- 客户端使用
message/send发送消息:
{
"jsonrpc": "2.0",
"id": "req-003",
"method": "message/send",
"params": {
"message": {
"role": "user",
"parts": [{ "kind": "text", "text": "I'd like to book a flight." }]
},
"messageId": "c53ba666-3f97-433c-a87b-6084276babe2"
}
}
- 服务器响应,任务状态为
input-required:
{
"jsonrpc": "2.0",
"id": "req-003",
"result": {
"id": "3f36680c-7f37-4a5f-945e-d78981fafd36",
"contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4",
"status": {
"state": "input-required",
"message": {
"role": "agent",
"parts": [
{
"kind": "text",
"text": "Sure, I can help with that! Where would you like to fly to, and from where? Also, what are your preferred travel dates?"
}
],
"messageId": "c2e1b2dd-f200-4b04-bc22-1b0c65a1aad2",
"taskId": "3f36680c-7f37-4a5f-945e-d78981fafd36",
"contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4"
},
"timestamp": "2024-03-15T10:10:00Z"
},
"history": [
{
"role": "user",
"parts": [
{
"kind": "text",
"text": "I'd like to book a flight."
}
],
"messageId": "c53ba666-3f97-433c-a87b-6084276babe2",
"taskId": "3f36680c-7f37-4a5f-945e-d78981fafd36",
"contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4"
}
],
"kind": "task"
}
}
- 客户端
message/send(提供请求的输入,使用相同的任务 ID):
{
"jsonrpc": "2.0",
"id": "req-004",
"method": "message/send",
"params": {
"message": {
"role": "user",
"parts": [
{
"kind": "text",
"text": "I want to fly from New York (JFK) to London (LHR) around October 10th, returning October 17th."
}
],
"contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4",
"taskId": "3f36680c-7f37-4a5f-945e-d78981fafd36",
"messageId": "0db1d6c4-3976-40ed-b9b8-0043ea7a03d3"
},
"configuration": {
"blocking": true
}
}
}
- 服务器处理新输入并响应(例如,任务完成或需要更多输入):
{
"jsonrpc": "2.0",
"id": "req-004",
"result": {
"id": "3f36680c-7f37-4a5f-945e-d78981fafd36",
"contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4",
"status": {
"state": "completed",
"message": {
"role": "agent",
"parts": [
{
"kind": "text",
"text": "Okay, I've found a flight for you. Confirmation XYZ123. Details are in the artifact."
}
]
}
},
"artifacts": [
{
"artifactId": "9b6934dd-37e3-4eb1-8766-962efaab63a1",
"name": "FlightItinerary.json",
"parts": [
{
"kind": "data",
"data": {
"confirmationId": "XYZ123",
"from": "JFK",
"to": "LHR",
"departure": "2024-10-10T18:00:00Z",
"arrival": "2024-10-11T06:00:00Z",
"returnDeparture": "..."
}
}
]
}
],
"history": [
{
"role": "user",
"parts": [
{
"kind": "text",
"text": "I'd like to book a flight."
}
],
"messageId": "c53ba666-3f97-433c-a87b-6084276babe2",
"taskId": "3f36680c-7f37-4a5f-945e-d78981fafd36",
"contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4"
},
{
"role": "agent",
"parts": [
{
"kind": "text",
"text": "Sure, I can help with that! Where would you like to fly to, and from where? Also, what are your preferred travel dates?"
}
],
"messageId": "c2e1b2dd-f200-4b04-bc22-1b0c65a1aad2",
"taskId": "3f36680c-7f37-4a5f-945e-d78981fafd36",
"contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4"
},
{
"role": "user",
"parts": [
{
"kind": "text",
"text": "I want to fly from New York (JFK) to London (LHR) around October 10th, returning October 17th."
}
],
"contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4",
"taskId": "3f36680c-7f37-4a5f-945e-d78981fafd36",
"messageId": "0db1d6c4-3976-40ed-b9b8-0043ea7a03d3"
}
],
"kind": "task",
"metadata": {}
}
}
9.5. 推送通知设置和使用¶
场景: 客户端请求长时间运行的报告生成,并希望在完成后通过 webhook 通知。
- 客户端
message/send带有pushNotification配置:
{
"jsonrpc": "2.0",
"id": "req-005",
"method": "message/send",
"params": {
"message": {
"role": "user",
"parts": [
{
"kind": "text",
"text": "Generate the Q1 sales report. This usually takes a while. Notify me when it's ready."
}
],
"messageId": "6dbc13b5-bd57-4c2b-b503-24e381b6c8d6"
},
"configuration": {
"pushNotificationConfig": {
"url": "https://client.example.com/webhook/a2a-notifications",
"token": "secure-client-token-for-task-aaa",
"authentication": {
"schemes": ["Bearer"]
// Assuming server knows how to get a Bearer token for this webhook audience,
// or this implies the webhook is public/uses the 'token' for auth.
// 'credentials' could provide more specifics if needed by the server.
}
}
}
}
}
- 服务器确认任务(例如,状态为
submitted或working):
{
"jsonrpc": "2.0",
"id": "req-005",
"result": {
"id": "43667960-d455-4453-b0cf-1bae4955270d",
"contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4",
"status": { "state": "submitted", "timestamp": "2024-03-15T11:00:00Z" }
// ... other fields ...
}
}
-
(稍后)A2A 服务器完成任务并通过
https://client.example.com/webhook/a2a-notifications发送通知: -
HTTP 头可能包括:
Authorization: Bearer <server_jwt_for_webhook_audience>(如果服务器对 webhook 进行身份验证)Content-Type: application/jsonX-A2A-Notification-Token: secure-client-token-for-task-aaa
- HTTP 主体(任务对象作为 JSON 有效载荷发送):
{
"id": "43667960-d455-4453-b0cf-1bae4955270d",
"contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4",
"status": { "state": "completed", "timestamp": "2024-03-15T18:30:00Z" },
"kind": "task"
// ... other fields ...
}
-
客户端的 Webhook 服务:
-
接收 POST。
- 验证
Authorization头(如果适用)。 - 验证
X-A2A-Notification-Token。 - 内部处理通知(例如,更新应用程序状态,通知终端用户)。
9.6. 文件交换(上传和下载)¶
场景: 客户端发送图像进行分析,智能体返回修改后的图像。
- 客户端
message/send带有FilePart(上传图像字节):
{
"jsonrpc": "2.0",
"id": "req-007",
"method": "message/send",
"params": {
"message": {
"role": "user",
"parts": [
{
"kind": "text",
"text": "Analyze this image and highlight any faces."
},
{
"kind": "file",
"file": {
"name": "input_image.png",
"mimeType": "image/png",
"bytes": "iVBORw0KGgoAAAANSUhEUgAAAAUA..." // Base64 encoded image data
}
}
],
"messageId": "6dbc13b5-bd57-4c2b-b503-24e381b6c8d6"
}
}
}
- 服务器处理图像并响应带有
FilePart的工件(例如,提供修改后图像的 URI):
{
"jsonrpc": "2.0",
"id": "req-007",
"result": {
"id": "43667960-d455-4453-b0cf-1bae4955270d",
"contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4",
"status": { "state": "completed", "timestamp": "2024-03-15T12:05:00Z" },
"artifacts": [
{
"artifactId": "9b6934dd-37e3-4eb1-8766-962efaab63a1",
"name": "processed_image_with_faces.png",
"parts": [
{
"kind": "file",
"file": {
"name": "output.png",
"mimeType": "image/png",
// Server might provide a URI to a temporary storage location
"uri": "https://storage.example.com/processed/task-bbb/output.png?token=xyz"
// Or, alternatively, it could return bytes directly:
// "bytes": "ASEDGhw0KGgoAAAANSUhEUgAA..."
}
}
]
}
],
"kind": "task"
}
}
9.7. 结构化数据交换(请求和提供 JSON)¶
场景: 客户端请求特定 JSON 格式的开放支持凭证列表。
- 客户端
message/send,Part.metadata提示所需的输出模式/媒体类型: (注意:A2A 在 v0.2.0 中不正式标准化模式协商,但metadata可以用于客户端/服务器之间的约定协商。)
{
"jsonrpc": "2.0",
"id": 9,
"method": "message/send",
"params": {
"message": {
"role": "user",
"parts": [
{
"kind": "text",
"text": "Show me a list of my open IT tickets",
"metadata": {
"mimeType": "application/json",
"schema": {
"type": "array",
"items": {
"type": "object",
"properties": {
"ticketNumber": { "type": "string" },
"description": { "type": "string" }
}
}
}
}
}
],
"messageId": "85b26db5-ffbb-4278-a5da-a7b09dea1b47"
},
"metadata": {}
}
}
- 服务器响应结构化 JSON 数据:
{
"jsonrpc": "2.0",
"id": 9,
"result": {
"id": "d8c6243f-5f7a-4f6f-821d-957ce51e856c",
"contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4",
"status": {
"state": "completed",
"timestamp": "2025-04-17T17:47:09.680794"
},
"artifacts": [
{
"artifactId": "c5e0382f-b57f-4da7-87d8-b85171fad17c",
"parts": [
{
"kind": "text",
"text": "[{\"ticketNumber\":\"REQ12312\",\"description\":\"request for VPN access\"},{\"ticketNumber\":\"REQ23422\",\"description\":\"Add to DL - team-gcp-onboarding\"}]"
}
]
}
],
"kind": "task"
}
}
这些示例说明了 A2A 在处理各种交互模式和数据类型方面的灵活性。实现者应参考所有字段和约束的详细对象定义。
10. 附录¶
10.1. 与 MCP(模型上下文协议)的关系¶
A2A 和 MCP 是互补协议,设计用于代理系统的不同方面:
- 模型上下文协议 (MCP): 专注于标准化 AI 模型和代理如何连接到和交互工具、API、数据源和其他外部资源。它定义了描述工具功能(如 LLM 中的函数调用)、传递输入和接收结构化输出的结构化方式。将 MCP 视为代理如何使用特定功能或访问资源的"如何"。
- Agent2Agent 协议 (A2A): 专注于标准化独立且通常不透明的AI 代理如何相互通信和协作。A2A 为代理提供了一个应用程序级协议,用于发现彼此、协商交互模式、管理共享任务并交换对话上下文或复杂结果。这是关于代理如何合作或委托工作。
它们如何一起工作: 一个 A2A 客户端代理可能会请求 A2A 服务器代理执行复杂任务。服务器代理可能会使用 MCP 与几个底层工具、API 或数据源交互,以收集信息或执行必要的操作,以完成 A2A 任务。
有关更详细的比较,请参见 A2A 和 MCP 指南。
10.2. 安全注意事项总结¶
安全性是 A2A 的关键考虑因素。关键考虑因素包括:
- 传输安全性: 在生产环境中始终使用 HTTPS 和强 TLS 配置。
- 身份验证:
- 通过标准 HTTP 机制处理(例如,
Authorization头中的 Bearer 令牌、API 密钥)。 - 在
AgentCard中声明要求。 - 客户端必须通过带外方式获取凭证。
- A2A 服务器必须对每个请求进行身份验证。
- 通过标准 HTTP 机制处理(例如,
- 授权:
- 基于已认证的客户端/用户身份的服务器端责任。
- 实施最小权限原则。
- 可以根据技能、操作或数据进行细粒度控制。
- 推送通知安全性:
- Webhook URL 验证(通过 A2A 服务器发送通知)对于防止 SSRF 至关重要。
- A2A 服务器对客户端 webhook 的身份验证是必不可少的。
- 客户端 webhook 接收者(验证它来自合法的 A2A 服务器并且相关)对通知的验证至关重要。
- 请参阅 流式和异步操作指南 了解详细的推送通知安全性。
- 输入验证: 服务器必须严格验证所有 RPC 参数和
Message和Artifact部分中的数据/结构,以防止注入攻击或处理错误。 - 资源管理: 实施速率限制、并发控制和资源限制,以保护代理免受滥用或过载。
- 数据隐私: 遵守所有适用隐私法规,在
Message和Artifact部分中交换的数据。最小化敏感数据传输。
有关全面讨论,请参见 企业级功能指南。