# Streaming & Asynchronous Operations in A2A

The Agent2Agent (A2A) protocol is designed to handle tasks that may not complete immediately. Many AI-driven operations can be long-running, involve multiple steps, produce incremental results, or require human intervention. A2A provides robust mechanisms for managing such asynchronous interactions, ensuring that clients can receive updates effectively, whether they remain continuously connected or operate in a more disconnected fashion.

## 1. Streaming with Server-Sent Events (SSE)

For tasks that produce incremental results (like generating a long document or streaming media) or provide ongoing status updates, A2A supports real-time communication using Server-Sent Events (SSE). This is ideal when the client can maintain an active HTTP connection with the A2A Server.

**Key Characteristics:**

- **Initiation:** The client uses the `tasks/sendSubscribe` RPC method to send an initial message (e.g., a prompt or command) and simultaneously subscribe to updates for that task.
- **Server Capability:** The A2A Server must indicate its support for streaming by setting `capabilities.streaming: true` in its [Agent Card](../specification.md#552-agentcapabilities-object).
- **Server Response (Connection):** If the subscription is successful, the server responds with an HTTP `200 OK` status and a `Content-Type: text/event-stream`. This HTTP connection remains open for the server to push events.
- **Event Structure:** The server sends events over this stream. Each event's `data` field contains a JSON-RPC 2.0 Response object, specifically a [`SendTaskStreamingResponse`](../specification.md#721-sendtaskstreamingresponse-object). The `id` in this JSON-RPC response matches the `id` from the client's original `tasks/sendSubscribe` request.
- **Event Types (within `SendTaskStreamingResponse.result`):**
    - [`TaskStatusUpdateEvent`](../specification.md#722-taskstatusupdateevent-object): Communicates changes in the task's lifecycle state (e.g., from `working` to `input-required` or `completed`). It can also provide intermediate messages from the agent (e.g., "I'm currently analyzing the data...").
    - [`TaskArtifactUpdateEvent`](../specification.md#723-taskartifactupdateevent-object): Delivers new or updated [Artifacts](../specification.md#67-artifact-object) generated by the task. This is used to stream large files or data structures in chunks. The `Artifact` object itself contains fields like `index`, `append`, and `lastChunk` to help the client reassemble the complete artifact.
- **Stream Termination:** The server signals the end of updates for a particular interaction cycle (i.e., for the current `tasks/sendSubscribe` request) by setting `final: true` in a `TaskStatusUpdateEvent`. This typically occurs when the task reaches a terminal state (`completed`, `failed`, `canceled`) or an `input-required` state (where the server expects further input from the client). After sending a `final: true` event, the server usually closes the SSE connection for that specific request.
- **Resubscription:** If a client's SSE connection breaks prematurely while a task is still active (and the server hasn't sent a `final: true` event for that phase), the client can attempt to reconnect to the stream using the `tasks/resubscribe` RPC method. The server's behavior regarding missed events during the disconnection period (e.g., whether it backfills or only sends new updates) is implementation-dependent.

**When to Use Streaming:**

- Real-time progress monitoring of long-running tasks.
- Receiving large results (artifacts) incrementally, allowing processing to begin before the entire result is available.
- Interactive, conversational exchanges where immediate feedback or partial responses are beneficial.
- Applications requiring low-latency updates from the agent.

Refer to the Protocol Specification for detailed structures:

- [`tasks/sendSubscribe`](../specification.md#72-taskssendsubscribe)
- [`tasks/resubscribe`](../specification.md#77-tasksresubscribe)

## 2. Push Notifications for Disconnected Scenarios

For very long-running tasks (e.g., lasting minutes, hours, or even days) or when clients cannot or prefer not to maintain persistent connections (like mobile clients or serverless functions), A2A supports asynchronous updates via push notifications. This mechanism allows the A2A Server to actively notify a client-provided webhook when a significant task update occurs.

**Key Characteristics:**

- **Server Capability:** The A2A Server must indicate its support for this feature by setting `capabilities.pushNotifications: true` in its [Agent Card](../specification.md#552-agentcapabilities-object).
- **Configuration:** The client provides a [`PushNotificationConfig`](../specification.md#68-pushnotificationconfig-object) to the server. This configuration can be supplied:
    - Within the initial `tasks/send` or `tasks/sendSubscribe` request (via the optional `pushNotification` parameter in `TaskSendParams`).
    - Separately, using the `tasks/pushNotification/set` RPC method for an existing task.
    The `PushNotificationConfig` includes:
    - `url`: The absolute HTTPS webhook URL where the A2A Server should send (POST) task update notifications.
    - `token` (optional): A client-generated opaque string (e.g., a secret or task-specific identifier). The server SHOULD include this token in the notification request (e.g., in a custom header like `X-A2A-Notification-Token`) for validation by the client's webhook receiver.
    - `authentication` (optional): An [`AuthenticationInfo`](../specification.md#69-authenticationinfo-object-for-push-notifications) object specifying how the A2A Server should authenticate itself *to the client's webhook URL*. The client (receiver of the webhook) defines these authentication requirements.
- **Notification Trigger:** The A2A Server decides when to send a push notification. Typically, this happens when a task reaches a significant state change, such as transitioning to a terminal state (`completed`, `failed`, `canceled`) or an `input-required` state, particularly after its associated message and artifacts are fully generated and stable.
- **Notification Payload:** The A2A protocol itself does **not** strictly define the HTTP body payload of the push notification sent by the server to the client's webhook. However, the notification **SHOULD** contain sufficient information for the client to identify the `taskId` and understand the general nature of the update (e.g., the new `TaskState`). Servers might send a minimal payload (just `taskId` and new state) or a more comprehensive one (e.g., a summary or even the full [`Task`](../specification.md#61-task-object) object).
- **Client Action:** Upon receiving a push notification (and successfully verifying its authenticity and relevance), the client typically uses the `tasks/get` RPC method with the `taskId` from the notification to retrieve the complete, updated `Task` object, including any new artifacts or detailed messages.

**The Push Notification Service (Client-Side Webhook Infrastructure):**

- The target `url` specified in `PushNotificationConfig.url` points to a **Push Notification Service**. This service is a component on the client's side (or a service the client subscribes to) responsible for receiving the HTTP POST notification from the A2A Server.
- Its responsibilities include:
    - Authenticating the incoming notification (i.e., verifying it's from the legitimate A2A Server).
    - Validating the notification's relevance (e.g., checking the `token`).
    - Relaying the notification or its content to the appropriate client application logic or system.
- In simple scenarios (e.g., local development), the client application itself might directly expose the webhook endpoint.
- In enterprise or production settings, this is often a robust, secure service that handles incoming webhooks, authenticates callers, and routes messages (e.g., to a message queue, an internal API, a mobile push notification gateway, or another event-driven system).

### Security Considerations for Push Notifications

Security is paramount for push notifications due to their asynchronous and server-initiated outbound nature. Both the A2A Server (sending the notification) and the client's webhook receiver have responsibilities.

#### A2A Server Security (When Sending Notifications to Client Webhook)

1. **Webhook URL Validation:**
    - Servers **SHOULD NOT** blindly trust and send POST requests to any `url` provided by a client in `PushNotificationConfig`. Malicious clients could provide URLs pointing to internal services or unrelated third-party systems to cause harm (Server-Side Request Forgery - SSRF attacks) or act as Distributed Denial of Service (DDoS) amplifiers.
    - **Mitigation Strategies:**
        - **Allowlisting:** Maintain an allowlist of trusted domains or IP ranges for webhook URLs, if feasible.
        - **Ownership Verification / Challenge-Response:** Before sending actual notifications, the server can (and SHOULD ideally) perform a verification step. For example, it could issue an HTTP `GET` or `OPTIONS` request to the proposed webhook URL with a unique `validationToken` (as a query parameter or header). The webhook service must respond appropriately (e.g., echo back the token or confirm readiness) to prove ownership and reachability. The [A2A Python samples](https://github.com/google/A2A/blob/main/samples/python/agents/langgraph/task_manager.py) demonstrate a simple validation token check mechanism.
        - **Network Controls:** Use egress firewalls or network policies to restrict where the A2A Server can send outbound HTTP requests.

2. **Authenticating to the Client's Webhook:**
    - The A2A Server **MUST** authenticate itself to the client's webhook URL according to the scheme(s) specified in `PushNotificationConfig.authentication`.
    - Common authentication schemes for server-to-server webhooks include:
        - **Bearer Tokens (OAuth 2.0):** The A2A Server obtains an access token (e.g., using the OAuth 2.0 client credentials grant flow if the webhook provider supports it) for an audience/scope representing the client's webhook, and includes it in the `Authorization: Bearer <token>` header of the notification POST request.
        - **API Keys:** A pre-shared API key that the A2A Server includes in a specific HTTP header (e.g., `X-Api-Key`).
        - **HMAC Signatures:** The A2A Server signs the request payload (or parts of the request) with a shared secret key using HMAC, and includes the signature in a header (e.g., `X-Hub-Signature`). The webhook receiver then verifies this signature.
        - **Mutual TLS (mTLS):** If supported by the client's webhook infrastructure, the A2A Server can present a client TLS certificate.

#### Client Webhook Receiver Security (When Receiving Notifications from A2A Server)

1. **Authenticating the A2A Server:**
    - The webhook endpoint **MUST** rigorously verify the authenticity of incoming notification requests to ensure they originate from the legitimate A2A Server and not an imposter.
    - **Verify Signatures/Tokens:**
        - If using JWTs (e.g., as Bearer tokens), validate the JWT's signature against the A2A Server's trusted public keys (e.g., fetched from a JWKS endpoint provided by the A2A Server, if applicable). Also, validate claims like `iss` (issuer), `aud` (audience - should identify your webhook), `iat` (issued at), and `exp` (expiration time).
        - If using HMAC signatures, recalculate the signature on the received payload using the shared secret and compare it to the signature in the request header.
        - If using API keys, ensure the key is valid and known.
    - **Validate `PushNotificationConfig.token`:** If the client provided an opaque `token` in its `PushNotificationConfig` when setting up notifications for the task, the webhook should check that the incoming notification includes this exact token (e.g., in a custom header like `X-A2A-Notification-Token`). This helps ensure the notification is intended for this specific client context and task, adding a layer of authorization.

2. **Preventing Replay Attacks:**
    - **Timestamps:** Notifications should ideally include a timestamp (e.g., `iat` - issued at - claim in a JWT, or a custom timestamp header). The webhook should reject notifications that are too old (e.g., older than a few minutes) to prevent attackers from replaying old, captured notifications. The timestamp should be part of the signed payload (if using signatures) to ensure its integrity.
    - **Nonces/Unique IDs:** For critical notifications, consider using unique, single-use identifiers (nonces or event IDs) for each notification. The webhook should track received IDs (for a reasonable window) to prevent processing duplicate notifications. A JWT's `jti` (JWT ID) claim can serve this purpose.

3. **Secure Key Management and Rotation:**
    - If using cryptographic keys (symmetric secrets for HMAC, or asymmetric key pairs for JWT signing/mTLS), implement secure key management practices, including regular key rotation.
    - For asymmetric keys where the A2A Server signs and the client webhook verifies, protocols like JWKS (JSON Web Key Set) allow the server to publish its public keys (including new ones during rotation) at a well-known endpoint. Client webhooks can then dynamically fetch the correct public key for signature verification, facilitating smoother key rotation.

##### Example Asymmetric Key Flow (JWT + JWKS)

1. Client sets `PushNotificationConfig` specifying `authentication.schemes: ["Bearer"]` and possibly an expected `issuer` or `audience` for the JWT.
2. A2A Server, when sending a notification:
    - Generates a JWT, signing it with its private key. The JWT includes claims like `iss` (issuer), `aud` (audience - the webhook), `iat` (issued at), `exp` (expires), `jti` (JWT ID), and `taskId`.
    - The JWT header (`alg` and `kid`) indicates the signing algorithm and key ID.
    - The A2A Server makes its public keys available via a JWKS endpoint (URL for this endpoint might be known to the webhook provider or discovered).
3. Client Webhook, upon receiving the notification:
    - Extracts the JWT from the `Authorization` header.
    - Inspects the `kid` in the JWT header.
    - Fetches the corresponding public key from the A2A Server's JWKS endpoint (caching keys is recommended).
    - Verifies the JWT signature using the public key.
    - Validates claims (`iss`, `aud`, `iat`, `exp`, `jti`).
    - Checks the `PushNotificationConfig.token` if provided.

This comprehensive, layered approach to security for push notifications ensures that messages are authentic, integral, and timely, protecting both the sending A2A Server and the receiving client webhook infrastructure.
