Self-hosted service
agent-infra/sandbox avatar
agent-infra/sandbox

agent-infra/sandbox: an all-in-one Docker sandbox for AI agents

All-in-One Sandbox for AI Agents that combines Browser, Shell, File, MCP and VSCode Server in a single Docker container.

5,940 stars532 forksPythonApache-2.0

At a glance

What is it?
One container bundles a browser, shell, file API, MCP servers and VSCode Server behind a single port. It removes the file-sharing problem between agent tools, at the cost of running everything with an unconfined seccomp profile.
Who is it for?
Adopt agent-infra/sandbox if your agent needs a browser and a shell to see the same files and you accept a single-container trust boundary. Do not adopt it if you need per-tool isolation, a small image, or a documented rollback story; the README documents neither.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 16 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 17, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem agent-infra/sandbox solves: agents that cannot share files

Most agent stacks assemble several sandboxes. A browser runs in one container, a Python executor in another, a shell in a third. The README names this directly: traditional sandboxes are single-purpose (browser, code, or shell), and coordinating them makes file sharing difficult. The failure is mundane. An agent downloads a PDF in the browser sandbox, then cannot open it from the code sandbox, so the developer writes a copy step, mounts a volume, or serializes bytes through the orchestrator.

agent-infra/sandbox collapses those processes into one container. The README's first selling point is a unified file system: files downloaded in the browser are instantly available in Shell and File operations. The audience is agent developers who are tired of wiring storage between tools, and who want a single endpoint to hand to a framework such as LangGraph, AG2, browser-use or OpenAI's tool-calling loop. The repository ships examples for each of those under examples/.

What actually runs inside the container

The container is not one service. It is a set of long-lived processes bound to distinct ports, which docker-compose.yaml spells out. MCP_HUB_PORT is 8079, SANDBOX_SRV_PORT is 8091, MCP_SERVER_BROWSER_PORT is 8100, MCP_SERVER_MARKITDOWN_PORT is 8101, MCP_SERVER_CHROME_DEVTOOLS_PORT is 8102, JUPYTER_LAB_PORT is 8888, CODE_SERVER_PORT is 8200, VNC_SERVER_PORT is 5900, BROWSER_REMOTE_DEBUGGING_PORT is 9222, and PUBLIC_PORT is 8080. WAIT_PORTS is set to 8079,8091, so the entrypoint waits on the MCP hub and the sandbox server before declaring the container ready.

Only 8080 is published. Everything else is reached through it, which is why the quick start binds the host side to 127.0.0.1. The browser is exposed three ways: VNC for a human looking at a remote desktop, CDP on port 9222 for programmatic control, and MCP tools for an agent. The same filesystem backs VSCode Server, JupyterLab and the shell API, so a file written by one is visible to the others without a copy.

The compose file also sets mem_limit to 8g, cpus to 4, and shm_size to 2gb. That last value is not decorative. Chromium needs shared memory, and the default Docker shm size of 64 MB is a common cause of browser crashes in containers.

Running agent-infra/sandbox: install and first call

The README gives a docker run command as the recommended path. It enables API key authentication with SANDBOX_API_KEY, which the README says protects all services: the API, JupyterLab and VNC. Three methods are accepted: an X-AIO-API-Key header, an Authorization: Bearer header, or an ?api_key= query parameter. The README states plainly that without SANDBOX_API_KEY the services remain open, described as backward compatible. Treat that as the default you must override.

bash
docker run --security-opt seccomp=unconfined --rm -it \
  -e SANDBOX_API_KEY=your-secret-key \
  -p 127.0.0.1:8080:8080 ghcr.io/agent-infra/sandbox:latest

The seccomp=unconfined flag is required by the documented command, not optional polish; the sandbox needs syscalls the default Docker profile blocks. After the container starts, the README lists four entry points on port 8080: /v1/docs for the API documentation, /vnc/index.html?autoconnect=true for the VNC browser, /code-server/ for VSCode Server, and /mcp for MCP services. Open /v1/docs first; it is the live contract for every endpoint below.

For a reproducible deployment, pin the tag instead of using latest. The README's example uses 1.11.0.

bash
docker run --security-opt seccomp=unconfined --rm -it \
  -p 127.0.0.1:8080:8080 ghcr.io/agent-infra/sandbox:1.11.0

On the client side, the Python SDK installs from PyPI as agent-sandbox. The README's example initializes a client, reads the home directory from the context endpoint, runs a shell command, reads a file and takes a screenshot.

python
from agent_sandbox import Sandbox

client = Sandbox(base_url="http://localhost:8080")
home_dir = client.sandbox.get_context().home_dir
result = client.shell.exec_command(command="ls -la")
print(result.data.output)
screenshot = client.browser.screenshot()

TypeScript and Go clients exist too: npm install @agent-infra/sandbox and go get github.com/agent-infra/sandbox-sdk-go. The TypeScript client takes a baseURL option and exposes sandbox.shell.exec and sandbox.file.read. Note the naming difference between the two SDKs: the Python client calls exec_command and read_file, the TypeScript client calls exec and read. If you port code between them, that is where it breaks.

