Agent2Agent (A2A) 协议规范

版本: 0.1.0

1. 简介

Agent2Agent (A2A) 协议是一个开放标准,旨在促进独立、可能不透明的AI代理系统之间的通信和互操作性。在一个代理可能使用不同框架、语言或由不同供应商构建的生态系统中,A2A提供了通用语言和交互模型。

本文档提供了A2A协议的详细技术规范。其主要目标是使代理能够:

  • 发现彼此的能力
  • 协商交互模式(文本、文件、结构化数据)
  • 管理协作任务
  • 安全交换信息以实现用户目标,而无需访问彼此的内部状态、记忆或工具

1.1. A2A的关键目标

  • 互操作性:弥合不同代理系统之间的通信鸿沟
  • 协作:使代理能够委派任务、交换上下文并共同处理复杂的用户请求
  • 发现:允许代理动态发现并理解其他代理的能力
  • 灵活性:支持各种交互模式,包括同步请求/响应、实时更新的流式传输以及长时间运行任务的异步推送通知
  • 安全性:采用标准Web安全实践,支持适合企业环境的安全通信模式
  • 异步性:原生支持可能涉及人工干预场景的长时间运行任务和交互

1.2. 指导原则

  • 简单:重用现有的、易于理解的标准(HTTP、JSON-RPC 2.0、服务器发送事件)
  • 企业就绪:通过与企业实践保持一致,解决认证、授权、安全、隐私、跟踪和监控问题
  • 异步优先:设计用于(可能非常)长时间运行的任务和人工干预的交互
  • 模式无关:支持交换多种内容类型,包括文本、音频/视频(通过文件引用)、结构化数据/表单以及潜在的嵌入式UI组件(例如部件中引用的iframe)
  • 不透明执行:代理基于声明的能力和交换的信息进行协作,而无需共享其内部思想、计划或工具实现

有关A2A目的和好处的更广泛理解,请参见什么是A2A?

2. 核心概念摘要

