The A2A Protocol Production Deployment: What Works After 18 Months

I spent 8 months building agent systems before I understood the problem wasn't the agents. It was the protocol between them. A2A (Agent-to-Agent) protocol is...

protocol production deployment what works after months
By Nishaant Dixit
The A2A Protocol Production Deployment: What Works After 18 Months

The A2A Protocol Production Deployment: What Works After 18 Months

Free Technical Audit

Expert Review

Get Started →
The A2A Protocol Production Deployment: What Works After 18 Months

I spent 8 months building agent systems before I understood the problem wasn't the agents.

It was the protocol between them.

A2A (Agent-to-Agent) protocol is Google's open standard for agents talking to each other across service boundaries. Not function calls inside a monolith. Real agent-to-agent conversation where neither party controls the other's runtime.

In July 2026, this isn't theoretical anymore. I've deployed A2A in production at 3 companies in the last 14 months. One processes insurance claims. One handles customer escalation routing. One is internal tooling for a fintech.

This guide walks through an actual production deployment of A2A — the decisions, the failures, the numbers, and the code. No theory. No "both sides have merit." I'll tell you what broke and what didn't.


What Actually Happens When Two Agents Talk

Most people think agent-to-agent communication is like API calls with more steps.

Wrong.

A2A defines a task-oriented protocol. Agent A sends a task to Agent B. Agent B can accept it, reject it, stream progress, request clarification, or hand it off. The protocol handles:

  • Task cards – structured descriptions of what the task is
  • Message streaming – incremental output as the agent works
  • Artifact transfer – passing files, images, or structured data
  • Card resolution – asking for more input when ambiguous

This isn't RPC. It's asynchronous conversation with state.

The spec (v0.9 as of this month) defines the wire format as JSON over HTTP, with SSE for streaming. The Arxiv survey of AI agent protocols puts A2A at the top of the interoperability charts, but that's paper talk. Let me tell you what matters in practice.


Why I Stopped Building Monolithic Agent Frameworks

At first I thought the agent framework decision was everything. LangChain, CrewAI, AutoGen, Semantic Kernel — I tried them all.

Here's the problem: frameworks optimize for building one agent. Not for connecting many agents built by different teams, running on different stacks, with different reliability expectations.

A survey of agentic AI frameworks from Instaclustr lists 10 options. They're all good at different things. None of them solve inter-agent communication natively.

This is why A2A exists. It's the HTTP of agent communication. You don't need both agents to use the same framework. You just need both to speak A2A.

I know a team at a healthtech that uses CrewAI for their triage agent, LangGraph for their claims processing agent, and a custom Python service for their document extraction agent. They communicate over A2A. It works.


The Production Deployment: Step by Step

I'll use the insurance claims system as our example. This went live in February 2026.

The Architecture

Three agents:

  1. Triage Agent – receives incoming claims, classifies type, extracts metadata
  2. Validation Agent – checks policy coverage, flags discrepancies
  3. Processing Agent – calculates payout, generates documentation

Each agent runs as a separate service. Each exposes an A2A endpoint.

Step 1: The A2A Agent Card

Every agent publishes an agent card (a JSON descriptor of capabilities). Discovery is your first production challenge.

json
{
  "agentName": "ClaimValidationAgent",
  "version": "2.1.0",
  "capabilities": [
    {
      "taskType": "validate_policy",
      "inputSchema": {
        "type": "object",
        "properties": {
          "policyNumber": { "type": "string" },
          "claimAmount": { "type": "number" },
          "claimDate": { "type": "string", "format": "date" }
        },
        "required": ["policyNumber"]
      },
      "outputSchema": {
        "type": "object",
        "properties": {
          "status": { "type": "string", "enum": ["approved", "flagged", "denied"] },
          "explanation": { "type": "string" }
        }
      }
    }
  ],
  "authentication": {
    "type": "bearer_token",
    "endpoint": "https://validation.service.internal/a2a"
  }
}

What I learned: keep agent cards in a registry, not hardcoded. We used Consul. The triage agent queries the registry to find the validation agent. When we deploy a new version with different capabilities, the registry updates automatically.

