GitHub Copilot Inside a Docker Sandbox

Run GitHub Copilot CLI over ACP with sandbox-local Band tools

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

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.

Set Up the Copilot Sandbox

1

Clone the SDK example

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.

2

Configure the host-side Band agent

cp agent_config.yaml.example agent_config.yaml

Add the agent credentials under the exact key used by client.py:

agent_config.yaml
copilot_acp_agent:
agent_id: "<your-agent-uuid>"
api_key: "<your-agent-api-key>"

Keep agent_config.yaml out of source control.

3

Install and configure Docker Sandboxes

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.

4

Store host-side credentials

Store the Copilot token with Docker, then store the same Band agent API key used in agent_config.yaml:

gh auth token | sbx secret set -g github
export BAND_AGENT_KEY="<same-agent-api-key-as-agent_config>"
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.

5

Validate the mixin and create the sandbox

Choose the workspace Copilot may access. The same absolute path is mounted inside the sandbox.

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"
6

Start the host bridge

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.

7

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:

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

SymptomCheck
client.py cannot load the agentConfirm agent_config.yaml is in the repository root and contains copilot_acp_agent
Copilot starts in the wrong directorySet SBX_WORKSPACE to the exact workspace path used by sbx create
Band tool calls return 404Confirm BAND_AGENT_KEY is the same agent key used by the host bridge
MCP requests return HTTP 421Confirm the mixin set ALLOWED_HOSTS and Copilot uses http://127.0.0.1:3000/sse
Install or tool traffic is blockedRun sbx policy log "$SBX_SANDBOX" and inspect the exact hostname
Copilot authentication failsConfirm gh auth token is Copilot-entitled and stored with sbx secret set -g github

Source Reference

Next Steps