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

# Protocol and App Bridges

> Reference for the band-sdk 6.0.1 adapters that bridge Band to another protocol or app: A2AAdapter and A2AGatewayAdapter, BandACPServerAdapter with ACPServer, and SlackAdapter with SlackApp.

These adapters connect Band to something that is not an agent framework: a remote A2A agent, A2A clients, an ACP editor, or Slack. The bridges that need Band credentials read them from the [`PlatformConnection`](/reference/sdk/agent-and-config#platformconnection) the runtime injects, so none takes `api_key` or `rest_url`. Every adapter follows the shared [adapter construction](/reference/sdk/features#adapter-construction) rules and takes the [feature keywords](/reference/sdk/features#adapter-features).

## `A2AAdapter`

Brings a remote A2A agent into a room as a Band participant.

```python
from band.adapters import A2AAdapter, A2AAdapterConfig
from band.adapters.a2a import A2AAuth

adapter = A2AAdapter(
    config: A2AAdapterConfig,
    **features: Unpack[FeatureKwargs],
)
```

| `A2AAdapterConfig` field | Type              | Required | Description                                           |
| :----------------------- | :---------------- | :------- | :---------------------------------------------------- |
| `remote_url`             | `str`             | Yes      | Base URL of the A2A agent                             |
| `auth`                   | `A2AAuth \| None` | No       | Authentication: API key, bearer token, or headers     |
| `streaming`              | `bool`            | No       | Enable SSE streaming for responses; default is `True` |

```python
from band.adapters import A2AAdapter, A2AAdapterConfig

adapter = A2AAdapter(A2AAdapterConfig(remote_url="http://localhost:9999"))
```

Declares no emit kinds or capabilities, and the remote agent's turns are not judged by the [turn-outcome rule](/reference/sdk/platform-tools#turn-outcome). See [A2A Adapter](/integrate/a2a/adapter) for a worked example.

## `A2AGatewayAdapter`

Exposes Band peers as A2A HTTP endpoints.

```python
from band.adapters import A2AGatewayAdapter, A2AGatewayAdapterConfig

adapter = A2AGatewayAdapter(
    config: A2AGatewayAdapterConfig | None = None,
    *,
    rest_client: AsyncRestClient | None = None,
    **features: Unpack[FeatureKwargs],
)
```

| `A2AGatewayAdapterConfig` field | Type            | Required | Description                                                                                                                                                                              |
| :------------------------------ | :-------------- | :------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `gateway_url`                   | `str \| None`   | No       | Public URL for AgentCards; unset derives `http://localhost:{port}`                                                                                                                       |
| `port`                          | `int`           | No       | HTTP server port; default is `10000`                                                                                                                                                     |
| `response_timeout_s`            | `float \| None` | No       | Seconds to wait for a Band peer to answer an inbound A2A request; default is `300.0`. `None` waits indefinitely; `0` or less raises `ValidationError` (`Input should be greater than 0`) |

`rest_client` is a test injection seam; normally leave it unset. `api_key` and `rest_url` are not constructor parameters; passing either raises `TypeError`. The adapter builds its REST client at startup from the injected `PlatformConnection`. Declares no emit kinds or capabilities. See [A2A Gateway](/integrate/a2a/gateway) for a worked example.

## ACP Server

### `BandACPServerAdapter`

Platform bridge for editor-facing ACP integrations. Import it from `band.adapters`.

```python
from band.adapters import BandACPServerAdapter

adapter = BandACPServerAdapter(
    config: BandACPServerAdapterConfig | None = None,
    *,
    rest_client: AsyncRestClient | None = None,
    **features: Unpack[FeatureKwargs],
)
```

`BandACPServerAdapterConfig` has no fields yet. `rest_client` is a test injection seam. `api_key` and `rest_url` are not constructor parameters; passing either raises `TypeError`. The adapter builds its REST client from the injected `PlatformConnection` and declares no emit kinds or capabilities, so a nonempty `emit` or `capabilities` raises `BandConfigError`.

### `ACPServer`

ACP protocol handler used with `BandACPServerAdapter`.

```python
from band import Agent
from band.adapters import ACPServer, BandACPServerAdapter

adapter = BandACPServerAdapter()
server = ACPServer(adapter)
agent = Agent.from_config("my_agent", adapter=adapter)
```

`ACPServer` implements twelve ACP methods:

| Handler             | ACP method                      |
| :------------------ | :------------------------------ |
| `initialize`        | `initialize`                    |
| `authenticate`      | `authenticate`                  |
| `new_session`       | `session/new`                   |
| `load_session`      | `session/load`                  |
| `list_sessions`     | `session/list`                  |
| `set_session_mode`  | `session/set_mode`              |
| `set_config_option` | `session/set_config_option`     |
| `prompt`            | `session/prompt`                |
| `cancel`            | `session/cancel` (notification) |
| `fork_session`      | `session/fork`                  |
| `resume_session`    | `session/resume`                |
| `close_session`     | `session/close`                 |

It also exposes `ext_method` and `ext_notification` for ACP extension traffic. `set_config_option` is acknowledged and ignored. `initialize` advertises `session/list`, `session/resume`, `session/fork`, and `session/close`; the last three are unstable ACP routes that answer only when the server runs through `run_acp_server(server)` from `band.integrations.acp`, which is what `band-acp` uses, and plain `acp.run_agent(server)` returns `method_not_found` for them. `session/close` cancels the session's active prompt.

See [ACP Server](/integrate/acp/server) for a worked example.

## `SlackAdapter`

Wraps an inner framework adapter and bridges it into Slack.

```python
from band.integrations.slack import SlackAdapter, SlackAdapterConfig, SlackApp

adapter = SlackAdapter(
    config: SlackAdapterConfig,
    *,
    inner: SimpleAdapter,
    web_client_factory: WebClientFactory | None = None,
    rest_client: AsyncRestClient | None = None,
    **features: Unpack[FeatureKwargs],
)
```

| `SlackAdapterConfig` field | Type                   | Default                    | Description                                                                                                                                                                    |
| :------------------------- | :--------------------- | :------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `apps`                     | `tuple[SlackApp, ...]` | required                   | One or more Slack app configurations with unique slugs; each gets an HTTP route at `/{slug}/events`. A repeated slug raises `ValidationError` (`Duplicate SlackApp slug: ...`) |
| `transport`                | `"http" \| "socket"`   | `"http"`                   | `"http"` mounts a router via `adapter.router`; `"socket"` opens a Socket Mode WebSocket per app                                                                                |
| `write_tool_names`         | `frozenset[str]`       | the platform's write tools | Tool names treated as state-changing writes for Slack progress rendering, such as `band_send_message` and `band_add_participant`                                               |
| `show_tool_progress`       | `bool`                 | `True`                     | Render Block Kit plan and task progress blocks in Slack                                                                                                                        |
| `mirror_slack_context`     | `bool`                 | `True`                     | Mirror inbound Slack turns into the bound Band room as context-only events                                                                                                     |

| Argument             | Type                       | Required | Description                                                                                                                |
| :------------------- | :------------------------- | :------- | :------------------------------------------------------------------------------------------------------------------------- |
| `inner`              | `SimpleAdapter`            | Yes      | Framework adapter that runs the reasoning, such as `AnthropicAdapter`                                                      |
| `web_client_factory` | `WebClientFactory \| None` | No       | Factory for Slack web clients, mainly for tests                                                                            |
| `rest_client`        | `AsyncRestClient \| None`  | No       | REST client injection seam, mainly for tests. Left unset, the bridge builds its own from the injected `PlatformConnection` |

```python
from band.adapters import AnthropicAdapter
from band.integrations.slack import SlackAdapter, SlackAdapterConfig, SlackApp

adapter = SlackAdapter(
    SlackAdapterConfig(
        apps=(SlackApp(slug="dev", bot_token="xoxb-...", signing_secret="..."),),
    ),
    inner=AnthropicAdapter(),
)
```

`SlackAdapter` has no `port` setting: mount `adapter.router` into your own ASGI app. Passing `port` to `SlackAdapterConfig` raises `ValidationError`.

Omit every feature keyword and the bridge adopts the inner adapter's resolved features unchanged. Pass one and it merges over the inner adapter's features field by field, writes the result onto the inner adapter, and validates against the inner adapter's supported sets.

### `SlackApp`

Configuration for one Slack app served by `SlackAdapter`. The required tokens depend on the config's `transport`; the wrong combination raises `ValidationError` at config construction, for example `transport='socket' requires app_token and bot_token on every SlackApp; missing for: dev`.

| Parameter        | Type  | Required    | Description                                                                                     |
| :--------------- | :---- | :---------- | :---------------------------------------------------------------------------------------------- |
| `slug`           | `str` | Yes         | Identifier used as the HTTP route segment `/{slug}/events`                                      |
| `bot_token`      | `str` | Yes         | Slack bot token (`xoxb-...`) for outbound API calls                                             |
| `signing_secret` | `str` | Conditional | Slack signing secret for request verification; required for HTTP transport                      |
| `app_token`      | `str` | Conditional | Slack app-level token (`xapp-...`) that opens a Socket Mode WebSocket; required for Socket Mode |

See [Slack](/integrate/slack) for a worked example.