We skip a discovery step. No service mesh. No complex routing. Just registry lookups.

Step 2: Sending a Task

The triage agent sends a task to validation. Here's the actual HTTP call:

python
import httpx
import json

async def send_validation_task(claim_data: dict, validation_endpoint: str, token: str) -> dict:
    task_payload = {
        "jsonrpc": "2.0",
        "method": "tasks.send",
        "params": {
            "taskId": f"task-claim-{claim_data['claimId']}",
            "taskCard": {
                "taskType": "validate_policy",
                "input": {
                    "policyNumber": claim_data["policyNumber"],
                    "claimAmount": claim_data["amount"],
                    "claimDate": claim_data["date"]
                }
            }
        },
        "id": 1
    }
    
    async with httpx.AsyncClient(timeout=30.0) as client:
        response = await client.post(
            validation_endpoint,
            json=task_payload,
            headers={"Authorization": f"Bearer {token}"}
        )
        response.raise_for_status()
        return response.json()

That "jsonrpc" is critical. A2A uses JSON-RPC 2.0 as its transport. It's boring, well-understood, and every language has a library for it. The LangChain team's thinking on agent frameworks emphasizes keeping transport simple — they're right.

Step 3: The Validation Agent Processes

The validation agent receives the task. This is where the real work happens.

python
from fastapi import FastAPI, Request
from pydantic import BaseModel
import asyncio

app = FastAPI()

@app.post("/a2a")
async def handle_a2a(request: Request):
    body = await request.json()
    
    if body["method"] == "tasks.send":
        task_id = body["params"]["taskId"]
        task_card = body["params"]["taskCard"]
        
        # Acknowledge immediately, process async
        asyncio.create_task(process_task(task_id, task_card))
        
        return {
            "jsonrpc": "2.0",
            "result": {
                "taskId": task_id,
                "status": "working",
                "agentName": "ClaimValidationAgent"
            },
            "id": body["id"]
        }

Notice we return "working" immediately. The triage agent polls for results or receives them via a callback URL. We use polling because it's simpler and our callbacks kept timing out under load.

Decision: polling over push. Every time I've tried push-based results in production, something breaks — NAT traversal, firewalls, authentication on the return path. Polling is boring and reliable.

Step 4: Streaming Results Back

Long-running tasks need incremental progress. A2A supports streaming via SSE.

python
# From the triage agent, polling for updates
async def poll_for_result(task_id: str, endpoint: str, token: str, polling_interval: int = 2):
    max_polls = 30  # 60 seconds total
    for i in range(max_polls):
        response = await send_get_request(endpoint, {
            "jsonrpc": "2.0",
            "method": "tasks.get",
            "params": {"taskId": task_id},
            "id": 1
        }, token)
        
        status = response["result"]["status"]
        if status == "completed":
            return response["result"]["artifact"]
        elif status == "failed":
            raise Exception(f"Task failed: {response['result'].get('error', 'unknown')}")
        elif status == "input_required":
            # The agent needs clarification
            clarifications = response["result"].get("cardResolution", [])
            # Send resolution back
            await send_resolution(task_id, clarifications, endpoint, token)
        
        await asyncio.sleep(polling_interval)
    
    raise TimeoutError("Task did not complete in expected time")

The "input_required" status is where A2A separates from simple RPC. The validation agent found ambiguous policy language. It asks the triage agent for clarification. The triage agent might escalate to a human.

This negotiation loop is where most of my production bugs live. Let me save you the pain.


The Three Things That Break in Production

1. Timeouts Kill Everything

You think you have timeout handling. You don't.

The validation agent takes 45 seconds on a complex claim. Your polling timeout is 30 seconds. The triage agent drops the task. The validation agent finishes and has no one to send results to.

Fix: set timeouts based on the agent card's stated max processing time. We added a maxProcessingTime field to every capability. The triage agent uses it to set its polling window.

Task never returns in production? Now it's a dead letter that your monitoring catches, not a silent dropout.

2. State Inconsistency Between Agents

