Wiki · Research
A2A — opaque-agent discovery, task ownership, and artifact delivery
Shelf
Research

A2A — opaque-agent discovery, task ownership, and artifact delivery

This extraction answers WI-026’s bounded question: what survives when one independently operated, opaque agent discovers another, authenticates, submits work, receives progress/artifacts, and reaches a terminal task state. It follows the protocol track template. It is not an SDK audit, production identity-provider audit, or comparison with MCP; WI-028 owns cross-protocol synthesis.

Snapshot and normative authority

Measured — The source is the public a2aproject/A2A repository at commit 1eb4aa03b07589d3a00ce7deab0dde679120ed30, read 2026-08-15. git describe --tags --always reports v1.0.1-43-g1eb4aa0; the pinned checkout is therefore a post-tag source snapshot. The versioned specification document identifies 1.0.0 as the latest released protocol version at this read boundary; patch/repository tag context is not substituted for the protocol version.

Measured — The bounded checkout measurement was:

git -C C:\Temp\rungs-follow-on-20260815\a2a ls-files
  132 tracked files
   45 Markdown files
    1 Protocol Buffer source
    5 JSON files

The counts describe tracked paths at the pin. They do not measure SDK implementations, server availability, production identity, task latency, or interoperability with non-pinned agents.

Normative — specification/a2a.proto is the canonical protocol data model and request/response source. The specification says generated JSON is a non-normative build artifact and SDKs/schemas must be regenerated from the proto. The versioned specification defines abstract operations, task semantics, versioning, auth responsibilities, and the JSON-RPC, gRPC, and HTTP+JSON bindings. The repository’s LICENSE is Apache-2.0.

Documented — No SDK, TCK, sample agent, or remote endpoint was pinned or executed. The specification/json/ README explicitly says its generated JSON is non-normative and transient; the proto and specification are the read boundary. Claims about “enterprise ready” are treated as positioning unless backed by the normative requirements below.

Agent Card discovery and interface selection

Normative — An A2A server must make an Agent Card available. The card describes name, description, provider, ordered supported interfaces, protocol version, capabilities, skills, default input/output modes, security schemes/requirements, optional tenant routing, and optional signatures. Clients may discover it through the well-known URI /.well-known/agent-card.json, a registry, or direct configuration. The first supported interface is preferred; its URL, binding, protocol version, and tenant value are used for subsequent requests (Agent Card requirements, proto AgentCard).

Normative — The card’s optional capabilities gate streaming, push notifications, extended authenticated cards, and extensions. A client should inspect the card before using those features; the server must return a capability error if a requested operation was not declared. An extension marked required is a compatibility boundary: a client that does not declare support must be rejected rather than silently ignoring it.

Normative — Cards may be signed with JWS. If signing is used, the content must be canonicalized with JCS and clients verifying signatures must reconstruct field presence correctly; clients should verify at least one signature before trusting a card. Signing is optional, so an unsigned card is a discovery description, not cryptographic proof of provider identity (card signing).

Normative — A2A protocol versions are negotiated as Major.Minor (for example, 1.0); patch versions do not affect compatibility and must not be used for negotiation. Clients send A2A-Version on each request, and servers process the requested major/minor or return VersionNotSupportedError. The source says an empty value is interpreted as 0.3; a client that requires newer features should request them explicitly rather than silently falling back (versioning).

One task lifecycle through the JSON-RPC binding

Normative — The JSON-RPC binding uses JSON-RPC 2.0 over HTTP(S), PascalCase A2A methods, and SSE for streaming. The lifecycle below is a single bounded interaction; the remote agent’s internal memory, tools, prompts, and planning remain opaque.

fetch Agent Card
  -> choose supported interface + declared auth + A2A-Version
  -> SendMessage(Message)
  -> direct Message OR Task(submitted/working)
  -> poll GetTask, SubscribeToTask, or receive push updates
  -> status/artifact updates, optional input/auth interruption
  -> completed | failed | canceled | rejected

Normative — SendMessage may return a direct Message for a simple interaction or a Task for asynchronous work. With return_immediately=false/unset, the operation waits for a terminal state or interrupted INPUT_REQUIRED/AUTH_REQUIRED state; with return_immediately=true, it returns after task creation and the client must poll, subscribe, or use push notifications. A task is immutable after COMPLETED, FAILED, CANCELED, or REJECTED; a refinement starts a new task within the same context.

Implemented in the normative model — The proto names stable task identity (id), conversational grouping (context_id), current TaskStatus, artifacts, optional history, and metadata. States are SUBMITTED, WORKING, COMPLETED, FAILED, CANCELED, INPUT_REQUIRED, REJECTED, and AUTH_REQUIRED. The server creates a new task id; clients treat server-generated context ids as opaque (Task and states).

Normative — SendStreamingMessage begins with either one Message (then closes) or a Task followed by TaskStatusUpdateEvent and TaskArtifactUpdateEvent objects. The stream must close at a terminal state. Events must be delivered in generation order; multiple active streams receive the same ordered events, but a stream disconnect does not change task lifecycle.

Normative — GetTask retrieves current status, artifacts, and bounded history; ListTasks uses cursor pagination, returns only tasks visible to the authenticated client, and must apply authorization scoping; CancelTask attempts cancellation and returns updated state, but success is not guaranteed if work already completed or cannot be canceled. SubscribeToTask begins with the current Task to avoid a polling/subscription race and ends at a terminal state.

Artifacts, context, and continuation

Normative — Messages are communication turns; Artifacts are task outputs. A task artifact has a unique id within the task, name/description, one or more parts (text, raw bytes, URL, or structured data), and optional metadata/extensions. The specification recommends returning outputs as artifacts rather than status messages. A TaskArtifactUpdateEvent can append chunks to an existing artifact and mark the final chunk (artifact model).

