How to Get Started with the A2A Protocol
The A2A protocol has official SDKs in Python, Go, JavaScript, and Java. This guide uses the Python SDK because it is the most mature and has the broadest documentation. The concepts transfer directly to other languages, as the protocol is the same regardless of which SDK you use.
You need Python 3.10 or later installed on your machine. The SDK has minimal dependencies (it uses standard library modules plus a lightweight HTTP framework) and installs in seconds. No database, message broker, or external service is required for local development.
Install the A2A Python SDK
The official Python SDK is published on PyPI as a2a-sdk. Install it in your project environment:
pip install a2a-sdk
This installs the core library including the server framework, client utilities, Agent Card builder, JSON-RPC message handling, and SSE streaming support. The package has a small dependency footprint, primarily relying on httpx for HTTP operations and uvicorn for the ASGI server.
Verify the installation by checking the version: python -c "import a2a; print(a2a.__version__)". As of mid-2026, the latest stable version is in the 0.3.x series. The API is stabilizing but minor changes between versions are still possible, so pin your version in requirements.txt for production projects.
Define Your Agent Card
The Agent Card describes what your agent can do. For this starter project, we will create a simple text-processing agent with two skills: summarization and translation. Define the card as a Python dictionary or use the SDK's AgentCard builder class.
The required fields are: name (your agent's display name), description (a detailed explanation of capabilities), url (the endpoint where the agent accepts A2A requests), and skills (an array of capability definitions). Each skill needs an id, name, and description. Optional but recommended fields include inputSchema and outputSchema for each skill, and authentication for specifying auth requirements.
For local development, set the URL to http://localhost:8000/a2a and leave authentication as none. In production, you would use HTTPS and configure OAuth 2.0 or API key authentication. The Agent Card is automatically served at /.well-known/agent.json by the SDK's server component.
Write skill descriptions as if you are explaining the capability to someone who has never used your agent. Include what inputs the skill expects, what it produces, and any limitations. "Summarizes text documents up to 50,000 words, producing a concise summary of 100 to 500 words. Works best with English-language technical and business documents." is much more useful than "Summarizes text."
Implement the Task Handler
The task handler is the function that does the actual work when your agent receives a task. The SDK calls this function with the incoming task object, and your handler processes it and returns results. The handler receives the task's messages (containing the client's instructions) and must return updated task state with any produced artifacts.
A basic handler examines the incoming message, determines which skill the client is requesting (based on the message content or metadata), performs the work, and returns the result. For our text-processing agent, the handler would check whether the client wants summarization or translation, process the input text accordingly, and return the output as a TextPart in an artifact.
The handler can set the task to different states depending on the situation. Return completed with artifacts when the work is done. Return input-required with a message when you need more information from the client. Return failed with an error message when something goes wrong. The SDK handles the state transitions and JSON-RPC response formatting.
For this starter project, keep the handler simple: extract the text from the incoming message's TextPart, process it (you can use a local LLM call, an API call to an AI provider, or even a mock implementation for testing), and return the result as a completed task with one artifact containing a TextPart.
Start the A2A Server
The SDK provides a server class that handles HTTP routing, Agent Card serving, JSON-RPC parsing, and dispatching requests to your handler. Configure the server with your Agent Card and handler function, then start it.
The server binds to the specified host and port (default: 0.0.0.0:8000) and begins accepting connections. It automatically sets up two routes: /.well-known/agent.json for Agent Card discovery and the A2A endpoint URL you specified in the card for JSON-RPC requests. The SDK handles content type negotiation, error formatting, and CORS headers.
Start the server and verify it is running by opening http://localhost:8000/.well-known/agent.json in a browser. You should see your Agent Card as formatted JSON. This confirms that the server is up and the Agent Card is being served correctly. The A2A endpoint itself only accepts POST requests, so attempting to visit it in a browser will return a method-not-allowed error, which is expected.
For development, the SDK includes hot-reload support when running with uvicorn's reload flag. This lets you modify your handler code and see changes immediately without restarting the server. In production, run the server behind a reverse proxy (nginx, Caddy, or a cloud load balancer) with TLS termination.
Build and Test a Client
With the server running, build a client that interacts with it. The SDK's client class handles Agent Card fetching, task construction, JSON-RPC formatting, and response parsing. Create a new Python script for the client (it runs as a separate process from the server).
The client workflow has three phases. First, fetch the Agent Card by providing the server's base URL. The client sends a GET request to /.well-known/agent.json and parses the response into an AgentCard object. Second, construct a task with a unique ID and a message containing your request. The message includes a TextPart with the text you want summarized or translated. Third, send the task using the send_task method, which calls tasks/send on the server and returns the completed task with artifacts.
Extract the result from the task's artifacts. Each artifact contains parts (TextPart, DataPart, or FilePart), and you access the text content of the first TextPart to get the summarized or translated text. Print it to the console to verify the end-to-end flow works.
Test error scenarios too. Send a task with empty text and verify the server returns a meaningful error. Send a task referencing a skill the server does not support and check the response. These tests help you understand how the protocol handles edge cases and build more robust agents.
Add Streaming Support
Once basic request-response works, upgrade to streaming for a better user experience. Replace the client's send_task call with send_task_subscribe, which uses the tasks/sendSubscribe method and returns an async iterator of SSE events instead of a single response.
On the server side, modify your handler to yield partial results instead of returning a single completed result. The SDK supports a streaming handler pattern where you yield status updates and partial artifacts as you work. For a summarization task, you might yield a "working" status update when you start processing, yield partial summary text as it is generated, and yield the final completed status with the full artifact when done.
The client iterates over the event stream and processes each event as it arrives. TaskStatusUpdateEvent events indicate state changes (submitted, working, completed). TaskArtifactUpdateEvent events carry partial or complete artifacts. The client can display progress to the user, update a UI, or pipe results to another system as they stream in.
Streaming is optional in A2A, and not all agents need it. Short tasks that complete in under a second do not benefit from streaming complexity. But for tasks that take more than a few seconds, streaming provides a significantly better experience because the client can show progress rather than a blank wait.
What to Build Next
With a working server and client, you have several natural next steps. Add authentication by configuring OAuth 2.0 or API key support in your Agent Card and server. Connect your handler to a real LLM (Claude, GPT, Gemini, or a local model via Ollama) instead of a mock implementation. Add more skills to your agent by expanding the Agent Card and handler. Build a second agent and have the two agents collaborate through A2A.
For production deployment, you will need HTTPS (use a reverse proxy with Let's Encrypt or a cloud load balancer), persistent task storage (the SDK stores tasks in memory by default, which is lost on restart), logging and monitoring (the SDK emits structured logs compatible with standard observability tools), and proper error handling with retry logic in your client.
If you already have agents built on LangGraph, CrewAI, Google ADK, or another framework, the next step is adding an A2A adapter layer. Each framework has community or official adapters that wrap your existing agent as an A2A server with minimal code changes. You keep your existing agent logic intact and just add the A2A protocol layer on top.
Getting started with A2A requires four things: the SDK (pip install a2a-sdk), an Agent Card defining your capabilities, a task handler that does the work, and a client to test with. A complete working prototype takes under 100 lines of Python.