--- hide: - navigation --- # Agent2Agent (A2A) Protocol Specification **Version:** `{{ a2a_version }}` See [Release Notes](https://github.com/a2aproject/A2A/releases) for changes made between versions. ## 1. Introduction The Agent2Agent (A2A) Protocol is an open standard designed to facilitate communication and interoperability between independent, potentially opaque AI agent systems. In an ecosystem where agents might be built using different frameworks, languages, or by different vendors, A2A provides a common language and interaction model. This document provides the detailed technical specification for the A2A protocol. Its primary goal is to enable agents to: - Discover each other's capabilities. - Negotiate interaction modalities (text, files, structured data). - Manage collaborative tasks. - Securely exchange information to achieve user goals **without needing access to each other's internal state, memory, or tools.** ### 1.1. Key Goals of A2A - **Interoperability:** Bridge the communication gap between disparate agentic systems. - **Collaboration:** Enable agents to delegate tasks, exchange context, and work together on complex user requests. - **Discovery:** Allow agents to dynamically find and understand the capabilities of other agents. - **Flexibility:** Support various interaction modes including synchronous request/response, streaming for real-time updates, and asynchronous push notifications for long-running tasks. - **Security:** Facilitate secure communication patterns suitable for enterprise environments, relying on standard web security practices. - **Asynchronicity:** Natively support long-running tasks and interactions that may involve human-in-the-loop scenarios. ### 1.2. Guiding Principles - **Simple:** Reuse existing, well-understood standards (HTTP, JSON-RPC 2.0, Server-Sent Events). - **Enterprise Ready:** Address authentication, authorization, security, privacy, tracing, and monitoring by aligning with established enterprise practices. - **Async First:** Designed for (potentially very) long-running tasks and human-in-the-loop interactions. - **Modality Agnostic:** Support exchange of diverse content types including text, audio/video (via file references), structured data/forms, and potentially embedded UI components (e.g., iframes referenced in parts). - **Opaque Execution:** Agents collaborate based on declared capabilities and exchanged information, without needing to share their internal thoughts, plans, or tool implementations. For a broader understanding of A2A's purpose and benefits, see [What is A2A?](./topics/what-is-a2a.md). ## 2. Core Concepts Summary A2A revolves around several key concepts. For detailed explanations, please refer to the [Key Concepts guide](./topics/key-concepts.md). - **A2A Client:** An application or agent that initiates requests to an A2A Server on behalf of a user or another system. - **A2A Server (Remote Agent):** An agent or agentic system that exposes an A2A-compliant HTTP endpoint, processing tasks and providing responses. - **Agent Card:** A JSON metadata document published by an A2A Server, describing its identity, capabilities, skills, service endpoint, and authentication requirements. - **Message:** A communication turn between a client and a remote agent, having a `role` ("user" or "agent") and containing one or more `Parts`. - **Task:** The fundamental unit of work managed by A2A, identified by a unique ID. Tasks are stateful and progress through a defined lifecycle. - **Part:** The smallest unit of content within a Message or Artifact (e.g., `TextPart`, `FilePart`, `DataPart`). - **Artifact:** An output (e.g., a document, image, structured data) generated by the agent as a result of a task, composed of `Parts`. - **Streaming (SSE):** Real-time, incremental updates for tasks (status changes, artifact chunks) delivered via Server-Sent Events. - **Push Notifications:** Asynchronous task updates delivered via server-initiated HTTP POST requests to a client-provided webhook URL, for long-running or disconnected scenarios. - **Context:** An optional, server-generated identifier to logically group related tasks. - **Extension:** A mechanism for agents to provide additional functionality or data beyond the core A2A specification. ## 3. Transport and Format ### 3.1. Transport Protocol - A2A communication **MUST** occur over **HTTP(S)**. - The A2A Server exposes its service at a URL defined in its `AgentCard`. ### 3.2. Data Format A2A uses **[JSON-RPC 2.0](https://www.jsonrpc.org/specification)** as the payload format for all requests and responses (excluding the SSE stream wrapper). - Client requests and server responses **MUST** adhere to the JSON-RPC 2.0 specification. - The `Content-Type` header for HTTP requests and responses containing JSON-RPC payloads **MUST** be `application/json`. ### 3.3. Streaming Transport (Server-Sent Events) When streaming is used for methods like `message/stream` or `tasks/resubscribe`: - The server responds with an HTTP `200 OK` status and a `Content-Type` header of `text/event-stream`. - The body of this HTTP response contains a stream of **[Server-Sent Events (SSE)](https://html.spec.whatwg.org/multipage/server-sent-events.html#server-sent-events)** as defined by the W3C. - Each SSE `data` field contains a complete JSON-RPC 2.0 Response object (specifically, a [`SendStreamingMessageResponse`](#721-sendstreamingmessageresponse-object)). ## 4. Authentication and Authorization A2A treats agents as standard enterprise applications, relying on established web security practices. Identity information is **not** transmitted within A2A JSON-RPC payloads; it is handled at the HTTP transport layer. For a comprehensive guide on enterprise security aspects, see [Enterprise-Ready Features](./topics/enterprise-ready.md). ### 4.1. Transport Security As stated in section 3.1, production deployments **MUST** use HTTPS. Implementations **SHOULD** use modern [TLS](https://datatracker.ietf.org/doc/html/rfc8446) configurations (TLS 1.3+ recommended) with strong cipher suites. ### 4.2. Server Identity Verification A2A Clients **SHOULD** verify the A2A Server's identity by validating its TLS certificate against trusted certificate authorities (CAs) during the TLS handshake. ### 4.3. Client/User Identity & Authentication Process 1. **Discovery of Requirements:** The client discovers the server's required authentication schemes via the `authentication` field in the [`AgentCard`](#55-agentcard-object-structure). Scheme names often align with [OpenAPI Authentication methods](https://swagger.io/docs/specification/authentication/) (e.g., "Bearer" for OAuth 2.0 tokens, "Basic" for Basic Auth, "ApiKey" for API keys). 2. **Credential Acquisition (Out-of-Band):** The client obtains the necessary credentials (e.g., API keys, OAuth tokens, JWTs) through an **out-of-band process** specific to the required authentication scheme and the identity provider. This process is outside the scope of the A2A protocol itself. 3. **Credential Transmission:** The client includes these credentials in the appropriate [HTTP headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers) (e.g., `Authorization: Bearer `, `X-API-Key: `) of every A2A request sent to the server. ### 4.4. Server Responsibilities for Authentication The A2A Server: - **MUST** authenticate every incoming request based on the provided HTTP credentials and its declared authentication requirements from its Agent Card. - **SHOULD** use standard HTTP status codes like [`401 Unauthorized`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/401) or [`403 Forbidden`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/403) for authentication challenges or rejections. - **SHOULD** include relevant HTTP headers (e.g., [`WWW-Authenticate`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/WWW-Authenticate)) with `401 Unauthorized` responses to indicate the required authentication scheme(s), guiding the client. ### 4.5. In-Task Authentication (Secondary Credentials) If an agent, during the execution of a task, requires _additional_ credentials for a _different_ system or resource (e.g., to access a specific tool on behalf of the user that requires its own auth): 1. It **SHOULD** transition the A2A task to the `auth-required` state (see [`TaskState`](#63-taskstate-enum)). 2. The accompanying `TaskStatus.message` (often a [`DataPart`](#653-datapart-object)) **SHOULD** provide details about the required secondary authentication, potentially using an [`PushNotificationAuthenticationInfo`](#69-pushnotificationauthenticationinfo-object)-like structure to describe the need. 3. The A2A Client then obtains these new credentials out-of-band and provides them in a subsequent [`message/send`](#71-messagesend) or [`message/stream`](#72-messagestream) request. How these credentials are used (e.g., passed as data within the A2A message if the agent is proxying, or used by the client to interact directly with the secondary system) depends on the specific scenario. ### 4.6. Authorization Once a client is authenticated, the A2A Server is responsible for authorizing the request based on the authenticated client/user identity and its own policies. Authorization logic is implementation-specific and MAY be enforced based on: - The specific skills requested (e.g., as identified by `AgentSkill.id` from the Agent Card). - The actions attempted within the task. - Data access policies relevant to the resources the agent manages. - OAuth scopes associated with the presented token, if applicable. Servers should implement the principle of least privilege. ## 5. Agent Discovery: The Agent Card ### 5.1. Purpose A2A Servers **MUST** make an Agent Card available. The Agent Card is a JSON document that describes the server's identity, capabilities, skills, service endpoint URL, and how clients should authenticate and interact with it. Clients use this information for discovering suitable agents and for configuring their interactions. For more on discovery strategies, see the [Agent Discovery guide](./topics/agent-discovery.md). ### 5.2. Discovery Mechanisms Clients can find Agent Cards through various methods, including but not limited to: - **Well-Known URI:** Accessing a predefined path on the agent's domain (see [Section 5.3](#53-recommended-location)). - **Registries/Catalogs:** Querying curated catalogs or registries of agents (which might be enterprise-specific, public, or domain-specific). - **Direct Configuration:** Clients may be pre-configured with the Agent Card URL or the card content itself. ### 5.3. Recommended Location If using the well-known URI strategy, the recommended location for an agent's Agent Card is: `https://{server_domain}/.well-known/agent.json` This follows the principles of [RFC 8615](https://datatracker.ietf.org/doc/html/rfc8615) for well-known URIs. ### 5.4. Security of Agent Cards Agent Cards themselves might contain information that is considered sensitive. - If an Agent Card contains sensitive information, the endpoint serving the card **MUST** be protected by appropriate access controls (e.g., mTLS, network restrictions, authentication required to fetch the card). - It is generally **NOT RECOMMENDED** to include plaintext secrets (like static API keys) directly in an Agent Card. Prefer authentication schemes where clients obtain dynamic credentials out-of-band. ### 5.5. `AgentCard` Object Structure ```ts { .no-copy } --8<-- "types/src/types.ts:AgentCard" ``` #### 5.5.1. `AgentProvider` Object Information about the organization or entity providing the agent. ```ts { .no-copy } --8<-- "types/src/types.ts:AgentProvider" ``` #### 5.5.2. `AgentCapabilities` Object Specifies optional A2A protocol features supported by the agent. ```ts { .no-copy } --8<-- "types/src/types.ts:AgentCapabilities" ``` #### 5.5.2.1. `AgentExtension` Object Specifies an extension to the A2A protocol supported by the agent. ```ts { .no-copy } --8<-- "types/src/types.ts:AgentExtension" ``` #### 5.5.3. `SecurityScheme` Object Describes the authentication requirements for accessing the agent's `url` endpoint. Refer [Sample Agent Card](#56-sample-agent-card) for an example. ```ts { .no-copy } --8<-- "types/src/types.ts:SecurityScheme" ``` #### 5.5.4. `AgentSkill` Object Describes a specific capability, function, or area of expertise the agent can perform or address. ```ts { .no-copy } --8<-- "types/src/types.ts:AgentSkill" ``` #### 5.5.5. `AgentInterface` Object Provides a declaration of a combination of the target url and the supported transport to interact with the agent. ```ts { .no-copy } --8<-- "types/src/types.ts:AgentInterface" ``` ### 5.6. Sample Agent Card ```json { "protocolVersion": "0.2.9", "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", "preferredTransport": "JSONRPC", "additionalInterfaces" : [ {"url": "https://georoute-agent.example.com/a2a/v1", "transport": "JSONRPC"}, {"url": "https://georoute-agent.example.com/a2a/grpc", "transport": "GRPC"}, {"url": "https://georoute-agent.example.com/a2a/json", "transport": "HTTP+JSON"} ], "provider": { "organization": "Example Geo Services Inc.", "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", "openIdConnectUrl": "https://accounts.google.com/.well-known/openid-configuration" } }, "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. 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. A task which has reached a terminal state (completed, canceled, rejected, or failed) can't be restarted. Tasks in completed state SHOULD use artifacts for returning the generated output to the clients. For more information, refer to the [Life of a Task guide](./topics/life-of-a-task.md). ```ts { .no-copy } --8<-- "types/src/types.ts:Task" ``` ### 6.2. `TaskStatus` Object Represents the current state and associated context (e.g., a message from the agent) of a `Task`. ```ts { .no-copy } --8<-- "types/src/types.ts:TaskStatus" ``` ### 6.3. `TaskState` Enum Defines the possible lifecycle states of a `Task`. ```ts { .no-copy } --8<-- "types/src/types.ts:TaskState" ``` ### 6.4. `Message` Object Represents a single communication turn or a piece of contextual information between a client and an agent. Messages are used for instructions, prompts, replies, and status updates. ```ts { .no-copy } --8<-- "types/src/types.ts:Message" ``` ### 6.5. `Part` Union Type Represents a distinct piece of content within a `Message` or `Artifact`. A `Part` is a union type representing exportable content as either `TextPart`, `FilePart`, or `DataPart`. All `Part` types also include an optional `metadata` field (`Record`) for part-specific metadata. ```ts { .no-copy } --8<-- "types/src/types.ts:Part" ``` ```ts { .no-copy } --8<-- "types/src/types.ts:PartBase" ``` It **MUST** be one of the following: #### 6.5.1. `TextPart` Object For conveying plain textual content. ```ts { .no-copy } --8<-- "types/src/types.ts:TextPart" ``` #### 6.5.2. `FilePart` Object For conveying file-based content. ```ts { .no-copy } --8<-- "types/src/types.ts:FilePart" ``` #### 6.5.3. `DataPart` Object For conveying structured JSON data. Useful for forms, parameters, or any machine-readable information. ```ts { .no-copy } --8<-- "types/src/types.ts:DataPart" ``` ### 6.6 `FileBase` Object Base entity for File Contents. ```ts { .no-copy } --8<-- "types/src/types.ts:FileBase" ``` #### 6.6.1 `FileWithBytes` Object Represents the data for a file, used within a `FilePart`. ```ts { .no-copy } --8<-- "types/src/types.ts:FileWithBytes" ``` #### 6.6.2 `FileWithUri` Object Represents the URI for a file, used within a `FilePart`. ```ts { .no-copy } --8<-- "types/src/types.ts:FileWithUri" ``` ### 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. ```ts { .no-copy } --8<-- "types/src/types.ts:Artifact" ``` ### 6.8. `PushNotificationConfig` Object Configuration provided by the client to the server for sending asynchronous push notifications about task updates. ```ts { .no-copy } --8<-- "types/src/types.ts:PushNotificationConfig" ``` ### 6.9. `PushNotificationAuthenticationInfo` Object A generic structure for specifying authentication requirements, typically used within `PushNotificationConfig` to describe how the A2A Server should authenticate to the client's webhook. ```ts { .no-copy } --8<-- "types/src/types.ts:PushNotificationAuthenticationInfo" ``` ### 6.10. `TaskPushNotificationConfig` Object Used as the `params` object for the [`tasks/pushNotificationConfig/set`](#75-taskspushnotificationconfigset) method and as the `result` object for the [`tasks/pushNotificationConfig/get`](#76-taskspushnotificationconfigget) method. ```ts { .no-copy } --8<-- "types/src/types.ts:TaskPushNotificationConfig" ``` ### 6.11. JSON-RPC Structures A2A adheres to the standard [JSON-RPC 2.0](https://www.jsonrpc.org/specification) 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., `"message/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`](#612-jsonrpcerror-object) 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. ```ts { .no-copy } --8<-- "types/src/types.ts:JSONRPCError" ``` ## 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. `message/send` Sends a message to an agent to initiate a new interaction 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. A task which has reached a terminal state (completed, canceled, rejected, or failed) can't be restarted. Sending a message to such a task will result in an error. For more information, refer to the [Life of a Task guide](./topics/life-of-a-task.md).
=== "JSON-RPC" - **URL:** `message/send` - **HTTP Method:** `POST` - **Payload**: [`MessageSendParams`](#711-messagesendparams-object) - **Response**: [`Task` | `Message`](#61-task-object) (A message object or the current or final state of the task after processing the message). === "gRPC" - **URL:** `SendMessage` - **HTTP Method:** `POST` - **Payload:** ```proto message SendMessageRequest { Message msg = 1; SendMessageConfiguration configuration = 2; } ``` - **Response:** ```proto message SendMessageResponse { oneof payload { Task task = 1; Message msg = 2; } } ``` === "REST" - **URL:** `/v1/message:send` - **HTTP Method:** `POST` - **Payload:** ```typescript { message: Message, configuration?: MessageSendConfiguration, metadata?: { [key: string]: any } } ``` - **Response:** ```typescript // Returns one of a message or a task { message?: Message, task?: Task } ```
The `error` response for all transports in case of failure is a [`JSONRPCError`](#612-jsonrpcerror-object) or equivalent. #### 7.1.1. `MessageSendParams` Object ```ts { .no-copy } --8<-- "types/src/types.ts:MessageSendParams" --8<-- "types/src/types.ts:MessageSendConfiguration" ``` ### 7.2. `message/stream` 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`. Just like `message/send`, a task which has reached a terminal state (completed, canceled, rejected, or failed) can't be restarted. Sending a message to such a task will result in an error. For more information, refer to the [Life of a Task guide](./topics/life-of-a-task.md).
=== "JSON-RPC" - **URL:** `message/stream` - **HTTP Method:** `POST` - **Payload**: [`MessageSendParams`](#711-messagesendparams-object) (same as `message/send`) - **Response**: A stream of Server-Sent Events. Each SSE `data` field contains a [`SendStreamingMessageResponse`](#721-sendstreamingmessageresponse-object) === "gRPC" - **URL:** `SendStreamingMessage` - **HTTP Method:** `POST` - **Payload:** ```proto message SendMessageRequest { Message msg = 1; SendMessageConfiguration configuration = 2; } ``` - **Response:** ```proto message StreamResponse { oneof payload { Task task; Message msg; TaskStatusUpdateEvent status_update; TaskArtifactUpdateEvent artifact_update; } } ``` === "REST" - **URL:** `/v1/message:stream` - **HTTP Method:** `POST` - **Payload:** ```typescript { message: Message, configuration?: MessageSendConfiguration, metadata?: { [key: string]: any } } ``` - **Response:** ```typescript { message?: Message task?: Task statusUpdate?: TaskStatusUpdateEvent artifactUpdate?: TaskArtifactUpdateEvent } ```
#### 7.2.1. `SendStreamingMessageResponse` 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 `message/stream` request or `tasks/resubscribe` request. ```ts { .no-copy } --8<-- "types/src/types.ts:SendStreamingMessageResponse" --8<-- "types/src/types.ts:SendStreamingMessageSuccessResponse" ``` #### 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 `SendStreamingMessageSuccessResponse`. ```ts { .no-copy } --8<-- "types/src/types.ts:TaskStatusUpdateEvent" ``` #### 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`. ```ts { .no-copy } --8<-- "types/src/types.ts:TaskArtifactUpdateEvent" ``` ### 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 `message/send`, or for fetching the final state of a task after being notified via a push notification or after an SSE stream has ended.
=== "JSON-RPC" - **URL:** `tasks/get` - **HTTP Method:** `POST` - **Payload**: [`TaskQueryParams`](#731-taskqueryparams-object) - **Response**: `Task` === "gRPC" - **URL:** `GetTask` - **HTTP Method:** `POST` - **Payload:** ```proto message GetTaskRequest { // name=tasks/{id} string name; int32 history_length; } ``` - **Response**: `Task` === "REST" - **URL:** `v1/tasks/{id}?historyLength={historyLength}` - **HTTP Method:** `GET` - **Payload:** None - **Response**: `Task`
#### 7.3.1. `TaskQueryParams` Object ```ts { .no-copy } --8<-- "types/src/types.ts:TaskQueryParams" ``` ### `tasks/list`
=== "JSON-RPC" - N/A === "gRPC" - **URL:** `ListTask` - **HTTP Method:** `GET` - **Payload:** ```proto {} ``` - **Response**: `repeated Task` === "REST" - **URL:** `/v1/tasks` - **HTTP Method:** `GET` - **Payload:** ```typescript {} ``` - **Response**: `[Task]`
### 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).
=== "JSON-RPC" - **URL:** `tasks/cancel` - **HTTP Method:** `POST` - **Payload**: [`TaskIdParams`](#741-taskidparams-object-for-taskscancel-and-taskspushnotificationconfigget) - **Response**: `Task` === "gRPC" - **URL:** `CancelTask` - **HTTP Method:** `POST` - **Payload:** ```proto message CancelTaskRequest{ // name=tasks/{id} string name; } ``` - **Response**: `Task` === "REST" - **URL:** `/v1/tasks/{id}:cancel` - **HTTP Method:** `POST` - **Payload:** ```typescript { name: string } ``` - **Response**: `Task`
#### 7.4.1. `TaskIdParams` Object (for `tasks/cancel` and `tasks/pushNotificationConfig/get`) A simple object containing just the task ID and optional metadata. ```ts { .no-copy } --8<-- "types/src/types.ts:TaskIdParams" ``` ### 7.5. `tasks/pushNotificationConfig/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`.
=== "JSON-RPC" - **URL:** `tasks/pushNotificationConfig/set` - **HTTP Method:** `POST` - **Payload**: [`TaskPushNotificationConfig`](#610-taskpushnotificationconfig-object) - **Response**: [`TaskPushNotificationConfig`](#610-taskpushnotificationconfig-object) === "gRPC" - **URL:** `CreateTaskPushNotification` - **HTTP Method:** `POST` - **Payload:** ```proto message SetTaskPushNotificationRequest { TaskPushNotificationConfig config = 1; } ``` - **Response**: `TaskPushNotificationConfig` === "REST" - **URL:** `/v1/tasks/{id}/pushNotificationConfigs` - **HTTP Method:** `POST` - **Payload:** ```typescript { config: TaskPushNotificationConfig } ``` - **Response**: `TaskPushNotificationConfig`
### 7.6. `tasks/pushNotificationConfig/get` Retrieves the current push notification configuration for a specified task. Requires the server to have `AgentCard.capabilities.pushNotifications: true`.
=== "JSON-RPC" - **URL:** `tasks/pushNotificationConfig/get` - **HTTP Method:** `POST` - **Payload**: [`GetTaskPushNotificationConfigParams`](#761-gettaskpushnotificationconfigparams-object-taskspushnotificationconfigget) - **Response**: [`TaskPushNotificationConfig`](#610-taskpushnotificationconfig-object) === "gRPC" - **URL:** `GetTaskPushNotification` - **HTTP Method:** `POST` - **Payload:** ```proto message TaskSubscriptionRequest { // name=tasks/{id}/pushNotification/{id} string name; } ``` - **Response**: `TaskPushNotificationConfig` === "REST" - **URL:** `/v1/tasks/{taskId}/pushNotificationConfigs/{configId}` - **HTTP Method:** `GET` - **Payload:** None - **Response**: `TaskPushNotificationConfig`
**Response `error` type (on failure)**: [`JSONRPCError`](#612-jsonrpcerror-object) (e.g., [`PushNotificationNotSupportedError`](#82-a2a-specific-errors), [`TaskNotFoundError`](#82-a2a-specific-errors)). #### 7.6.1. `GetTaskPushNotificationConfigParams` Object (`tasks/pushNotificationConfig/get`) A object for fetching the push notification configuration for a task. ```ts { .no-copy } --8<-- "types/src/types.ts:GetTaskPushNotificationConfigParams" ``` ### 7.7. `tasks/pushNotificationConfig/list` Retrieves the associated push notification configurations for a specified task. Requires the server to have `AgentCard.capabilities.pushNotifications: true`.
=== "JSON-RPC" - **URL:** `tasks/pushNotificationConfig/list` - **HTTP Method:** `POST` - **Payload:** [`ListTaskPushNotificationConfigParams`](#771-listtaskpushnotificationconfigparams-object-taskspushnotificationconfiglist) - **Response**: `TaskPushNotificationConfig[]` === "gRPC" - **URL:** `ListTaskPushNotification` - **HTTP Method:** `POST` - **Payload:** ```proto message ListTaskPushNotificationRequest { // parent=tasks/{id} string parent = 1; } ``` - **Response**: `repeated TaskPushNotificationConfig` === "REST" - **URL:** `/v1/tasks/{id}/pushNotificationConfigs` - **HTTP Method:** `GET` - **Payload:**: None - **Response**: `[TaskPushNotificationConfig]`
#### 7.7.1. `ListTaskPushNotificationConfigParams` Object (`tasks/pushNotificationConfig/list`) A object for fetching the push notification configurations for a task. ```ts { .no-copy } --8<-- "types/src/types.ts:ListTaskPushNotificationConfigRequest" ``` ### 7.8. `tasks/pushNotificationConfig/delete` Deletes an associated push notification configuration for a task. Requires the server to have `AgentCard.capabilities.pushNotifications: true`. - **Request `params` type**: [`DeleteTaskPushNotificationConfigParams`](#781-deletetaskpushnotificationconfigparams-object-taskspushnotificationconfigdelete) - **Response `result` type (on success)**: [`null`] - **Response `error` type (on failure)**: [`JSONRPCError`](#612-jsonrpcerror-object) (e.g., [`PushNotificationNotSupportedError`](#82-a2a-specific-errors), [`TaskNotFoundError`](#82-a2a-specific-errors)). #### 7.8.1. `DeleteTaskPushNotificationConfigParams` Object (`tasks/pushNotificationConfig/delete`) A object for deleting an associated push notification configuration for a task. ```ts { .no-copy } --8<-- "types/src/types.ts:DeleteTaskPushNotificationConfigParams" ``` ### 7.9. `tasks/resubscribe` Allows a client to reconnect to an SSE stream for an ongoing task after a previous connection (from `message/stream` 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.
=== "JSON-RPC" - **URL:** `tasks/resubscribe` - **HTTP Method:** `POST` - **Payload**: [`TaskIdParams`](#741-taskidparams-object-for-taskscancel-and-taskspushnotificationconfigget) - **Response**: A stream of Server-Sent Events. Each SSE `data` field contains a [`SendStreamingMessageResponse`](#721-sendstreamingmessageresponse-object) === "gRPC" - **URL:** `TaskSubscription` - **HTTP Method:** `POST` - **Payload:** ```proto message TaskSubscriptionRequest{ // name=tasks/{id} string name; } ``` - **Response:** ```proto message StreamResponse { oneof payload { Task task; Message msg; TaskStatusUpdateEvent status_update; TaskArtifactUpdateEvent artifact_update; } } ``` === "REST" - **URL:** `/v1/tasks/{id}:subscribe` - **HTTP Method:** `POST` - **Payload:** ```typescript { name: string } ``` - **Response:** ```typescript { message?: Message task?: Task statusUpdate?: TaskStatusUpdateEvent artifactUpdate?: TaskArtifactUpdateEvent } ```
### 7.10. `agent/authenticatedExtendedCard` Retrieves a potentially more detailed version of the Agent Card after the client has authenticated. This endpoint is available only if `AgentCard.supportsAuthenticatedExtendedCard` is `true`. - **Endpoint URL**: `{AgentCard.url}/../agent/authenticatedExtendedCard` (relative to the base URL specified in the public Agent Card). - **HTTP Method**: `GET` - **Authentication**: The client **MUST** authenticate the request using one of the schemes declared in the public `AgentCard.securitySchemes` and `AgentCard.security` fields. - **Request `params`**: None (HTTP GET request). - **Response `result` type (on success)**: `AgentCard` (A complete Agent Card object, which may contain additional details or skills not present in the public card). - **Response `error` type (on failure)**: Standard HTTP error codes. - `401 Unauthorized`: Authentication failed (missing or invalid credentials). The server **SHOULD** include a `WWW-Authenticate` header. - `403 Forbidden`: Authentication succeeded, but the client/user is not authorized to access the extended card. - `404 Not Found`: The `supportsAuthenticatedExtendedCard` capability is declared, but the server has not implemented this endpoint at the specified path. - `5xx Server Error`: An internal server error occurred.
=== "JSON-RPC" - **URL:** `agent/authenticatedExtendedCard` - **HTTP Method:** `POST` - **Payload:** None - **Response:** `AgentCard` === "gRPC" - **URL:** `GetAgentCard` - **HTTP Method:** `POST` - **Payload:** None - **Response:** `AgentCard` === "REST" - **URL:** `/v1/card` - **HTTP Method:** `GET` - **Payload:** None - **Response:** `AgentCard`
Clients retrieving this authenticated card **SHOULD** replace their cached public Agent Card with the content received from this endpoint for the duration of their authenticated session or until the card's version changes. #### 7.10.1. `AuthenticatedExtendedCardParams` Object This endpoint does not use JSON-RPC `params`. Any parameters would be included as HTTP query parameters if needed (though none are defined by the standard). #### 7.10.2. `AuthenticatedExtendedCardResponse` Object The successful response body is a JSON object conforming to the `AgentCard` interface. ```ts { .no-copy } --8<-- "types/src/types.ts:AuthenticatedExtendedCardResponse" ``` ## 8. Error Handling A2A uses standard [JSON-RPC 2.0 error codes and structure](https://www.jsonrpc.org/specification#error_object) for reporting errors. Errors are returned in the `error` member of the `JSONRPCErrorResponse` object. See [`JSONRPCError` Object definition](#612-jsonrpcerror-object). ### 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/pushNotificationConfig/set`) but the server agent does not support them (i.e., `AgentCard.capabilities.pushNotifications` is `false`). | | `-32004` | `UnsupportedOperationError` | 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 [Media Type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types) 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` | `InvalidAgentResponseError` | Invalid agent response type | Agent generated an invalid response for the requested method | 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, context 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. Fetching Authenticated Extended Agent Card **Scenario:** A client discovers a public Agent Card indicating support for an authenticated extended card and wants to retrieve the full details. 1. **Client fetches the public Agent Card:** ```none GET https://example.com/.well-known/agent.json ``` _Server responds with the public Agent Card (like the example in Section 5.6), including `supportsAuthenticatedExtendedCard: true` (at the root level) and `securitySchemes`._ 2. **Client identifies required authentication from the public card.** 3. **Client obtains necessary credentials out-of-band (e.g., performs OAuth 2.0 flow with Google, resulting in an access token).** 4. **Client fetches the authenticated extended Agent Card:** ```none GET https://example.com/a2a/agent/authenticatedExtendedCard Authorization: Bearer ``` 5. **Server authenticates and authorizes the request.** 6. **Server responds with the full Agent Card:** ### 9.2. Basic Execution (Synchronous / Polling Style) **Scenario:** Client asks a simple question, and the agent responds quickly with a task 1. **Client sends a message using `message/send`:** ```json { "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": {} } } ``` 2. **Server processes the request, creates a task and responds (task completes quickly)** ```json { "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": {} } } ``` **Scenario:** Client asks a simple question, and the agent responds quickly without a task 1. **Client sends a message using `message/send`:** ```json { "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": {} } } ``` 2. **Server processes the request, responds quickly without a task** ```json { "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": {} } } ``` _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": "363422be-b0f9-4692-a24d-278670e7c7f1"}` until the task reaches a terminal state._ ### 9.3. Streaming Task Execution (SSE) **Scenario:** Client asks the agent to write a long paper describing an attached picture. 1. **Client sends a message and subscribes using `message/stream`:** ```json { "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": "" } } ], "messageId": "bbb7dee1-cf5c-4683-8a6f-4114529da5eb" }, "metadata": {} } } ``` 2. **Server responds with HTTP 200 OK, `Content-Type: text/event-stream`, and starts sending SSE events:** _Event 1: Task status update - working_ ```json 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": "" } } ], "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": [ {"kind":"text", "text": "
"} ] }, "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": [ {"kind":"text", "text": "
"} ], }, "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": [ {"kind":"text", "text": "
"} ] }, "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" } } ``` _(Server closes the SSE connection after the `final:true` event)._ ### 9.4. Multi-Turn Interaction (Input Required) **Scenario:** Client wants to book a flight, and the agent needs more information. 1. **Client sends a message using `message/send`:** ```json { "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" } } ``` 2. **Server responds, task state is `input-required`:** ```json { "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" } } ``` 3. **Client `message/send` (providing the requested input, using the _same_ task ID):** ```json { "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 } } } ``` 4. **Server processes the new input and responds (e.g., task completed or more input needed):** ```json { "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. 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 `message/send` with `pushNotification` config:** ```json { "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. } } } } } ``` 2. **Server acknowledges the task (e.g., status `submitted` or `working`):** ```json { "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 ... } } ``` 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 ` (if server authenticates to webhook) - `Content-Type: application/json` - `X-A2A-Notification-Token: secure-client-token-for-task-aaa` - **HTTP Body (Task object is sent as JSON payload):** ```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 ... } ``` 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). ### 9.6. File Exchange (Upload and Download) **Scenario:** Client sends an image for analysis, and the agent returns a modified image. 1. **Client `message/send` with a `FilePart` (uploading image bytes):** ```json { "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" } } } ``` 2. **Server processes the image and responds with a `FilePart` in an artifact (e.g., providing a URI to the modified image):** ```json { "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. Structured Data Exchange (Requesting and Providing JSON) **Scenario:** Client asks for a list of open support tickets in a specific JSON format. 1. **Client `message/send`, `Part.metadata` hints at desired output schema/Media Type:** _(Note: A2A doesn't formally standardize schema negotiation in v0.2.0, but `metadata` can be used for such hints by convention between client/server)._ ```json { "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": {} } } ``` 2. **Server responds with structured JSON data:** ```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" } } ``` 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)](https://modelcontextprotocol.io/):** 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](./topics/a2a-and-mcp.md). ### 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](./topics/streaming-and-async.md#security-considerations-for-push-notifications) 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](./topics/enterprise-ready.md).