Normative — contextId groups related tasks and messages. A client may continue a specific task with taskId, start another task in an existing context with contextId, and reference prior work with referenceTaskIds. Mismatched contextId/taskId is rejected; if only task id is supplied, the agent infers the context. Context expiration and internal history policy are implementation choices that should be documented.

Strongest delivery limitation — Task history is not a complete transcript guarantee. Agents may omit transient or pre-task messages, clients may miss streamed status updates after disconnect, and clients must not treat messages as reliable delivery for critical information. A client that needs durable output should retrieve the terminal Task/artifacts or use a negotiated persistence mechanism; the protocol does not make an external artifact store transactional.

Progress, push, retries, and duplicate delivery

Normative — Push notification configuration registers a webhook URL, task id, optional token, and authentication info. The agent POSTs StreamResponse payloads for status/artifact updates until task completion or explicit deletion. Webhook delivery uses plain HTTP regardless of the selected agent binding. Clients should process notifications idempotently and verify their source; agents may retry with exponential backoff. Duplicate deliveries are therefore possible and exactly-once delivery is not established (push notifications).

Normative — Get/List/extended-card operations are naturally idempotent. Send Message may be idempotent when an agent uses the client-created messageId to detect duplicates. Cancel Task is idempotent, although a duplicate may return TaskNotFoundError if the task was purged. The protocol does not define a universal idempotency key, retry budget, deduplication store, or compensation for an already-applied external side effect.

Authentication, authorization, and trust boundaries

BoundaryWhat A2A specifiesWhat remains outside the protocol
Agent CardDeclares security schemes, scopes, interfaces, and optional signatureAuthenticity unless transport trust or a verified signature is used
ClientDiscovers requirements, obtains credentials out of band, sends them on each request, and should verify TLS/card identityCredential issuance, user identity proofing, local secret handling
ServerMust authenticate every request, authorize by identity/policy, scope task visibility, and avoid leaking unauthorized-resource existenceExact policy, tenant model, downstream permissions, revocation semantics
TaskCan enter AUTH_REQUIRED and explain required authorizationCredential scope, representation, validity, revocation, and what operation it authorizes
Artifact/messageCarries content and metadata across the boundaryWhether content is truthful, safe, non-sensitive, or free of prompt/data injection

Normative — Production HTTP deployments must use HTTPS (gRPC uses TLS); clients should verify the server certificate. Credentials are transmitted through binding-appropriate headers/metadata, not as an A2A payload identity field. The server must reject invalid/missing credentials and must not reveal whether an unauthorized task exists. Authorization is server policy and may consider skills, actions, data rules, and scopes (auth and authorization).

Normative — AUTH_REQUIRED is a task state, not an authorization grant. The agent must explain what is needed, and the client may negotiate, obtain, or delegate credentials. The source explicitly says the protocol does not define the authorization decision’s scope, validity, or revocation and that an agent must not assume the state transition authorizes a particular operation or future messages. This is a strong boundary against treating a handoff marker as consent.

Normative — The media-type security section requires schema validation, sanitization of user-provided content, file-reference validation against SSRF, auth enforcement, and protection of sensitive history/artifacts. These are implementation obligations; they do not prove that an arbitrary remote agent has implemented them. Prompt/data injection remains possible because the protocol intentionally carries exchanged content without exposing internal reasoning or tools.

Compatibility and failure semantics

Normative — Capability mismatches have explicit errors: unsupported streaming/push/extended-card operations, required extension support, unsupported content types, invalid agent responses, and unsupported versions. Generic failures separate authentication, authorization, validation, resource not-found, and system/unavailability categories. Bindings must preserve error code/message/details semantics; JSON-RPC maps details to error.data and A2A-specific codes occupy a reserved range.

Normative — Retry guidance is intentionally partial. Servers may include retry hints for temporary failures and should log errors; clients must combine protocol idempotency rules with their own retry policy. A streaming connection can be lost while the task continues, and push delivery can duplicate or fail. The durable recovery primitive is GetTask/task identity, not an exactly-once stream.

Not established — The pinned source contains JSON-RPC, gRPC, and HTTP+JSON binding descriptions, but no executable server/TCK was used here to establish cross-binding equivalence. The proto says bindings must be functionally equivalent; this extraction does not verify an SDK or remote endpoint.

Candidate pattern consequences (deferred to WI-028)

CandidateEvidenceProvisional disposition
handoffNormative — Agent Card discovery selects a remote interface; task/context ids cross the boundary without sharing internal state.Candidate; distinguish ownership transfer from state transfer.
neighbourNormative — Opaque agents collaborate through Messages, Tasks, Artifacts, and declared capabilities.Candidate; compare with in-process sub-agent evidence only after boundary alignment.
explicit-outputNormative — Artifacts are the task output unit and may stream/append chunks independently of Messages.Candidate; include delivery gaps and artifact-store policy.
confirmation-gateNormative — AUTH_REQUIRED delegates an authorization request to the client but does not define the credential or grant.Candidate; never equate the state with authenticated approval.
audit-trailNormative — Task ids, status timestamps, artifacts, and optional history support traceability; history/stream delivery is incomplete.Candidate with an explicit evidence-retention boundary.
protocol-escape-hatchNormative — JSON-RPC/gRPC/HTTP bindings carry one abstract task model across process/network boundaries.Candidate; reconcile with MCP only in WI-028.

No catalogue, module, or CLI file changed. WI-024 owns ADK’s internal adapter/runtime evidence, WI-025 owns MCP, and WI-028 owns cross-protocol reconciliation.