AI coding agents have moved surprisingly quickly from being simple chat interfaces to tools that can actually work with a development environment. They can inspect files, write code, execute commands, test applications, and, increasingly, work as part of larger development workflows.

But there is an important question that comes with that capability:

Where should the agent actually run?

This is where containers and sandboxes become interesting.

Recently, I started looking at how OpenHands Agent Canvas could be packaged as a Docker SBX kit. The result is the openhands-canvas kit, a standalone agent kit that brings OpenHands Agent Canvas into a Docker Sandbox environment.

What I like about this approach is that you don't have to manually build a Docker image, install Node.js, install the Agent Canvas package, configure everything yourself, and then figure out how to expose the web interface.

The kit handles those pieces for you.

In this article, I'll walk through what the kit does, how authentication works, how to run it, how to access the web interface, and some of the practical lessons I learned while working through the setup.

What exactly is Docker SBX?

Before jumping into OpenHands, let's quickly understand Docker SBX.

Think of a Docker Sandbox as an isolated environment where an agent can work without directly operating inside your normal development environment.

Docker's current kit architecture allows a kit to describe things such as the sandbox image, startup commands, environment variables, credentials, network permissions, ports, and files. The sbx engine then applies that configuration when the sandbox is created.

That makes the idea of an agent kit quite interesting.

Instead of saying:

"Here are 25 commands you need to run to configure this agent."

you can effectively say:

"Here is the kit. Start the sandbox with it."

For people who regularly experiment with AI coding agents, this can save quite a bit of setup work.

What is OpenHands Agent Canvas?

OpenHands Agent Canvas is the visual interface from OpenHands for working with AI coding agents.

According to OpenHands, Agent Canvas is designed as a local visual workspace for running AI coding agents. It can work with multiple agent harnesses through the Agent Client Protocol, including OpenHands Agent, Claude Code, Codex, and Gemini CLI.

That distinction is important.

Agent Canvas isn't simply another chatbot window.

The goal is to provide a workspace where agents can actually participate in software development workflows.

For example, imagine that you have a small application with a bug.

Instead of copying the error into a chat window and manually applying the suggested changes, an agent operating in a development environment can inspect the repository, understand the surrounding code, make changes, and run commands.

That is where the combination of Agent Canvas + Docker Sandbox starts becoming useful.

Introducing the openhands-canvas SBX kit

The openhands-canvas project is a standalone kind: agent kit for Docker SBX.

The basic idea is straightforward:

  1. Start a Docker Sandbox.

  2. Install OpenHands Agent Canvas inside the sandbox.

  3. Configure authentication for the model provider.

  4. Start Agent Canvas automatically.

  5. Expose its web interface through port 8000.

The kit installs Agent Canvas through npm during sandbox creation and uses it as the sandbox entrypoint.

By default, Agent Canvas listens on:

8000

That means the architecture is relatively simple:

Your Browser
     |
     | localhost:8000
     v
Docker SBX
     |
     +---- OpenHands Agent Canvas
     |
     +---- AI Agent
     |
     +---- Your Workspace

This is one of those setups where the complexity is mostly hidden inside the kit.

And that's exactly what I want from a good sandbox kit.

Before starting: API authentication

There is one prerequisite you shouldn't skip.

The agent needs access to an AI model provider.

The kit supports providers such as Anthropic and OpenAI through Docker SBX's secret mechanism.

For example, for Anthropic:

sbx secret set-custom -g \
    --host api.anthropic.com \
    --env ANTHROPIC_API_KEY \
    --placeholder "sk-ant-{rand}" \
    --value "$ANTHROPIC_API_KEY"

For OpenAI:

sbx secret set-custom -g \
    --host api.openai.com \
    --env OPENAI_API_KEY \
    --placeholder "sk-{rand}" \
    --value "$OPENAI_API_KEY"

At first glance, this might look like the API key is simply being passed into the container.

That's not the interesting part.

The important part is how the SBX network and credential system handles it.

How authentication works

The kit defines the provider API hosts and tells the sandbox proxy how credentials should be injected.

For Anthropic, the relevant API host is:

api.anthropic.com

and authentication uses the x-api-key header.

For OpenAI, the API host is:

api.openai.com

and authentication uses:

Authorization: Bearer <key>

The idea is that the sandbox doesn't need to expose the real credential directly to the application as a normal secret value.

The proxy can intercept the outbound request, identify the configured service, and inject the appropriate authentication header.