The triage agent thinks it sent task claim-123-abc. The validation agent never received it. Network blip. Now you have an orphan claim.

Fix: idempotency keys. Every task has a UUID. The validation agent stores processed task IDs. If it sees a duplicate, it returns the cached result.

python
processed_tasks = {}  # Redis-backed in production

async def process_task(task_id: str, task_card: dict):
    if task_id in processed_tasks:
        return processed_tasks[task_id]
    
    result = await validate_policy(task_card["input"])
    processed_tasks[task_id] = result
    return result

This sounds obvious. I'm telling you because my first deployment didn't have it and we lost 47 claims in 2 weeks.

3. Agent Card Drift

The validation agent's capabilities changed in a deploy. The triage agent's cached agent card was stale. It sent a task the validation agent didn't understand anymore.

Fix: version the agent cards and require periodic refresh. Every agent re-fetches capabilities every 5 minutes. If the version changed mid-request, the triage agent can retry with the new schema.


Observability Changes Everything

Standard logging isn't enough for agent systems. You need ai agent observability production — the ability to trace a task across agent boundaries.

IBM's research on AI agent frameworks mentions observability as a key consideration. They're not wrong but they undersell it.

We built a tracing layer on top of A2A:

python
import asyncio
import json
from datetime import datetime

class A2ATrace:
    def __init__(self, agent_name: str):
        self.agent_name = agent_name
        self.span_id = f"{agent_name}-{datetime.utcnow().timestamp()}"
        self.children = []
        self.metrics = {
            "llm_calls": 0,
            "total_llm_tokens": 0,
            "total_processing_ms": 0
        }
    
    def track_llm_call(self, tokens: int, duration_ms: int):
        self.metrics["llm_calls"] += 1
        self.metrics["total_llm_tokens"] += tokens
        self.metrics["total_processing_ms"] += duration_ms
    
    def to_json(self):
        return {
            "agent": self.agent_name,
            "span": self.span_id,
            "metrics": self.metrics,
            "children": [c.to_json() for c in self.children]
        }

Each agent wraps its task processing with a trace span. The trace propagates via the A2A task's metadata. At the end, the triage agent aggregates the full trace tree.

This is how we found the 45-second outlier on validation. An LLM call was retrying 4 times due to rate limiting. Without tracing, we'd have blamed the protocol.


The AI Agent Deployment Pipeline Tutorial

The AI Agent Deployment Pipeline Tutorial

Let me give you the exact ai agent deployment pipeline tutorial we use.

  1. Schema validation – every agent card is validated against a JSON Schema before deployment
  2. Integration test – spin up both agents locally, send a test task, verify the full flow
  3. Canary deploy – deploy the new agent to 10% of traffic, route only test tasks
  4. Dark launch – run the new agent alongside the old one, compare outputs
  5. Full rollout – only after 24 hours of matching results
yaml
# .github/workflows/deploy-agent.yaml (simplified)
deploy:
  steps:
    - run: python validate_agent_card.py agent-card.json
    - run: pytest tests/test_a2a_flow.py --agent-endpoint=http://localhost:8080/a2a
    - run: kubectl set image deployment/validation-agent agent=registry/validation:v2.1.1 --record
    - run: python canary_check.py --deployment validation-agent --percentage 10
    - run: python dark_launch_compare.py --old v2.1.0 --new v2.1.1 --duration 24h
    - run: kubectl rollout status deployment/validation-agent

The integration test is the hardest part. You need two agents running. We containerize each and use docker-compose for tests. The test sends a known task and asserts the response structure.

We skip unit tests on the A2A handler itself. The protocol is simple. What breaks is the state management around it, and unit tests don't catch that.


When A2A Doesn't Work

I'm not selling A2A as universal. Here's where it failed for me:

High-frequency trading bots – the JSON-RPC overhead is too high. sub-millisecond latency needs a binary protocol.

Real-time video processing – the streaming model doesn't handle continuous media. Use WebRTC instead.

Single-agent systems – if you have one agent doing one thing, A2A is overengineering. Just call a function.

SSONetwork's analysis of AI agent protocols lists 10 protocols. Each has a use case. A2A shines when you have multiple independently maintained agents that need to coordinate.


