Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Builds Agent-to-Agent (A2A) servers and clients following Google's open protocol for agent interoperability. Use when the user wants to create an A2A-compliant agent, build an Agent Card, implement task management, connect agents across frameworks, set up agent discovery, handle streaming responses, implement push notifications, or orchestrate multi-agent workflows. Trigger words: a2a, agent to agent, agent2agent, a2a protocol, a2a server, a2a client, agent card, agent interoperability, agent co
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 71% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 45% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 36% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 47% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 68% | 0% |
Implements the Agent2Agent (A2A) open protocol for communication between AI agents built on different frameworks. A2A enables agents to discover each other via Agent Cards, negotiate interaction modalities, manage collaborative tasks, and exchange data — all without exposing internal state, memory, or tools. Supports JSON-RPC 2.0 over HTTP(S), streaming via SSE, gRPC, and async push notifications.
/.well-known/agent.json describing identity, capabilities, skills, endpoint, authbashpip install a2a-sdk # Core pip install "a2a-sdk[http-server]" # With FastAPI/Starlette pip install "a2a-sdk[grpc]" # With gRPC
pythonfrom a2a.types import AgentCard, AgentSkill, AgentCapabilities from a2a.server.agent_execution import AgentExecutor, RequestContext from a2a.server.events import EventQueue from a2a.server.apps.starlette import A2AStarletteApplication from a2a.server.request_handler import DefaultRequestHandler from a2a.types import Message, TextPart, TaskState, TaskStatus import uvicorn agent_card = AgentCard( name="Research Assistant", description="Searches the web and answers questions with citations.", url="https://research-agent.example.com", version="1.0.0", capabilities=AgentCapabilities(streaming=True, pushNotifications=True), skills=[AgentSkill( id="web-search", name="Web Search", description="Search the web for current information", tags=["search", "research"], examples=["Find the latest news about AI regulation"], )], defaultInputModes=["text/plain"], defaultOutputModes=["text/plain", "application/json"], ) class ResearchAgentExecutor(AgentExecutor): async def execute(self, context: RequestContext, event_queue: EventQueue): query = context.get_user_message().parts[0].text await event_queue.enqueue_event( TaskStatus(state=TaskState.working, message=Message( role="agent", parts=[TextPart(text="Searching...")] )) ) result = await self._research(query) await event_queue.enqueue_event( TaskStatus(state=TaskState.completed, message=Message( role="agent", parts=[TextPart(text=result)] )) ) async def cancel(self, context: RequestContext, event_queue: EventQueue): await event_queue.enqueue_event(TaskStatus(state=TaskState.canceled)) async def _research(self, query: str) -> str: return f"Research results for: {query}" # Start server — Agent Card auto-served at /.well-known/agent.json agent_executor = ResearchAgentExecutor() request_handler = DefaultRequestHandler(agent_executor=agent_executor, task_store=InMemoryTaskStore()) app = A2AStarletteApplication(agent_card=agent_card, http_handler=request_handler) uvicorn.run(app.build(), host="0.0.0.0", port=8000)
pythonfrom a2a.client import A2AClient from a2a.types import MessageSendParams, SendMessageRequest, Message, TextPart client = await A2AClient.get_client_from_agent_card_url( "https://research-agent.example.com/.well-known/agent.json" ) # Synchronous request request = SendMessageRequest(params=MessageSendParams( message=Message(role="user", parts=[TextPart(text="Latest quantum computing developments?")]) )) response = await client.send_message(request) if hasattr(response, 'status'): print(f"Task {response.id}: {response.status.state}") if response.status.message: print(response.status.message.parts[0].text) # Streaming response async for event in client.send_message_streaming(request): if hasattr(event, 'status') and event.status.message: for part in event.status.message.parts: if hasattr(part, 'text'): print(part.text, end="", flush=True)
bashnpm install @a2a-js/sdk
javascriptimport { A2AServer, A2AClient, TaskState } from '@a2a-js/sdk'; // Server const server = new A2AServer({ agentCard: { name: 'Code Reviewer', description: 'Reviews code for bugs and best practices', url: 'https://code-reviewer.example.com', version: '1.0.0', capabilities: { streaming: true }, skills: [{ id: 'review', name: 'Code Review', description: 'Analyze code for issues', tags: ['code', 'review'] }], defaultInputModes: ['text/plain'], defaultOutputModes: ['text/plain'], }, async onMessage(context, eventQueue) { const userText = context.getUserMessage().parts[0].text; await eventQueue.enqueue({ status: { state: TaskState.WORKING, message: { role: 'agent', parts: [{ text: 'Reviewing...' }] } } }); const review = await reviewCode(userText); await eventQueue.enqueue({ status: { state: TaskState.COMPLETED, message: { role: 'agent', parts: [{ text: review }] } } }); }, }); server.listen(8000); // Client const client = await A2AClient.fromAgentCardUrl('https://code-reviewer.example.com/.well-known/agent.json'); const response = await client.sendMessage({ message: { role: 'user', parts: [{ text: 'Review: function add(a,b) { return a + b; }' }] }, });
python# Sequential: research → write → review research_agent = await A2AClient.get_client_from_agent_card_url("https://research-agent.example.com/.well-known/agent.json") writer_agent = await A2AClient.get_client_from_agent_card_url("https://writer-agent.example.com/.well-known/agent.json") research_result = await research_agent.send_message(SendMessageRequest( params=MessageSendParams(message=Message(role="user", parts=[TextPart(text="Research quantum computing breakthroughs 2025")])) )) article = await writer_agent.send_message(SendMessageRequest( params=MessageSendParams(message=Message(role="user", parts=[TextPart(text=f"Write blog post: {research_result.status.message.parts[0].text}")])) )) # Parallel fan-out import asyncio results = await asyncio.gather( query_agent(agent_a, "Analyze market trends"), query_agent(agent_b, "Analyze competitor products"), query_agent(agent_c, "Analyze customer feedback"), )
| | A2A | MCP | |---|---|---| | Purpose | Agent-to-agent communication | Agent-to-tool communication | | Actors | Agent ↔ Agent | Agent ↔ Tool/Data source | | Tasks | Stateful, long-running, async | Stateless function calls | | Use when | Delegating to another autonomous agent | Calling a specific tool/API |
Input: "Build an A2A server that acts as a customer support router. It receives customer queries and delegates to specialized agents: billing-agent, technical-agent, and sales-agent based on the query content."
Output: A2A server with Agent Card listing routing as its primary skill, message handler that classifies queries, A2A client connections to 3 downstream agents, task forwarding with context preservation, aggregated response, and fallback to human handoff.
Input: "Create a multi-agent code pipeline: code-writer generates code, test-writer creates tests, code-reviewer reviews both. Each is an independent A2A server. Build an orchestrator."
Output: 3 A2A server implementations each with Agent Card and execution logic, orchestrator client with sequential pipeline (write → test → review), streaming updates, and error handling with feedback loops on rejection.
/.well-known/agent.json — this is the standard discovery endpointinput-required state for human-in-the-loop scenariosOther measured skills in the registry, with their headline benchmark lift.