Agent-to-Agent (A2A) Protocol is the emerging standard for how AI agents discover and invoke each other. Where MCP exposes tools to a local model, A2A exposes an entire agent as a callable endpoint that other agents can plan around. If you run a SaaS, publishing an A2A Agent Card makes your service usable by autonomous agents without an integration engineer on the other side. This is the step-by-step for doing it right.
MCP: "here is a toolbox of functions my model can call locally." A2A: "here is a full agent exposing skills, discoverable over HTTP, that another agent can call remotely."
The registration flow
- Pick the skills your agent will expose.
- Publish a valid Agent Card at
/.well-known/agent.json. - Expose a compliant endpoint (HTTP + streaming).
- Implement authentication (OAuth 2.0 or API keys with the right scopes).
- Handle capability negotiation on first connect.
- List yourself in public directories.
Step 1 — Define your skills
A skill is a named capability with a JSON Schema input and output. For us, one skill is test_inbox_placement — input: sender, subject, HTML; output: per-provider folder verdicts + auth report. Another is check_domain_authentication. Start small. Three well-defined skills beat twelve half-done ones.
- Give each skill a unique machine id and a human name.
- Write a one-sentence description that explains when to call it.
- Specify input/output with JSON Schema. Agents will use your schema for validation and planning.
- Mark destructive or billable skills with
"destructive": true.
Step 2 — Publish the Agent Card
The Agent Card is a JSON document served at /.well-known/agent.json. It is the discovery artifact — the A2A equivalent of robots.txt for crawlers.
{
"a2aVersion": "0.2",
"name": "Inbox Check",
"url": "https://check.live-direct-marketing.online",
"description": "Free email deliverability testing across 20+ providers.",
"authentication": {
"schemes": ["bearer"],
"oauth2": {
"authorizationUrl": "https://check.live-direct-marketing.online/oauth/authorize",
"tokenUrl": "https://check.live-direct-marketing.online/oauth/token",
"scopes": {
"tests:read": "Read placement test results",
"tests:write": "Create placement tests"
}
}
},
"capabilities": { "streaming": true, "pushNotifications": true },
"skills": [
{
"id": "test_inbox_placement",
"name": "Test Inbox Placement",
"description": "Send a seed test message and report folder placement across 20+ providers.",
"tags": ["email", "deliverability"],
"input": { "$ref": "#/components/schemas/TestInput" },
"output": { "$ref": "#/components/schemas/TestResult" }
}
],
"contact": { "email": "support@live-direct-marketing.online" }
}- Serve with
Content-Type: application/json. - Serve over HTTPS — plaintext cards are rejected by compliant clients.
- Enable CORS for browser-based agents:
Access-Control-Allow-Origin: *. - Return it at the apex too — both
/.well-known/agent.jsonand your subdomain's path.
Step 3 — Expose a compliant endpoint
A2A uses JSON-RPC 2.0 over HTTP(S) with optional Server-Sent Events for streaming responses. Your endpoint has to support the a2a/tasks.send and a2a/tasks.get methods at minimum, plus the stream endpoint if you set capabilities.streaming = true.
POST /a2a HTTP/1.1
Content-Type: application/json
Authorization: Bearer xxx
{
"jsonrpc": "2.0",
"id": 1,
"method": "a2a/tasks.send",
"params": {
"skillId": "test_inbox_placement",
"input": { "sender": "hello@example.com", "subject": "hi", "html": "<p>...</p>" },
"sessionId": "sess_0123"
}
}Respond with a task id. Agents poll or stream until the task is done. Returnerror objects with standard JSON-RPC error codes (-32600 invalid request, -32601 method not found, -32602 invalid params) for transport failures and a custom code range for skill-level errors.
Step 4 — Authentication and scopes
- OAuth 2.0 (recommended). Register clients (the agents calling you), issue access tokens, honour scopes. Works for multi-tenant SaaS.
- API key. Simpler but opaque. Use for B2B integrations where you control both sides.
- No auth. Fine for read-only, non-billable skills. Rate-limit aggressively.
Match scopes to skills in the Agent Card. An agent that only has tests:read should not be able to call test_inbox_placement — return 403 and a machine-readable error so the remote agent can request elevation.
Step 5 — Capability negotiation
On first connect, the calling agent hits your Agent Card and verifies your declared capabilities match what it needs. Be honest in the card — claiming streaming: true without a working SSE endpoint will get you quietly delisted. Expose a GET /a2a/health that returns a timestamp; other agents use it to decide whether to fall back to the polling path.
Step 6 — List in directories
A2A directories are the equivalent of npm for agents. They crawl agent.json files and offer a searchable index. Submit your card to:
- The official A2A registry (github.com/google-a2a/registry, PR-based).
- Third-party curated lists.
- Any vertical-specific directories in your industry.
/.well-known/agent.jsonreturns 200, is valid against the A2A schema.- Every skill has JSON Schema input + output, one-line description, tag.
- Auth scheme declared and enforced on the endpoint.
POST /a2ahandlestasks.sendandtasks.get.- Health endpoint returns under 500ms.
- Rate limits + error codes documented.