Products
Sandboxes
Isolated microVM environments for running code from AI agents: exec, files, a Python kernel, port previews, SDK, MCP and the AI Gateway.
Sandboxes (Dashboard → project → Sandboxes) are on-demand isolated environments where an AI agent or your app can safely run arbitrary code. Each sandbox is its own machine: a microVM by default (Kata Containers + Cloud Hypervisor, its own kernel and KVM isolation) or gVisor (cheaper, faster start, user-space kernel). Sandboxes run only on the dedicated workers host, with no access to databases.
Quickstart
curl -X POST https://host.ulewicz.space/api/v1/projects/<ref>/sandboxes \
-H "Authorization: Bearer $HOSTBASE_TOKEN" -H "Content-Type: application/json" \
-d '{"template":"python-3.12"}'
# -> { "id": "sbx...", "state": "running", "timings": { "total_ms": 40, "from_pool": true }, ... }
curl -X POST .../sandboxes/<id>/exec -H "Authorization: Bearer $HOSTBASE_TOKEN" \
-d '{"cmd":"python3 -c \"print(1+1)\""}'
# -> { "exit_code": 0, "stdout": "2\n", "stderr": "" }
curl -X DELETE .../sandboxes/<id> -H "Authorization: Bearer $HOSTBASE_TOKEN"
Templates
| Id | Name | Contents |
|---|---|---|
python-3.12 | Python 3.12 (data science) | numpy, pandas, matplotlib, scipy, scikit-learn, seaborn; Jupyter-like kernel with PNG charts and HTML tables |
node-22 | Node.js 22 | Node.js 22 LTS, npm, git, build tools |
bun | Bun 1 | Bun runtime, package manager, test runner |
ubuntu | Ubuntu 24.04 (base) | Ubuntu 24.04 + Python 3, pip, git, curl, jq, build-essential |
playwright-chromium | Playwright + Chromium | Playwright with Chromium/Firefox/WebKit (headless browser automation) |
Limits and plans
Defaults: 1 vCPU, 1024 MB RAM, 5 GB disk (/workspace), shutdown after 5 minutes idle (idle_timeout_s, 30 s – 24 h; API calls, preview traffic and CPU load of 10% of a vCPU or more reset the counter) and after 1 h of lifetime at most (lifetime_s, up to 24 h). /workspace is a separate fixed-size ext4 image - writes beyond the limit fail with "No space left".
| Plan | max vCPU | max RAM | max disk | max lifetime | concurrent | included (vCPU-h / GB-h) |
|---|---|---|---|---|---|---|
| free | 1 | 1024 MB | 2 GB | 1 h | 2 | 5 / 10 |
| pro | 2 | 4096 MB | 20 GB | 24 h | 10 | 100 / 200 |
| team | 4 | 8192 MB | 50 GB | 24 h | 40 | 500 / 1000 |
Exec and streaming
POST …/exec takes cmd (a string run with bash -c, or an argv array), cwd, env, timeout_s (default 60) and stdin. With "stream": true the response is an SSE stream of {"type":"stdout"|"stderr"|"exit",…} events. With "background": true the process starts detached (output goes to a log file), e.g. an HTTP server. Environment variables set at creation apply to every call. The interactive terminal (xterm.js) lives in the dashboard; in the API use terminal + the SSE stream + input.
Files
Relative paths resolve under /workspace. files/list, files/content (raw bytes, GET/PUT/DELETE), files/mkdir and files/archive (tar - bulk upload and directory download). Single-file limit: 256 MB.
Running code (kernel)
POST …/run-code with {"code": "…", "language": "python"} behaves like a notebook cell: the Python kernel (templates python-3.12 and ubuntu) keeps state across calls with the same context_id. The response holds results: stdout, stderr, the last expression's value (text/plain), text/html tables (pandas), matplotlib charts as image/png (base64) and an error object with the traceback. For javascript (Node/Bun) and bash every run is stateless.
Port preview URLs
Any sandbox port is reachable at https://<id>-<port>.sbx.workers-waw1.host.ulewicz.space (TLS, WebSockets supported). Previews are public by default (the URL contains a random id); with "preview": "private" a token is required (x-hostbase-sandbox-token header or ?hb_token=, returned at creation). Responses carry X-Robots-Tag: noindex. Requests to the URL count as activity (they reset the idle timeout).
Pause and resume
pause in freeze mode freezes the machine in memory (resume takes tens of ms and processes survive; only half the RAM rate is billed, no CPU). stop mode stops the machine and frees its RAM but keeps the /workspace disk (resume is a ~2 s cold start, processes do not survive). A paused sandbox expires after 24 h.
Egress policy
open- the internet is reachable (default);allowlist- only the listed hostnames or IP/CIDR (names are resolved and refreshed every 5 min; DNS to 1.1.1.1 / 8.8.8.8 is allowed);none- no outbound traffic.
Always blocked regardless of mode: private networks (RFC1918, including the database hosts), the cloud metadata service, other sandboxes' networks, port 25 and ports typical for crypto miners (stratum).
Metrics, logs, usage
metrics returns samples every 10 s (CPU, memory, network, processes) and disk usage; logs - lifecycle events and the kernel log; usage - monthly project and organization usage against the plan allowance.
Billing
You pay for reserved resources while the sandbox runs: vCPU-seconds and GB-seconds of RAM. Included: Free 5 vCPU-h and 10 GB-h (hard limit), Pro 100 / 200, Team 500 / 1000. Beyond that: 0.25 PLN net per vCPU-hour and 0.04 PLN per GB-hour. Lines appear in Costs and on the invoice.
Security model
- Isolation: Kata + Cloud Hypervisor microVMs - a separate guest kernel and a hardware (KVM) boundary; gVisor as an option. Code cannot see the host or other sandboxes.
- Network: a separate bridge and subnet per sandbox; no access to private networks, the cloud metadata service, databases or other sandboxes.
- Resources: hard CPU, memory, PID and disk limits, forced shutdown after idling and after the maximum lifetime.
- Abuse: we detect pegged CPU, miner processes and stratum connection attempts. A sandbox running a miner is shut down and the owner is notified.
- Secrets: a sandbox gets no project keys - only the
envvariables you pass explicitly.
Token scopes
sandboxes:read (list, metrics, logs, usage) and sandboxes:write (create, exec, files, terminal, close); sandboxes:* grants both. Among project roles owner, admin and developer can write; readonly only reads.
Management API
GET|POST /api/v1/projects/{ref}/sandboxes (?all=1 includes recently ended)
GET /api/v1/projects/{ref}/sandboxes/templates
GET /api/v1/projects/{ref}/sandboxes/usage
GET|DELETE /api/v1/projects/{ref}/sandboxes/{id}
POST /api/v1/projects/{ref}/sandboxes/{id}/pause { mode: "freeze" | "stop" }
POST /api/v1/projects/{ref}/sandboxes/{id}/resume
POST /api/v1/projects/{ref}/sandboxes/{id}/timeout { idle_timeout_s, lifetime_s }
POST /api/v1/projects/{ref}/sandboxes/{id}/egress { mode: "open"|"allowlist"|"none", hosts }
POST /api/v1/projects/{ref}/sandboxes/{id}/ports { port }
POST /api/v1/projects/{ref}/sandboxes/{id}/exec { cmd, cwd, env, timeout_s, stdin, stream, background }
POST /api/v1/projects/{ref}/sandboxes/{id}/run-code { code, language, context_id, timeout_s }
GET /api/v1/projects/{ref}/sandboxes/{id}/files/list?path=
GET|PUT|DELETE /api/v1/projects/{ref}/sandboxes/{id}/files/content?path=
POST /api/v1/projects/{ref}/sandboxes/{id}/files/mkdir?path=
GET|PUT /api/v1/projects/{ref}/sandboxes/{id}/files/archive?path= (tar)
GET /api/v1/projects/{ref}/sandboxes/{id}/metrics
GET /api/v1/projects/{ref}/sandboxes/{id}/logs
POST /api/v1/projects/{ref}/sandboxes/{id}/terminal { cols, rows } -> { session_id }
GET /api/v1/projects/{ref}/sandboxes/{id}/terminal/{sid}/stream (SSE, base64 chunks)
POST /api/v1/projects/{ref}/sandboxes/{id}/terminal/{sid}/input { data, base64 }
POST /api/v1/projects/{ref}/sandboxes/{id}/terminal/{sid}/resize { cols, rows }
DELETE /api/v1/projects/{ref}/sandboxes/{id}/terminal/{sid}
TypeScript SDK
import { Sandbox } from "@hostbase/sandbox";
const sbx = await Sandbox.create({ apiKey: process.env.HOSTBASE_TOKEN!, project: "<ref>", template: "python-3.12", timeoutS: 600 });
const r = await sbx.exec("ls -la /workspace"); // { exitCode, stdout, stderr }
await sbx.files.write("/workspace/hello.py", "print('hi')");
const text = await sbx.files.read("/workspace/hello.py");
const run = await sbx.runCode("import numpy as np; np.arange(5).sum()");
await sbx.close();
A Python SDK skeleton lives in the repository (sdk/sandbox-python).
MCP
Tools for Claude Code, Cursor and other agents: create_sandbox, sandbox_exec, sandbox_run_code, sandbox_write_file, sandbox_read_file, list_sandboxes and close_sandbox. They require the sandboxes:write scope (listing: sandboxes:read).
AI Gateway: code_interpreter
Add "hostbase_tools": ["code_interpreter"] to a request to /api/ai/v1/chat/completions. The gateway gives the model a tool that runs Python in a sandbox of your project (a stateful kernel; charts come back as images) and drives the tool loop for up to 4 rounds; the sandbox is closed when the response finishes.
Start-up performance
For each template we keep a small warm pool of default-sized microVMs (1 vCPU / 1 GB / 5 GB). Creating a sandbox with default parameters claims a ready machine (tens of milliseconds); custom parameters or an empty pool mean a cold start (~2 s). The timings field in the response shows which path was taken.
Measured on host-workers-waw1 (D4as_v5, 4 vCPU / 16 GB)
| Step | Median / range |
|---|---|
| Create, warm pool (default size, microVM) | 12-29 ms |
| First exec after create (docker exec round-trip) | 130-200 ms |
| Create, cold microVM (python / ubuntu / node / bun / playwright) | 1.9-2.1 s / 1.8-1.9 s / 1.6 s / 1.6 s / 1.6 s |
| Create, cold gVisor (python / ubuntu) | 0.65 s / 0.60 s |
| Management API POST /sandboxes end-to-end (warm) | ~260 ms |
| Pause (freeze) / resume | 41-46 ms / 37-48 ms |
| Pause (stop) / resume (VM boot) | 0.54 s / 1.4 s |
| run-code Python, first call (imports pandas + matplotlib) / next call | 2.5 s / 0.12 s |
| Close (destroy VM, disk, network) | 0.63-0.68 s |
Warm pool: 3 x python-3.12, 2 x ubuntu, 2 x node-22 (refilled in the background, ~2 s each). Cold numbers include creating the per-sandbox bridge, the ext4 disk image, booting the Kata + Cloud Hypervisor VM and waiting for the guest agent.