This is a much cleaner approach than putting an API key directly into a Dockerfile or committing it into an environment file.

Docker's kit specification treats credentials and network permissions as explicit parts of the kit configuration, rather than assuming every outbound connection should automatically be trusted.

That separation is particularly useful when you're experimenting with autonomous agents.

Running the OpenHands Canvas sandbox

Once the required secret is configured, starting the kit is surprisingly simple.

You can run the kit directly from the Docker community repository:

sbx run --kit \
"git+https://github.com/docker/sbx-kits-contrib.git#dir=openhands-canvas" \
openhands-canvas

I like this model because you don't have to clone the repository just to try the kit.

The --kit option can consume a kit from a Git repository, and Docker's current documentation also supports pinning a kit to a branch, tag, or commit when reproducibility matters.

For local development, you can instead clone the repository and run:

sbx run --kit ./openhands-canvas openhands-canvas

That second approach is particularly useful if you're modifying the kit itself.

What happens during installation?

This is one of the parts I found interesting.

The kit doesn't assume that the base environment already contains exactly the Node.js version required by Agent Canvas.

During the initial sandbox setup, it upgrades Node.js to version 22 using the n package.

After that, it installs Agent Canvas globally:

npm install -g @openhands/agent-canvas

The resulting executable is placed under:

/usr/local/share/npm-global/bin/agent-canvas

The kit then uses that executable as the entrypoint.

So, conceptually:

Sandbox Creation
       |
       v
Install/upgrade Node.js 22
       |
       v
Install @openhands/agent-canvas
       |
       v
Start agent-canvas
       |
       v
Listen on port 8000

This is a good example of why an SBX kit can be more convenient than manually building an environment every time you want to test an agent.

The part that initially confused me: accessing the UI

The sandbox is isolated from your host network.

That means starting Agent Canvas on port 8000 inside the sandbox does not automatically mean that your browser can open:

http://localhost:8000

This is an important Docker Sandbox concept.

Docker's documentation explains that sandbox services need to be explicitly forwarded from the sandbox to the host.

So, after the sandbox is running, open another terminal and execute:

sbx ports openhands-canvas-sbx-kits-contrib --publish 8000:8000

Now you can open:

http://localhost:8000

and you should reach the Agent Canvas interface.

This two-terminal workflow is worth remembering:

Terminal 1

sbx run --kit "git+https://github.com/docker/sbx-kits-contrib.git#dir=openhands-canvas" openhands-canvas

Terminal 2

sbx ports openhands-canvas-sbx-kits-contrib --publish 8000:8000

Then open the browser.

What if port 8000 is already being used?

This is probably one of the first problems you'll encounter if you already run development servers locally.

Fortunately, you don't need to change Agent Canvas's internal port.

You can simply map a different host port to port 8000 inside the sandbox:

sbx ports openhands-canvas-sbx-kits-contrib --publish 8080:8000

The mapping now becomes:

localhost:8080
       |
       v
sandbox:8000

So you would open:

http://localhost:8080

This is a useful distinction:

Host port != sandbox port

The application can continue listening on 8000 inside the sandbox while your machine exposes it through another available port.

Docker follows this same host-to-sandbox port-forwarding model for services running inside sandboxes.

What makes this approach useful?

For me, the biggest benefit isn't simply that OpenHands can run inside Docker.

We've been running applications inside containers for years.

The interesting part is combining three things:

AI agent + isolated sandbox + reusable kit

That combination changes the workflow.

Suppose I'm testing an agent and I don't completely trust what it might do.

I can give it an isolated environment instead of giving it unrestricted access to my normal machine.

Suppose I want to test the same setup tomorrow.

I don't have to remember every installation command.

I can use the kit again.

Suppose I want to modify the kit.

I can clone the repository, change the configuration, validate it, and run the local version.

Docker's kit tooling also provides commands such as sbx kit validate and sbx kit inspect, which are useful when developing or troubleshooting kits.

That repeatability is probably the biggest practical advantage.

A simple mental model

If you're new to Docker SBX, don't overcomplicate the architecture.

Think about it like this:

                 Your Laptop
                      |
                 Web Browser
                      |
                 localhost:8000
                      |
              +-------v-------+
              |   Docker SBX  |
              |               |
              | Agent Canvas  |
              |      |        |
              |      v        |
              | AI Agent      |
              |      |        |
              |      v        |
              | Workspace     |
              +---------------+
                      |
                 Proxy / Network
                      |
              AI Provider API

