Por que o A2A Surgiu
Em 2025, o ecossistema de agentes explodiu. LangChain, CrewAI, AutoGen, Vertex AI, LlamaIndex — cada framework criou sua própria forma de agentes se comunicarem internamente. O problema: um agente LangChain não falava com um agente CrewAI sem código customizado de integração.
O Problema que A2A Resolve
Antes do A2A:
- Cada framework tem protocolo proprietário
- Integração entre sistemas requer código customizado
- Agentes não se descobrem dinamicamente
- Sem padrão de capacidades, auth ou schema
- Multi-cloud multi-vendor impossível sem wrapper
Com A2A:
- Protocolo HTTP padrão, JSON-RPC 2.0
- Qualquer agente descobre e chama qualquer outro
- Agent Card autodescritivo (como OpenAPI)
- Autenticação padronizada via OAuth 2.0
- Interoperabilidade cross-vendor nativa
Linha do Tempo A2A
Abril 2025 — Lançamento
Google anuncia A2A com suporte de 50+ parceiros (Salesforce, SAP, Atlassian, Deloitte)
Junho 2025 — Spec v1.0
Especificação estabilizada com suporte a streaming, push notifications e artifacts
2026 — Adoção enterprise
Principais cloud providers oferecem suporte nativo; frameworks open-source adotam como padrão
A2A é complementar ao MCP
MCP (Model Context Protocol da Anthropic) define como agentes se conectam a ferramentas e dados. A2A define como agentes se conectam entre si. Não competem — são camadas diferentes de um mesmo ecossistema.
Arquitetura A2A
A2A usa HTTP como transporte e JSON-RPC 2.0 como protocolo de mensagens. Cada agente expõe um endpoint — o "A2A Server" — que responde requisições de outros agentes (A2A Clients).
Diagrama de Componentes
Orquestrador
A2A Client
Agente Remoto
A2A Server
/.well-known/agent.json
Endpoints Padrão A2A
Modos de Comunicação
Síncrono
/tasks/send — aguarda resultado completo
Streaming (SSE)
/tasks/sendSubscribe — recebe atualizações em tempo real via Server-Sent Events
Push (Webhook)
Agente notifica URL configurada quando task completa
JSON-RPC — Estrutura de Requisição A2A
{
"jsonrpc": "2.0",
"id": "req-abc123",
"method": "tasks/send",
"params": {
"id": "task-uuid-456",
"sessionId": "session-789",
"message": {
"role": "user",
"parts": [
{
"type": "text",
"text": "Analise o relatório Q4 e extraia os KPIs principais"
},
{
"type": "file",
"mimeType": "application/pdf",
"uri": "gs://bucket/relatorio-q4.pdf"
}
]
},
"metadata": {
"priority": "high",
"timeout_seconds": 120
}
}
}
Agent Card
O Agent Card é o "cartão de visita" do agente — um JSON autodescritivo servido em
/.well-known/agent.json que declara
o que o agente sabe fazer, como se autenticar, quais formatos aceita e quais skills possui.
É para agentes o que o OpenAPI é para APIs REST.
JSON — Agent Card Completo
{
"name": "Analista Financeiro IA",
"description": "Especialista em análise de demonstrativos financeiros, KPIs e forecasting",
"version": "2.1.0",
"url": "https://agents.minhaempresa.com/financial-analyst",
"documentationUrl": "https://docs.minhaempresa.com/financial-agent",
"capabilities": {
"streaming": true,
"pushNotifications": true,
"stateTransitionHistory": true
},
"authentication": {
"schemes": ["Bearer"],
"oauthConfig": {
"tokenUrl": "https://auth.minhaempresa.com/token",
"scopes": ["agent:financial:read", "agent:financial:write"]
}
},
"defaultInputModes": ["text/plain", "application/json"],
"defaultOutputModes": ["application/json", "text/plain"],
"skills": [
{
"id": "analyze_balance_sheet",
"name": "Análise de Balanço Patrimonial",
"description": "Analisa balanços e extrai índices financeiros (liquidez, endividamento, rentabilidade)",
"tags": ["financial", "balance-sheet", "kpi"],
"examples": [
"Analise o balanço do Q3 e calcule o índice de liquidez corrente",
"Compare endividamento dos últimos 4 trimestres"
],
"inputModes": ["application/pdf", "application/json"],
"outputModes": ["application/json"]
},
{
"id": "forecast_revenue",
"name": "Previsão de Receita",
"description": "Gera forecast de receita para próximos N períodos com intervalos de confiança",
"tags": ["forecast", "revenue", "ml"],
"examples": [
"Projete receita para os próximos 6 meses com base no histórico"
],
"inputModes": ["application/json"],
"outputModes": ["application/json", "text/csv"]
}
]
}
Descoberta Dinâmica de Agentes
O orquestrador pode buscar agentes em um registro (agent registry) filtrado por tags.
Ex: registry.find(tags=["financial", "kpi"]) retorna todos os agentes
registrados com essas capacidades — sem precisar hardcodar URLs.
Task Protocol
O Task Protocol define o ciclo de vida de uma tarefa no A2A: estados, transições e formato de resposta. Uma task tem um ID único, passa por estados bem definidos e pode retornar artefatos (artifacts) como resultado.
Ciclo de Vida de uma Task A2A
submitted
Recebida
working
Executando
input-required
Aguardando
completed
Concluída
failed
canceled
JSON — Resposta de Task Concluída
{
"id": "task-uuid-456",
"sessionId": "session-789",
"status": {
"state": "completed",
"timestamp": "2026-03-03T14:23:45Z"
},
"artifacts": [
{
"name": "kpi_analysis",
"description": "KPIs extraídos do relatório Q4",
"mimeType": "application/json",
"parts": [
{
"type": "data",
"data": {
"receita_liquida": 4250000,
"margem_ebitda": 0.284,
"crescimento_yoy": 0.187,
"nps": 72,
"churn_rate": 0.031
}
}
]
},
{
"name": "executive_summary",
"description": "Resumo executivo em texto",
"mimeType": "text/plain",
"parts": [
{
"type": "text",
"text": "Q4 demonstrou crescimento de 18.7% YoY com melhora de margem..."
}
]
}
],
"history": [
{"role": "user", "parts": [{"type": "text", "text": "Analise o relatório Q4..."}]},
{"role": "agent", "parts": [{"type": "text", "text": "Processando PDF..."}]}
]
}
Estado input-required
Quando o agente precisa de mais informação para continuar, transita para
input-required e aguarda o client enviar
/tasks/{'{'}id{'}'}/send com os dados adicionais.
Isso permite diálogos multi-turno entre agentes.
Implementando em Python
Como criar um servidor A2A (agente que outros podem chamar) e um cliente A2A (orquestrador que chama outros agentes) usando Python com FastAPI e httpx.
Python — Servidor A2A (Agente Remoto)
from fastapi import FastAPI, HTTPException
from fastapi.responses import StreamingResponse
import uuid, json, asyncio
from pydantic import BaseModel
app = FastAPI()
# Agent Card
AGENT_CARD = {
"name": "Analista de Texto IA",
"version": "1.0.0",
"url": "https://meu-agente.com",
"capabilities": {"streaming": True},
"skills": [
{
"id": "summarize",
"name": "Resumir Texto",
"description": "Gera resumo conciso de textos longos",
"tags": ["nlp", "summarization"]
}
]
}
# Registry de tasks ativas
tasks: dict = {}
@app.get("/.well-known/agent.json")
async def get_agent_card():
return AGENT_CARD
@app.post("/tasks/send")
async def send_task(request: dict):
task_id = request.get("id") or str(uuid.uuid4())
message = request["params"]["message"]
# Cria task
tasks[task_id] = {"state": "submitted", "result": None}
# Executa (em background)
asyncio.create_task(process_task(task_id, message))
# Retorna imediatamente com estado submitted
return {
"jsonrpc": "2.0",
"id": request.get("id"),
"result": {
"id": task_id,
"status": {"state": "working"}
}
}
@app.get("/tasks/{task_id}/status")
async def get_task_status(task_id: str):
if task_id not in tasks:
raise HTTPException(404, "Task não encontrada")
return tasks[task_id]
async def process_task(task_id: str, message: dict):
tasks[task_id]["state"] = "working"
text = message["parts"][0]["text"]
# Chama LLM
summary = await summarize_with_llm(text)
tasks[task_id] = {
"state": "completed",
"artifacts": [{
"name": "summary",
"mimeType": "text/plain",
"parts": [{"type": "text", "text": summary}]
}]
}
Python — Cliente A2A (Orquestrador)
import httpx
import asyncio
from typing import Optional
class A2AClient:
def __init__(self, agent_url: str, token: Optional[str] = None):
self.agent_url = agent_url.rstrip("/")
self.headers = {"Authorization": f"Bearer {token}"} if token else {}
async def get_agent_card(self) -> dict:
async with httpx.AsyncClient() as client:
resp = await client.get(
f"{self.agent_url}/.well-known/agent.json",
headers=self.headers
)
return resp.json()
async def send_task(self, message: str, task_id: str = None) -> dict:
payload = {
"jsonrpc": "2.0",
"id": "req-1",
"method": "tasks/send",
"params": {
"id": task_id or str(uuid.uuid4()),
"message": {
"role": "user",
"parts": [{"type": "text", "text": message}]
}
}
}
async with httpx.AsyncClient(timeout=30) as client:
resp = await client.post(
f"{self.agent_url}/tasks/send",
json=payload,
headers=self.headers
)
return resp.json()
async def wait_for_completion(
self,
task_id: str,
poll_interval: float = 0.5,
timeout: float = 120.0
) -> dict:
"""Polling até task completar."""
import time
start = time.time()
while time.time() - start < timeout:
async with httpx.AsyncClient() as client:
resp = await client.get(
f"{self.agent_url}/tasks/{task_id}/status",
headers=self.headers
)
status = resp.json()
state = status.get("state")
if state in ("completed", "failed", "canceled"):
return status
await asyncio.sleep(poll_interval)
raise TimeoutError(f"Task {task_id} não completou em {timeout}s")
# Uso no orquestrador
async def orchestrate():
client = A2AClient("https://meu-agente.com", token="bearer-token")
# Descobre capacidades
card = await client.get_agent_card()
print(f"Agente: {card['name']} — Skills: {[s['id'] for s in card['skills']]}")
# Envia task
result = await client.send_task("Resuma o relatório anual...")
task_id = result["result"]["id"]
# Aguarda resultado
final = await client.wait_for_completion(task_id)
summary = final["artifacts"][0]["parts"][0]["text"]
print(f"Resumo: {summary}")
A2A vs MCP vs Chamada Direta
Três abordagens para integração entre agentes — cada uma com trade-offs claros de complexidade, flexibilidade e interoperabilidade. Escolher a certa depende do contexto.
| Critério | Chamada Direta | MCP | A2A |
|---|---|---|---|
| Complexidade | Baixa | Média | Alta |
| Interoperabilidade | Nenhuma | Ferramentas | Total |
| Descoberta dinâmica | Não | Parcial | Sim (Agent Card) |
| Autenticação padronizada | Não | Básica | OAuth 2.0 |
| Streaming nativo | Não | Parcial | SSE nativo |
| Casos de uso | Agentes internos, mesmo framework | Agente + tools externas | Multi-empresa, cross-cloud, enterprise |
Use Chamada Direta quando...
- Agentes no mesmo processo/framework
- Equipe pequena, MVP rápido
- Não precisa de interoperabilidade
- Latência é crítica
Use MCP quando...
- Agente precisa de tools externas padronizadas
- Quer reusar servidores MCP existentes
- Foco em agente + contexto + dados
- Ecossistema Anthropic
Use A2A quando...
- Agentes de múltiplos vendors/times
- Necessidade de descoberta dinâmica
- Enterprise cross-cloud
- Publicar agente como serviço
Visão de Futuro: Ecossistema Unificado
A convergência de A2A (agente-a-agente) + MCP (agente-a-ferramenta) + modelos cada vez mais capazes cria um ecossistema onde qualquer agente pode colaborar com qualquer outro, usar qualquer ferramenta, e ser descoberto por qualquer orquestrador — independente de vendor ou framework. Quem dominar essa arquitetura hoje tem vantagem definitiva em 2026-2027.
Resumo do Módulo
Módulo 10 de 10 da Trilha 4 — Multi-Agentes e Orquestração
Conceitos centrais
- → A2A resolve interoperabilidade cross-vendor de agentes
- → HTTP + JSON-RPC 2.0 como protocolo de transporte
- → Agent Card é o OpenAPI dos agentes
- → Task lifecycle: submitted → working → completed
Na prática
- → FastAPI + httpx para servidor e cliente A2A
- → A2A e MCP são complementares, não concorrentes
- → Streaming nativo via SSE para tasks longas
- → Descoberta dinâmica via registry + tags
Trilha 4 Concluida
Voce completou a Trilha 4 — Multi-Agentes e Orquestracao. Da arquitetura hierarquica ao protocolo A2A, agora voce tem o repertorio completo para construir sistemas agênticos de producao.
Proximo passo: Trilha 5 — Memoria e Contexto