Streaming and Asynchronous Operations

Streaming and Asynchronous Operations

The A2A protocol is explicitly designed for tasks that may not complete immediately. Many AI-driven operations are long-running, involve multiple steps, produce incremental results, or need human intervention. A2A provides mechanisms to manage such asynchronous interactions so that clients receive updates effectively, whether they stay connected or operate in a more disconnected fashion.

Streaming with Server-Sent Events (SSE)

For tasks that produce incremental results (such as generating a long document or streaming media) or provide ongoing status updates, A2A supports real-time communication over Server-Sent Events (SSE). This suits clients that can maintain an active HTTP connection with the A2A server.

  • Server capability: The A2A server must declare streaming support by setting capabilities.streaming: true in its Agent Card.
  • Initiating a stream: The client calls SendStreamingMessage to send an initial message (a prompt or command, for example) and subscribe to updates for that task at the same time.
  • Server response and connection: If the subscription succeeds, the server responds with HTTP 200 and Content-Type: text/event-stream. The connection stays open so the server can push events to the client.
  • Event structure and types: Each event carries a StreamResponse whose payload is one of:
    • task (Task): a snapshot of the task’s current state;
    • message (Message): a message from the agent;
    • statusUpdate (TaskStatusUpdateEvent): a change in the task’s lifecycle state (for example from working to input-required or completed), which can also carry intermediate agent messages;
    • artifactUpdate (TaskArtifactUpdateEvent): new or updated artifacts produced by the task, used to stream large files or data structures in chunks, with fields such as append and lastChunk to help reassemble them.
  • Stream termination: When a task reaches a terminal or interrupted state (such as TASK_STATE_COMPLETED, TASK_STATE_FAILED, TASK_STATE_CANCELED, TASK_STATE_REJECTED, or TASK_STATE_INPUT_REQUIRED), the server closes the stream and sends no further updates.
  • Resubscription: If the SSE connection breaks while the task is still active, the client can reconnect to the stream with SubscribeToTask.

How events are framed depends on the protocol binding:

BindingStreaming mechanismContent of each event
JSON-RPC 2.0SSE (text/event-stream)The data field is a JSON-RPC response object whose result is a StreamResponse
HTTP+JSON/RESTSSE (text/event-stream)The data field is a StreamResponse JSON object directly
gRPCServer-streaming RPCEach stream message is a StreamResponse

An SSE response with the HTTP+JSON binding looks like this:

HTTP/1.1 200 OK
Content-Type: text/event-stream

data: {"task": {"id": "task-uuid", "contextId": "context-uuid", "status": {"state": "TASK_STATE_WORKING"}}}

data: {"artifactUpdate": {"taskId": "task-uuid", "contextId": "context-uuid", "artifact": {"parts": [{"text": "# Climate Change Report\n\n"}]}}}

data: {"statusUpdate": {"taskId": "task-uuid", "contextId": "context-uuid", "status": {"state": "TASK_STATE_COMPLETED"}}}

When to use streaming

  • Real-time progress monitoring of long-running tasks.
  • Receiving large results (artifacts) incrementally.
  • Interactive, conversational exchanges where immediate feedback or partial responses help.
  • Applications that need low-latency updates from the agent.

Push notifications for disconnected scenarios

For very long-running tasks (minutes, hours, even days), or when clients cannot or prefer not to hold a persistent connection (mobile clients, serverless functions), A2A supports asynchronous updates through push notifications: the A2A server actively notifies a client-provided webhook when a significant task update occurs.

  • Server capability: The A2A server must declare support by setting capabilities.pushNotifications: true in its Agent Card.
  • Configuration: The client gives the server a TaskPushNotificationConfig, either in the initial SendMessage / SendStreamingMessage request or separately with CreateTaskPushNotificationConfig for an existing task. It includes a url (the HTTPS webhook address), an optional token (for client-side validation), and optional authentication details (used by the A2A server to authenticate to the webhook, with scheme and credentials).
  • Trigger: The A2A server decides when to send a notification, typically on a significant state change (a terminal state, input-required, or auth-required).
  • Payload: The HTTP body is a StreamResponse object, matching the format used by streaming operations, and contains one of task, message, statusUpdate, or artifactUpdate.
  • Client action: After receiving a notification and verifying its authenticity, the client typically calls GetTask with the taskId from the notification to retrieve the complete, updated Task, including any new artifacts.

When to use push notifications

  • Very long-running tasks that can take minutes, hours, or days.
  • Clients that cannot or prefer not to maintain persistent connections, such as mobile apps or serverless functions.
  • Scenarios where clients need only significant state-change notifications rather than continuous updates.

Client-side push notification service

The url in TaskPushNotificationConfig points to a client-side push notification service. It receives the HTTP POST from the A2A server, authenticates the incoming notification, validates its relevance, and relays it to the appropriate client application logic.

Security considerations for push notifications

Because push notifications are asynchronous and initiated outbound by the server, security is paramount. Both the A2A server (sender) and the client’s webhook receiver carry critical responsibilities.

A2A server (when sending notifications to the client webhook)

  • Webhook URL validation: Servers should not blindly trust and send POST requests to any URL a client provides. Malicious clients could supply URLs pointing to internal services or unrelated third-party systems, leading to Server-Side Request Forgery (SSRF) or acting as DDoS amplifiers. Mitigations include allowlisting trusted domains, ownership verification (for example challenge-response), and network controls (such as egress firewalls).
  • Authenticating to the client’s webhook: The A2A server must authenticate itself to the webhook URL using the scheme specified in TaskPushNotificationConfig.authentication. Common schemes include Bearer tokens (OAuth 2.0), API keys, HMAC signatures, and mutual TLS (mTLS).

Client webhook (when receiving notifications from the A2A server)

  • Authenticating the A2A server: The webhook must rigorously verify that notification requests come from the legitimate A2A server and not an imposter. Methods include verifying signatures or tokens (for example, JWT signatures against the server’s trusted public keys, HMAC signatures, or API key validation) and validating TaskPushNotificationConfig.token when provided.
  • Preventing replay attacks: Notifications should include a timestamp, and the webhook should reject notifications that are too old. For critical notifications, consider unique single-use identifiers (such as the JWT jti claim or event IDs) to avoid processing duplicates.
  • Secure key management and rotation: Apply secure key management, including regular rotation of cryptographic keys. Protocols such as JWKS (JSON Web Key Set) make rotating asymmetric keys easier.

Example asymmetric key flow (JWT + JWKS)

  1. The client creates a TaskPushNotificationConfig with authentication.scheme: "Bearer", and possibly an expected issuer or audience for the JWT.
  2. When sending a notification, the A2A server signs a JWT with its private key, including claims such as iss, aud, iat, exp, jti, and taskId. The JWT header names the signing algorithm and key ID (kid), and the server publishes its public keys through a JWKS endpoint.
  3. On receiving the notification, the client webhook extracts the JWT from the Authorization header, reads the kid from the JWT header, fetches the matching public key from the server’s JWKS endpoint (caching keys is recommended), verifies the signature, validates the claims (iss, aud, iat, exp, jti), and checks TaskPushNotificationConfig.token if provided.

This layered approach helps ensure that push notifications are authentic, intact, and timely, protecting both the sending A2A server and the receiving client’s webhook infrastructure.

Further reading

Source: Official A2A documentation: Streaming & Asynchronous Operations