« Phase 03 · Warmup · Track Overview
Core Contributor Notes — How the Real Protocols Work
Table of Contents
- 1. A2A's shape on the wire
- 2. Agent Card discovery in practice
- 3. Streaming and resumption
- 4. Push notifications, properly authenticated
- 5. ACP's differences that matter
- 6. The hyperscaler fabrics
- 7. Sharp edges
- 8. What the miniature simplifies
- 9. References
1. A2A's shape on the wire
A2A is JSON-RPC 2.0 over HTTP by default, with gRPC and REST bindings defined as alternatives. The core methods map one-to-one onto the lab:
| Method | Lab equivalent |
|---|---|
message/send | A2AServer.message_send |
message/stream | A2AServer.message_stream (SSE in the real thing) |
tasks/get | tasks_get |
tasks/cancel | tasks_cancel |
tasks/pushNotificationConfig/set and /get | set_push_config |
tasks/resubscribe | (not in the lab) — reattach to a stream after disconnect |
tasks/resubscribe is the one worth knowing about even though the lab omits it: it exists because
SSE connections die, and a long-running task must be re-attachable without re-delegating. Its
existence tells you something about the design philosophy — the task, not the connection, is the
durable thing. Any implementation where losing the connection loses the work has misunderstood
the protocol.
The same design decision explains why Task carries history and artifacts: a client that
reconnects needs to catch up from the object, not from a replayed stream.
2. Agent Card discovery in practice
Cards are conventionally served at a well-known path (/.well-known/agent-card.json), which makes
discovery a plain HTTPS GET and lets an organization publish a card without any A2A-specific
infrastructure.
Three refinements the spec adds that the lab does not:
Authenticated extended cards. A public card may advertise a subset; an authenticated caller can fetch a fuller one. This is the spec's own acknowledgement of the Phase 02 principle — discovery is answered relative to a principal — and it is worth using rather than reimplementing.
Signatures. Cards may be signed (JWS), so a caller can verify the card came from the claimed issuer rather than from whoever answers that URL today. For a bank consuming external agents this should be mandatory, and it is the direct answer to the "hostile card is a persistent prompt injection" risk.
Transport and interface declarations. A card can advertise several endpoints with different bindings, so a caller picks the one it supports. Which means "does this agent support A2A?" is usually the wrong question; the right one is "which binding do we share?"
3. Streaming and resumption
Real streaming is Server-Sent Events, with two event types matching the lab's:
TaskStatusUpdateEvent and TaskArtifactUpdateEvent, terminated by a status update with
final: true.
Artifact streaming uses append and lastChunk, which the lab declares but does not exercise. The
semantics: an artifact may arrive in pieces; append: false replaces, append: true extends, and
lastChunk: true closes it. A client that ignores append and concatenates everything will
duplicate the first chunk of any artifact that was re-sent after a reconnect.
The practical infrastructure notes, which are the same ones that bite MCP's streamable HTTP:
- Buffering proxies break SSE. An API gateway that buffers responses turns a stream into a single delayed blob. Configure explicitly.
- Idle timeouts kill long tasks. A four-hour task will not hold a stream; that is what push notifications are for, and treating streaming as a substitute is a design error.
- Reconnection needs
Last-Event-IDsemantics plustasks/resubscribe, or a reconnecting client silently misses updates.
4. Push notifications, properly authenticated
The lab requires a token in the config and checks the host against an allow-list. Production adds the part that makes the callback trustworthy in the other direction:
The callee authenticates itself to the caller's webhook. The config declares an authentication scheme; the callee signs its callback (typically a JWT with the caller as audience), and the caller validates it. Without this, anyone who learns the webhook URL can drive the caller's view of a task's state.
So there are two independent authentication directions and both are needed:
| Direction | Purpose | Lab |
|---|---|---|
caller → callee (message/send) | prove who is delegating | CallerContext (a stand-in for a token) |
| callee → caller (the webhook) | prove the update is genuine | token presence only |
Plus the two hardening controls: allow-listed destination hosts, and egress control on the callee's network path. The spec is explicit that webhook URL validation is the implementer's responsibility — which is the polite way of saying this is where the SSRFs will be.
5. ACP's differences that matter
ACP is REST-shaped rather than JSON-RPC-shaped, and the differences are more than cosmetic:
| A2A | ACP | |
|---|---|---|
| Style | JSON-RPC (gRPC/REST bindings) | REST resources |
| Unit of work | Task | Run |
| Async | streaming + push | polling, callbacks, and streamed responses |
| Discovery | Agent Card at a well-known path | agent manifests / registry |
| Session | contextId groups tasks | session_id groups runs |
The REST shape has one genuine advantage worth acknowledging in a design discussion: it is
trivially inspectable by existing infrastructure. An API gateway, a WAF, a proxy and a logging
pipeline all understand POST /runs and GET /runs/{id} without any protocol awareness. For a
bank whose network controls are built around HTTP semantics, that is not nothing.
The lab's position — internal model, adapters at the edge — is what lets you take that advantage without betting on either protocol. If ACP's REST shape suits your ingress and A2A suits your counterparties, you can speak both, and the kernel never knows.
6. The hyperscaler fabrics
Each fabric hosts agents and each has its own session, invocation and identity model. What matters for interop is not the API surface but what happens to identity at the boundary:
- Azure AI Foundry Agent Service — agents with threads and runs, integrated with Entra ID. Because Entra is likely your own identity provider, the identity story is the best of the three if the calling agent is invoked with a user context rather than a service principal. The failure mode is a fabric-hosted agent running as an app registration with broad permissions.
- AWS Bedrock Agents / AgentCore — action groups, session isolation (microVM per session in AgentCore Runtime), and Gateway/Identity components that front tools with policy. IAM is the authority, and IAM's model is workload-shaped; carrying an end-user identity through it requires deliberate design.
- Google ADK + Agent Engine — sessions with scoped state (
user:,app:,temp:), an event-driven runner, and increasingly first-class A2A support.
The recurring integration risk in all three, stated once: the fabric's natural credential is a
workload identity, and your action gateway needs a user. An adapter that papers over this is the
audit finding from
PRINCIPAL-DEEP-DIVE §6. The correct behaviour is a
rejected task with a reason, and a conversation with the fabric team about propagating user
context.
7. Sharp edges
A2A and ACP are young and moving. Versions change; protocolVersion exists for a reason. Pin
what you have tested, negotiate at connect, and log the negotiated version per counterparty.
"Agent" is not a defined term across ecosystems. One vendor's agent is another's tool, and a "multi-agent system" may be a prompt chain. When integrating, ask what the counterparty actually does — judgement or execution — because the answer determines whether A2A is the right protocol at all.
Task ids are not globally unique. They are unique within a server. Correlating across
organizations needs your contextId plus the counterparty's identity, or you will join two
unrelated task-1s.
Cancellation is advisory. tasks/cancel asks. A callee that has already moved money cannot
un-move it, and the protocol has no notion of compensation. Anything with side effects needs the
saga machinery from Phase 10; treating canceled as "it
did not happen" is a serious error.
Artifacts may carry data you cannot hold. Check classification on the return path. The spec has no opinion about this and your regulator does.
SSE through a corporate proxy will be buffered, chunk-rewritten, or closed. Test the real path early; a streaming implementation that works on a laptop and not in the DMZ is the default outcome.
8. What the miniature simplifies
| Miniature | Reality |
|---|---|
| Direct method calls | JSON-RPC over HTTPS, with SSE for streaming and gRPC/REST bindings |
CallerContext parameter | a validated token carrying identity, tenant and an act chain |
AgentCard object | an HTTPS resource at a well-known path, optionally signed, with authenticated extended variants |
| No resubscription | tasks/resubscribe and Last-Event-ID |
pushed list | authenticated webhook POSTs with retries, backoff and receiver idempotency |
append/lastChunk declared, unused | real chunked artifact streaming |
| One directory, in memory | a governed registry with card pinning, review and deprecation |
| Counter timestamps | wall-clock times, and clock-skew tolerance |
| No compensation | sagas for anything with side effects |
| Classification checked outbound | checked in both directions |
9. References
- A2A — a2a-protocol.org: specification, Agent Card schema, task
lifecycle,
message/stream,tasks/resubscribe, push-notification configuration and its security guidance. Linux Foundation project since 2025. - ACP — agentcommunicationprotocol.dev: runs, multipart messages, sync/async execution, agent manifests.
- MCP — modelcontextprotocol.io, for the contrast in scope.
- Server-Sent Events — the WHATWG HTML spec's EventSource section;
Last-Event-IDand reconnection semantics. - RFC 8693 (token exchange, the
actclaim) and RFC 9068 (JWT access tokens) — what makes the delegation chain unforgeable; Phase 08. - Azure AI Foundry Agent Service, AWS Bedrock Agents / AgentCore, Google ADK / Agent Engine — read each one's session and identity documentation first; that is where interop succeeds or fails.
- OWASP Top 10 for LLM Applications — Excessive Agency, which covers unbounded delegation explicitly.