The Cost Reality

Running A2A in production costs more than you think. Not in compute. In operational complexity.

Every task crossing an agent boundary means:

  • Serialization/deserialization overhead
  • At least one additional LLM call for understanding the task
  • State management for the task lifecycle
  • Retry logic
  • Monitoring dashboards

For our claims system, each A2A handshake adds 300-500ms of latency and $0.002 in LLM costs (context overhead). That's fine for insurance. It would kill a real-time system.

Mitigation: we cache agent cards aggressively and use bulk task submission where possible. If 50 claims come in at once, we batch them into a single A2A task with a list of inputs.


What I'd Do Differently Next Time

  1. Start with a registry – we used environment variables for the first month. Disaster.
  2. Make polling async from day one – we had sync polling in the prototype. Timeout hell.
  3. Version every agent card – schema drift is the silent killer of A2A systems.
  4. Test with network failurestc on Linux to simulate packet loss. Our third outage was a flaky load balancer.

The top open-source agentic AI frameworks for 2026 list includes A2A support in several. CrewAI has it. LangGraph added it in v0.7. AutoGen has experimental support. The ecosystem is maturing fast.


FAQ

Q: Does A2A replace REST APIs?
A: No. A2A sits above REST. Your agents still call internal APIs via REST. A2A handles the agent-to-agent coordination layer. Think of it as an orchestration protocol, not a transport protocol.

Q: Can agents from different companies talk via A2A?
A: That's the dream. In practice, every cross-org deployment I've seen has auth and schema negotiation issues. It works within a single org today. Cross-org is bleeding edge.

Q: What happens when an agent goes down mid-task?
A: The task enters "abandoned" state. The requesting agent needs to detect this via polling timeout and either retry or escalate. We use a dead-letter queue for abandoned tasks.

Q: How do you version A2A itself?
A: The protocol has a version field in every message. We pin to a specific version in our agent cards. Upgrades are coordinated across all agents.

Q: Is A2A better than MCP (Model Context Protocol)?
A: Different tool. MCP is for model-to-tool communication. A2A is for agent-to-agent. They complement each other. We use both — MCP for the validation agent to query the policy database, A2A to talk to other agents.

Q: What's the most common production bug?
A: Schema mismatch. Agent A's task card says it needs field X. Agent B's capability expects field Y. Both are valid JSON. Neither validates until runtime.

Q: How do you test A2A in CI/CD?
A: Integration tests with mock agents. Our validation agent has a test mode that returns known results immediately. The triage agent test suite runs against this mock.


The Bottom Line

The Bottom Line

A2A protocol production deployment isn't about the protocol. It's about the operational infrastructure around it.

The protocol itself is solid. Google got it right — JSON-RPC, streaming support, task-oriented design. The hard parts are idempotency, state management, observability, and schema governance.

I've deployed this in production. It works. The claims system processed 12,000 tasks in April without a single protocol-level failure. The failures were all infrastructure — a Redis outage, a misconfigured ingress, a certificate expiration.

Treat A2A like you'd treat any production HTTP service. Health checks. Circuit breakers. Rate limiting. Monitoring. The protocol is just the wire between your agents. The system is what you build around it.

If you're building multi-agent systems today, stop writing custom protocols. Use A2A. You'll waste less time on plumbing and more time on actual agent intelligence.


Nishaant Dixit — Founder of SIVARO. Building data infrastructure and production AI systems since 2018. Built systems processing 200K events/sec.

Free · No Commitment · 48-Hour Delivery

Get a free infrastructure audit

2-hour remote session. We audit your data infrastructure, identify what's costing you time and money, and deliver a written roadmap with specific, measurable targets. No pitch.

Book Your Free Audit
N
Nishaant Dixit
Founder & Lead Engineer at SIVARO

Building data-intensive systems since 2018. 200K events/sec pipelines, production RAG systems, Kubernetes infrastructure. LinkedIn →

Start a Project
Need help with your infrastructure?

From data platforms to AI systems — we build production-grade infrastructure that scales.

Explore Our Services