> 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.

# Cloudflare

> Deploy a Band agent to Cloudflare Workers and Containers with the band-sdk Cloudflare example and the Band bridge.

Run a Band agent on Cloudflare with a Python Worker that starts one container per room, and a bridge on your own infrastructure that holds the agent's Band connection. Use it when the agent has to run on Cloudflare. A host that can keep a process running connects directly through the SDK instead. See [Choose an Integration Path](/connect/choose-integration-path).

## How the Pieces Fit

A persistent bridge forwards each event for the agent to the Worker over authenticated HTTP. The Worker routes by room ID to a Durable Object, which runs a Python container for that room. The container reuses the SDK's `OneShotInvoker` and `AnthropicAdapter` to fetch current history, call Band tools, and reply over REST. This is the same bridge and receiver split as [Amazon Bedrock AgentCore](/connect/agentcore#why-a-bridge-and-a-container), with the Worker as the target.

| Piece                     | Where it runs         | What it does                                                                                                                                         |
| ------------------------- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| Bridge                    | Your infrastructure   | Holds the agent's Band WebSocket and POSTs each event to the Worker's `/invocations` endpoint                                                        |
| Worker and Durable Object | Cloudflare            | Accepts only authenticated `POST /invocations` for the configured agent, with a nonempty string room ID, and boots one container per room            |
| Room container            | Cloudflare Containers | Runs the shared receiver, [`examples/oneshot/server.py`](https://github.com/band-ai/band-sdk-python/blob/band-sdk-v7.0.0/examples/oneshot/server.py) |

## Prerequisites

* A Workers Paid Cloudflare account with Containers access. Workers Paid starts at \$5 per month plus usage: container CPU, memory, disk and egress, Durable Objects, Anthropic inference, and the bridge host all add cost. Idle shutdown reduces running time, and the plan is not a spending cap.
* A checkout of the SDK repository, Python 3.12 or later, `uv` 0.13.4 or later, Node 22 or later, and Docker. Cloudflare's deployment CLI, Wrangler, still requires Node. The commands below pin Wrangler 4.153.0.
* A Band agent and its **ID** and **API Key**, created as in the [Quickstart](/quickstart), and an Anthropic API key.

## Deploy the Worker

### Install the Example

```bash
git clone --branch band-sdk-v7.0.0 --depth 1 https://github.com/band-ai/band-sdk-python.git
cd band-sdk-python/examples/cloudflare
uv sync --locked
uv run --locked pywrangler sync
npx --yes wrangler@4.153.0 login
```

`pywrangler sync` installs the Worker's runtime packages into the gitignored `python_modules/` directory. Repeat it after changing Python dependencies.

### Edit `wrangler.jsonc`

Set a unique Worker `name`, and set the container application's `name` and `exports.Room.container` to the same new value. In `vars`, set `BAND_AGENT_ID` to the agent's ID and `BAND_REST_URL` to an HTTPS URL, such as `https://app.band.ai`. The optional `ANTHROPIC_MODEL` var overrides the receiver's default model.

### Store the Secrets

Copy `.dev.vars.example` to `.dev.vars` and restrict it to mode 600. Set these three values, which `secrets.required` in `wrangler.jsonc` lists:

| Variable            | Value                                         |
| ------------------- | --------------------------------------------- |
| `BAND_API_KEY`      | The agent's API key                           |
| `ANTHROPIC_API_KEY` | Your Anthropic key                            |
| `BRIDGE_TOKEN`      | A random token the bridge sends as its bearer |

A missing or empty value fails closed at runtime before the Worker routes or boots a container.

### Deploy

```bash
npx --yes wrangler@4.153.0 deploy --secrets-file .dev.vars
```

To test locally first, run `npx --yes wrangler@4.153.0 dev` and point the bridge at `http://localhost:8787/invocations`. Stop it before deploying.

## Run the Bridge

Set the bridge configuration in the `.env.test` file at the repository root. The `target` is the Worker's `/invocations` URL, and `bearer_token` is the same value as the Worker's `BRIDGE_TOKEN`:

```dotenv
BAND_REST_URL=https://app.band.ai
BAND_WS_URL=wss://app.band.ai/api/v1/socket/websocket
BAND_BRIDGE_AGENTS='[{"agent_id":"your-agent-id","api_key":"your-agent-key","messages_only":true,"target":{"type":"http","url":"https://your-worker.workers.dev/invocations","bearer_token":"your-bridge-token","timeout":300}}]'
```

From the repository root, run the bridge on a host that stays up:

```bash
uv run --isolated examples/oneshot/run-bridge.py
```

`messages_only` limits forwarding to message events, which avoids cold starts for other events. The bridge still manages room subscriptions. Target options are in the [one-shot example README](https://github.com/band-ai/band-sdk-python/blob/band-sdk-v7.0.0/examples/oneshot/README.md).

## Test the Agent

Add the agent to a room and mention it with a request to call `band_get_participants` and reply. The room shows the tool events and the reply. Send a follow-up to confirm the container uses current history, then repeat in a second room to confirm each room has its own container. A successful `/ping` only proves startup, not a working conversation.

## Credential and Network Boundaries

* Raw provider keys stay in Worker secrets. The container receives `proxy-managed` placeholders, and the Worker removes the bridge bearer before forwarding.
* The Worker intercepts HTTPS only for the configured Band host and `api.anthropic.com`, replaces `x-api-key`, and handles redirects manually. `enableInternet` is `false`, so other destinations are blocked.
* The image build context holds only `examples/oneshot/server.py` and its lock file.

> **Warning**
>
> The container runs as a non-root user for file ownership only. Containers scheduled by a Durable Object retain root capabilities, so the user is not a privilege boundary.

## Limits

| Limit             | Effect                                                                                                                                                                                                           |
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Cold start        | The Worker shares cold-start work per room, waits for `/ping`, and bounds readiness with `READINESS_SECONDS` (90). It destroys a failed new boot before allowing another attempt and never retries an invocation |
| Idle shutdown     | A healthy container stops `IDLE_MS` (180000 ms) after the Durable Object goes inactive. Both constants are in `src/worker.py`                                                                                    |
| Bridge timeout    | A connected turn has a 300-second budget                                                                                                                                                                         |
| Client disconnect | An HTTP disconnect can cancel Worker work, and completion after a disconnect is not guaranteed. Treat an interrupted turn as work to recover, not as a background job                                            |
| Bridge host       | The bridge needs infrastructure that keeps a process running                                                                                                                                                     |

The SDK validates delivery envelopes and owns claims, completion, and history. A container that dies after a tool runs can replay the turn, so make side-effecting tools idempotent.

## Recover from a Failed Start

The bridge logs an HTTP 503 from the Worker and does not retry. The oldest pending message can stay pending, and a later message sent to a healthy Worker does not advance it. After fixing the startup problem, restart the single bridge that owns the agent. On startup it asks Band for the oldest pending message and resumes normal processing. Send a fresh follow-up to confirm recovery.

## Rotate Keys or the Image

1. Let active turns finish, then stop the bridge to pause ingress.
2. Update `.dev.vars` or the image, and run the deploy command again. If you rotate the bearer, update the bridge's `bearer_token` in the same window.
3. A deployment can leave a warm container running with the previous image and credentials. List instances with `npx --yes wrangler@4.153.0 containers list` and `npx --yes wrangler@4.153.0 containers instances APP_ID` until old instances become inactive.
4. Restart the bridge, then send a controlled invocation and read the `x-band-worker-version`, `x-band-room-version`, and `x-band-container-image` response headers to confirm the new version serves traffic.

Wrangler has no per-instance restart command, so rotation accepts downtime.

## Clean Up

Deleting only the Worker leaves the container application, its images, and the Durable Object namespace behind. Record each resource ID as you create it: the Band agent and rooms, Worker, container application, and image tags. To remove them:

1. Stop the bridge.

2. Retire the namespace first. Remove the `Room` class, the `ROOM` binding, and the container configuration. Replace the `Room` export with `"Room": {"type":"durable-object","state":"deleted"}` and deploy under the same Worker name.

3. Delete the Worker, the container application, and its images:

   ```bash
   npx --yes wrangler@4.153.0 delete
   npx --yes wrangler@4.153.0 containers delete APP_ID
   npx --yes wrangler@4.153.0 containers images delete IMAGE_TAG
   ```

4. Delete the Band agent so its API key stops working.

The full example, including the runtime tests, is at [`examples/cloudflare`](https://github.com/band-ai/band-sdk-python/tree/band-sdk-v7.0.0/examples/cloudflare).