Skip to main content

features

A2A Protocol

Agent-to-Agent discovery and communication using the open A2A protocol. Agent Cards, task lifecycle, JSON-RPC methods, and integration examples.

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
  }
}
FieldDescription
namePlatform name
versionPlatform version (semver)
protocolProtocol identifier and version
agentsArray of available agents with skills and status
capabilitiesPlatform-level feature flags

Each agent entry includes:

FieldDescription
idUnique agent identifier
urlRelative endpoint for sending tasks to this agent
skillsArray of skill tags describing the agent's capabilities
statusCurrent availability (available, busy, offline)

Core concepts

A2A defines four primitives:

ConceptDescription
Agent CardsJSON documents describing identity, capabilities, and contact URL
TasksUnits of work sent between agents with a tracked lifecycle
MessagesDirect communication between agents (not tracked as tasks)
ArtifactsOutputs 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
StateMeaning
submittedTask received, queued for processing
workingAgent is actively processing the task
completedTask finished successfully, artifacts available
failedTask could not be completed
canceledTask 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.

MethodPurpose
tasks/sendSend a task to an agent
tasks/getCheck the status of a task
tasks/cancelCancel a running task
tasks/sendSubscribeSend a task and stream updates (SSE)
message/sendSend 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:

SchemeUsage
bearerAPI key or OAuth 2.0 token in Authorization header
oauth2Full OAuth 2.0 flow for external integrations

Discovery flow

A typical integration follows three steps:

  1. Discover — Fetch the Agent Card to learn which agents are available and what skills they offer.
  2. Authenticate — Obtain a Bearer token with svc:a2a:write scope.
  3. 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:

A2AMCP
PurposeAgent-to-agent communicationAgent-to-tool communication
InteractionTask delegation, collaborationTool invocation, data access
DiscoveryAgent Cards at /.well-known/agent.jsonTool manifests
TransportHTTP + JSON-RPC 2.0stdio, 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 status is available in the Agent Card. Sending to an offline agent 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, and canceled — not just the happy path.
  • Scope keys narrowly. A key with svc:a2a:write + agent:cto can only talk to the CTO agent. Don't use agent:* unless you need to reach all agents.
  • Prefer tasks/send over message/send. Tasks have a lifecycle and are trackable. Messages are fire-and-forget.

Related

Ready to put this in production? Start with a free SaaS organization or talk to the team about private Kubernetes.