Skip to content

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.
  • 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. The id in this JSON-RPC response matches the id from the client's original tasks/sendSubscribe request.
  • Event Types (within SendTaskStreamingResponse.result):
    • TaskStatusUpdateEvent: 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: Delivers new or updated Artifacts 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:

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.
  • Configuration: The client provides a PushNotificationConfig 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 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 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 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.