Skip to content

A2A Protocol

CodeTether Server is a production implementation of the A2A (Agent-to-Agent) Protocol, an open standard from the Linux Foundation.

What is A2A?

The Agent-to-Agent Protocol defines how AI agents communicate, collaborate, and solve problems together. It provides:

  • Standardized discovery via Agent Cards
  • Task-based communication with JSON-RPC 2.0
  • Real-time streaming via Server-Sent Events
  • Multi-turn conversations with session state

Official SDK Integration

CodeTether now uses the official A2A Python SDK (a2a-sdk>=0.3.22) from the A2A Project. This provides:

  • Protocol compliance - All data structures and methods match the official specification
  • Battle-tested streaming - Robust SSE implementation with proper backpressure handling
  • Standard error codes - Consistent error handling across all A2A implementations
  • Type safety - Full Pydantic models for request/response validation

Our previous custom implementation has been replaced with thin wrappers around the SDK, ensuring interoperability with any A2A-compliant agent.

Specification Compliance

CodeTether aims to be A2A-compliant and implements the core pieces used by this project:

Section Feature Status
§5 Agent Discovery (Agent Card) ✅ Full
§6 Protocol Data Objects ✅ Full
§7 JSON-RPC Methods ✅ Full
§8 Streaming (SSE) ✅ Full
§9 Common Workflows ✅ Full

Agent Card

Every CodeTether server exposes an Agent Card at /.well-known/agent-card.json:

curl https://api.codetether.run/.well-known/agent-card.json
{
  "name": "CodeTether Server",
  "description": "Production A2A coordination server",
  "url": "https://api.codetether.run",
  "version": "1.0.0",
  "provider": {
    "organization": "CodeTether",
    "url": "https://codetether.run"
  },
  "capabilities": {
    "streaming": true,
    "push_notifications": true,
    "state_transition_history": true
  },
  "skills": [
    {
      "id": "task-coordination",
      "name": "Task Coordination",
      "description": "Coordinate tasks between multiple agents"
    },
    {
      "id": "code-assistance",
      "name": "Code Assistance",
      "description": "AI-powered coding assistance via CodeTether"
    }
  ],
  "authentication": [
    {"scheme": "bearer"}
  ]
}

JSON-RPC Methods

CodeTether supports the following JSON-RPC methods:

message/send

Send a task to the agent.

{
  "jsonrpc": "2.0",
  "method": "message/send",
  "params": {
    "message": {
      "parts": [{"type": "text", "content": "Analyze this code"}]
    }
  },
  "id": "1"
}

message/stream

Send a task and subscribe to streaming updates.

{
  "jsonrpc": "2.0",
  "method": "message/stream",
  "params": {
    "message": {
      "parts": [{"type": "text", "content": "Generate a report"}]
    }
  },
  "id": "1"
}

tasks/get

Get the current state of a task.

{
  "jsonrpc": "2.0",
  "method": "tasks/get",
  "params": {
    "task_id": "task-123"
  },
  "id": "2"
}

tasks/cancel

Cancel a running task.

{
  "jsonrpc": "2.0",
  "method": "tasks/cancel",
  "params": {
    "task_id": "task-123"
  },
  "id": "3"
}

Standard Endpoints

CodeTether exposes the following A2A-compliant endpoints:

Endpoint Method Description
/.well-known/agent-card.json GET Agent discovery (A2A spec)
/a2a/jsonrpc POST JSON-RPC 2.0 endpoint
/a2a/rest/message:send POST REST binding for message/send
/a2a/rest/message:stream POST SSE streaming endpoint
/a2a/rest/tasks/{id} GET Get task status
/a2a/rest/tasks/{id}:cancel POST Cancel a task

The JSON-RPC endpoint accepts all methods (message/send, message/stream, tasks/get, tasks/cancel) via a single URL, while the REST bindings provide more traditional HTTP semantics.

Task States

Tasks in A2A follow a defined state machine:

                    ┌─────────────┐
                    │  submitted  │
                    └──────┬──────┘
              ┌────────────┼────────────┐
              ▼            ▼            ▼
        ┌──────────┐ ┌──────────┐ ┌──────────┐
        │ rejected │ │ working  │ │auth-req'd│
        └──────────┘ └────┬─────┘ └──────────┘
           ┌──────────────┼──────────────┐
           ▼              ▼              ▼
     ┌───────────┐  ┌───────────┐  ┌───────────┐
     │ completed │  │  failed   │  │input-req'd│
     └───────────┘  └───────────┘  └───────────┘
                    ┌───────────┐
                    │ cancelled │
                    └───────────┘
State Description Terminal?
submitted Task received, awaiting processing No
working Agent is actively processing No
input-required Agent needs additional input No
auth-required Authentication/authorization needed No
completed Task finished successfully Yes
failed Task encountered an error Yes
cancelled Task was cancelled by client Yes
rejected Task was rejected by agent Yes

Error Codes

The A2A protocol defines standard JSON-RPC error codes:

Code Name Description
-32001 TaskNotFound The specified task does not exist
-32002 TaskNotCancellable Task is in a terminal state
-32003 PushNotificationNotSupported Agent doesn't support push notifications
-32004 UnsupportedOperation Requested operation not supported
-32005 ContentTypeNotSupported Unsupported content type in message
-32006 InvalidAgentResponse Agent returned malformed response
-32007 AgentUnavailable Target agent is not reachable
-32008 AuthenticationRequired Request requires authentication
-32009 AuthorizationFailed Insufficient permissions

Standard JSON-RPC errors (-32600 to -32700) also apply for malformed requests.

Agent Discovery with Role:Instance Pattern

CodeTether v1.2.2 introduces production-grade agent discovery with unique identities and TTL-based liveness.

How It Works

When a worker registers as an agent, it gets two identities:

Field Purpose Example
name Unique discovery identity code-reviewer:dev-vm:abc123
role Routing identity for send_to_agent code-reviewer

Important: Use role with send_to_agent for routing. The name field is unique per-instance and will NOT route tasks.

Discovery Response

{
  "agents": [
    {
      "name": "code-reviewer:dev-vm:abc123",
      "role": "code-reviewer",
      "instance_id": "dev-vm:abc123",
      "description": "CodeTether worker agent...",
      "url": "https://api.codetether.run",
      "capabilities": {"streaming": true, "push_notifications": true},
      "last_seen": "2026-01-15T12:00:00"
    }
  ],
  "routing_note": "Use 'role' with send_to_agent for routing."
}

TTL-Based Liveness

  • Workers must call refresh_agent_heartbeat every 45s
  • Agents not seen within 120s are filtered from discovery
  • Configurable via A2A_AGENT_DISCOVERY_MAX_AGE environment variable
  • Stale agents are lazily cleaned up from all indexes

Worker Configuration

# Register worker as a discoverable agent
python -m agent_worker.worker \
  --agent-name code-reviewer \
  --agent-description "Python code review specialist" \
  --server https://api.codetether.run

Routing Example

# Discover available agents
agents = await discover_agents()
# Returns: [{"name": "code-reviewer:host-a:1", "role": "code-reviewer", ...}]

# Route to agent by ROLE (not name!)
await send_to_agent(
    agent_name="code-reviewer",  # Uses role
    message="Review auth.py for security issues"
)

Learn More