A2A围绕几个关键概念展开。详细解释请参考关键概念指南

  • A2A客户端:代表用户或其他系统向A2A服务器发起请求的应用程序或代理
  • A2A服务器(远程代理):公开A2A兼容HTTP端点的代理或代理系统,处理任务并提供响应
  • 代理卡片:由A2A服务器发布的JSON元数据文档,描述其身份、能力、技能、服务端点和认证要求
  • 任务:A2A管理的基本工作单元,由唯一ID标识。任务是有状态的,并通过定义的生命周期进行
  • 消息:任务中的通信回合,具有role("user"或"agent")并包含一个或多个Parts
  • 部件:消息或工件中的最小内容单元(例如TextPartFilePartDataPart
  • 工件:代理作为任务结果生成的输出(例如文档、图像、结构化数据),由Parts组成
  • 流式传输(SSE):通过服务器发送事件(SSE)交付任务的实时增量更新(状态更改、工件块)
  • 推送通知:通过服务器发起的HTTP POST请求到客户端提供的webhook URL交付的异步任务更新,用于长时间运行或断开连接的场景
  • 会话:可选,客户端生成的标识符,用于逻辑上分组相关任务

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. 流式传输(服务器发送事件)

当对tasks/sendSubscribetasks/resubscribe等方法使用流式传输时:

  • 服务器响应HTTP 200 OK状态和Content-Type头为text/event-stream
  • 此HTTP响应的正文包含由W3C定义的**服务器发送事件(SSE)**流
  • 每个SSE的data字段包含一个完整的JSON-RPC 2.0响应对象(具体来说是SendTaskStreamingResponse

4. 认证与授权

A2A将代理视为标准企业应用程序,依赖于已建立的Web安全实践。身份信息不会在A2A JSON-RPC有效载荷中传输;它在HTTP传输层处理。

有关企业安全方面的全面指南,请参见企业就绪功能

4.1. 传输安全

如第3.1节所述,生产部署必须使用HTTPS。实现应该使用现代TLS配置(推荐TLS 1.2+)和强密码套件

4.2. 服务器身份验证

A2A客户端应该通过在TLS握手期间根据受信任的证书颁发机构(CA)验证A2A服务器的TLS证书来验证其身份

4.3. 客户端/用户身份验证流程

  1. 需求发现:客户端通过AgentCard中的authentication字段发现服务器所需的认证方案。方案名称通常与OpenAPI认证方法对齐(例如,"Bearer"用于OAuth 2.0令牌,"Basic"用于基本认证,"ApiKey"用于API密钥)
  2. 凭证获取(带外):客户端通过特定于所需认证方案和身份提供者的带外流程获取必要的凭证(例如API密钥、OAuth令牌、JWT)。此流程不在A2A协议本身的范围内
  3. 凭证传输:客户端在每个发送到服务器的A2A请求的适当HTTP头中包含这些凭证(例如Authorization: Bearer <token>X-API-Key: <value>

4.4. 服务器的认证责任

A2A服务器:

  • 必须基于提供的HTTP凭证及其从代理卡中声明的认证要求对每个传入请求进行认证
  • 应该使用标准HTTP状态码如401 Unauthorized403 Forbidden进行认证挑战或拒绝
  • 应该401 Unauthorized响应中包含相关HTTP头(例如WWW-Authenticate)以指示所需的认证方案,指导客户端

4.5. 任务内认证(二次凭证)

如果代理在执行任务期间需要_额外_凭证用于_不同_系统或资源(例如代表用户访问需要自己认证的特定工具):

  1. 应该将A2A任务转换为input-required状态(参见TaskState
  2. 伴随的TaskStatus.message(通常是DataPart应该提供关于所需二次认证的详细信息,可能使用类似AuthenticationInfo的结构来描述需求
  3. A2A客户端然后通过带外获取这些新凭证,并在后续的tasks/sendtasks/sendSubscribe请求中提供它们。这些凭证的使用方式(例如如果代理正在代理,则在A2A消息中作为数据传递,或由客户端直接与辅助系统交互使用)取决于特定场景

4.6. 授权

一旦客户端被认证,A2A服务器负责基于认证的客户端/用户身份及其自身策略授权请求。授权逻辑是特定于实现的,可以基于以下内容强制执行:

  • 请求的特定技能(例如从代理卡中识别的AgentSkill.id
  • 任务中尝试的操作
  • 与代理管理的资源相关的数据访问策略
  • 如果适用,与呈现令牌关联的OAuth范围

服务器应实施最小权限原则

5. 代理发现:代理卡

5.1. 目的

A2A服务器必须提供代理卡。代理卡是一个JSON文档,描述服务器的身份、能力、技能、服务端点URL以及客户端应如何认证和与其交互。客户端使用此信息发现合适的代理并配置其交互

有关发现策略的更多信息,请参见代理发现指南

5.2. 发现机制

客户端可以通过各种方法找到代理卡,包括但不限于:

  • 知名URI:访问代理域上的预定义路径(参见第5.3节
  • 注册表/目录:查询代理的精选目录或注册表(可能是企业特定的、公共的或领域特定的)
  • 直接配置:客户端可能预先配置了代理卡URL或卡片内容本身

5.3. 推荐位置

如果使用知名URI策略,代理卡的推荐位置是: https://{server_domain}/.well-known/agent.json 这遵循RFC 8615对知名URI的原则

5.4. 代理卡的安全性

代理卡本身可能包含被视为敏感的信息(例如仅内部代理的URL,或authentication.credentials中的方案特定信息)

  • 如果代理卡包含敏感信息,提供卡片的端点必须受到适当的访问控制保护(例如mTLS、网络限制、获取卡片需要认证)
  • 通常不建议在代理卡中直接包含明文秘密(如静态API密钥)。更喜欢客户端通过带外获取动态凭证的认证方案。如果使用authentication.credentials,它应该用于非秘密信息,如OAuth流URL或API密钥_名称_(不是值)

5.5. AgentCard对象结构

// AgentCard传达关于A2A服务器的关键信息:
// - 整体身份和描述性细节
// - 服务端点URL
// - 支持的A2A协议能力(流式传输、推送通知)
// - 认证要求
// - 默认输入/输出内容类型(MIME类型)
// - 代理提供的特定技能列表
interface AgentCard {
  // 代理的人类可读名称(例如"Recipe Advisor Agent")
  name: string;
  // 代理及其一般目的的人类可读描述
  // 可以使用[CommonMark](https://commonmark.org/)进行富文本格式化
  // (例如"此代理帮助用户查找食谱、计划膳食和获取烹饪说明")
  description?: string | null;
  // 代理A2A服务的基本URL端点(发送JSON-RPC请求的地方)
  // 生产环境必须是绝对HTTPS URL(例如`https://agent.example.com/a2a/api`)
  // 仅用于本地开发/测试时可以使用HTTP
  url: string;
  // 关于提供代理的组织或实体的信息
  provider?: AgentProvider | null;
  // 代理或其A2A实现的版本字符串
  // (格式由提供者定义,例如"1.0.0"、"2023-10-26-beta")
  version: string;
  // 指向代理人类可读文档的URL(例如API使用、详细技能描述)
  documentationUrl?: string | null;
  // 指定此代理支持的A2A协议可选功能
  capabilities: AgentCapabilities;
  // 与代理的`url`端点交互所需的认证方案
  // 如果为`null`、省略或空`schemes`数组,则没有明确广告的A2A级认证
  // (不建议用于生产;其他安全措施如网络ACL可能仍然适用)
  authentication?: AgentAuthentication | null;
  // 代理在所有技能中通常接受的输入[MIME类型](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types)数组
  // 除非被特定技能覆盖,省略时默认为`["text/plain"]`。例如`["text/plain", "image/png"]`
  defaultInputModes?: string[];
  // 代理在所有技能中通常产生的输出MIME类型数组
  // 除非被特定技能覆盖,省略时默认为`["text/plain"]`。例如`["text/plain", "application/json"]`
  defaultOutputModes?: string[];
  // 代理提供的特定技能或能力数组
  // 如果代理预期执行超出简单存在的操作,则必须包含至少一个技能
  skills: AgentSkill[];
}
字段名 类型 必填 描述
name string 代理的人类可读名称
description string | null 人类可读描述。可以使用CommonMark
url string 代理A2A服务的基本URL。必须是绝对URL。生产环境使用HTTPS
provider AgentProvider | null 关于代理提供者的信息
version string 代理或A2A实现的版本字符串
documentationUrl string | null 指向代理文档的URL
capabilities AgentCapabilities 指定支持的A2A协议可选功能(例如流式传输、推送通知)
authentication AgentAuthentication | null 所需的认证方案。null或空表示没有A2A级认证广告(生产环境不建议)
defaultInputModes string[] 默认接受的输入MIME类型。省略时默认为["text/plain"]
defaultOutputModes string[] 默认产生的输出MIME类型。省略时默认为["text/plain"]
skills AgentSkill[] 技能数组。如果代理执行操作则必须至少有一个

5.5.1. AgentProvider对象

关于提供代理的组织或实体的信息

interface AgentProvider {
  // 组织或实体的名称
  organization: string;
  // 提供者组织网站或相关联系页面的URL
  url?: string | null;
}
字段名 类型 必填 描述
organization string 组织/实体的名称
url string | null 提供者网站/联系页面的URL

5.5.2. AgentCapabilities对象

指定代理支持的A2A协议可选功能

interface AgentCapabilities {
  // 如果为`true`,代理支持`tasks/sendSubscribe`和`tasks/resubscribe`通过服务器发送事件(SSE)进行实时更新。默认:`false`
  streaming?: boolean;
  // 如果为`true`,代理支持`tasks/pushNotification/set`和`tasks/pushNotification/get`通过webhook进行异步任务更新。默认:`false`
  pushNotifications?: boolean;
  // 如果为`true`,代理可能在`Task`对象中包含状态更改的详细历史(未来增强;具体机制待定)。默认:`false`
  stateTransitionHistory?: boolean;
}
字段名 类型 必填 默认 描述
streaming boolean false 表示支持SSE流式方法(tasks/sendSubscribetasks/resubscribe
pushNotifications boolean false 表示支持推送通知方法(tasks/pushNotification/*
stateTransitionHistory boolean false 未来功能的占位符:公开详细的任务状态更改历史

5.5.3. AgentAuthentication对象

描述访问代理url端点所需的认证要求

interface AgentAuthentication {
  // 代理端点支持/要求的认证方案名称数组
  // (例如"Bearer"、"Basic"、"OAuth2"、"ApiKey")
  // 应尽可能使用标准名称(例如来自OpenAPI规范、IANA注册表)
  // 空数组表示没有特定的A2A级方案广告
  schemes: string[];
  // 可选字段,可能包含非秘密的、方案特定信息
  // 示例:对于"OAuth2",可能是包含`tokenUrl`、`authorizationUrl`、`scopes`的JSON字符串
  // 对于"ApiKey",可能指定头名称(`in: "header"`、`name: "X-Custom-API-Key"`)
  // **关键**:此字段不得包含明文秘密(例如实际的API密钥值、密码)
  // 如果由于此字段包含敏感URL或配置而需要保护代理卡本身,则提供代理卡的端点必须受到保护
  credentials?: string | null; // 例如,客户端可解析的JSON字符串,用于方案详情
}
字段名 类型 必填 描述
schemes string[] 认证方案名称数组(例如"Bearer"、"OAuth2"、"ApiKey")
credentials string | null 非秘密的方案特定信息。不得包含明文秘密。如果包含敏感信息,代理卡端点必须受到保护

5.5.4. AgentSkill Object

Describes a specific capability, function, or area of expertise the agent can perform or address.

interface AgentSkill {
  // A unique identifier for this skill within the context of this agent
  // (e.g., "currency-converter", "generate-image-from-prompt", "summarize-text-v2").
  // Clients MAY use this ID to request a specific skill if the agent supports such dispatch.
  id: string;
  // Human-readable name of the skill (e.g., "Currency Conversion Service", "Image Generation AI").
  name: string;
  // Detailed description of what the skill does, its purpose, and any important considerations.
  // [CommonMark](https://commonmark.org/) MAY be used for rich text formatting.
  description?: string | null;
  // Array of keywords or categories for discoverability and categorization
  // (e.g., ["finance", "conversion"], ["media", "generative ai", "image"]).
  tags?: string[] | null;
  // Array of example prompts, inputs, or use cases illustrating how to use this skill
  // (e.g., ["convert 100 USD to EUR", "generate a photorealistic image of a cat wearing a wizard hat"]).
  // These help clients (and potentially end-users or other agents) understand how to formulate requests for this skill.
  examples?: string[] | null;
  // Overrides `agentCard.defaultInputModes` specifically for this skill.
  // If `null` or omitted, the agent's `defaultInputModes` apply.
  inputModes?: string[] | null; // Array of MIME types
  // Overrides `agentCard.defaultOutputModes` specifically for this skill.
  // If `null` or omitted, the agent's `defaultOutputModes` apply.
  outputModes?: string[] | null; // Array of MIME types
}
Field Name Type Required Description
id string Yes Unique skill identifier within this agent.
name string Yes Human-readable skill name.
description string | null No Detailed skill description. CommonMark MAY be used.
tags string[] | null No Keywords/categories for discoverability.
examples string[] | null No Example prompts or use cases demonstrating skill usage.
inputModes string[] | null No Overrides defaultInputModes for this specific skill. Accepted MIME types.
outputModes string[] | null No Overrides defaultOutputModes for this specific skill. Produced MIME types.

5.6. Sample Agent Card

{
  "name": "GeoSpatial Route Planner Agent",
  "description": "Provides advanced route planning, traffic analysis, and custom map generation services. This agent can calculate optimal routes, estimate travel times considering real-time traffic, and create personalized maps with points of interest.",
  "url": "https://georoute-agent.example.com/a2a/v1",
  "provider": {
    "organization": "Example Geo Services Inc.",
    "url": "https://www.examplegeoservices.com"
  },
  "version": "1.2.0",
  "documentationUrl": "https://docs.examplegeoservices.com/georoute-agent/api",
  "capabilities": {
    "streaming": true,
    "pushNotifications": true,
    "stateTransitionHistory": false
  },
  "authentication": {
    "schemes": ["OAuth2"],
    "credentials": "{\"authorizationUrl\": \"https://auth.examplegeoservices.com/authorize\", \"tokenUrl\": \"https://auth.examplegeoservices.com/token\", \"scopes\": {\"route:plan\": \"Allows planning new routes.\", \"map:custom\": \"Allows creating and managing custom maps.\"}}"
  },
  "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"
      ]
    }
  ]
}

6. Protocol Data Objects

These objects define the structure of data exchanged within the JSON-RPC methods of the A2A protocol.

6.1. Task Object

Represents the stateful unit of work being processed by the A2A Server for an A2A Client. A task encapsulates the entire interaction related to a specific goal or request.

interface Task {
  // A unique identifier for the task. This ID is typically generated by the client
  // when initiating the task and MUST be used by the server to refer to this task.
  // It should be sufficiently unique (e.g., a UUID v4).
  id: string;
  // An optional, client-generated identifier used to group related tasks into a logical session.
  // Useful for maintaining context across multiple, sequential, or related tasks.
  sessionId?: string | null;
  // The current status of the task, including its lifecycle state, an optional associated message,
  // and a timestamp.
  status: TaskStatus;
  // An array of outputs (artifacts) generated by the agent for this task.
  // This array can be populated incrementally, especially during streaming.
  // Artifacts represent the tangible results of the task.
  artifacts?: Artifact[] | null;
  // An optional array of recent messages exchanged within this task,
  // ordered chronologically (oldest first).
  // This history is included if requested by the client via the `historyLength` parameter
  // in `TaskSendParams` or `TaskQueryParams`.
  history?: Message[] | null;
  // Arbitrary key-value metadata associated with the task.
  // Keys SHOULD be strings; values can be any valid JSON type (string, number, boolean, array, object).
  // This can be used for application-specific data, tracing info, etc.
  metadata?: Record<string, any> | null;
}
Field Name Type Required Description
id string Yes Unique task identifier (e.g., UUID), typically client-generated.
sessionId string | null No Optional client-generated ID to group related tasks into a session.
status TaskStatus Yes Current status of the task (state, message, timestamp).
artifacts Artifact[] | null No Array of outputs generated by the agent for this task.
history Message[] | null No Optional array of recent messages exchanged, if requested by historyLength.
metadata Record<string, any> | null No Arbitrary key-value metadata associated with the task.

6.2. TaskStatus Object

Represents the current state and associated context (e.g., a message from the agent) of a Task.

interface TaskStatus {
  // The current lifecycle state of the task.
  state: TaskState;
  // An optional message associated with the current status.
  // This could be a progress update from the agent, a prompt for more input,
  // a summary of the final result, or an error message.
  message?: Message | null;
  // The date and time (UTC is STRONGLY recommended) when this status was recorded by the server.
  // Format: ISO 8601 `date-time` string (e.g., "2023-10-27T10:00:00Z").
  timestamp?: string | null;
}
Field Name Type Required Description
state TaskState Yes Current lifecycle state of the task.
message Message | null No Optional message providing context for the current status.
timestamp string (ISO 8601) | null No Timestamp (UTC recommended) when this status was recorded.

6.3. TaskState Enum

Defines the possible lifecycle states of a Task.

type TaskState =
  | 'submitted' // Task received by server, acknowledged, but processing has not yet actively started.
  | 'working' // Task is actively being processed by the agent.
  | 'input-required' // Agent requires additional input from the client/user to proceed. (Task is paused)
  | 'completed' // Task finished successfully. (Terminal state)
  | 'canceled' // Task was canceled by the client or potentially by the server. (Terminal state)
  | 'failed' // Task terminated due to an error during processing. (Terminal state)
  | 'unknown'; // The state of the task cannot be determined (e.g., task ID invalid or expired). (Effectively a terminal state from client's PoV for that ID)
Value Description Terminal?
submitted Task received by the server and acknowledged, but processing has not yet actively started. No
working Task is actively being processed by the agent. Client may expect further updates or a terminal state. No
input-required Agent requires additional input from the client/user to proceed. The task is effectively paused. No (Pause)
completed Task finished successfully. Results are typically available in Task.artifacts or TaskStatus.message. Yes
canceled Task was canceled (e.g., by a tasks/cancel request or server-side policy). Yes
failed Task terminated due to an error during processing. TaskStatus.message may contain error details. Yes
unknown The state of the task cannot be determined (e.g., task ID is invalid, unknown, or has expired). Yes

6.4. Message Object

Represents a single communication turn or a piece of contextual information within a Task. Messages are used for instructions, prompts, replies, and status updates.

interface Message {
  // Indicates the sender of the message:
  // "user" for messages originating from the A2A Client (acting on behalf of an end-user or system).
  // "agent" for messages originating from the A2A Server (the remote agent).
  role: 'user' | 'agent';
  // An array containing the content of the message, broken down into one or more parts.
  // A message MUST contain at least one part.
  // Using multiple parts allows for rich, multi-modal content (e.g., text accompanying an image).
  parts: Part[];
  // Arbitrary key-value metadata associated with the message.
  // Keys SHOULD be strings; values can be any valid JSON type.
  // Useful for timestamps, source identifiers, language codes, etc.
  metadata?: Record<string, any> | null;
}
Field Name Type Required Description
role "user" | "agent" Yes Indicates the sender: "user" (from A2A Client) or "agent" (from A2A Server).
parts Part[] Yes Array of content parts. Must contain at least one part.
metadata Record<string, any> | null No Arbitrary key-value metadata associated with this message.

6.5. Part Union Type

Represents a distinct piece of content within a Message or Artifact. A Part object is a discriminated union, identified by its mandatory type field. All Part types also include an optional metadata field (Record<string, any> | null) for part-specific metadata.

It MUST be one of the following:

6.5.1. TextPart Object

For conveying plain textual content.

interface TextPart {
  type: 'text'; // Discriminator
  text: string; // The actual textual content.
  metadata?: Record<string, any> | null; // Optional metadata (e.g., language, formatting hints if any)
}
Field Name Type Required Description
type "text" (literal) Yes Identifies this part as textual content.
text string Yes The textual content of the part.
metadata Record<string, any> | null No Optional metadata specific to this text part.

6.5.2. FilePart Object

For conveying file-based content.

interface FilePart {
  type: 'file'; // Discriminator
  file: FileContent; // Contains the file details and data (or reference).
  metadata?: Record<string, any> | null; // Optional metadata (e.g., purpose of the file)
}
Field Name Type Required Description
type "file" (literal) Yes Identifies this part as file content.
file FileContent Yes Contains the file details and data/reference.
metadata Record<string, any> | null No Optional metadata specific to this file part.

6.5.3. DataPart Object

For conveying structured JSON data. Useful for forms, parameters, or any machine-readable information.

interface DataPart {
  type: 'data'; // Discriminator
  // The structured JSON data payload. This can be any valid JSON object or array.
  // The schema of this data is application-defined and may be implicitly understood
  // by the interacting agents or explicitly described (e.g., via a JSON Schema reference
  // in the `metadata` or associated `AgentSkill`).
  data: Record<string, any> | any[];
  metadata?: Record<string, any> | null; // Optional metadata (e.g., schema URL, version)
}
Field Name Type Required Description
type "data" (literal) Yes Identifies this part as structured data.
data Record<string, any> | any[] Yes The structured JSON data payload (an object or an array).
metadata Record<string, any> | null No Optional metadata specific to this data part (e.g., reference to a schema).

6.6. FileContent Object

Represents the data or reference for a file, used within a FilePart.

interface FileContent {
  // The original filename, if known (e.g., "document.pdf", "avatar.png").
  name?: string | null;
  // The [MIME type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types)
  // of the file (e.g., "application/pdf", "image/png"). Strongly recommended for proper handling.
  mimeType?: string | null;
  // Base64 encoded string of the raw file content.
  // Use this for embedding small to medium-sized files directly.
  bytes?: string | null; // Base64 string
  // A URI (absolute URL is STRONGLY recommended) pointing to the file content.
  // Accessibility of this URI depends on the context (e.g., public URL, pre-signed URL, internal URL).
  // The client and server must have a way to resolve and access this URI if used.
  uri?: string | null;

  // Constraint: If file content is being transmitted, exactly one of `bytes` or `uri` MUST be non-null.
  // Both MAY be `null` or absent if the `FilePart` is merely representing a file reference
  // without transmitting its content in the current message (e.g., referring to a previously uploaded file).
}
Field Name Type Required Description
name string | null No Original filename (e.g., "report.pdf").
mimeType string | null No MIME type (e.g., image/png). Strongly recommended.
bytes string | null Conditionally (See Constraint) Base64 encoded file content.
uri string | null Conditionally (See Constraint) URI (absolute URL strongly recommended) to file content. Accessibility is context-dependent.

Constraint: If file content is being transmitted, exactly one of bytes or uri MUST be provided and non-null. Both MAY be null or absent if the FilePart is only a reference or metadata about a file whose content is not being transferred in this specific part.

6.7. Artifact Object

Represents a tangible output generated by the agent during a task. Artifacts are the results or products of the agent's work.

interface Artifact {
  // A descriptive name for the artifact (e.g., "Quarterly Sales Report.pdf", "Generated Logo Design", "analysis_results.json").
  // This name might be used by the client for display or identification.
  name?: string | null;
  // A human-readable description of the artifact. [CommonMark](https://commonmark.org/) MAY be used.
  description?: string | null;
  // An array containing the content of the artifact, broken down into one or more parts.
  // An artifact MUST contain at least one part.
  // Using multiple parts allows for complex artifacts (e.g., a report with embedded images or data tables).
  parts: Part[];
  // A non-negative integer index for ordering artifacts or identifying artifact chunks during streaming.
  // Multiple artifacts (or artifact updates) can share the same index if they represent parts of the same logical output
  // that are being streamed or delivered separately.
  // Default: 0 if omitted.
  index?: number;
  // Used with streaming (`TaskArtifactUpdateEvent`):
  // If `true`, indicates this update's `parts` should be appended to the content of the artifact
  // currently identified by the same `index` value. This is useful for streaming textual data or
  // appending elements to a list in a `DataPart`.
  // If `false` or `null` (or omitted), this update replaces the artifact content at the given `index`.
  // This field is typically `false` for the first chunk of a streamed artifact.
  append?: boolean | null;
  // Used with streaming (`TaskArtifactUpdateEvent`):
  // If `true`, indicates this is the final update/chunk for the artifact at this `index`.
  // Signals the end of a streamed file or data structure.
  lastChunk?: boolean | null;
  // Arbitrary key-value metadata associated with the artifact.
  // Keys SHOULD be strings; values can be any valid JSON type.
  // Useful for creation timestamps, versioning info, checksums, etc.
  metadata?: Record<string, any> | null;
}
Field Name Type Required Default Description
name string | null No null Descriptive name for the artifact.
description string | null No null Human-readable description of the artifact.
parts Part[] Yes Content of the artifact, as one or more Part objects. Must have at least one.
index integer No 0 Non-negative index for ordering artifacts or identifying chunks during streaming.
append boolean | null No false In streaming (TaskArtifactUpdateEvent), true means append parts to artifact at index; false (default) means replace.
lastChunk boolean | null No false In streaming (TaskArtifactUpdateEvent), true indicates this is the final update for the artifact at this index.
metadata Record<string, any> | null No null Arbitrary key-value metadata associated with the artifact.

6.8. PushNotificationConfig Object

Configuration provided by the client to the server for sending asynchronous push notifications about task updates.

interface PushNotificationConfig {
  // The absolute HTTPS webhook URL where the A2A Server should POST task updates.
  // This URL MUST be HTTPS for security.
  url: string;
  // An optional, client-generated opaque token (e.g., a secret, a task-specific identifier, or a nonce).
  // The A2A Server SHOULD include this token in the notification request it sends to the `url`
  // (e.g., in a custom HTTP header like `X-A2A-Notification-Token` or similar).
  // This allows the client's webhook receiver to validate the relevance and authenticity of the notification.
  token?: string | null;
  // Authentication details the A2A Server needs to use when calling the client's `url`.
  // The client's webhook endpoint defines these requirements. This tells the A2A Server how to authenticate *itself* to the client's webhook.
  authentication?: AuthenticationInfo | null;
}
Field Name Type Required Description
url string Yes Absolute HTTPS webhook URL for the A2A Server to POST task updates to.
token string | null No Optional client-generated opaque token for the client's webhook receiver to validate the notification (e.g., server includes it in an X-A2A-Notification-Token header).
authentication AuthenticationInfo | null No Authentication details the A2A Server must use when calling the url. The client's webhook (receiver) defines these requirements.

6.9. AuthenticationInfo Object (for Push Notifications)

A generic structure for specifying authentication requirements, typically used within PushNotificationConfig to describe how the A2A Server should authenticate to the client's webhook.

interface AuthenticationInfo {
  // Array of authentication scheme names the caller (i.e., the A2A Server, in the context of push notifications)
  // must use when sending the request to the webhook URL (e.g., "Bearer" for an OAuth token, "ApiKey" for a pre-shared key, "Basic").
  // Standard names SHOULD be used.
  schemes: string[];
  // Optional field for providing static credentials or scheme-specific information
  // that the A2A Server needs to use.
  // Examples:
  // - For "ApiKey": A JSON string like `{"in": "header", "name": "X-Client-Webhook-Key", "value": "actual_api_key_value"}`.
  // - For "Bearer": If the A2A Server is expected to use a specific pre-issued token, it could be provided here. More commonly, the server would obtain its own token using OAuth client credentials flow if this field specifies an OAuth scheme.
  // **CRITICAL**: Use with extreme caution if this field contains secrets. This configuration is sent from client to server.
  // Prefer mechanisms where the server fetches its own credentials dynamically (e.g., OAuth client credentials flow with a pre-configured client ID/secret on the server side for the webhook's audience)
  // rather than having the client provide secrets to the server.
  // If this field *must* carry a secret, the A2A communication channel itself must be exceptionally secure, and both client and server must handle this data with care.
  credentials?: string | null; // E.g., A JSON string parsable by the server.
}
Field Name Type Required Description
schemes string[] Yes Array of auth scheme names the A2A Server must use when calling the client's webhook (e.g., "Bearer", "ApiKey").
credentials string | null No Optional static credentials or scheme-specific configuration info. Handle with EXTREME CAUTION if secrets are involved. Prefer server-side dynamic credential fetching where possible.

6.10. TaskPushNotificationConfig Object

Used as the params object for the tasks/pushNotification/set method and as the result object for the tasks/pushNotification/get method.

interface TaskPushNotificationConfig {
  // The ID of the task for which push notification settings are being configured or retrieved.
  id: string;
  // The push notification configuration details.
  // When used as params for `set`, this provides the configuration to apply.
  // When used as result for `get`, this reflects the currently active configuration (server MAY omit secrets).
  // If `null` when setting, it might indicate clearing existing configuration (server-dependent).
  pushNotificationConfig: PushNotificationConfig | null;
}
Field Name Type Required Description
id string Yes The ID of the task to configure push notifications for, or retrieve configuration from.
pushNotificationConfig PushNotificationConfig | null Yes The push notification configuration. For set, the desired config. For get, the current config (secrets MAY be omitted by server). null might clear config on set.

6.11. JSON-RPC Structures

A2A adheres to the standard JSON-RPC 2.0 structures for requests and responses.

6.11.1. JSONRPCRequest Object

All A2A method calls are encapsulated in a JSON-RPC Request object.

  • jsonrpc: A String specifying the version of the JSON-RPC protocol. MUST be exactly "2.0".
  • method: A String containing the name of the method to be invoked (e.g., "tasks/send", "tasks/get").
  • params: A Structured value that holds the parameter values to be used during the invocation of the method. This member MAY be omitted if the method expects no parameters. A2A methods typically use an object for params.
  • id: An identifier established by the Client that MUST contain a String, Number, or NULL value if included. If it is not included it is assumed to be a notification. The value SHOULD NOT be NULL for requests expecting a response, and Numbers SHOULD NOT contain fractional parts. The Server MUST reply with the same value in the Response object if included. This member is used to correlate the context between the two objects. A2A methods typically expect a response or stream, so id will usually be present and non-null.

6.11.2. JSONRPCResponse Object

Responses from the A2A Server are encapsulated in a JSON-RPC Response object.

  • jsonrpc: A String specifying the version of the JSON-RPC protocol. MUST be exactly "2.0".
  • id: This member is REQUIRED. It MUST be the same as the value of the id member in the Request Object. If there was an error in detecting the id in the Request object (e.g. Parse error/Invalid Request), it MUST be null.
  • EITHER result: This member is REQUIRED on success. This member MUST NOT exist if there was an error invoking the method. The value of this member is determined by the method invoked on the Server.
  • OR error: This member is REQUIRED on failure. This member MUST NOT exist if there was no error triggered during invocation. The value of this member MUST be an JSONRPCError object.
  • The members result and error are mutually exclusive: one MUST be present, and the other MUST NOT.

6.12. JSONRPCError Object

When a JSON-RPC call encounters an error, the Response Object will contain an error member with a value of this structure.

interface JSONRPCError {
  // A Number that indicates the error type that occurred.
  // This MUST be an integer.
  code: number;
  // A String providing a short description of the error.
  // The message SHOULD be limited to a concise single sentence.
  message: string;
  // A Primitive or Structured value that contains additional information about the error.
  // This may be omitted. The value of this member is defined by the Server (e.g. detailed error codes,
  // debugging information).
  data?: any;
}
Field Name Type Required Description
code integer Yes Integer error code. See Section 8 (Error Handling) for standard and A2A-specific codes.
message string Yes Short, human-readable summary of the error.
data any | null No Optional additional structured information about the error.

7. Protocol RPC Methods

All A2A RPC methods are invoked by the A2A Client by sending an HTTP POST request to the A2A Server's url (as specified in its AgentCard). The body of the HTTP POST request MUST be a JSONRPCRequest object, and the Content-Type header MUST be application/json.

The A2A Server's HTTP response body MUST be a JSONRPCResponse object (or, for streaming methods, an SSE stream where each event's data is a JSONRPCResponse). The Content-Type for JSON-RPC responses is application/json. For SSE streams, it is text/event-stream.

7.1. tasks/send

Sends a message to an agent to initiate a new task or to continue an existing one. This method is suitable for synchronous request/response interactions or when client-side polling (using tasks/get) is acceptable for monitoring longer-running tasks.

  • Request params type: TaskSendParams
  • Response result type (on success): Task (The current or final state of the task after processing the message).
  • Response error type (on failure): JSONRPCError.

7.1.1. TaskSendParams Object

interface TaskSendParams {
  // The ID for the task.
  // - If this is the first message for a new task, the client generates this ID.
  // - If this message continues an existing task (e.g., providing more input after an `input-required` state),
  //   this ID MUST match the ID of the existing task.
  id: string;
  // Optional client-generated session ID to group this task with others.
  sessionId?: string | null;
  // The message to send to the agent. The `role` within this message is typically "user".
  message: Message;
  // Optional: If initiating a new task, the client MAY include push notification configuration.
  // If provided for an existing task, server behavior (e.g., update config, ignore) is server-dependent.
  // Requires `AgentCard.capabilities.pushNotifications: true`.
  pushNotification?: PushNotificationConfig | null;
  // Optional: If a positive integer `N` is provided, the server SHOULD include the last `N` messages
  // (chronologically) of the task's history in the `Task.history` field of the response.
  // If `0`, `null`, or omitted, no history is explicitly requested (server MAY still include some by default).
  historyLength?: number | null;
  // Arbitrary metadata for this specific `tasks/send` request.
  metadata?: Record<string, any> | null;
}
Field Name Type Required Description
id string Yes Task ID. If new, the server SHOULD create the task. If existing, this message continues the task.
sessionId string | null No Optional client-generated session ID.
message Message Yes The message content to send. Message.role is typically "user".
pushNotification PushNotificationConfig | null No Optional: sets push notification configuration for the task (usually on the first send). Requires server capability.
historyLength integer | null No If positive, requests the server to include up to N recent messages in Task.history.
metadata Record<string, any> | null No Request-specific metadata.

7.2. tasks/sendSubscribe

Sends a message to an agent to initiate/continue a task AND subscribes the client to real-time updates for that task via Server-Sent Events (SSE). This method requires the server to have AgentCard.capabilities.streaming: true.

  • Request params type: TaskSendParams (same as tasks/send).
  • Response (on successful subscription):
    • HTTP Status: 200 OK.
    • HTTP Content-Type: text/event-stream.
    • HTTP Body: A stream of Server-Sent Events. Each SSE data field contains a SendTaskStreamingResponse JSON object.
  • Response (on initial subscription failure):
    • Standard HTTP error code (e.g., 4xx, 5xx).
    • The HTTP body MAY contain a standard JSONRPCResponse with an error object detailing the failure.

7.2.1. SendTaskStreamingResponse Object

This is the structure of the JSON object found in the data field of each Server-Sent Event sent by the server for a tasks/sendSubscribe or tasks/resubscribe stream. It's a JSONRPCResponse where the result is one of the event types.

interface SendTaskStreamingResponse extends JSONRPCResponse {
  // The `id` MUST match the `id` from the originating `tasks/sendSubscribe` (or `tasks/resubscribe`)
  // JSON-RPC request that established this SSE stream.
  id: string | number; // Overrides JSONRPCResponse 'id' type for clarity and to emphasize it matches the original request.
  // The `result` field contains the actual event payload for this streaming update.
  // It will be either a TaskStatusUpdateEvent or a TaskArtifactUpdateEvent.
  result: TaskStatusUpdateEvent | TaskArtifactUpdateEvent;
  // For streaming events, `error` is typically `null` or absent.
  // If a fatal error occurs that terminates the stream, the server MAY send a final
  // SSE event with this `error` field populated before closing the connection.
  error?: JSONRPCError | null;
}
Field Name Type Required Description
jsonrpc "2.0" (literal) Yes JSON-RPC version string.
id string | number Yes Matches the id from the originating tasks/sendSubscribe or tasks/resubscribe request.
result Either TaskStatusUpdateEvent OR TaskArtifactUpdateEvent Yes The event payload: either a status update or an artifact update.
error JSONRPCError | null No Typically null or absent for stream events. If a fatal stream error occurs, this MAY be populated in the final SSE message before the stream closes.

7.2.2. TaskStatusUpdateEvent Object

Carries information about a change in the task's status during streaming. This is one of the possible result types in a SendTaskStreamingResponse.

interface TaskStatusUpdateEvent {
  // The ID of the task being updated. This MUST match the `TaskSendParams.id`
  // from the `tasks/sendSubscribe` request that initiated this stream.
  id: string;
  // The new status object for the task.
  status: TaskStatus;
  // If `true`, this `TaskStatusUpdateEvent` signifies the terminal status update for the current
  // `tasks/sendSubscribe` interaction cycle. This means the task has reached a state like
  // `completed`, `failed`, `canceled`, or `input-required`, and the server does not expect to send
  // more updates for *this specific* `sendSubscribe` request. The server typically closes the SSE
  // connection after sending an event with `final: true`.
  // Default: `false` if omitted.
  final?: boolean;
  // Arbitrary metadata for this specific status update event.
  metadata?: Record<string, any> | null;
}
Field Name Type Required Default Description
id string Yes Task ID being updated, matching the original request's task ID.
status TaskStatus Yes The new TaskStatus object.
final boolean No false If true, indicates this is the terminal status update for the current stream cycle. The server typically closes the SSE connection after this.
metadata Record<string, any> | null No null Event-specific metadata.

7.2.3. TaskArtifactUpdateEvent Object

Carries a new or updated artifact (or a chunk of an artifact) generated by the task during streaming. This is one of the possible result types in a SendTaskStreamingResponse.

interface TaskArtifactUpdateEvent {
  // The ID of the task that generated this artifact. This MUST match the `TaskSendParams.id`
  // from the `tasks/sendSubscribe` request that initiated this stream.
  id: string;
  // The artifact data. This could be a complete artifact or an incremental chunk.
  // The client uses `artifact.index`, `artifact.append`, and `artifact.lastChunk`
  // to correctly assemble or update the artifact on its side.
  artifact: Artifact;
  // Arbitrary metadata for this specific artifact update event.
  metadata?: Record<string, any> | null;
}
Field Name Type Required Default Description
id string Yes Task ID that generated the artifact, matching the original request's task ID.
artifact Artifact Yes The Artifact data. Could be a complete artifact or an incremental chunk. Use index, append, and lastChunk fields within Artifact for client-side assembly.
metadata Record<string, any> | null No null Event-specific metadata.

7.3. tasks/get

Retrieves the current state (including status, artifacts, and optionally history) of a previously initiated task. This is typically used for polling the status of a task initiated with tasks/send, or for fetching the final state of a task after being notified via a push notification or after an SSE stream has ended.

7.3.1. TaskQueryParams Object

interface TaskQueryParams {
  // The ID of the task to retrieve.
  id: string;
  // Optional: If a positive integer `N` is provided, the server SHOULD include the last `N` messages
  // (chronologically) of the task's history in the `Task.history` field of the response.
  // If `0`, `null`, or omitted, no history is explicitly requested.
  historyLength?: number | null;
  // Arbitrary metadata for this specific `tasks/get` request.
  metadata?: Record<string, any> | null;
}
Field Name Type Required Description
id string Yes The ID of the task whose current state is to be retrieved.
historyLength integer | null No If positive, requests the server to include up to N recent messages in Task.history.
metadata Record<string, any> | null No Request-specific metadata.

7.4. tasks/cancel

Requests the cancellation of an ongoing task. The server will attempt to cancel the task, but success is not guaranteed (e.g., the task might have already completed or failed, or cancellation might not be supported at its current stage).

7.4.1. TaskIdParams Object (for tasks/cancel and tasks/pushNotification/get)

A simple object containing just the task ID and optional metadata.

interface TaskIdParams {
  // The ID of the task to which the operation applies (e.g., cancel, get push notification config).
  id: string;
  // Arbitrary metadata for this specific request.
  metadata?: Record<string, any> | null;
}
Field Name Type Required Description
id string Yes The ID of the task.
metadata Record<string, any> | null No Request-specific metadata.

7.5. tasks/pushNotification/set

Sets or updates the push notification configuration for a specified task. This allows the client to tell the server where and how to send asynchronous updates for the task. Requires the server to have AgentCard.capabilities.pushNotifications: true.

7.6. tasks/pushNotification/get

Retrieves the current push notification configuration for a specified task. Requires the server to have AgentCard.capabilities.pushNotifications: true.

7.7. tasks/resubscribe

Allows a client to reconnect to an SSE stream for an ongoing task after a previous connection (from tasks/sendSubscribe or an earlier tasks/resubscribe) was interrupted. Requires the server to have AgentCard.capabilities.streaming: true.

The purpose is to resume receiving subsequent updates. The server's behavior regarding events missed during the disconnection period (e.g., whether it attempts to backfill some missed events or only sends new ones from the point of resubscription) is implementation-dependent and not strictly defined by this specification.

  • Request params type: TaskQueryParams (The historyLength parameter is typically ignored for resubscription, as the focus is on future events, but it's included for structural consistency).
  • Response (on successful resubscription):
    • HTTP Status: 200 OK.
    • HTTP Content-Type: text/event-stream.
    • HTTP Body: A stream of Server-Sent Events, identical in format to tasks/sendSubscribe, carrying subsequent SendTaskStreamingResponse events for the task.
  • Response (on resubscription failure):
    • Standard HTTP error code (e.g., 4xx, 5xx).
    • The HTTP body MAY contain a standard JSONRPCResponse with an error object. Failures can occur if the task is no longer active, doesn't exist, or streaming is not supported/enabled for it.

8. Error Handling

A2A uses standard JSON-RPC 2.0 error codes and structure for reporting errors. Errors are returned in the error member of the JSONRPCResponse object. See JSONRPCError Object definition.

8.1. Standard JSON-RPC Errors

These are standard codes defined by the JSON-RPC 2.0 specification.

Code JSON-RPC Spec Meaning Typical A2A message Description
-32700 Parse error Invalid JSON payload Server received JSON that was not well-formed.
-32600 Invalid Request Invalid JSON-RPC Request The JSON payload was valid JSON, but not a valid JSON-RPC Request object.
-32601 Method not found Method not found The requested A2A RPC method (e.g., "tasks/foo") does not exist or is not supported.
-32602 Invalid params Invalid method parameters The params provided for the method are invalid (e.g., wrong type, missing required field).
-32603 Internal error Internal server error An unexpected error occurred on the server during processing.
-32000 to -32099 Server error (Server-defined) Reserved for implementation-defined server-errors. A2A-specific errors use this range.

8.2. A2A-Specific Errors

These are custom error codes defined within the JSON-RPC server error range (-32000 to -32099) to provide more specific feedback about A2A-related issues. Servers SHOULD use these codes where applicable.

Code Error Name (Conceptual) Typical message string Description
-32001 TaskNotFoundError Task not found The specified task id does not correspond to an existing or active task. It might be invalid, expired, or already completed and purged.
-32002 TaskNotCancelableError Task cannot be canceled An attempt was made to cancel a task that is not in a cancelable state (e.g., it has already reached a terminal state like completed, failed, or canceled).
-32003 PushNotificationNotSupportedError Push Notification is not supported Client attempted to use push notification features (e.g., tasks/pushNotification/set) but the server agent does not support them (i.e., AgentCard.capabilities.pushNotifications is false).
-32004 OperationNotSupportedError This operation is not supported The requested operation or a specific aspect of it (perhaps implied by parameters) is not supported by this server agent implementation. Broader than just method not found.
-32005 ContentTypeNotSupportedError Incompatible content types A MIME type provided in the request's message.parts (or implied for an artifact) is not supported by the agent or the specific skill being invoked.
-32006 StreamingNotSupportedError Streaming is not supported Client attempted tasks/sendSubscribe or tasks/resubscribe but the server agent does not support streaming (i.e., AgentCard.capabilities.streaming is false).
-32007 AuthenticationRequiredError Authentication required The request lacks necessary authentication credentials, or the provided credentials are invalid or insufficient. This often accompanies an HTTP 401 Unauthorized status.
-32008 AuthorizationFailedError Authorization failed The authenticated identity is not authorized to perform the requested action or access the specified resource (e.g., a specific task or skill). This often accompanies an HTTP 403 Forbidden status.
-32009 InvalidTaskStateError Invalid task state for operation The operation is not valid for the task's current TaskState (e.g., trying to send a message to a task that is already completed).
-32010 RateLimitExceededError Rate limit exceeded The client has made too many requests in a given amount of time.
-32011 ResourceUnavailableError A required resource is unavailable The server cannot complete the request because a necessary downstream resource or service is temporarily or permanently unavailable.

Servers MAY define additional error codes within the -32000 to -32099 range for more specific scenarios not covered above, but they SHOULD document these clearly. The data field of the JSONRPCError object can be used to provide more structured details for any error.

9. Common Workflows & Examples

This section provides illustrative JSON examples of common A2A interactions. Timestamps, session IDs, and request/response IDs are for demonstration purposes. For brevity, some optional fields might be omitted if not central to the example.

9.1. Basic Task Execution (Synchronous / Polling Style)

Scenario: Client asks a simple question, and the agent responds quickly.

  1. Client sends a message using tasks/send:

    {
      "jsonrpc": "2.0",
      "id": "req-001",
      "method": "tasks/send",
      "params": {
        "id": "task-abc-123",
        "sessionId": "session-xyz-789",
        "message": {
          "role": "user",
          "parts": [
            {
              "type": "text",
              "text": "What is the capital of France?"
            }
          ]
        }
      }
    }
  2. Server processes the request and responds (task completes quickly):

    {
      "jsonrpc": "2.0",
      "id": "req-001",
      "result": {
        "id": "task-abc-123",
        "sessionId": "session-xyz-789",
        "status": {
          "state": "completed",
          "message": {
            "role": "agent",
            "parts": [
              {
                "type": "text",
                "text": "The capital of France is Paris."
              }
            ]
          },
          "timestamp": "2024-03-15T10:00:05Z"
        },
        "artifacts": [
          {
            "name": "Answer",
            "index": 0,
            "parts": [
              {
                "type": "text",
                "text": "The capital of France is Paris."
              }
            ]
          }
        ]
      }
    }

    If the task were longer-running, the server might initially respond with status.state: "working". The client would then periodically call tasks/get with params: {"id": "task-abc-123"} until the task reaches a terminal state.

9.2. Streaming Task Execution (SSE)

Scenario: Client asks the agent to write a short story, and the agent streams the story incrementally.

  1. Client sends a message and subscribes using tasks/sendSubscribe:

    {
      "jsonrpc": "2.0",
      "id": "req-002",
      "method": "tasks/sendSubscribe",
      "params": {
        "id": "task-story-456",
        "message": {
          "role": "user",
          "parts": [
            {
              "type": "text",
              "text": "Write a very short story about a curious robot exploring Mars."
            }
          ]
        }
      }
    }
  2. Server responds with HTTP 200 OK, Content-Type: text/event-stream, and starts sending SSE events:

    Event 1: Task status update - working

    id: sse-evt-101
    event: message
    data: {"jsonrpc":"2.0","id":"req-002","result":{"id":"task-story-456","status":{"state":"working","message":{"role":"agent","parts":[{"type":"text","text":"Okay, I'm starting to write that story for you..."}]},"timestamp":"2024-03-15T10:05:01Z"},"final":false}}

    Event 2: Artifact update - first chunk of the story

    id: sse-evt-102
    event: message
    data: {"jsonrpc":"2.0","id":"req-002","result":{"id":"task-story-456","artifact":{"name":"MarsStory.txt","index":0,"parts":[{"type":"text","text":"Unit 734, a small rover with oversized optical sensors, trundled across the ochre plains. "}]}}}

    Event 3: Artifact update - second chunk (appended)

    id: sse-evt-103
    event: message
    data: {"jsonrpc":"2.0","id":"req-002","result":{"id":"task-story-456","artifact":{"name":"MarsStory.txt","index":0,"append":true,"parts":[{"type":"text","text":"Its mission: to find the source of a peculiar signal. "}]}}}

    Event 4: Artifact update - final chunk

    id: sse-evt-104
    event: message
    data: {"jsonrpc":"2.0","id":"req-002","result":{"id":"task-story-456","artifact":{"name":"MarsStory.txt","index":0,"append":true,"lastChunk":true,"parts":[{"type":"text","text":"Olympus Mons loomed, a silent giant, as Unit 734 beeped excitedly."}]}}}

    Event 5: Task status update - completed

    id: sse-evt-105
    event: message
    data: {"jsonrpc":"2.0","id":"req-002","result":{"id":"task-story-456","status":{"state":"completed","message":{"role":"agent","parts":[{"type":"text","text":"The story is complete!"}]},"timestamp":"2024-03-15T10:05:05Z"},"final":true}}

    (Server closes the SSE connection after the final:true event). (Note: SSE id and event fields are part of the SSE protocol itself, distinct from the JSON-RPC id within the data payload).

9.3. Multi-Turn Interaction (Input Required)

Scenario: Client wants to book a flight, and the agent needs more information.

  1. Client tasks/send (initial request):

    {
      "jsonrpc": "2.0",
      "id": "req-003",
      "method": "tasks/send",
      "params": {
        "id": "task-flightbook-789",
        "message": {
          "role": "user",
          "parts": [{ "type": "text", "text": "I'd like to book a flight." }]
        }
      }
    }
  2. Server responds, task state is input-required:

    {
      "jsonrpc": "2.0",
      "id": "req-003",
      "result": {
        "id": "task-flightbook-789",
        "status": {
          "state": "input-required",
          "message": {
            "role": "agent",
            "parts": [
              {
                "type": "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?"
              }
            ]
          },
          "timestamp": "2024-03-15T10:10:00Z"
        }
      }
    }
  3. Client tasks/send (providing the requested input, using the same task ID):

    {
      "jsonrpc": "2.0",
      "id": "req-004",
      "method": "tasks/send",
      "params": {
        "id": "task-flightbook-789" /* Same task ID */,
        "message": {
          "role": "user",
          "parts": [
            {
              "type": "text",
              "text": "I want to fly from New York (JFK) to London (LHR) around October 10th, returning October 17th."
            }
          ]
        }
      }
    }
  4. Server processes the new input and responds (e.g., task completed or more input needed):

    {
      "jsonrpc": "2.0",
      "id": "req-004",
      "result": {
        "id": "task-flightbook-789",
        "status": {
          "state": "completed",
          "message": {
            "role": "agent",
            "parts": [
              {
                "type": "text",
                "text": "Okay, I've found a flight for you. Confirmation XYZ123. Details are in the artifact."
              }
            ]
          },
          "timestamp": "2024-03-15T10:11:00Z"
        },
        "artifacts": [
          {
            "name": "FlightItinerary.json",
            "parts": [
              {
                "type": "data",
                "data": {
                  "confirmationId": "XYZ123",
                  "from": "JFK",
                  "to": "LHR",
                  "departure": "2024-10-10T18:00:00Z",
                  "arrival": "2024-10-11T06:00:00Z",
                  "returnDeparture": "..."
                }
              }
            ]
          }
        ]
      }
    }

9.4. Push Notification Setup and Usage

Scenario: Client requests a long-running report generation and wants to be notified via webhook when it's done.

  1. Client tasks/send with pushNotification config:

    {
      "jsonrpc": "2.0",
      "id": "req-005",
      "method": "tasks/send",
      "params": {
        "id": "task-reportgen-aaa",
        "message": {
          "role": "user",
          "parts": [
            {
              "type": "text",
              "text": "Generate the Q1 sales report. This usually takes a while. Notify me when it's ready."
            }
          ]
        },
        "pushNotification": {
          "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.
          }
        }
      }
    }
  2. Server acknowledges the task (e.g., status submitted or working):

    {
      "jsonrpc": "2.0",
      "id": "req-005",
      "result": {
        "id": "task-reportgen-aaa",
        "status": { "state": "submitted", "timestamp": "2024-03-15T11:00:00Z" }
        // ... other fields ...
      }
    }
  3. (Later) A2A Server completes the task and POSTs a notification to https://client.example.com/webhook/a2a-notifications:

    • HTTP Headers might include:
      • Authorization: Bearer <server_jwt_for_webhook_audience> (if server authenticates to webhook)
      • Content-Type: application/json
      • X-A2A-Notification-Token: secure-client-token-for-task-aaa
    • HTTP Body (example, actual payload is server-defined, but SHOULD include taskId and status):
    {
      "eventType": "taskUpdate",
      "taskId": "task-reportgen-aaa",
      "status": { "state": "completed", "timestamp": "2024-03-15T18:30:00Z" },
      "summary": "Q1 sales report generated successfully."
      // Server MAY include more details or a link to fetch the full task.
    }
  4. Client's Webhook Service:

    • Receives the POST.
    • Validates the Authorization header (if applicable).
    • Validates the X-A2A-Notification-Token.
    • Internally processes the notification (e.g., updates application state, notifies end-user).
  5. Client (optionally, upon receiving and validating the push notification) calls tasks/get to retrieve full artifacts:

    {
      "jsonrpc": "2.0",
      "id": "req-006",
      "method": "tasks/get",
      "params": { "id": "task-reportgen-aaa" }
    }

    (Server responds with the full Task object, including the generated report in Task.artifacts).

9.5. File Exchange (Upload and Download)

Scenario: Client sends an image for analysis, and the agent returns a modified image.

  1. Client tasks/send with a FilePart (uploading image bytes):

    {
      "jsonrpc": "2.0",
      "id": "req-007",
      "method": "tasks/send",
      "params": {
        "id": "task-imageanalysis-bbb",
        "message": {
          "role": "user",
          "parts": [
            {
              "type": "text",
              "text": "Analyze this image and highlight any faces."
            },
            {
              "type": "file",
              "file": {
                "name": "input_image.png",
                "mimeType": "image/png",
                "bytes": "iVBORw0KGgoAAAANSUhEUgAAAAUA..." // Base64 encoded image data
              }
            }
          ]
        }
      }
    }
  2. Server processes the image and responds with a FilePart in an artifact (e.g., providing a URI to the modified image):

    {
      "jsonrpc": "2.0",
      "id": "req-007",
      "result": {
        "id": "task-imageanalysis-bbb",
        "status": { "state": "completed", "timestamp": "2024-03-15T12:05:00Z" },
        "artifacts": [
          {
            "name": "processed_image_with_faces.png",
            "index": 0,
            "parts": [
              {
                "type": "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..."
                }
              }
            ]
          }
        ]
      }
    }

9.6. Structured Data Exchange (Requesting and Providing JSON)

Scenario: Client asks for a list of open support tickets in a specific JSON format.

  1. Client tasks/send, Part.metadata hints at desired output schema/MIME type: (Note: A2A doesn't formally standardize schema negotiation in v0.1.0, but metadata can be used for such hints by convention between client/server).

    {
      "jsonrpc": "2.0",
      "id": "req-008",
      "method": "tasks/send",
      "params": {
        "id": "task-gettickets-ccc",
        "message": {
          "role": "user",
          "parts": [
            {
              "type": "text",
              "text": "List my open IT support tickets created in the last week.",
              "metadata": {
                "desiredOutputMimeType": "application/json",
                "desiredOutputSchemaRef": "https://schemas.example.com/supportTicketList_v1.json"
                // This metadata is a convention, not strictly enforced by A2A spec
              }
            }
          ]
        }
      }
    }
  2. Server responds with a DataPart containing the structured JSON data:

    {
      "jsonrpc": "2.0",
      "id": "req-008",
      "result": {
        "id": "task-gettickets-ccc",
        "status": { "state": "completed", "timestamp": "2024-03-15T12:15:00Z" },
        "artifacts": [
          {
            "name": "open_support_tickets.json",
            "index": 0,
            "parts": [
              {
                "type": "data",
                "metadata": {
                  "mimeType": "application/json", // Explicitly state MIME type
                  "schemaRef": "https://schemas.example.com/supportTicketList_v1.json" // Confirming schema
                },
                "data": [
                  {
                    "ticketId": "IT00123",
                    "summary": "Cannot connect to VPN",
                    "status": "Open",
                    "createdDate": "2024-03-14T09:30:00Z"
                  },
                  {
                    "ticketId": "IT00125",
                    "summary": "Printer not working on 3rd floor",
                    "status": "In Progress",
                    "createdDate": "2024-03-13T15:00:00Z"
                  }
                ]
              }
            ]
          }
        ]
      }
    }

These examples illustrate the flexibility of A2A in handling various interaction patterns and data types. Implementers should refer to the detailed object definitions for all fields and constraints.

10. Appendices

10.1. Relationship to MCP (Model Context Protocol)

A2A and MCP are complementary protocols designed for different aspects of agentic systems:

  • Model Context Protocol (MCP): Focuses on standardizing how AI models and agents connect to and interact with tools, APIs, data sources, and other external resources. It defines structured ways to describe tool capabilities (like function calling in LLMs), pass inputs, and receive structured outputs. Think of MCP as the "how-to" for an agent to use a specific capability or access a resource.
  • Agent2Agent Protocol (A2A): Focuses on standardizing how independent, often opaque, AI agents communicate and collaborate with each other as peers. A2A provides an application-level protocol for agents to discover each other, negotiate interaction modalities, manage shared tasks, and exchange conversational context or complex results. It's about how agents partner or delegate work.

How they work together: An A2A Client agent might request an A2A Server agent to perform a complex task. The Server agent, in turn, might use MCP to interact with several underlying tools, APIs, or data sources to gather information or perform actions necessary to fulfill the A2A task.

For a more detailed comparison, see the A2A and MCP guide.

10.2. Security Considerations Summary

Security is a paramount concern in A2A. Key considerations include:

  • Transport Security: Always use HTTPS with strong TLS configurations in production environments.
  • Authentication:
    • Handled via standard HTTP mechanisms (e.g., Authorization header with Bearer tokens, API keys).
    • Requirements are declared in the AgentCard.
    • Credentials MUST be obtained out-of-band by the client.
    • A2A Servers MUST authenticate every request.
  • Authorization:
    • A server-side responsibility based on the authenticated identity.
    • Implement the principle of least privilege.
    • Can be granular, based on skills, actions, or data.
  • Push Notification Security:
    • Webhook URL validation (by the A2A Server sending notifications) is crucial to prevent SSRF.
    • Authentication of the A2A Server to the client's webhook is essential.
    • Authentication of the notification by the client's webhook receiver (verifying it came from the legitimate A2A Server and is relevant) is critical.
    • See the Streaming & Asynchronous Operations guide for detailed push notification security.
  • Input Validation: Servers MUST rigorously validate all RPC parameters and the content/structure of data in Message and Artifact parts to prevent injection attacks or processing errors.
  • Resource Management: Implement rate limiting, concurrency controls, and resource limits to protect agents from abuse or overload.
  • Data Privacy: Adhere to all applicable privacy regulations for data exchanged in Message and Artifact parts. Minimize sensitive data transfer.

For a comprehensive discussion, refer to the Enterprise-Ready Features guide.

ON THIS PAGE