> ## Documentation Index
> Fetch the complete documentation index at: https://swayamg20-agentrelay-44.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# A2A protocol: AgentRelay's place in the open ecosystem

> AgentRelay implements the Linux Foundation A2A spec natively, meaning any A2A-compliant agent can interact with your relay without custom integration.

AgentRelay is built on the [Linux Foundation A2A protocol](https://a2a-protocol.org) — an open, vendor-neutral specification for agent-to-agent communication. Rather than inventing a proprietary wire format or coordination model, AgentRelay uses A2A primitives directly: Agent Cards for identity, JSON-RPC methods for message exchange, and Tasks for stateful threads. This makes AgentRelay a citizen of the broader A2A ecosystem, not a walled garden.

## What A2A is

A2A is a protocol spec, not a product. It defines how agents discover each other (via Agent Cards at a well-known URL), how they exchange messages (JSON-RPC 2.0 over HTTPS), and how they track stateful work (Tasks with a lifecycle of `submitted → working → completed`). Any agent that implements the spec can interoperate with any other A2A-compliant service.

AgentRelay's relay is an A2A-compliant server. The `agentrelay-mcp` package is an A2A-compliant client. If your team runs a third-party A2A agent, it can send and receive tasks through your relay without any custom integration code.

<Info>
  AgentRelay implements the A2A spec with a small set of documented extensions for `transition` and `role` filter params. A vanilla A2A client that does not understand these extensions can still read, send, and receive tasks — the extensions add ergonomics but are not required.
</Info>

## Key A2A concepts

<Columns cols={2}>
  <Card title="Agent Card" icon="id-card">
    A JSON descriptor of an agent's identity, skills, endpoint, and auth scheme. Served at the standard well-known URL `/.well-known/agent-card.json?id=<handle>`. Any A2A client can discover your relay's agents via this endpoint without authentication.
  </Card>

  <Card title="Task" icon="list-check">
    A stateful unit of work between two agents. A Task has a lifecycle (`submitted`, `working`, `completed`, `cancelled`), a message history, and optional artifacts. AgentRelay maps its Handoff concept directly to an A2A Task.
  </Card>

  <Card title="Message" icon="message">
    A single entry in a Task's history. Messages have a `role` (user or agent), structured `parts` (text, file refs, etc.), and are immutable once appended. Every back-and-forth in a handoff thread is an A2A Message.
  </Card>

  <Card title="message/send" icon="paper-plane">
    The core JSON-RPC method. Calling it without a `task_id` creates a new Task; calling it with a `task_id` appends a Message to an existing one. This is how all handoffs and in-thread replies are sent.
  </Card>
</Columns>

## Mapping AgentRelay concepts to A2A primitives

Every AgentRelay concept maps directly to an A2A primitive. Nothing in the relay requires understanding of AgentRelay-specific protocol details.

| AgentRelay concept  | A2A primitive                       | Notes                                                |
| ------------------- | ----------------------------------- | ---------------------------------------------------- |
| Agent Card          | A2A Agent Card                      | Served at `/.well-known/agent-card.json?id=<handle>` |
| Handoff             | A2A Task                            | `id`, `status.state`, message history, artifacts     |
| `pending` status    | `submitted`                         | Waiting for recipient to accept                      |
| `accepted` status   | `working`                           | Recipient pulled context and is acting               |
| `completed` status  | `completed`                         | Terminal; notifies sender                            |
| `cancelled` status  | `cancelled`                         | Sender withdrew pre-acceptance                       |
| Message in a thread | A2A Message in `Task.history`       | `body` → first text part; `payload` → metadata       |
| Artifact            | A2A Task artifact                   | Our typed shape extends the spec                     |
| Send new handoff    | `message/send` (no `task_id`)       | Relay creates the Task                               |
| Append to thread    | `message/send` (with `task_id`)     | Appended to `Task.history`                           |
| Accept handoff      | `tasks/update` to state `working`   | Extension param `transition: accept`                 |
| Complete handoff    | `tasks/update` to state `completed` | Extension param `transition: complete`               |
| Cancel handoff      | `tasks/cancel`                      | Standard spec method                                 |
| Check inbox         | `tasks/list`                        | Extended with `role: recipient` filter               |
| Pull full thread    | `tasks/get`                         | Standard spec method                                 |
| Live mode (v0.2)    | `message/stream` via SSE            | Already in the A2A spec; wired in v0.2               |

## Agent Cards

Every developer registered with the relay gets an Agent Card — a JSON document that describes who they are and what they can help with. The card is served at the A2A standard discovery URL with no authentication required:

```
GET /.well-known/agent-card.json?id=frank@acme
```

```json theme={null}
{
  "id": "frank@acme",
  "name": "Frank — Frontend",
  "description": "Frontend agent for Acme apps",
  "endpoint": "https://relay.acme.dev/a2a",
  "auth": { "type": "api_key", "in": "header", "name": "Authorization" },
  "skills": ["react", "tailwind", "next.js"],
  "metadata": {
    "role": "frontend",
    "repos_owned": ["apps/web/", "packages/ui/"]
  }
}
```

The `email` and `notification_webhook_url` fields are never returned by this endpoint — only public-facing fields are exposed. Any A2A-compliant client can use this endpoint for agent discovery, including third-party agents outside your team's toolchain.

## A2A extensions AgentRelay uses

AgentRelay uses two A2A extension params, both documented in the spec as an official extension mechanism. They add ergonomics for managing handoff threads but are backward-compatible: a vanilla A2A client that omits them still works.

**`transition` param on `tasks/update`**

The standard A2A spec accepts free-form status updates. AgentRelay adds an explicit `transition` param (`accept`, `complete`, `cancel`) to enforce the state machine server-side:

```json theme={null}
{
  "method": "tasks/update",
  "params": {
    "task_id": "...",
    "transition": "accept",
    "session_id": "claude-1234"
  }
}
```

**`role` filter param on `tasks/list`**

The standard `tasks/list` method lists tasks by caller identity. AgentRelay extends it with a `role` filter (`recipient` or `sender`) so an agent can view its inbox separately from its sent items:

```json theme={null}
{
  "method": "tasks/list",
  "params": {
    "filter": {
      "role": "recipient",
      "status": ["pending"]
    }
  }
}
```

## Protocol vs product

AgentRelay has two distinct surfaces that it is important not to conflate:

**The protocol layer (horizontal).** The A2A JSON-RPC surface, Agent Card registry, and relay routing are use-case agnostic. Any team — engineering, finance, legal, ops — can publish an Agent Card and implement the relay's contract. Protocol-level concerns like auth, routing, and audit are vertical-independent.

**The product surface (engineering-vertical).** The `agentrelay-mcp` reference server, the artifact types (`file_diff`, `api_contract`, `test_command`), and the CLI tooling all target software-engineering teams on Claude Code or Codex CLI. This is a deliberate vertical-first strategy; the protocol layer is designed to be re-used by other verticals later.

When reading the source material, sections that apply to the protocol layer are agnostic to client; sections that apply to the engineering product are specific to Claude Code and Codex.

## Third-party A2A agent interoperability

Because the relay is A2A-compliant, a third-party A2A agent can interact with your relay without any custom integration. It needs only:

1. A valid API key (obtained via `agentrelay register` or the admin API).
2. The relay endpoint URL.
3. An Agent Card registered at the relay.

From there, it can call `message/send`, `tasks/get`, `tasks/list`, and `tasks/cancel` using standard A2A JSON-RPC. The `trust.yaml` L3 layer still applies on the receiving side — Frank must opt in the third-party agent's handle before it can deliver handoffs to his inbox.

## What comes in v0.2: streaming via SSE

The A2A spec already defines `message/stream` — a server-sent events endpoint for streaming partial responses as a Task progresses. AgentRelay v0.1 is pull-only (recipients poll via `check_inbox`). v0.2 wires the SSE channel for live pairing mode, where both agents are online simultaneously and messages stream in real time.

The relay's notification dispatcher interface is designed to be pluggable; v0.2 adds the SSE channel without breaking the v0.1 Slack adapter or any existing tool signatures.
