Skip to main content
xbot
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

Sandbox Guide

Overview

xbot supports multiple sandbox modes to control the isolation level when the agent executes shell commands.

ModeDescriptionBest For
noneNo isolation, execute directly on the hostPersonal dev machine, running inside Docker
dockerOne isolated Docker container per userMulti-user servers

Configuration

Configure in ~/.xbot/config.json:

{
  "sandbox": {
    "mode": "none"
  }
}

SandboxConfig Reference

The sandbox config struct (config/config.go):

type SandboxConfig struct {
    Mode       string   `json:"mode"`        // sandbox mode: "none" (default) or "remote"
    RemoteMode  string   `json:"remote_mode"`  // remote sandbox mode
    IdleTimeout Duration `json:"idle_timeout"` // idle timeout before auto-destroy
    WSPort      int      `json:"ws_port"`      // WebSocket port for remote sandbox
    AuthToken   string   `json:"auth_token"`   // Runner authentication token
    PublicURL   string   `json:"public_url"`   // Public URL for runner connection
}
FieldDefaultDescription
mode"none"Sandbox mode: "none" or "remote"
remote_mode""Remote sandbox mode
idle_timeout"30m"Idle timeout (0 = never auto-destroy)
ws_port8080WebSocket port for remote sandbox connections
auth_token""Shared authentication token for runners
public_url""Public URL runners use to connect

Commands execute directly on the host machine. On Windows, PowerShell is used.

{
  "sandbox": {
    "mode": "none"
  }
}
Warning
No isolation means the agent can execute any command your current user has permission to run. Ensure you trust the agent’s behavior. Use sandboxing on shared or production servers.
Warning
The local Docker sandbox was removed entirely on 2026-09-16 (sandboxing now goes through a Runner). For isolation use the remote Runner below — commands run on your own machine; the server no longer manages containers. The default mode is "none" (local).

Remote Sandbox

Users can connect their own remote runners to execute commands on their own machines. Configure via the CLI /settings panel.

How it works:

  1. A runner (xbot-runner) connects to the xbot server over WebSocket
  2. Authentication uses a shared token (auth_token), verified with subtle.ConstantTimeCompare
  3. The server routes tool execution to the runner’s machine
  4. Supports stdio streaming output and runner-local LLM models

Server-side configuration:

{
  "sandbox": {
    "remote_mode": "remote",
    "auth_token": "your-secure-token",
    "ws_port": 8080,
    "public_url": "ws://your-server.com:8080"
  }
}

Runner-side (on the managed machine):

xbot-runner --server ws://your-server.com:8080/ws --token your-secure-token --name my-runner

--name is how the machine is identified; the server resolves ownership through the one-shot connect token, so the name the runner reports and the name in the registry stay in sync.

Routing rules (per session — there is exactly one operator):

Session stateSandbox used
Bound to runner R, R onlineR’s RemoteSandbox
Bound to runner R, R offlineHard failure — tools refuse to run (never a silent local fallback)
Not boundNone (local host)

Bind a session with the config tool (runner action, sub=switch name=...; sub=unbind goes back to the local host) or over RPC (runner_session_set / runner_session_get).

Tip

Multiple machines, one operator: any number of runners can connect at once, each with its own name and token. Bindings are per session, so two sessions can work on two different machines simultaneously. Nothing is keyed by user — see docs/design/runner-ssh-provisioning.md.

Provisioning & connection model (VS Code Remote style): the built-in xbot.ssh-runner plugin (plugins/xbot-ssh-runner/) takes an SSH command, probes the machine, installs xbot-runner, and then connects by opening an SSH session in which the runner runs in the foreground — the pipe owns its lifetime, and every (re)connect kills the previous runner before starting a new one, so two runners can never race for the same name.

By default the connection is tunnelled (ssh -R): the runner dials 127.0.0.1:<port> on the managed machine and that port is forwarded back to your server, so the managed machine needs no network path to the server at all — only you need to reach it over SSH (works behind NAT on both sides). Set connectionMode: direct if the machine can reach the server on its own.

SandboxRouter Architecture

SandboxRouter (tools/sandbox_router.go) is the unified sandbox entry point. It routes execution requests to different backends based on per-user configuration:

  • Implements both Sandbox and SandboxResolver interfaces
  • Only two backends: Remote (Runner) and None (local; the default)
  • Routes independently per user — different users can use different backends
  • Runner selection is configurable per user via the settings panel

Sync Configuration

When using remote runners, xbot can sync the skills/ and agents/ directories from the server to the runner. This ensures the runner has access to the same tools and agent definitions.

Enable sync in the runner settings via /settings → Runner panel.

See also