Why seccomp=unconfined and a shared filesystem are the same trade-off

The design decision that makes the unified filesystem work is also the one that weakens isolation. Everything shares a filesystem, so a browser exploit and a shell command have the same reach. The documented run command disables the seccomp filter. The README's own cloud guidance is to keep port 8080 private and publish it through a reverse proxy or Ingress, which tells you the authors expect the container to sit behind something else rather than face the internet.

This is the wrong tool when you need per-tool blast-radius separation. If a policy requires that untrusted web content never shares a namespace with code execution, a single container cannot satisfy it, no matter how the API keys are set. It is also the wrong tool for lightweight tasks. An 8 GB memory limit and 4 CPUs in the compose file reflect a full desktop stack: Chromium, JupyterLab, code-server and a terminal. Running a one-line Python snippet does not need any of that, and the image carries all of it.

There is a second constraint worth naming. The compose file disables JupyterLab and code-server only through DISABLE_JUPYTER and DISABLE_CODE_SERVER, both defaulting to false. The README does not document what else can be turned off, so trimming the surface area means editing the compose file and knowing which ports the entrypoint still waits on.

agent-infra/sandbox compared with a plain Docker container plus Playwright

The obvious alternative is what most teams build first: a base image with Python and Node, plus Playwright or Puppeteer for browsing, and your own file handling. That approach gives you full control over the image, the user, the seccomp profile and the network policy. It also gives you the coordination work the README complains about. You own the download directory, the volume mounts, the browser process lifecycle, and the screenshot plumbing.

The difference in approach is where the boundary sits. With a hand-built container, the boundary is whatever you configure, and the agent talks to your code. With agent-infra/sandbox, the boundary is the container itself and the agent talks to a fixed HTTP surface: shell, file, browser and MCP endpoints on port 8080. You trade configurability for a documented API and pre-wired MCP servers for browser, file, shell and Markitdown document conversion.

A narrower alternative is to keep separate single-purpose sandboxes and connect them with a shared volume. That preserves isolation between the browser and the shell while solving the file-sharing complaint. It costs more orchestration, and the README does not discuss this pattern, but it is the honest middle ground if the unconfined seccomp flag is a blocker for your environment.

Maintenance, releases and the Apache-2.0 licence

The repository is not archived, and the last push was on 2026-09-10. Releases are tagged at a steady cadence: v1.9.3 on 2026-05-29, v1.10.0 on 2026-06-15, v1.11.0 on 2026-06-23. The gap between the latest release and the last push suggests work continues on main between tags, but the README does not describe a release cadence or a support window, and it does not document an upgrade or rollback procedure. Pinning a tag is therefore the only documented way to make a deployment reproducible.

The upgrade cost is mostly image size and re-pulling. Because the browser, JupyterLab, code-server and the MCP servers are baked in, a version bump replaces all of them at once; you cannot upgrade the browser independently of the shell tooling. If your agent depends on a specific Chrome behaviour, pin the tag and test before moving.

The project is Apache-2.0. That permits commercial use and modification, and it includes an explicit patent grant. It also means redistributions must carry the licence and notice, and modified files must be marked. The image bundles third-party components, including Chromium and JupyterLab, under their own licences, so a redistribution needs its own review of those notices. This is a description of the licence text, not legal advice; check with counsel before shipping a modified image.

Editorial conclusion

Adopt agent-infra/sandbox if your agent needs a browser and a shell to see the same files and you accept a single-container trust boundary. Do not adopt it if you need per-tool isolation, a small image, or a documented rollback story; the README documents neither. Before anything else, verify the pinned release tag you intend to run and whether SANDBOX_API_KEY is set, because the README states that without it all services stay open.

Frequently asked questions

What is agent-infra/sandbox?

It is an all-in-one agent sandbox environment that combines Browser, Shell, File, MCP operations and VSCode Server in a single Docker container, built on cloud-native lightweight sandbox technology. It is published under Apache-2.0.

How do I install agent-infra/sandbox?

Run the documented docker run command against ghcr.io/agent-infra/sandbox, pinning a tag such as 1.11.0 for reproducible deployments. Client SDKs install separately with pip install agent-sandbox or npm install @agent-infra/sandbox.

Which ports does agent-infra/sandbox expose?

Only PUBLIC_PORT 8080 is published by the documented command. Internal services sit on their own ports, including MCP_HUB_PORT 8079, SANDBOX_SRV_PORT 8091, JUPYTER_LAB_PORT 8888, CODE_SERVER_PORT 8200 and BROWSER_REMOTE_DEBUGGING_PORT 9222.

Why does the agent-infra/sandbox command use --security-opt seccomp=unconfined?

The README's recommended command includes that flag, meaning the container runs without the default Docker seccomp filter. The README does not explain which syscalls require it, so treat the flag as a documented requirement rather than a tuning option.

Official sources

  1. agent-infra/sandbox on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/agent-infra-sandbox.svg)](https://hysenlabs.com/projects/agent-infra-sandbox)