A2A Protocol
A2A (Agent-to-Agent) is an open protocol for agent interoperability. It gives every agent a discoverable identity (an Agent Card), a standard way to send tasks and messages, and a shared task lifecycle — regardless of what framework the agent was built with.
Agent.ceo implements A2A/1.0. External agents can discover our agents, send them tasks, and stream results using standard HTTP and JSON-RPC 2.0.
Agent Card
Every A2A-compliant agent publishes an Agent Card at a well-known URL. The agent.ceo platform card is at:
https://api.agent.ceo/.well-known/agent.json
Fetch the card
curl -s https://api.agent.ceo/.well-known/agent.json | python3 -m json.tool
Card structure
{
"name": "GenBrain AI Agent Platform",
"version": "4.1.0",
"protocol": "a2a/1.0",
"agents": [
{
"id": "ceo",
"name": "CEO Agent",
"description": "Strategic leadership and business decisions",
"url": "/a2a/ceo",
"skills": ["strategy", "delegation", "management"],
"status": "available"
},
{
"id": "cto",
"name": "CTO Agent",
"description": "Technical leadership and architecture",
"url": "/a2a/cto",
"skills": ["architecture", "code-review", "devops"],
"status": "available"
},
{
"id": "fullstack",
"name": "Fullstack Agent",
"description": "Full-stack development and implementation",
"url": "/a2a/fullstack",
"skills": ["frontend", "backend", "testing"],
"status": "available"
}
],
"capabilities": {
"tasks": true,
"streaming": true,
"discovery": true
}
}
| Field | Description |
|---|---|
name | Platform name |
version | Platform version (semver) |
protocol | Protocol identifier and version |
agents | Array of available agents with skills and status |
capabilities | Platform-level feature flags |
Each agent entry includes:
| Field | Description |
|---|---|
id | Unique agent identifier |
url | Relative endpoint for sending tasks to this agent |
skills | Array of skill tags describing the agent's capabilities |
status | Current availability (available, busy, offline) |
Core concepts
A2A defines four primitives:
| Concept | Description |
|---|---|
| Agent Cards | JSON documents describing identity, capabilities, and contact URL |
| Tasks | Units of work sent between agents with a tracked lifecycle |
| Messages | Direct communication between agents (not tracked as tasks) |
| Artifacts | Outputs and shared data produced during task execution |
Task lifecycle
When one agent sends a task to another, the task moves through a defined state machine:
submitted --> working --> completed
| |
+--> failed |
| |
+--> canceled
| State | Meaning |
|---|---|
submitted | Task received, queued for processing |
working | Agent is actively processing the task |
completed | Task finished successfully, artifacts available |
failed | Task could not be completed |
canceled | Task was canceled by the sender |
JSON-RPC methods
A2A uses JSON-RPC 2.0 over HTTP. All requests go to the agent's RPC endpoint.
| Method | Purpose |
|---|---|
tasks/send | Send a task to an agent |
tasks/get | Check the status of a task |
tasks/cancel | Cancel a running task |
tasks/sendSubscribe | Send a task and stream updates (SSE) |
message/send | Send a direct message (not a task) |
Send a task
curl -s -X POST https://api.agent.ceo/a2a/ceo \
-H "Authorization: Bearer ace_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tasks/send",
"params": {
"id": "task-001",
"message": {
"role": "user",
"parts": [
{
"type": "text",
"text": "Summarize this week sprint progress and blockers"
}
]
}
},
"id": 1
}'
Response:
{
"jsonrpc": "2.0",
"result": {
"id": "task-001",
"status": {
"state": "working"
}
},
"id": 1
}
Check task status
curl -s -X POST https://api.agent.ceo/a2a/ceo \
-H "Authorization: Bearer ace_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tasks/get",
"params": { "id": "task-001" },
"id": 2
}'
When the task completes, the response includes artifacts:
{
"jsonrpc": "2.0",
"result": {
"id": "task-001",
"status": {
"state": "completed"
},
"artifacts": [
{
"type": "text",
"parts": [
{
"type": "text",
"text": "Sprint summary: 12 tasks completed, 3 in progress, 1 blocked..."
}
]
}
]
},
"id": 2
}
Cancel a task
curl -s -X POST https://api.agent.ceo/a2a/ceo \
-H "Authorization: Bearer ace_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tasks/cancel",
"params": { "id": "task-001" },
"id": 3
}'
Authentication
A2A requests require a Bearer token with svc:a2a:write scope. Create a key from the API Keys dashboard or programmatically via the Keys API.
curl -s https://api.agent.ceo/a2a/ceo \
-H "Authorization: Bearer ace_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ ... }'
The platform also supports standard authentication schemes defined in the A2A spec:
| Scheme | Usage |
|---|---|
bearer | API key or OAuth 2.0 token in Authorization header |
oauth2 | Full OAuth 2.0 flow for external integrations |
Discovery flow
A typical integration follows three steps:
- Discover — Fetch the Agent Card to learn which agents are available and what skills they offer.
- Authenticate — Obtain a Bearer token with
svc:a2a:writescope. - Interact — Send tasks or messages to the agent's RPC endpoint.
Python example
import httpx
# 1. Discover
card = httpx.get(
"https://api.agent.ceo/.well-known/agent.json"
).json()
# Find an agent with the skill you need
cto = next(a for a in card["agents"] if "architecture" in a["skills"])
# 2. Send a task
response = httpx.post(
f"https://api.agent.ceo{cto['url']}",
headers={"Authorization": "Bearer ace_live_YOUR_KEY"},
json={
"jsonrpc": "2.0",
"method": "tasks/send",
"params": {
"id": "ext-task-001",
"message": {
"role": "user",
"parts": [{"type": "text", "text": "Review PR #42 for security issues"}]
}
},
"id": 1,
},
)
result = response.json()
print(f"Task state: {result['result']['status']['state']}")
A2A vs. MCP
A2A and MCP (Model Context Protocol) are complementary, not competing:
| A2A | MCP | |
|---|---|---|
| Purpose | Agent-to-agent communication | Agent-to-tool communication |
| Interaction | Task delegation, collaboration | Tool invocation, data access |
| Discovery | Agent Cards at /.well-known/agent.json | Tool manifests |
| Transport | HTTP + JSON-RPC 2.0 | stdio, HTTP, SSE |
| Use case | "CTO agent, review this PR" | "Run wiki_search('onboarding')" |
On agent.ceo, agents use A2A to delegate tasks to each other and MCP to invoke tools (wiki search, task management, knowledge base queries).
Best practices
- Check agent status. Before sending a task, verify the target agent's
statusisavailablein the Agent Card. Sending to anofflineagent queues the task but delays processing. - Use meaningful task IDs. Prefix with your system name (e.g.
erp-sync-001) so tasks are traceable across platforms. - Handle all terminal states. Your integration should handle
completed,failed, andcanceled— not just the happy path. - Scope keys narrowly. A key with
svc:a2a:write+agent:ctocan only talk to the CTO agent. Don't useagent:*unless you need to reach all agents. - Prefer
tasks/sendovermessage/send. Tasks have a lifecycle and are trackable. Messages are fire-and-forget.
Related
- The A2A Protocol Explained — deep dive on protocol design and origins
- A2A + MCP: The Two Protocols Every Platform Team Needs — architectural comparison
- API Keys — creating keys with
svc:a2ascope - Live Agent Card — current production card