Agent-to-agent protocols are becoming a distributed systems layer
A2A is turning agent collaboration from custom prompt glue into a networked software problem with discovery, task state, security, versioning, and failure semantics.

AI agents are starting to look less like features inside one application and more like services on a network.
One agent searches policy documents. Another checks inventory. Another negotiates delivery options. Another creates a purchase order. Another waits for a manager to approve a sensitive action. These agents may be written in different languages, built with different frameworks, deployed by different companies, and secured by different identity systems.
The intelligence is not the only hard part anymore.
Coordination is becoming the hard part.
That is why agent-to-agent protocols matter.
Google introduced the Agent2Agent protocol, usually called A2A, in April 2025. The project moved to the Linux Foundation in June of the same year. By 2026, the project had shipped a stable 1.0 specification, added official SDKs across several languages, gained support from major cloud and enterprise vendors, and introduced features such as multiple protocol bindings, version negotiation, multi-tenancy, and signed Agent Cards.
The Linux Foundation reported in April 2026 that more than 150 organizations supported the standard and that production deployments were appearing in financial services, insurance, supply chains, and IT operations. That figure is a project adoption signal, not proof that every enterprise has standardized on A2A. Still, it shows that the problem is no longer theoretical.
Agents need a common way to discover one another, describe capabilities, exchange messages, track long-running work, request more input, return artifacts, stream progress, authenticate, and handle version differences.
Those are distributed systems concerns.
A2A does not solve all of them. It does not make untrusted agents safe. It does not define business semantics for every industry. It does not remove the need for orchestration, authorization, observability, or durable state.
What it does is more important than it first appears.
It gives agent systems a common network contract.
That is why agent-to-agent protocols are becoming a distributed systems layer.
Agents are escaping the single application boundary
The first generation of agent products was usually monolithic.
One application contained one large prompt, one model, a list of tools, some memory, and a loop that called tools until it produced an answer.
This approach works for small products.
It becomes difficult when the agent gains dozens of responsibilities.
The agent monolith has familiar problems
A large agent can become the AI equivalent of a backend monolith with weak internal boundaries.
Every new capability adds:
More tools
More prompt instructions
More permissions
More failure modes
More context
More tests
More ways for one change to affect unrelated behavior
A support agent that reads tickets, checks billing, approves refunds, searches legal policy, updates the CRM, sends email, and produces reports is not one capability. It is a collection of specialized systems hiding behind one conversational surface.
Teams eventually want to decompose it.
This decomposition brings the same benefits that service decomposition can bring to ordinary software:
Smaller responsibility boundaries
Focused prompts and tools
Independent deployment
Smaller permission sets
Better evaluation
Clearer ownership
Reduced failure blast radius
It also brings the same costs.
Now the agents need to communicate.
Internal framework calls do not solve cross-boundary collaboration
Inside one framework, agent delegation may be easy. A parent agent can call a sub-agent as a function or invoke a framework-specific handoff API.
That works as long as every agent shares:
The same framework
The same runtime
The same deployment
The same trust boundary
The same data model
The same version lifecycle
Real organizations rarely stay that uniform.
A company may have:
A Python research agent built with one framework
A Java procurement agent built by another team
A .NET compliance agent owned by a regulated department
A vendor-hosted logistics agent
A partner's insurance agent behind a separate identity domain
A customer-facing coordinator built with a cloud platform
Custom integration can connect them, but every pair needs its own adapter.
This creates an integration graph that grows faster than the number of agents.
A shared protocol changes the shape.
The agents can still use different models, frameworks, languages, tools, and internal planning methods. They only need to agree on the external interaction contract.
That is the same reason HTTP, REST, gRPC, AMQP, and database protocols became important. The implementation can vary behind a stable boundary.
Agents are not always tools
It is tempting to expose every agent as a tool.
For simple capabilities, that is reasonable.
A currency converter, document lookup, or tax calculation can look like a function with structured input and output.
A remote agent may be different.
It may:
Negotiate the goal
Ask for missing information
Work for minutes or days
Stream partial progress
Produce several artifacts
Pause for authorization
Reject the task
Continue a multi-turn interaction
Hide its internal model, tools, and reasoning
A function-call abstraction becomes awkward when the remote system has its own state and agency.
This is the main distinction between A2A and the Model Context Protocol.
MCP standardizes how an agent connects to tools and data resources. A2A standardizes how independent agents collaborate on tasks.
The protocols are complementary.
MCP helps an agent use capabilities.
A2A helps agents partner on work.
The network boundary changes the threat model
A local sub-agent may inherit the application's process, credentials, and trust model.
A remote agent should not.
Once agents communicate across network and organizational boundaries, teams must think about:
Discovery
Identity
Authentication
Authorization
Version compatibility
Rate limits
Retries
Timeouts
Idempotency
Data classification
Tenant isolation
Audit trails
Observability
Contract testing
This is why A2A is best understood as infrastructure, not only AI tooling.
The model may decide what to ask.
The protocol decides how that request moves through a production system.
What A2A actually standardizes
A2A is designed for independent and potentially opaque agent systems.
Opaque does not mean unaccountable. It means one agent does not need access to another agent's prompt, model, private memory, chain of thought, or internal tools to collaborate with it.
The public contract is built from a small group of concepts.
Agent Cards provide capability discovery
An A2A server publishes an Agent Card.
The card is a machine-readable description of the agent's identity, endpoint, protocol versions, supported transports, capabilities, security requirements, media types, and skills.
The recommended public discovery path is:
https://agent.example.com/.well-known/agent-card.json
A simplified version 1.0 card might look like this:
{
"name": "Supplier Research Agent",
"description": "Researches approved suppliers and compares quotations",
"version": "2.1.0",
"supportedInterfaces": [
{
"url": "https://supplier-agent.example.com/a2a/v1",
"protocolBinding": "HTTP+JSON",
"protocolVersion": "1.0"
},
{
"url": "https://supplier-agent.example.com/a2a/grpc",
"protocolBinding": "GRPC",
"protocolVersion": "1.0"
}
],
"capabilities": {
"streaming": true,
"pushNotifications": true,
"extendedAgentCard": true
},
"securitySchemes": {
"companyOidc": {
"openIdConnectSecurityScheme": {
"openIdConnectUrl": "https://identity.example.com/.well-known/openid-configuration"
}
}
},
"securityRequirements": [
{
"companyOidc": ["supplier.read", "quotation.request"]
}
],
"defaultInputModes": ["text/plain", "application/json"],
"defaultOutputModes": ["text/plain", "application/json"],
"skills": [
{
"id": "compare-suppliers",
"name": "Compare approved suppliers",
"description": "Compares approved suppliers for a requested product",
"tags": ["procurement", "supplier", "quotation"],
"examples": [
"Compare approved laptop suppliers for 20 engineering laptops"
],
"inputModes": ["text/plain", "application/json"],
"outputModes": ["application/json"]
}
]
}
This plays a role similar to service metadata plus an API description.
A client can use the card to answer:
Is this the right agent?
Which skill appears relevant?
Which protocol binding can I use?
Does it support streaming?
Can it send push notifications?
Which media types can it accept?
Which authentication scheme is required?
Which protocol version does it implement?
The card is descriptive, not magical.
A skill description does not prove the agent is competent. A public endpoint does not prove it is trustworthy. Discovery still needs governance, registries, allowlists, reputation, contracts, and security policy.
Signed Agent Cards establish metadata integrity
A2A version 1.0 added signed Agent Cards as an important production feature.
The card can be canonicalized using the JSON Canonicalization Scheme and signed using JSON Web Signature. A client can then verify that the metadata was not modified and that it came from the claimed signing identity.
A signature solves only part of the problem.
It can help establish integrity and provenance.
It does not prove that the agent will behave correctly, that its skills are accurate, or that the signer should be trusted for the requested action.
Trust remains a policy decision.
Messages carry conversational input
A Message is one unit of communication between the A2A client and server.
Messages include:
A unique message ID
A role
One or more Parts
Optional task and context identifiers
Optional metadata and extension identifiers
Parts can contain:
Text
Structured JSON data
Raw file data
A file URL
{
"message": {
"messageId": "msg-21b7",
"role": "ROLE_USER",
"parts": [
{
"text": "Compare approved suppliers for 20 laptops"
},
{
"data": {
"minimumRamGb": 32,
"maximumUnitPriceUsd": 1800,
"deliveryCountry": "NP"
}
}
]
}
}
This is more flexible than plain chat text.
A coordinator can send natural language for intent and structured data for constraints. A specialist can return a written explanation plus structured output that another system can process.
Tasks represent long-running work The Task is the core unit of action in A2A.
A server can return a direct Message when it can answer immediately. When the interaction involves ongoing work, it returns a Task.
A Task includes:
A server-generated task ID
An optional context ID
Current status
Output artifacts
Optional message history
Metadata
The standard task states are:
| State | Meaning |
|---|---|
TASK_STATE_SUBMITTED |
The server accepted the task |
TASK_STATE_WORKING |
The agent is processing it |
TASK_STATE_INPUT_REQUIRED |
More user or client input is needed |
TASK_STATE_AUTH_REQUIRED |
Additional authorization is needed |
TASK_STATE_COMPLETED |
The task finished successfully |
TASK_STATE_FAILED |
The task ended with an error |
TASK_STATE_CANCELED |
The task was canceled |
TASK_STATE_REJECTED |
The agent refused or could not accept it |
This state model is one reason A2A feels like a distributed systems protocol rather than a prompt format.
It gives independent systems a shared lifecycle for work.
Context IDs support related interactions
A task is one piece of work.
A context can group several related tasks and messages.
For example, a procurement conversation might contain:
Research approved suppliers.
Request new quotations.
Compare delivery dates.
Prepare an approval package.
Each could be a separate task under the same context.
This distinction matters.
Trying to store an entire long-running interaction in one endless chat thread makes state management, retries, audit, and cancellation difficult. Separate tasks provide cleaner units of work while the context preserves continuity.
Artifacts represent outputs
Artifacts are outputs produced by a task.
They can include text, structured data, files, or references.
A supplier comparison task might return:
A JSON ranking
A PDF quotation summary
A spreadsheet
A written recommendation
{
"task": {
"id": "task-7a12",
"contextId": "ctx-procurement-51",
"status": {
"state": "TASK_STATE_COMPLETED"
},
"artifacts": [
{
"artifactId": "artifact-ranking",
"name": "Supplier ranking",
"parts": [
{
"data": {
"recommendedSupplier": "supplier-42",
"score": 91,
"currency": "USD"
}
}
]
}
]
}
}
The distinction between messages and artifacts is useful.
Messages are communication.
Artifacts are task outputs.
A2A supports synchronous and asynchronous interaction
Agent tasks do not all finish at the same speed.
A2A supports three broad update patterns.
Polling
The client periodically retrieves task state.
This is simple and works across restrictive network boundaries, but it creates latency and unnecessary requests.
Streaming
The client opens a stream and receives status or artifact updates in real time. HTTP-based systems can use Server-Sent Events.
This works well for interactive progress.
Push notifications
The client registers a webhook, and the server sends updates when task state changes.
This is useful for work that continues after the client disconnects.
Streaming should not automatically be treated as durable event delivery. The specification warns that clients may miss updates if a stream disconnects and reconnects. Critical state should be retrieved from the Task resource or a reliable application-level event system.
Version 1.0 separates semantics from protocol bindings
A2A version 1.0 defines a canonical data model and operations, then maps them to protocol bindings.
The standard bindings include:
JSON-RPC
HTTP plus JSON REST-style endpoints
gRPC
The official Python SDK supports all three for version 1.0 and also provides compatibility support for version 0.3.
This layered design is familiar from distributed systems standards.
The semantics of sending a message or retrieving a task should remain consistent even when the transport representation changes.
Version 1.0 also uses protocol version declarations in supported interfaces and an A2A-Version HTTP header. Unsupported versions can be rejected explicitly rather than failing through ambiguous payload errors.
Why this is a distributed systems layer
Calling A2A a distributed systems layer is an argument, not an official category in the specification.
The argument is that the protocol now standardizes several concerns that normally sit between independently deployed services.
Agent discovery resembles service discovery
Traditional service discovery answers:
Where is the service?
Which version is available?
Which protocol does it speak?
What capabilities does it expose?
Agent Cards answer similar questions for agents.
Discovery can happen through:
A well-known URI
A registry or catalog
Direct configuration
Public discovery is useful for open agents. Enterprise systems will usually need curated registries, private catalogs, and policy-controlled onboarding.
This will likely create infrastructure similar to API catalogs and service registries:
Ownership metadata
Environment metadata
Trust level
Data classification
Allowed tenants
Supported protocol versions
Rate limits
Evaluation scores
Incident history
Deprecation status
The protocol defines the card format and discovery patterns. Organizations still need the registry operating model.
Skills resemble service contracts, but remain softer
An Agent Skill describes a focused ability.
This looks similar to an API operation, but it is not equally precise.
An OpenAPI operation can define exact fields, schemas, status codes, and constraints. An agent skill often uses descriptions, examples, tags, and media types.
That flexibility is useful for open-ended tasks.
It also creates ambiguity.
Two agents may both advertise compare-suppliers but apply different assumptions, data sources, ranking methods, and confidence thresholds.
This means agent interoperability needs two layers:
Protocol interoperability
Semantic interoperability
A2A improves the first.
The second still requires shared schemas, domain vocabularies, extensions, policies, and testing.
This is the same lesson learned in enterprise integration. Shared JSON does not guarantee shared meaning.
Tasks resemble distributed job state
A task ID, status, context, artifact list, and update stream form a distributed job contract.
The client does not need to know:
Which model runs the task
Which tools the agent uses
How many internal steps exist
Which framework coordinates the work
Where memory is stored
The server exposes the external lifecycle.
That is similar to submitting a job to a remote compute service.
Opaque execution allows implementation freedom.
It also creates operational questions.
If the remote agent fails internally, the client sees only the task contract. Service-level expectations must therefore be explicit outside the protocol:
Maximum task duration
Retry behavior
Retention period
Artifact availability
Cancellation guarantees
Data deletion guarantees
Support and escalation
A2A introduces distributed failure semantics
Once a client and remote agent communicate across a network, every request can produce an ambiguous result.
The client may not know whether:
The request never reached the server
The server accepted it but the response was lost
The task was created twice
The stream disconnected after an artifact update
The webhook arrived twice
A cancellation arrived after completion
An authorization token expired during execution
These are ordinary distributed systems problems.
A production A2A implementation needs:
Stable message IDs
Idempotent request handling
Duplicate detection
Bounded retries
Task lookup after timeout
Webhook signature verification
Event ordering
Cancellation rules
Reconciliation