The browser talks to Agent Canvas.

Agent Canvas runs inside the sandbox.

The agent works inside the sandbox environment.

Outbound API requests go through the sandbox's network and credential configuration.

That separation makes the system easier to reason about.

Don't forget the network policy

One thing I would strongly recommend when working with SBX kits is not to treat network access as an afterthought.

The current kit specification uses explicit network allow/deny rules. A domain required for credential injection also needs to be allowed by the network policy.

This is a good security boundary.

If something doesn't work, don't immediately assume the application is broken.

Check whether the sandbox is blocking an outbound request.

Docker's kit-authoring documentation specifically recommends using the policy log to identify blocked domains while developing kits.

This is especially relevant with AI agents because an agent may interact with several services during a single task.

Troubleshooting checklist

If Agent Canvas doesn't work as expected, I'd go through these checks in order.

1. Check whether the sandbox is running

Use:

sbx ls

Look for the openhands-canvas sandbox and confirm that it is running.

2. Check the stored secrets

Run:

sbx secret list -g

Make sure the required provider credential has been registered.

3. Check the port

Run:

sbx ports openhands-canvas-sbx-kits-contrib

You should see the active port mapping.

4. Try another host port

If 8000 is busy:

sbx ports openhands-canvas-sbx-kits-contrib --publish 8080:8000

Then open:

http://localhost:8080

5. Check network policy

If authentication or API calls fail, inspect the sandbox's network policy information.

A blocked domain can look like an application-level failure when the actual problem is simply that the sandbox isn't permitted to reach that host.

6. Validate the kit if you're developing it

If you've cloned and modified the kit:

sbx kit validate ./openhands-canvas/

This is much faster than discovering configuration mistakes only after starting a sandbox.

Removing credentials

If you no longer want the stored provider credential, you can remove it.

For Anthropic:

sbx secret rm -g --host api.anthropic.com

For OpenAI:

sbx secret rm -g --host api.openai.com

This is another reason I prefer the secret-store approach over putting API credentials directly into configuration files.

One thing I'd change for production use

If you're simply experimenting, running the kit from the default branch is perfectly reasonable.

For something more repeatable, however, I would pin the kit to a known Git ref.

Docker's current documentation supports specifying a branch, tag, or commit SHA in the Git kit URL.

For example, conceptually:

git+https://github.com/docker/sbx-kits-contrib.git#ref=<version>&dir=openhands-canvas

Why does that matter?

Because a repository's default branch can change.

If you build a workflow today and run exactly the same command six months later, you don't necessarily want the underlying kit to have silently changed.

Pinning a version gives you much better reproducibility.

For production or team environments, I'd strongly recommend that approach.

My overall take

What I find most interesting about the openhands-canvas kit isn't the npm installation itself.

The interesting part is the packaging.

We're moving toward a world where an AI agent isn't just something you install as a CLI and talk to.

The agent needs a workspace.

It needs tools.

It needs network access.

It may need credentials.

It may need a web interface.

And it needs boundaries.

Docker SBX provides a nice place to define those pieces together.

The openhands-canvas kit turns that setup into something repeatable.

Instead of manually preparing an environment every time, you can start with a kit and let the sandbox configure the environment for you.

For someone experimenting with AI coding agents, that's a compelling workflow.

Final thoughts

AI development tools are evolving quickly, and I think the next interesting phase isn't simply about which model is better.

It's about where the agent runs and what the agent is allowed to do.

That's why projects like OpenHands Agent Canvas and Docker SBX are interesting when viewed together.

OpenHands provides the agent experience and visual workspace. Agent Canvas is designed to work with different agent harnesses through ACP, while Docker SBX provides an isolated environment where a packaged agent can run.

The openhands-canvas kit brings those ideas together in a fairly simple workflow:

Configure API authentication
        ↓
Start Docker SBX kit
        ↓
Install Agent Canvas
        ↓
Start Agent Canvas
        ↓
Forward port 8000
        ↓
Open browser
        ↓
Start working with your AI agent

And honestly, that's the part I appreciate most.

The technology underneath can be complicated, but the experience doesn't have to be.

If you're already experimenting with Docker Sandboxes, AI coding agents, or OpenHands, the openhands-canvas kit is a great example of how an agent can be packaged as a reusable sandbox experience rather than treated as a one-off installation.

That's where I think things are getting really interesting.