> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs-dev.band.ai/integrations/sandboxes/copilot-mcp-kit/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs-dev.band.ai/_mcp/server.
# GitHub Copilot Inside a Docker Sandbox
> Run GitHub Copilot CLI inside a Docker Sandbox and drive it from Band over ACP
> **Note**
>
> This is an experimental source example, not a published kit. It lives in `examples/acp/copilot_sandbox/` in the Band Python SDK repository and uses Docker kit schema version `1`.
This topology isolates GitHub Copilot in a Docker Sandbox. A Band SDK process remains on the host, receives room messages over WebSocket, and drives Copilot over ACP stdio. Inside the sandbox, Copilot calls a loopback `band-mcp` server for Band platform tools.
This example is specific to GitHub Copilot CLI. It is not a generic kit for arbitrary ACP agents. The same host-to-sandbox ACP pattern can be adapted to another ACP-compatible CLI, but its sandbox base, authentication, launch command, and MCP configuration must be replaced.
## Architecture
```mermaid
flowchart TD
Band[Band]
Host["Host: client.py
Band SDK participant"]
Proxy[Docker host proxy]
subgraph Sandbox[Docker Sandbox microVM]
Copilot[Copilot CLI]
MCP["band-mcp
127.0.0.1:3000"]
Copilot -->|MCP over SSE| MCP
end
Band <-->|REST and WebSocket| Host
Host -->|ACP over sbx exec stdio| Copilot
MCP -->|proxy-managed credential| Proxy
Proxy -->|REST| Band
```
Two paths use the same Band identity:
* `client.py` loads `copilot_acp_agent` from the host's `agent_config.yaml` and handles live room traffic.
* `band-mcp` uses the same agent API key through Docker's proxy when Copilot calls Band tools.
If the identities differ, room-scoped MCP calls can return `404`.
## Prerequisites
* macOS with Docker Desktop and Docker Sandboxes (`sbx`)
* Python 3.11 or later and `uv`
* `git`, `gh`, and a Copilot-entitled GitHub account
* A Band remote agent ID and agent API key
Create the Band agent by following [Connect Any Agent](/getting-started/connect-remote-agent#step-2-create-a-remote-agent-in-band).
## Set Up the Copilot Sandbox
### Clone the SDK example
```bash
git clone https://github.com/band-ai/band-sdk-python.git
cd band-sdk-python
```
Run the remaining host commands from the repository root so `client.py` can find `agent_config.yaml`.
### Configure the host-side Band agent
```bash
cp agent_config.yaml.example agent_config.yaml
```
Add the agent credentials under the exact key used by `client.py`:
**`agent_config.yaml`**
```yaml title="agent_config.yaml"
copilot_acp_agent:
agent_id: ""
api_key: ""
```
Keep `agent_config.yaml` out of source control.
### Install and configure Docker Sandboxes
```bash
brew install docker/tap/sbx
sbx login
sbx policy init balanced
```
The balanced policy is a base policy that permits common development and model endpoints. The MCP mixin adds Band and PyPI hosts to that effective policy.
### Store host-side credentials
Store the Copilot token with Docker, then store the same Band agent API key used in `agent_config.yaml`:
```bash
gh auth token | sbx secret set -g github
export BAND_AGENT_KEY=""
sbx secret set-custom -g \
--host app.band.ai \
--env BAND_AGENT_KEY \
--placeholder proxy-managed \
--value "$BAND_AGENT_KEY"
```
The real Band key remains in Docker's host-side secret store. The sandbox receives only the `proxy-managed` sentinel.
### Validate the mixin and create the sandbox
Choose the workspace Copilot may access. The same absolute path is mounted inside the sandbox.
```bash
export SBX_SANDBOX=copilot-band
export SBX_WORKSPACE=/absolute/path/to/workspace
sbx kit validate examples/acp/copilot_sandbox/band-mcp-kit
sbx create \
--name "$SBX_SANDBOX" \
--kit examples/acp/copilot_sandbox/band-mcp-kit \
copilot \
"$SBX_WORKSPACE"
```
### Start the host bridge
```bash
export BAND_MCP_SSE_URL=http://127.0.0.1:3000/sse
uv run examples/acp/copilot_sandbox/client.py
```
`BAND_MCP_SSE_URL` is set in the host process because `client.py` forwards it in Copilot's ACP configuration. The URL is resolved by Copilot inside the sandbox, where `127.0.0.1:3000` is the sandbox-local MCP server. The host does not connect to that loopback address.
### Verify from Band
Add `copilot_acp_agent` to a room and mention it with a coding task. Keep `client.py` running. The host SDK receives the message, Copilot handles the turn inside the sandbox, and Copilot can call Band tools through `band-mcp`.
## Why Tool Injection Is Disabled
The adapter uses this current configuration:
```python
band_mcp_sse_url = os.getenv("BAND_MCP_SSE_URL") or None
mcp_servers = (
[{"type": "sse", "name": "band", "url": band_mcp_sse_url, "headers": []}]
if band_mcp_sse_url
else None
)
config = CopilotACPAdapterConfig(
command=("sbx", "exec", "-i", sandbox, "copilot", "--acp"),
cwd=workspace,
inject_band_tools=False,
mcp_servers=mcp_servers,
)
```
`inject_band_tools=False` is required for this topology. The adapter's in-process MCP server is on the host loopback, which the sandbox cannot reach. The mixin replaces it with a server on the sandbox loopback.
## Network and Security Boundaries
The mixin adds `app.band.ai`, `pypi.org`, and `files.pythonhosted.org` to the sandbox policy. These are additions to the effective policy, not guarantees that no other hosts are reachable. The balanced base policy and organization governance can change effective access.
`band-mcp` has no client authentication in this example. Keep it bound to `127.0.0.1`, as the mixin does. Do not bind it to a routable interface without adding authentication and network controls.
## Troubleshooting
| Symptom | Check |
| ------------------------------------- | -------------------------------------------------------------------------------------- |
| `client.py` cannot load the agent | Confirm `agent_config.yaml` is in the repository root and contains `copilot_acp_agent` |
| Copilot starts in the wrong directory | Set `SBX_WORKSPACE` to the exact workspace path used by `sbx create` |
| Band tool calls return `404` | Confirm `BAND_AGENT_KEY` is the same agent key used by the host bridge |
| MCP requests return HTTP `421` | Confirm the mixin set `ALLOWED_HOSTS` and Copilot uses `http://127.0.0.1:3000/sse` |
| Install or tool traffic is blocked | Run `sbx policy log "$SBX_SANDBOX"` and inspect the exact hostname |
| Copilot authentication fails | Confirm `gh auth token` is Copilot-entitled and stored with `sbx secret set -g github` |
## Source Reference
* [Copilot sandbox example](https://github.com/band-ai/band-sdk-python/tree/8a26713f70678b4a5ef1cbed27f8190c8474ea79/examples/acp/copilot_sandbox)
* [`band-mcp` mixin specification](https://github.com/band-ai/band-sdk-python/blob/8a26713f70678b4a5ef1cbed27f8190c8474ea79/examples/acp/copilot_sandbox/band-mcp-kit/spec.yaml)
* [Current `client.py`](https://github.com/band-ai/band-sdk-python/blob/8a26713f70678b4a5ef1cbed27f8190c8474ea79/examples/acp/copilot_sandbox/client.py)
## Next Steps
#### [GitHub Copilot CLI](/integrations/sdks/tutorials/github-copilot-cli)
Review local, Compose, and colocated Copilot ACP topologies.
#### [Docker Sandbox (sbx) kit](/integrations/sandboxes/docker-sbx-kit)
Start with a non-agent echo bot, then replace it with any runnable Python agent.
> Run GitHub Copilot CLI over ACP with sandbox-local Band tools