The protocol provides identifiers and task retrieval operations. The server still needs correct idempotency behavior.
Authentication is transport-level, authorization is application-level
A2A deliberately relies on established web security mechanisms.
Production HTTP communication must use HTTPS. gRPC uses TLS. Agent Cards can advertise security schemes such as OAuth 2.0, OpenID Connect, API keys, HTTP authentication, or mutual TLS.
Credentials are normally sent through HTTP headers or transport metadata, not inside the A2A message payload.
This separation is healthy.
The protocol should not invent a new identity system.
But authentication is only the beginning.
The server must still decide:
Can this client use the requested skill?
Can it access this tenant's data?
Can it request a purchase or only research one?
Can it send files?
Can it create tasks at this volume?
Can it use expensive models?
Can it trigger a human approval?
Authorization must be evaluated at the skill, action, data, tenant, and sometimes artifact level.
Multi-tenancy makes routing part of the protocol boundary
Version 1.0 added stronger multi-tenancy support.
A single endpoint can host multiple agents or tenants. Supported interfaces can carry an opaque tenant routing identifier that the client must repeat in requests.
This helps shared platforms expose many logical agents through one infrastructure layer.
It also raises familiar multi-tenant risks:
Cross-tenant task access
Incorrect cache keys
Shared rate limits
Artifact leakage
Incorrect registry visibility
Misrouted push notifications
Mixed audit records
Treat tenant routing data as security-sensitive context, even when the field itself is opaque.
Extensions resemble protocol evolution mechanisms
A2A extensions can add data, methods, requirements, and state transitions.
Agents advertise supported extensions in the Agent Card. Clients opt into them through binding-specific mechanisms such as the A2A-Extensions header.
This creates a path for domain-specific behavior without changing the core protocol for every use case.
Possible extension areas include:
Citations
Geographic context
Payments
Consent evidence
Industry-specific schemas
Data residency
Evaluation metadata
Policy decisions
The risk is fragmentation.
If every vendor creates incompatible extensions for the same concept, protocol interoperability survives while practical interoperability disappears.
Good extension governance will be as important as the core standard.
The hard problems move above the protocol
A common network protocol is valuable.
It does not make a multi-agent system reliable by itself.
Most difficult production problems remain above the wire format.
Discovery is not trust
An Agent Card tells you what an agent claims to be.
A signed Agent Card can tell you who signed that claim and whether the card was modified.
Neither tells you whether the agent is safe for the task.
Before delegating sensitive work, organizations may need to verify:
Provider identity
Contractual relationship
Security review
Data processing terms
Allowed regions
Model and data retention policy
Evaluation history
Incident response process
Skill-specific authorization
Financial limits
A useful trust architecture could look like this:
Trust should be task-specific.
An agent approved to search public documentation should not automatically be approved to submit payments.
Agent output is untrusted input
A remote agent response may contain:
Incorrect facts
Malicious instructions
Prompt injection
Unsafe URLs
Oversized files
Unexpected JSON
Sensitive data
Content designed to influence another model
Do not feed remote artifacts directly into a powerful local agent without validation.
The official sample repository warns developers to treat agents outside their control as potentially untrusted.
That should be the default assumption.
File exchange creates SSRF and data leakage risks
A Part can reference file content through a URL.
That is convenient and dangerous.
A malicious agent could return a URL pointing to:
Cloud metadata endpoints
Internal admin panels
Private network services
Huge files
Redirect chains
Malware
Time-limited URLs that later resolve differently
File retrieval services need:
URL allowlists or controlled fetch proxies
DNS and IP validation
Redirect limits
Size limits
Media-type validation
Malware scanning
Timeout limits
Private network blocking
Content hashing
Audit logs
Never let an LLM decide that an arbitrary URL is safe to fetch.
Identity delegation becomes complicated
An agent often acts on behalf of a user.
When Agent A delegates to Agent B, which identity should Agent B see?
Possible models include:
Agent A's service identity
The original user's identity
A delegated token representing both
A new task-specific workload identity
A tenant service account
Each model has tradeoffs.
Blindly forwarding the user's original token is dangerous.
The remote agent may receive broader permissions than necessary. Token audiences may be wrong. Audit logs may lose the distinction between user intent and agent action.
A better pattern is token exchange or delegation that creates a short-lived, audience-restricted, task-scoped credential.
The credential should answer:
Who is the user?
Which agent is acting?
Which tenant is involved?
Which task is authorized?
Which scopes are allowed?
When does permission expire?
A2A advertises and transports authentication requirements. Identity delegation architecture still belongs to the organization and identity platform.
Human approval remains outside the core task model
A task can enter TASK_STATE_INPUT_REQUIRED or TASK_STATE_AUTH_REQUIRED.
Those states are useful, but they do not define the full approval policy.
For a sensitive action, the system still needs to decide:
Who can approve?
What information must be shown?
Can the approver edit the action?
How long is approval valid?
Can another agent approve?
Is separation of duties required?
What evidence is recorded?
What happens if the task changes after approval?
The task state is a protocol signal.
The approval system is a business control.
Observability needs end-to-end correlation
A single user request may cross:
The user interface
A coordinator agent
Several remote agents
MCP servers
Internal APIs
Databases
Model providers
Human approvals

