A2A Protocol in Python: A Practical Guide to Agent Interoperability
Learn how A2A connects independently built AI agents, how it differs from MCP, and how to approach Agent Cards, tasks, Python clients, security, and production rollout.
AI agents become harder to integrate when each lives behind a different framework, deployment, identity system, and task model. Wrapping every remote agent as a one-off function can work for a prototype, but it often loses the ability to report progress, return artifacts, or continue long-running work. The Agent2Agent (A2A) protocol defines a shared way for independently built agent applications to discover each other and exchange task-oriented messages without requiring either side to expose its private reasoning or internal tools. This guide explains where A2A fits, how to start with the official Python SDK, and what still needs ordinary engineering discipline before a remote agent can be trusted in production.
What A2A is—and what it is not
A communication contract between independently operated agents, not a model or agent framework.
A2A gives a client agent a standard way to discover a remote agent's declared capabilities, send it a message, track task progress, and receive a result. The two agents can be built with different frameworks or model providers. The remote agent remains responsible for its own execution and can keep its internal prompts, memory, tools, and implementation private.
A2A standardizes the interaction boundary, not the quality of the remote agent's decisions. It does not make an untrusted agent safe, guarantee a task will finish, or remove the need to define success. Your application still needs timeouts, authorization, validation, retry rules, and a human escalation path for consequential actions.
If you are still designing a single agent before exposing it remotely, start with our production AI-agent guide; A2A is most useful after there is a real boundary between independently managed components.
| A2A provides | Your application still provides |
|---|---|
| A common message and task interaction model | Business rules and acceptance criteria |
| Capability discovery through an Agent Card | Trust decisions and permission checks |
| Task status and result/artifact exchange | Timeouts, retries, and recovery |
| Interoperability across implementations | Version compatibility and end-to-end tests |
A2A vs MCP vs an agent framework
Choose the layer that matches the interaction you need.
A2A and the Model Context Protocol (MCP) solve different integration problems. MCP is commonly used when an agent needs structured access to tools, APIs, or resources. A2A is for communication with another agent that owns its own task logic and may collaborate over several steps. An agent framework helps build and orchestrate an agent; it is not a replacement for either protocol.
A useful architecture can use all three: a framework runs the local agent, MCP connects it to tools, and A2A lets it delegate a bounded task to a remote agent. Avoid adding a protocol just because it is popular. A direct function call or ordinary HTTP API is often simpler when both components are deployed together and have a narrow contract.
For the tool-facing side of this architecture, compare our Google Cloud API Gateway MCP analysis and WebMCP guide; those cover different boundaries from remote agent collaboration.
| Layer | Best-fit question | Example |
|---|---|---|
| Agent framework | How do I build and orchestrate an agent? | Planning, state, and local tool selection |
| MCP | How does an agent access a tool or resource? | Query a database or call a bounded business tool |
| A2A | How do independently managed agents collaborate? | Delegate a task and receive progress plus an artifact |
| HTTP/API call | Can a deterministic service perform one operation? | Fetch a record or submit a validated request |
Messages, tasks, and artifacts
Model a remote call as work with a lifecycle, not just a returned string.
An agent task may involve retrieval, model calls, tools, retries, or human review. A2A's task-oriented model lets the server communicate status and results while work progresses. The client can distinguish 'accepted and still working' from 'completed with an artifact' or 'failed and needs recovery'.
Streaming is useful when the caller needs progress or incremental updates. It also creates operational responsibilities: clients must handle disconnects, partial results, tasks that outlive the original HTTP connection, and duplicate submissions after uncertain failures. If the caller only needs a final value, start with non-streaming behavior until measurements justify the extra complexity.
| State or event | Recommended client behavior |
|---|---|
| Submitted / accepted | Persist the task ID and show that work started; do not claim completion. |
| Working / status update | Update progress and apply an overall deadline. |
| Artifact update | Validate type, size, provenance, and schema before using the result. |
| Completed | Run business-level acceptance checks before downstream changes. |
| Failed or cancelled | Record the reason and retry only if the operation is safe. |
A Python client starting point
Use the official SDK's discovery and client helpers instead of inventing a private wire format.
The official Python quickstart demonstrates a discovery-first flow: fetch the remote Agent Card, create a client from the card, build a user message, and send it through the SDK. The example below follows that API shape and assumes a compatible test server is already running at the supplied base URL.
This is an illustrative client pattern, not a complete production integration. It intentionally omits authentication configuration, application-specific result parsing, retries, and deployment setup. Check the pinned SDK version's docs and sample application before copying it into a service.
a2a_client_example.pyimport asyncio
import httpx
from a2a.client import A2ACardResolver, ClientConfig, create_client
from a2a.helpers import new_text_message
from a2a.types import Role, SendMessageRequest
async def send_to_agent(base_url: str, prompt: str) -> None:
async with httpx.AsyncClient() as http_client:
resolver = A2ACardResolver(
httpx_client=http_client,
base_url=base_url,
)
agent_card = await resolver.get_agent_card()
client = await create_client(
agent=agent_card,
client_config=ClientConfig(streaming=False),
)
message = new_text_message(prompt, role=Role.ROLE_USER)
request = SendMessageRequest(message=message)
async for response in client.send_message(request):
print(response)
if __name__ == "__main__":
asyncio.run(
send_to_agent(
base_url="http://127.0.0.1:9999",
prompt="Summarize the test task status.",
)
)Tips
- Use the official a2a-samples repository as the runnable reference for a complete local client/server pair.
- Do not put access tokens, customer prompts, or private endpoint credentials in source control or log output.
- Keep a test fixture for the Agent Card so schema or interface changes fail in CI rather than at runtime.
Implementing the server boundary
Keep business logic separate from the protocol adapter.
The SDK's `AgentExecutor` interface is where application-specific work runs. The current Python tutorial defines asynchronous `execute` and `cancel` methods and uses an event queue to send task status and artifacts back to the protocol layer. This is a useful seam: the executor can call an existing workflow while the SDK handles the protocol interaction.
Separate input validation, authorization, task orchestration, side-effecting tools, and output validation. That makes it possible to test business logic without a network and to test the protocol adapter with a fake executor.
Define cancellation before exposing it. Cancelling a request does not reverse an email already sent, purchase already placed, or database write already committed. For side-effecting tasks, use idempotency controls in the application and compensating actions where rollback is possible.
- Validate messages and media types before handing them to the agent.
- Return structured artifacts with documented schemas.
- Emit meaningful working, completed, failed, and cancelled states.
- Make cancellation and retry behavior explicit for each side effect.
Security, reliability, and observability
Interoperability is not a reason to trust a remote agent with broad authority.
The A2A specification relies on familiar web-security practices: encrypted transport, server identity verification, and authentication/authorization appropriate to the deployment. Clients can discover declared security schemes through the card, but credentials should be obtained through a trusted process and checked by the server. A protocol-level description does not grant permission to execute a privileged action.
The main risk is confused authority. A remote agent can return plausible but incorrect instructions, and an authenticated caller may still request an action outside its business role. Enforce authorization at the receiving service and again at the resource or tool that performs the side effect. Treat remote output as untrusted input until validated.
Set an overall deadline for the business task and separate timeouts for discovery, connection, and execution. A retry is safe only when the operation is idempotent or duplicate work can be detected. If a connection drops after submission, build a recovery path that can find the existing task instead of blindly submitting a second copy.
For traces, latency, and sensitive-payload handling across model calls and tools, see our OpenTelemetry observability blueprint. Carry a correlation or task ID across the boundary, but keep prompt and artifact contents out of telemetry unless a reviewed policy requires them.
| Control | What to verify |
|---|---|
| Transport and identity | Use HTTPS/TLS and validate the expected server identity. |
| Authentication and authorization | Use trusted credentials and enforce tenant, resource, and action permissions server-side. |
| Data minimization | Send only the context needed; redact secrets and sensitive values from logs. |
| Output validation | Check artifact schema, size, type, provenance, and business invariants. |
| Reliability | Test deadlines, duplicate submissions, cancellation, disconnects, and terminal states. |
| Observability | Track task outcomes, latency, retries, and artifact validation failures without capturing unnecessary payloads. |
- Separate protocol health from business quality: a completed task can still be wrong.
- Pin SDK versions and rerun contract tests when the remote implementation or Agent Card changes.
- Keep a manual fallback for tasks whose failure would block a user or business process.
When A2A is worth the extra boundary
Adopt it when independent agent ownership or task semantics provide a measurable benefit.
A2A is a strong candidate when teams operate agents independently, need to preserve separate implementation and data boundaries, or must exchange progress and artifacts for long-running tasks. It can reduce bespoke point-to-point adapters, but it cannot eliminate domain-specific contracts, identity management, operational ownership, or acceptance tests.
For a single application with one deployment and a short deterministic operation, a local function or conventional API may be easier to secure and operate. Start with the smallest interface that meets the requirement, then introduce A2A when independent agent ownership or task semantics justify the extra moving parts.
| Situation | Recommended starting point | Reason |
|---|---|---|
| One service and a simple deterministic call | Function or ordinary HTTP API | Less operational overhead |
| An agent needs structured tools or resources | MCP or direct tool/API integration | The interaction is agent-to-tool |
| Separately managed agents must collaborate | Evaluate A2A | A shared task/discovery contract can reduce bespoke adapters |
| Long-running work needs progress and artifacts | Evaluate A2A task/streaming patterns | The caller can observe lifecycle state |
| Permissions, ownership, or rollback are unclear | Do not expose the task yet | Resolve the trust boundary first |
A staged rollout plan
Prove the boundary with a bounded, reversible task.
Start with one low-risk skill that has a clear input schema, a predictable output artifact, and no irreversible side effects. Run the official sample locally, then replace the demo executor with a small adapter around a real workflow. Measure discovery success, task completion, latency, and error recovery before adding streaming or more agents.
In staging, test authenticated and unauthorized callers, stale Agent Cards, malformed inputs, remote timeouts, streaming disconnects, duplicate requests, and cancellation. Review logs for accidental payload capture. Only after these checks pass should you add a write-capable skill. The milestone is not merely that two agents can talk; it is that the system can constrain, observe, validate, and recover from what they do.
- Phase 1 — local sample: pin the SDK, run a known-good client/server pair, and record the protocol binding.
- Phase 2 — read-only pilot: expose one narrow skill, validate all inputs/outputs, and keep a human fallback.
- Phase 3 — staging: add authentication, deadlines, telemetry, contract tests, and failure injection.
- Phase 4 — controlled production: monitor a small caller set and expand only when reliability and business value are demonstrated.
FAQ
What does A2A stand for?
A2A stands for Agent2Agent. It is an open protocol for communication and collaboration between independently built AI agent applications.
Is A2A a replacement for MCP?
No. MCP focuses on connecting an agent to tools and resources; A2A focuses on communication between agents. An application can use both at different boundaries.
Do I need a specific agent framework to use A2A?
No. A2A is designed to connect agents across frameworks and vendors. Each side still needs a compatible A2A implementation and protocol binding.
What is an Agent Card?
It is a machine-readable document describing an agent's identity, skills, supported interfaces, media types, and declared capabilities so clients can discover how to interact with it.
Can an A2A task run for a long time?
A2A supports task-oriented and streaming/asynchronous patterns. Your application still needs deadlines, task recovery, and a policy for disconnected clients.
Does an Agent Card make a remote agent trustworthy?
No. It describes the server and advertised capabilities. Trust still requires server identity verification, authentication, authorization, validation, and operational controls.
Is the Python example production-ready?
No. It follows the official quickstart's client API shape for a local test server. Production use needs version pinning, TLS, correct authentication, timeout/retry policies, result validation, and monitoring.
Which A2A version should I target?
Use the version supported by the SDK and remote server you have tested together. The official roadmap lists v1.1 work as ongoing as of September 2026, so do not assume roadmap items are part of the released v1.0 baseline.
Sources
Primary and authoritative sources reviewed for this article.
- A2A Protocol — official documentation
Primary documentation for the protocol's purpose, concepts, SDKs, and relationship with MCP.
- A2A Protocol — What is A2A?
Official explanation of discovery, authentication, messaging, and the agent stack.
- Official A2A Python SDK
SDK repository and supported Python integration options.
- Python quickstart — Agent Skills and Agent Card
Official reference for skills, Agent Card fields, interfaces, and media types.
- Python quickstart — Agent Executor
Official execute/cancel interface and task event behavior.
- Python quickstart — Interacting with the Server
Official client example using A2ACardResolver, create_client, and SendMessageRequest.
- A2A protocol specification
Normative reference for protocol bindings, transport security, authentication, and authorization expectations.
- A2A v1.0 release announcement
Official release announcement dated March 12, 2026.
- A2A Protocol roadmap
Official roadmap last updated September 15, 2026; used to distinguish planned v1.1 work from the v1.0 baseline.
Conclusion
A2A is useful when agents need to collaborate across real ownership or deployment boundaries, especially when tasks require progress updates and structured artifacts. It is not a shortcut around system design: discovery must be trusted, permissions enforced by the receiving service, outputs validated, and failures made recoverable. Start with one bounded task, use the official Python SDK as the reference implementation, and let contract tests and measured outcomes determine whether the protocol deserves a larger role in the system.