Agent2Agent Protocol Explained: The Missing Layer for AI Agents That Actually Talk to Each Other
Here’s the uncomfortable truth I’ve hit after building production AI systems at SIVARO for the last eight years: most agent frameworks are glorified function callers. They don't talk to each other. They don't negotiate. They don't hand off work.
In 2026, we have agents booking flights, writing code, and running complex data pipelines. But if you ask one agent to collaborate with another agent from a different vendor, you get a digital shrug. It’s like building a telephone network where every phone speaks a different dialect and refuses to learn the other’s.
The Agent2Agent (A2A) protocol is the fix for that. And it’s been staring us in the face since Google Cloud and 50+ partners (including LangChain, Elastic, and MongoDB) pushed the spec forward in April 2025 Google Cloud Blog. I’ve spent the last 18 months integrating this into real data infrastructure. Here’s the breakdown, the practical how-to, and the sharp edges I found.
What is the Agent2Agent Protocol, Really?
The Agent2Agent protocol is an open standard that lets autonomous AI agents discover each other, communicate, and execute tasks across different platforms and vendors. It’s not a framework you plug in. It’s a lingua franca.
Think of it as the HTTP for the agentic web. HTTP dictates how browsers and servers exchange pages. A2A dictates how agents exchange tasks and artifacts.
The core architecture rests on three pillars:
- Agent Card: A JSON file that advertises what the agent can do, its endpoints, and its auth requirements.
- Communication Flow: A structured set of operations (send, reply, cancel) that manage task lifecycles.
- Security & Trust: Authentication protocols that ensure Agent A doesn't get tricked into doing Agent B's dirty work (like deleting a production database).
Most people think this is a branding problem. It's not. It's a data-serialization and state-management problem. The hard part isn't getting agents to say "hello." It's getting them to agree on what "Task completed successfully" means when Agent A is a Python script in a Docker container and Agent B is a massive LLM running on TPUs in Oregon.
Why This Matters Now (September 2026)
We are past the demo phase. Organizations are moving agents from "chatbots that write emails" to "autonomous workers that trigger payments and move data between warehouses." When you have that scale, you hit the wall.
At SIVARO, we tested a multi-agent system for a logistics client in June. They had a scheduling agent (vendor A) and a route-optimization agent (vendor B). Without A2A, integrating them meant writing a bespoke middleware layer that translated JSON schemas and handled retries. It took three weeks. With A2A, the scheduling agent simply queried the route agent's Agent Card, sent a task request, and got back a structured artifact.
The differentiation is stark. If you are building an agent mesh in 2026 and you are not using A2A, you are building vendor lock-in for yourself. You are choosing to write point-to-point integrations that will break the moment one side updates their API.
The Anatomy of an A2A Conversation
Let's get technical. The protocol relies on JSON-RPC over HTTP. It is simple by design. You don't need a PhD to read the spec.
Here is the lifecycle: You (the client agent) send a message to a remote agent. That remote agent responds with a Task object. The Task object has states: submitted, working, input-required, completed, canceled, and failed.
Here’s an agent2agent communication setup example. I’m using a simple Python client to ping a remote agent tasked with "Data Quality Scoring."
python
import requests
import json
# Step 1: Discover the agent's capabilities
agent_card_url = "https://agent.example.com/.well-known/agent.json"
card = requests.get(agent_card_url).json()
# Step 2: Check its capabilities
print("Agent Name:", card["name"])
print("Skills:", [skill["id"] for skill in card["skills"]])
# Step 3: Send a task request
# The URL for sending tasks is usually in the card's endpoints
task_url = "https://agent.example.com/a2a/task/send"
payload = {
"jsonrpc": "2.0",
"id": 1,
"method": "tasks/send",
"params": {
"taskId": "task-12345",
"message": {
"role": "user",
"parts": [{"text": "Assess the data quality of the payload.json file"}]
}
}
}
response = requests.post(task_url, json=payload).json()
task_state = response["result"]["status"]["state"]
print("Initial Task State:", task_state)
That is the whole discovery process. You read a card. You send a message. The heavy lifting happens between those steps in how you handle the state machine.
Setting Up an A2A Agent Server
Building the agent side of the protocol involves exposing your existing agent logic through the A2A schema. You don't need a special LLM. You need a lightweight web server that translates A2A requests into your internal function calls.
Here is a minimal FastAPI implementation I used to wrap a legacy data-processing engine we have at SIVARO. We built this in one afternoon because we had already abstracted our business logic behind a single command interface.
python
from fastapi import FastAPI, Request
from pydantic import BaseModel
import uvicorn
app = FastAPI()
class TaskMessage(BaseModel):
taskId: str
message: dict
@app.post("/a2a/task/send")
async def handle_task(task_message: TaskMessage):
task_id = task_message.taskId
# Parse the text extraction
text = task_message.message["parts"][0]["text"]
# This is your internal system call - we map the text to a command
# Our legacy engine runs the actual code here.
result = run_my_data_engine(text)
# Return the A2A standard response structure
return {
"result": {
"id": task_id,
"status": {
"state": "completed",
"message": result
},
"artifacts": [
{
"name": "result.json",
"parts": [{"text": f"Task completed with status: {result['status']}"}]
}
]
}
}
# Don't forget: you also need a GET endpoint for task polling
@app.get("/a2a/task/{task_id}")
async def get_task(task_id: str):
task = task_store.get(task_id)
return {"result": task}
The brilliance (and frustration) of the protocol is that it is stateless unless you make it stateful. The agent card doesn't track sessions. You have to implement the retrieval logic. For simple tasks, this is fine. For long-running, multi-turn tasks, you need to implement the tasks/get and tasks/cancel endpoints properly.
The a2a Agent2Agent Protocol Example: A Real Orchestration
Let me show you a real a2a agent2agent protocol example from a system we shipped for a financial services firm in August. We had two agents: LedgerAgent (manages transactions) and ComplianceAgent (checks for fraud).
Here is how the orchestration kicked off when LedgerAgent noticed an unusual spike in transaction volume.
javascript
// Orchestrator code (Node.js) - Connecting the LedgerAgent to the ComplianceAgent
const ledgerAgent = new A2AClient('https://internal-ledger.sivaro.internal/a2a');
const complianceAgent = new A2AClient('https://internal-compliance.sivaro.internal/a2a');
// Step 1: Ask Compliance if it wants to handle this
const task = await complianceAgent.sendTask({
message: {
role: 'user',
parts: [{ text: 'Investigate anomaly #4452. Check the velocity across all accounts.' }]
},
context: {
// Metadata for the protocol to understand the request
authentication: { bearer: process.env.INTERNAL_TOKEN },
target: 'compliance-check'
}
});
// Step 2: Poll for the result (non-blocking is better, but this is illustrative)
let state = task.status.state;
while (state !== 'completed' && state !== 'failed') {
await new Promise(r => setTimeout(r, 1000));
state = (await complianceAgent.getTask(task.id)).status.state;
}
// Step 3: Get the artifact back
const artifact = task.artifacts[0];
console.log('Compliance Agent verdict:', artifact.parts[0].text);
// Output: "Verdict: Malicious pattern detected. Blocking 3 accounts."
The important thing here isn't the code. It's the semantics. Notice that I didn't have to import a specific ComplianceAgent SDK. I used a generic A2AClient. That is the power. You just need the URL.
The Security Gaps Nobody Talks About
Look, the spec is new. And while the security working group is doing good work, there are holes. In my testing, the biggest threat isn't the network sniffing. It's the Agent Card being a lie.
I tested a scenario in July where a malicious agent published an Agent Card claiming it was a legitimate "Logistics Optimizer." But its authentication field was empty. Our main orchestrator saw "empty auth" and flagged it. But a lower-level agent didn't care. It just saw a valid endpoint and sent over PII data.
You must enforce mutual TLS. Do not rely on API keys in headers for agent-to-agent comms. Keys get stored in vector databases, they leak into prompt history. Use mTLS or signed JWTs with short expiry.
Here is the configuration snippet we use at SIVARO to enforce this in our environment.
yaml
# A2A Client Configuration
agent2agent:
http:
tls:
# Use mTLS for production agents
mode: mutually-required
client_cert: /etc/a2a/certs/client.pem
client_key: /etc/a2a/certs/client-key.pem
ca_cert: /etc/a2a/certs/ca.pem
Treat the A2A protocol as an unsecured link layer. If you don't add security on top of it, you are just two strangers yelling through a pipe. The spec allows for this, but it doesn't force it. You have to be the adult in the room.
Agent2Agent Protocol Explained: The Hard Parts of Delegation
When I explain agent2agent protocol explained to engineers, they usually get the messaging part quickly. They struggle with the assertions.
In a normal API, you call GET /users/123. You know you're going to get a user object.
In A2A, you send a text prompt: "Find me a user with a history of late payments who is also browsing high-value items." That agent might return a user ID. It might return an array of IDs. It might return "I couldn't find them" or, worse, "I am not sure, can you clarify what 'high-value' means?"
The protocol helps by standardizing the input-required state. When an agent gets stuck, it sends back a request for more information. Your client agent needs a handler for that. It can't just crash.
We solved this by implementing a "Clarification Retry Tactical Operation." If an agent asks for clarification, we route that back to the human user via a notification channel like Slack. The user replies, and we inject that response back into task. This keeps the loop responsive.
A2A vs. MCP: Stop Confusing the Two
Every week, I meet someone who thinks the Model Context Protocol (MCP) and A2A are competitors. They are not. MCP (introduced by Anthropic) tells an LLM how to use tools. A2A tells different agents how to talk to each other.
MCP is for connecting the brain to the muscle. A2A is for connecting two brains (or two organisms containing brains and muscles).
If you are building an agent that needs to query a SQL database, use MCP. If you are building an agent that needs to ask another agent to query that database because you don't have direct credentials, use A2A.
In complex systems, they are complementary layers.
- Layer 1: Agent Orchestrator (thinks about which agent to call).
- Layer 2: A2A Transport (trust boundary and message routing).
- Layer 3: MCP Tool Calls (actual execution against systems of record).
I have a whiteboard diagram of this at the office. It looks like a train network. A2A is the rail system between cities. MCP is the streetcar network inside the city.
Practical Guide: Moving from Demo to Production
Enough theory. Here is the checklist I give my engineers when we go live with A2A.
1. Start with the Agent Card.
Write this JSON file first. It forces you to define scope. If you say your agent can "handle customer support," you are lying. Specify exactly what you support. We define minute actions like "Refund under $200", "Fetch order status".
2. Version Your Tasks.
Don't just take completed as gospel. Ask for an artifact. Have your client look inside the artifact for a schema version field. If the remote agent changes its output schema without telling you, you will create data rotting at the edge.
3. Timeouts are Non-Negotiable.
I said it before – set these hard. A2A is typically synchronous. But your network isn't reliable. Our rule: client requests wait 5 seconds. If no acknowledgment, the remote is marked dead and we queue the request.
4. Fail Loud and Early
If Agent B is down, do not tell Agent B's replacement (Agent C) to "just try again". Fail the task. Alert the operator.
I still see teams buy into the fantasy of self-healing meshes. The reality is when Agent B is down because their database is locked, the worst thing you can do is have Agent C try to brute force the same database. You need a circuit breaker that routes around specific broken paths, not the entire domain.
The Agent Card Schema (The Most Critical File)
I need to emphasize how much the agent.json matters. It is global metadata. If it’s wrong, nothing else matters. Here is the skeleton we use:
json
{
"name": "DataPipeline Controller",
"description": "Agent to orchestrate ETL jobs",
"version": "2.1.0",
"capabilities": {
"streaming": true,
"pushNotifications": false
},
"security": {
"authentication": ["bearer"],
"authorization": ["jwt"]
},
"skills": [
{
"id": "data.quality.report",
"name": "Generate Quality Report",
"description": "Runs DQ checks on a given table",
"inputModes": ["text"],
"outputModes": ["text", "file"]
}
],
"endpoints": [
{
"protocol": "a2a",
"version": "1.0",
"url": "https://agent.internal.sivaro.co/a2a",
"operations": [
"message",
"tasks/get",
"tasks/cancel",
"tasks/pushNotification"
]
}
]
}
Notice the skills array. That is how discovery actually works. If your agent claims to have data.quality.report, the calling agent will assume you know what a "Quality Report" means. This is where semantic drift happens. Communicate via precise language in your skill descriptions, not marketing fluff.
Where the Standard Stands Today
We are at version 1.0 as of late 2025, and the ecosystem is heating up. In my opinion, the most important thing Google did was not write the code. It was getting names like Oracle, PayPal, and Salesforce to sign the initial agreement back in 2025 The New Stack. That was the moment it stopped being a Google internal tool and became a cross-industry bet.
We tested interoperability with a Salesforce agent back in May. Our Python-based data enrichment agent talked to Salesforce's component. It was a pain.
Not because the protocol failed. But because the Salesforce agent's card didn't specify its output schema well. We had to guess the field names.
So my advice? In your 2026 planning, allocate budget for "Agent Contract Migration." The protocol works. The semantic overlays are still evolving.
The Distinction Between Agents and API Wrappers
Here is a contrarian take for you: If you are using A2A to call other systems, you are probably doing it wrong.
A2A is for agents that have some degree of autonomy. If your agent is just a lambda function that translates a string into a Postgres query, expose it as a REST API. Save yourself the overhead.
We use A2A only when the remote system holds a state machine or makes decisions. For example, we have a "Negotiator" agent. It doesn't just fetch prices. It asks clarifying questions. It holds state. That makes it a great A2A citizen.
But pure transactional stuff? Keep it synchronous and simple.
FAQ: The Questions I Get From Engineering Teams
Q: Does A2A replace workflow orchestration tools like Airflow or Temporal?
No. You still need an orchestrator to decide the order of operations. A2A is how agents communicate within those workflows.
Q: Is A2A useful for a small team building one or two agents?
Probably not. If all your agents live in the same codebase and share libraries, you don't need them to talk over HTTP. You can just call functions. You need A2A when crossing trust boundaries or language boundaries.
Q: What is the typical latency overhead of using A2A?
About 100-200 milliseconds for HTTP overhead and parse time. If your agent takes a minute to generate a response, it's negligible. If you're building real-time trading algorithms, it's killer.
Q: How does this relate to OpenAI's function calling?
Function calling is internal to the LLM. That agent determines "I need to call get_weather()". A2A is figuring out that "I need to ask the WeatherAgent to give me data". The former is a feature of the model. The latter is a feature of the infrastructure.
Q: Can I use A2A for text-only communication, or can it handle multi-modal file exchanges?
The latest spec supports FilePart objects for passing images and code artifacts.
Q: How do I handle versioning when my agent upgrades its logic?
The Agent Card has a version number. Your client agent looks at the card before connecting. If the version changed by a major number, your client should reject the connection and alert you.
The Infrastructure Puzzle
agent2agent protocol explained in the abstract sounds like a developer convenience. In practice, it is an operational discipline.
You need agent observability (we use OpenTelemetry B3 headers). You need to manage API tokens. You need a registry that lists all agent URLs.
Don't build this registry into your code. I made that mistake early on. Instead, make it a static file that your orchestrator reads at boot. You can generate this file from your infrastructure-as-code pipelines.
bash
# Generate agent registry from config
# This ensures we don't have to hardcode URLs
a2a-registry build --config ./agents.yaml --output ./registry.json
The "Golden Path" we take at SIVARO involves an agent state database (we use Redis with persistence) that tracks every task from every agent. This allows us to replay actions when a downstream system fails.
The Future: What's Coming Next Year
I see three trends for the A2A ecosystem heading into 2027.
First, aggregation of Agent Cards. We'll get service meshes that crawl the web and index Agent Cards, effectively a search engine for agents.
Second, Agent Identity Reconciliation. Right now, I trust the agent card if it's on a URL I expected. Next year, we will need a Web-of-Trust model, where a trusted root agent vouches for other agents. We are already testing decentralized identities.
Third, the maturation of the Agent-to-Agent marketplace. I think this is where the "agent2agent protocol example" becomes boring because it's simply built into every framework.
In my day-to-day, I warn clients: if you've been to a conference in 2026 and you saw "agent capability" demos, ask them if they used A2A under the hood. I don't trust agent frameworks that can't interop with vendor X. Every vendor says they are open. Few actually sign up for the cross-vendor test events.
Your Next Steps
Start building your first Agent Card today. Even if it is a dummy. The art is in defining capability boundaries.
Draw two squares. Agent A and Agent B. Decide what Agent A is authorized to ask for. Decide what Agent A is allowed to tell Agent B. Security boundaries are about data minimization, not just authentication. An agent should only ask for the minimum data it needs.
At SIVARO, we process over 200,000 events per second across our data infrastructure. A lot of that is ETL. We realized that when we start notifying our own data agents about upstream failures via A2A, we saw our mean time to resolution drop by 40% because we didn't have to map error codes across different internal frameworks. The protocol is just the start. The wins come when your organization standardizes how you describe state.
The agent mesh is coming, but it's not going to be built by magic. It’s built by engineers who agree on syntax, enforce security, and don't trust the other agent's marketing.
If you have questions about the protocol or are debugging an A2A setup right now, drop a comment. I read them all.
Nishaant Dixit — Founder of SIVARO. Building data infrastructure and production AI systems since 2018. Built systems processing 200K events/sec.