Logs from one agent are not enough.
At minimum, propagate and record:
Trace ID
A2A task ID
Context ID
Message ID
Agent identity
Skill ID
Tenant ID
User or delegated identity
Protocol version
Remote endpoint
Model and tool calls
Latency
Token and compute cost
Artifact IDs
Error category
A2A's use of HTTP and standard transports makes integration with tracing systems possible. Teams still need a semantic convention for agent handoffs and careful redaction of sensitive content.
Retries need idempotency and task reconciliation
If a send request times out, the client should not immediately create a new logical task with a new message ID.
A safer client flow is:
Generate a stable message ID.
Send the request.
If the response is ambiguous, retry with the same identity.
Query the task or context when possible.
Reconcile before repeating external side effects.
The server should deduplicate messages and return the existing task when appropriate.
Push notifications should also be treated as at-least-once delivery unless a stricter contract is established. Webhook consumers need event identifiers and duplicate handling.
Cancellation is a request, not time travel
A client can request task cancellation.
That does not guarantee that all external effects disappear.
If the remote agent already:
Sent an email
Created an order
Charged a payment
Shared a document
Triggered another agent
then cancellation may only stop future work.
The agent needs explicit cancellation semantics:
Best effort
Immediate before side effects
Stops after current step
Compensates completed actions
Cannot cancel after a terminal state
The protocol exposes a cancel operation. Business compensation remains implementation-specific.
Semantic drift will be harder than transport drift
Protocol version negotiation helps clients and servers agree on A2A versions.
It does not solve changes in what a skill means.
Suppose version 1 of compare-suppliers ranks price and delivery time. Version 2 adds carbon impact and supplier risk. The same skill ID may now produce different recommendations.
Treat agent skills like versioned products.
Consider:
Skill versions
Schema versions
Evaluation suites
Example-based contract tests
Deprecation dates
Capability flags
Policy review
Reproducible model configuration where required
An agent card should not be the only documentation.
Building a production A2A system
The best first A2A project is not an open marketplace containing hundreds of autonomous agents.
Start with one real boundary where custom integration is already painful.
Choose the right first use case
Good first candidates have:
Two independently owned agents
Clear responsibility boundaries
A task that may take time
Structured inputs or outputs
Limited financial or safety risk
A measurable manual integration cost
Examples:
Research agent delegating document verification
Support agent delegating policy interpretation
Procurement agent requesting supplier comparisons
IT agent requesting software-license checks
Travel coordinator requesting route analysis
Development agent requesting security review
Avoid starting with unrestricted purchasing, account deletion, production deployment, or other irreversible actions.
Decide whether the remote capability is a tool or an agent
Use a tool-like protocol when the remote capability is:
Stateless
Narrow
Deterministic
Fast
Defined by a strict schema
Not expected to negotiate or ask follow-up questions
Use A2A when the remote system:
Owns a task lifecycle
May ask for more input
May work asynchronously
Produces artifacts over time
Has its own reasoning and tools
Needs a separate trust boundary
Must remain implementation-opaque

