| marp | true |
|---|---|
| html | true |
| theme | default |
| paginate | true |
| title | Hyperlight Sandbox |
| description | End-user overview of the Python SDK, capabilities, backend timings, and the agent framework scenario. |
| style | section { padding-top: 30px; } section h1 { margin-bottom: 0.3em; } section h2 { margin-top: 0.2em; margin-bottom: 0.2em; } pre { margin-top: 0.3em; margin-bottom: 0.3em; background: #1e1e2e; } code { color: #cdd6f4; } :not(pre) > code { color: #1e1e2e; background: #e0e0e0; } pre code .hljs-comment { color: #7f849c; } pre code .hljs-string { color: #a6e3a1; } pre code .hljs-keyword { color: #cba6f7; } pre code .hljs-built_in { color: #89b4fa; } pre code .hljs-function { color: #89b4fa; } pre code .hljs-title { color: #89b4fa; } pre code .hljs-number { color: #fab387; } pre code .hljs-params { color: #f5e0dc; } pre code .hljs-attr { color: #89dceb; } .green { color: #2ea043; font-weight: bold; } .red { color: #f85149; font-weight: bold; } section.timing { font-size: 22px; } section.timing table { font-size: 20px; } |
Fast sandboxed execution for agents, tools, and apps
- Run untrusted code in an isolated sandbox
- Keep a simple Python API
- Add tools, files, snapshots, and network rules when you need them
from hyperlight_sandbox import Sandbox
sandbox = Sandbox(backend="wasm", module="python_guest.path")
result = sandbox.run('print("Hello, World!")')
print(result.stdout)That's it - create a sandbox, run code, read the output.
- File Processing: Process provided files in Python and return a summarized report
- Code Mode: Let an agent write a script that calls your tools directly, reducing token usage
- Sandboxed Execution as a library: drop into an existing app or library without building a custom runtime
- Agent Skills combine scripts into multi-step workflows that run in isolation (future)
- Embedded code execution in apps
- Safe plugin or user-script scenarios
- Data workflows that need controlled host access
- Agent workflows that need repeatable, isolated execution
sandbox = Sandbox(backend="wasm", module="python_guest.path")
result = sandbox.run('print(2 + 3)')sandbox = Sandbox(backend="wasm", module="javascript_guest.path")
result = sandbox.run('console.log(2 + 3)')sandbox = Sandbox(backend="hyperlight-js")
result = sandbox.run('console.log(2 + 3)')// JavaScript via QuickJS in a Nanvix microkernel
let mut sandbox = SandboxBuilder::new().guest(NanvixJavaScript).build()?;
let result = sandbox.run(r#"console.log("Hello from Nanvix!")"#)?;
// Python via Python in a Nanvix microkernel
let mut sandbox = SandboxBuilder::new().guest(NanvixPython).build()?;
let result = sandbox.run(r#"print("Hello from Nanvix!")"#)?;- The Wasm path is not limited to Python and JavaScript
- Any runtime or language that can target the expected Wasm/WASI guest model can fit here
- Python and JavaScript are just the packaged end-user examples in this repo today
Capability based external access. Off by default.
import tempfile
from pathlib import Path
input_dir = tempfile.mkdtemp(prefix="sandbox-input-")
Path(input_dir, "data.json").write_text('{"name": "Alice"}')
sandbox = Sandbox(backend="wasm", module="python_guest.path", input_dir=input_dir)
sandbox.allow_domain("https://example.com", methods=["GET"])- Files: read from
/input, write to/output - Network: outbound HTTP with a domain allowlist
Capture state, restore it later. Pay cold start once, reuse across mutliple tenants.
sandbox = Sandbox(backend="wasm", module="python_guest.path")
sandbox.register_tool("fetch_data", lambda table="": db.query(table))
# Warm up the runtime once
sandbox.run("")
snap = sandbox.snapshot()
# Each task starts from a clean, warm state
for task in tasks:
sandbox.restore(snap)
result = sandbox.run(task)
print(result.stdout)snapshot()captures runtime state and filesrestore()rewinds to that point — fast, no cold start- Tools survive a restore; runtime and file state do not
Register host functions and call them from sandboxed code.
sandbox = Sandbox(backend="wasm", module="python_guest.path")
sandbox.register_tool("fetch_data", lambda table="": db.query(table))
result = sandbox.run("""
users = call_tool('fetch_data', table='users')
sales = call_tool('fetch_data', table='sales')
print(f"Found {len(users)} users and {len(sales)} sales")
""")- Works for sync and async functions
- Lets sandboxed code ask the host for data or computation safely
import json, os, tempfile
from pathlib import Path
input_dir = tempfile.mkdtemp(prefix="sandbox-input-")
Path(input_dir, "data.json").write_text('{"name": "Alice"}')
sandbox = Sandbox(
backend="wasm",
module="python_guest.path",
input_dir=input_dir,
temp_output=True,
)
result = sandbox.run("""
import json, os
# Host-provided file is available
with open('/input/data.json') as f:
data = json.load(f)
# Files not added by the host don't exist
print(os.path.exists('/input/secret.env')) # False
with open('/output/report.txt', 'w') as f:
f.write(f"Hello, {data['name']}")
""")
output_dir = sandbox.output_path()
with open(os.path.join(output_dir, "report.txt")) as f:
report = f.read()# Allow GET to example.com
sandbox.allow_domain("https://example.com", methods=["GET"])
# 🟢 Allowed — GET to example.com
resp = http_get("https://example.com/api/users")
# 🟥 Denied — POST to example.com, wrong method
resp = http_post("https://example.com/api/users", ...)
# 🟥 Denied — GET to other.com, not in allowlist
resp = http_get("https://other.com/admin")- Deny-by-default — no network access until you opt in
- Allowlist by domain and HTTP method
allow_domain("https://domain")permits all methods;methods=["GET"]restricts further
Measured from benchmark.py (release build) — 5 cold / 10 warm rounds, averages shown.
========================================================================================== Step Wasm + Python Wasm + JavaScript HyperlightJS
Cold start (create + first run) 143.9 ms 119.9 ms 96.7 ms Warm run (no restore) 0.2 ms 0.3 ms 0.1 ms Cold start + tool dispatch 138.1 ms 114.5 ms 105.4 ms Warm tool dispatch (no restore) 0.4 ms 0.3 ms 0.1 ms Cold start + file I/O 125.7 ms 119.4 ms 101.8 ms Warm file I/O (no restore) 0.3 ms 0.4 ms 0.1 ms Snapshot 59.1 ms 59.7 ms 20.5 ms Restore 11.4 ms 11.1 ms 11.5 ms Restore + run 1.5 ms 1.3 ms 0.7 ms Restore + tool dispatch 1.3 ms 1.2 ms 0.6 ms
Instead of paying cold start every time:
- Create the sandbox once
- Warm it up once
- Take a clean snapshot
- Restore before each new task to avoid sharing information
That gives you:
- Clean state between runs
- Fast repeat execution
- Predictable behavior for agents and multi-step workflows
The agent example uses Hyperlight Sandbox as the safe execution engine.
Copilot Agent
|
| execute_code(code="...")
v
+-------------------------------------------+
| Sandbox |
| |
| sandbox.run(code) |
| | |
| |-- call_tool("fetch_data") -------+--> Host
| |-- call_tool("compute") -------+--> Host
| | |
| v |
| stdout captured |
+-------------------------------------------+
|
v
result returned to agent