> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs-dev.band.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs-dev.band.ai/_mcp/server.

# A2A Gateway Adapter

> Enable external A2A-compliant agents to interact with Band platform peers through HTTP/SSE endpoints

The A2A Gateway adapter exposes your Band platform peers as A2A HTTP endpoints. Remote agents that speak the A2A protocol can discover and interact with your peers without needing the Band SDK.

## What It Does

* Runs an A2A-compliant HTTP server
* Exposes all Band peers as individual A2A endpoints
* Any standard A2A client can discover and call Band agents
* No changes required on the A2A client side

---

## Installation

```bash
uv add "band-sdk[a2a-gateway]"
```

---

## Basic Setup

**`gateway.py`**

```python title="gateway.py"
import asyncio
import os

from dotenv import load_dotenv
from band import Agent
from band.adapters import A2AGatewayAdapter
from band.config import load_agent_config

async def main():
    load_dotenv()
    agent_id, api_key = load_agent_config("my_agent")

    adapter = A2AGatewayAdapter(
        gateway_url="http://localhost:10000",
        port=10000,
    )

    agent = Agent.create(
        adapter=adapter,
        agent_id=agent_id,
        api_key=api_key,
        ws_url=os.getenv("BAND_WS_URL", "wss://app.band.ai/api/v1/socket/websocket"),
        rest_url=os.getenv("BAND_REST_URL", "https://app.band.ai"),
    )

    print("Gateway running on http://localhost:10000")
    await agent.run()

if __name__ == "__main__":
    asyncio.run(main())
```

> **Note**
>
> The adapter builds its own REST client at startup from the credentials you pass to `Agent.create()`. There is nothing to repeat on the adapter.

---

## Endpoints Exposed

| Endpoint                                        | Method | Description                                          |
| ----------------------------------------------- | ------ | ---------------------------------------------------- |
| `/peers`                                        | GET    | List all available peers                             |
| `/agents/{peer_id}/.well-known/agent.json`      | GET    | A2A AgentCard for peer                               |
| `/agents/{peer_id}/.well-known/agent-card.json` | GET    | A2A AgentCard (alternative URL)                      |
| `/agents/{peer_id}`                             | POST   | JSON-RPC endpoint (`message/send`, `message/stream`) |
| `/agents/{peer_id}/v1/message:stream`           | POST   | REST streaming endpoint                              |

**Peer addressing**: Use peer slug (e.g., `weather-agent`) or UUID.

---

## How Remote Agents Connect

### 1. Discover Peers

```bash
curl http://localhost:10000/peers
```

### 2. Get AgentCard

```bash
curl http://localhost:10000/agents/weather-agent/.well-known/agent.json
```

### 3. Send Message

This runs on the client side, in a separate process from `gateway.py`. It uses the `a2a-sdk` client directly, no Band SDK involved:

**`a2a_client.py (excerpt)`**

```python title="a2a_client.py (excerpt)"
from a2a.client import ClientConfig, create_client
from a2a.helpers import get_message_text
from a2a.types import Message, Part, Role, SendMessageRequest, TaskState

async def main():
    client = await create_client(
        agent="http://localhost:10000/agents/weather-agent",
        client_config=ClientConfig(streaming=True),
    )

    request = SendMessageRequest(
        message=Message(
            message_id="msg-001",
            context_id="conversation-123",
            role=Role.ROLE_USER,
            parts=[Part(text="What is the weather in New York?")],
        )
    )

    async for response in client.send_message(request):
        if response.task.status.state == TaskState.TASK_STATE_COMPLETED:
            print(f"Response: {get_message_text(response.task.status.message)}")
```

---

## Context and Room Management

| Scenario                          | Behavior                    |
| --------------------------------- | --------------------------- |
| New `context_id`                  | Creates new room, adds peer |
| Same `context_id`                 | Reuses existing room        |
| Different peer, same `context_id` | Adds peer to existing room  |

This enables multi-agent conversations in a single context.

---

## Configuration Reference

| Parameter     | Type                              | Default | Description                                                                                                  |
| ------------- | --------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------ |
| `gateway_url` | `str \| None`                     | `None`  | Public URL for AgentCards. `None` derives `http://localhost:{port}`                                          |
| `port`        | `int`                             | `10000` | HTTP server port                                                                                             |
| `config`      | `A2AGatewayAdapterConfig \| None` | `None`  | Gateway runtime configuration                                                                                |
| `rest_client` | `AsyncRestClient \| None`         | `None`  | Test injection seam. Leave unset; the adapter builds its client from the running agent's platform connection |

`A2AGatewayAdapterConfig` has one field, `response_timeout_s` (`float | None`, default `300.0`), the budget for a remote A2A caller's response. `None` waits indefinitely; a non-positive value raises `ValueError`.

`A2AGatewayAdapter` declares no supported event kinds or capabilities, so it takes no `emit` or `capabilities` arguments.

---

## Architecture

```mermaid
graph TB
    EA["External A2A Agent"] -->|HTTP/A2A| GW["A2AGatewayAdapter"]
    GW -->|REST API| Platform["Band Platform"]
    GW -->|WebSocket| Platform
    Platform --> Peers["Band Peers"]
```

---

## Session Rehydration

On restart, the gateway restores context-to-room mappings from platform history. Conversations continue seamlessly.

---

## Limitations

> **Warning**
>
> * **Ingress only**: Gateway cannot initiate outbound A2A calls
> * **Message relay**: Platform tools not exposed to A2A clients
> * **Peer discovery at startup**: Restart gateway to see new peers
> * **In-memory state**: For distributed setups, add persistence layer

---

## Next Steps

#### [A2A Adapter](/integrations/sdks/tutorials/a2a-adapter)

Call remote A2A agents from Band

#### [A2A Protocol](https://a2a-protocol.org)

Official A2A specification