Do not turn every microservice into an agent.
A database lookup does not become better because an LLM sits in front of it.
Build an agent gateway
Large organizations will not want every agent to connect directly to every other agent across trust boundaries.
An agent gateway can centralize:
Agent Card discovery
Signature verification
Authentication
Token exchange
Authorization
Rate limiting
Tenant routing
Payload validation
File proxying
Audit logs
Protocol version enforcement
Tracing
Cost controls

The gateway should not become an invisible super-agent with unlimited access.
Keep its role infrastructural and policy-driven.
Maintain an approved registry
An internal registry should store more than Agent Cards.
Useful metadata includes:
| Field | Purpose |
|---|---|
| Owner | Identifies the responsible team |
| Environment | Separates development, staging, and production |
| Trust tier | Limits which workflows may delegate |
| Data classification | Controls data sharing |
| Allowed tenants | Prevents cross-tenant use |
| Skill approval | Lists reviewed capabilities |
| Protocol versions | Supports compatibility planning |
| Evaluation status | Shows whether behavior was tested |
| Cost policy | Limits expensive delegation |
| Deprecation date | Supports lifecycle management |
Agent discovery without governance creates a new shadow integration problem.
Use narrow, structured skills
An agent card with one skill named do-anything is not useful.
Skills should communicate boundaries.
{
"id": "business-helper",
"name": "Business Helper",
"description": "Helps with business tasks"
}
Better skill:
{
"id": "compare-approved-suppliers-v1",
"name": "Compare approved suppliers",
"description": "Ranks approved suppliers for a product request using price, delivery time, warranty, and current risk status",
"tags": ["procurement", "supplier-comparison"],
"examples": [
"Compare approved suppliers for 20 laptops under USD 1,800 each"
],
"inputModes": ["application/json", "text/plain"],
"outputModes": ["application/json"]
}
The agent can still reason flexibly inside the task. The public contract should remain focused.
Define structured payloads for business-critical data
Natural language is useful for intent.
Structured data is better for amounts, IDs, dates, permissions, and constraints.
Use schema validation at both ends.
{
"requestId": "purchase-request-921",
"productCategory": "ENGINEERING_LAPTOP",
"quantity": 20,
"requirements": {
"minimumRamGb": 32,
"minimumStorageGb": 1000,
"maximumUnitPrice": {
"amount": 1800,
"currency": "USD"
}
},
"delivery": {
"countryCode": "NP",
"requiredBy": "2026-08-15"
}
}
Do not ask a model to infer currency, quantity, or authorization limits from prose when the system can provide explicit fields.
Make the server idempotent
A server-side request handler should associate a stable message with one logical result.
Conceptual TypeScript:
type SendMessageRequest = {
message: {
messageId: string;
contextId?: string;
taskId?: string;
role: "ROLE_USER";
parts: unknown[];
};
};
async function handleMessage(
request: SendMessageRequest,
): Promise<unknown> {
const existing = await messageStore.findByMessageId(
request.message.messageId,
);
if (existing) {
return existing.protocolResponse;
}
return database.transaction(async (tx) => {
const task = await tx.tasks.create({
contextId: request.message.contextId,
state: "TASK_STATE_SUBMITTED",
});
const protocolResponse = toA2AResponse(task);
await tx.messages.record({
messageId: request.message.messageId,
taskId: task.id,
protocolResponse,
});
await tx.outbox.enqueue({
type: "START_AGENT_TASK",
taskId: task.id,
});
return protocolResponse;
});
}
The exact implementation depends on the SDK and storage model.
The principle is stable: one logical request should not create several tasks because of network retries.
Treat task state as durable application state
Do not keep important task state only in memory.
The server needs a durable store for:
Task status
Message history where required
Artifact metadata
Push notification configuration
Idempotency records
Cancellation state
Authorization state
Retention timestamps
An A2A server can use a workflow engine such as Temporal, durable functions, a queue-based architecture, or its own state machine internally. A2A does not require one specific execution platform.
A useful pattern is:
A2A for the external agent contract
Durable execution for the internal task lifecycle
MCP for tool and data access
These layers solve different problems.
Validate every boundary
On inbound requests, validate:
Protocol version
Authentication
Tenant
Skill authorization
Message ID format
Part size
Media type
JSON schema
File references
Extension support
Rate limits
On outbound results, validate:
Artifact schema
Data classification
PII rules
Allowed URLs
Output size
Citation requirements
Policy and safety checks
The model should not be the validator.
Use deterministic application code.
Propagate trace and task context
A client should attach tracing context to each A2A request. The server should create child spans and associate them with A2A identifiers.
A practical span model:
user.request
agent.coordinator
a2a.send supplier-agent
remote.task task-7a12
model.generate
mcp.call supplier-database
http.call risk-provider
artifact.create ranking
Recommended attributes include:
a2a.protocol.version = "1.0"
a2a.task.id = "task-7a12"
a2a.context.id = "ctx-procurement-51"
a2a.message.id = "msg-21b7"
a2a.agent.name = "Supplier Research Agent"
a2a.skill.id = "compare-approved-suppliers-v1"
a2a.transport = "HTTP+JSON"
tenant.id = "tenant-42"
Do not place raw prompts, secrets, or personal data into trace attributes by default.
Test interoperability separately from intelligence
Agent testing has two different layers.
Protocol conformance
Test:
Agent Card validity
Version negotiation
Authentication errors
Task state transitions
Message and artifact schemas
Streaming events
Push notification retries
Cancellation
Duplicate requests
Unsupported extensions
Cross-language SDK compatibility
Behavioral evaluation
Test:
Skill accuracy
Constraint following
Refusal behavior
Hallucination rate
Data leakage
Tool use
Adversarial input
Cost and latency
Regression across model changes
Passing one layer does not imply passing the other.
A perfectly conformant agent can still be incompetent.
A highly capable agent can still have a broken protocol implementation.
Roll out across trust zones gradually
A sensible adoption path:
Connect two agents inside one organization.
Use one low-risk read-only skill.
Add task persistence and observability.
Add structured artifacts.
Test retries, disconnections, and duplicates.
Introduce scoped OAuth credentials.
Add an approved internal registry.
Add one external partner agent.
Introduce signed Agent Cards and gateway policy.
Expand to higher-risk actions only after approval and audit controls mature.
Do not start with an open internet of agents.
Start with controlled interoperability.
Know what A2A does not solve
A2A does not define:
Which model an agent should use
How an agent plans
How memory works
How tools are implemented
How an organization evaluates quality
How business approvals work
How payments are authorized
How compensation works after failure
How agents are ranked or trusted
How global agent discovery should be governed
How semantic conflicts are resolved
That is not a weakness.
A useful protocol should have boundaries.
The mistake would be expecting the protocol to replace architecture.
The agent network will look familiar
The future agent ecosystem will probably not look like a magical swarm of models talking freely.
It will look surprisingly familiar to backend engineers.
There will be:
Registries
Gateways
Identity providers
Scoped credentials
Protocol versions
Schemas
Task stores
Queues
Durable workflows
Traces
Rate limits
Audit logs
Trust policies
Deprecation plans
The agents may reason in natural language.
The systems around them still need engineering discipline.
A2A matters because it starts to create a stable boundary between those two worlds.
Inside the boundary, an agent can use any model, framework, memory architecture, or tool system.
Across the boundary, it exposes a discoverable identity, skills, security requirements, messages, tasks, artifacts, state transitions, and supported protocol bindings.
That is enough to change how multi-agent systems are built.
Instead of custom prompt glue between every pair of agents, teams can begin designing an agent network.
Instead of treating a remote agent like a mysterious function, they can treat it like an independently operated service with a task lifecycle.
Instead of giving every agent broad access to every system, they can combine A2A delegation with scoped identity, MCP tools, policy gateways, and durable execution.
The protocol will not make the network trustworthy by itself.
It will make the network possible to reason about.
That is what infrastructure standards do.
They turn repeated integration problems into shared contracts.
Agent-to-agent protocols are becoming a distributed systems layer because agent collaboration is becoming a distributed systems problem.
The sooner engineering teams recognize that, the less likely they are to rebuild the same fragile integration stack inside prompts and framework-specific adapters.
References



