A3S Box
Sandbox SDK
Complete API reference for Rust, Python, and TypeScript SDKs
Sandbox SDK
Create, execute, and manage MicroVM sandboxes programmatically — no CLI or daemon required. All three SDKs wrap the same Rust runtime and provide identical capabilities.
Prop
Type
Rust SDK
Installation
[dependencies]
a3s-box-sdk = "0.5.3"
# Optional: bundle the shim binary into your application
a3s-box-sdk = { version = "0.5.3", features = ["embed-shim"] }With embed-shim, the SDK bundles a3s-box-shim into your binary and auto-extracts it to ~/.a3s/bin/ on first use. No separate installation needed.
BoxSdk
Entry point for creating and managing sandboxes.
use a3s_box_sdk::{BoxSdk, SandboxOptions};
// Use default home directory (~/.a3s/)
let sdk = BoxSdk::new().await?;
// Use custom home directory
let sdk = BoxSdk::with_home("/data/sandboxes").await?;
// Get home directory
let path: &Path = sdk.home_dir();SandboxOptions
pub struct SandboxOptions {
pub image: String, // OCI image reference (default: "alpine:latest")
pub cpus: u32, // vCPU count (default: 1)
pub memory_mb: u32, // Memory in MB (default: 256)
pub env: HashMap<String, String>, // Environment variables
pub workdir: Option<String>, // Working directory inside sandbox
pub mounts: Vec<MountSpec>, // Host-to-guest mounts
pub network: bool, // Enable networking (default: true)
pub tee: bool, // Enable AMD SEV-SNP (default: false)
pub name: Option<String>, // Sandbox name
pub port_forwards: Vec<PortForward>, // Port forwarding rules
pub workspace: Option<WorkspaceConfig>, // Persistent workspace
}
pub struct MountSpec {
pub host_path: String,
pub guest_path: String,
pub readonly: bool,
}
pub struct PortForward {
pub guest_port: u16,
pub host_port: u16, // 0 = auto-assign
pub protocol: String, // "tcp" or "udp"
}
pub struct WorkspaceConfig {
pub name: String,
pub guest_path: String, // default: "/workspace"
}Sandbox
// Create a sandbox
let sandbox: Sandbox = sdk.create(SandboxOptions {
image: "python:3.12-slim".into(),
cpus: 2,
memory_mb: 1024,
..Default::default()
}).await?;exec
Run a command and wait for it to complete.
pub async fn exec(&self, cmd: &str, args: &[&str]) -> Result<ExecResult>
pub struct ExecResult {
pub stdout: String,
pub stderr: String,
pub exit_code: i32,
pub metrics: ExecMetrics,
}
pub struct ExecMetrics {
pub duration_ms: u64,
pub stdout_bytes: u64,
pub stderr_bytes: u64,
}let result = sandbox.exec("python", &["-c", "print('hello')"]).await?;
println!("{}", result.stdout);
println!("exit: {}", result.exit_code);
println!("took: {}ms", result.metrics.duration_ms);exec_stream
Stream stdout/stderr in real-time.
pub async fn exec_stream(&self, cmd: &str, args: &[&str]) -> Result<impl Stream<Item = ExecEvent>>
pub enum ExecEvent {
Stdout(Vec<u8>),
Stderr(Vec<u8>),
Exit(i32),
}use futures::StreamExt;
let mut stream = sandbox.exec_stream(
"bash", &["-c", "for i in 1 2 3; do echo $i; sleep 1; done"]
).await?;
while let Some(event) = stream.next().await {
match event {
ExecEvent::Stdout(data) => print!("{}", String::from_utf8_lossy(&data)),
ExecEvent::Stderr(data) => eprint!("{}", String::from_utf8_lossy(&data)),
ExecEvent::Exit(code) => println!("exit: {}", code),
}
}upload / download
pub async fn upload(&self, host_path: &str, guest_path: &str) -> Result<()>
pub async fn download(&self, guest_path: &str, host_path: &str) -> Result<()>sandbox.upload("./config.yaml", "/app/config.yaml").await?;
sandbox.download("/app/output.json", "./output.json").await?;pause / resume
pub async fn pause(&self) -> Result<()>
pub async fn resume(&self) -> Result<()>pty
Open an interactive terminal session.
pub async fn pty(&self) -> Result<PtySession>
// PtySession provides read/write streams for terminal I/Ostop
pub async fn stop(&self) -> Result<()>Complete Example
use a3s_box_sdk::{BoxSdk, SandboxOptions, MountSpec, PortForward};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let sdk = BoxSdk::new().await?;
let sandbox = sdk.create(SandboxOptions {
image: "node:20-slim".into(),
cpus: 2,
memory_mb: 512,
env: [("NODE_ENV".into(), "production".into())].into(),
mounts: vec![MountSpec {
host_path: "./app".into(),
guest_path: "/app".into(),
readonly: false,
}],
port_forwards: vec![PortForward {
guest_port: 3000,
host_port: 0, // auto-assign
protocol: "tcp".into(),
}],
..Default::default()
}).await?;
let result = sandbox.exec("node", &["/app/server.js"]).await?;
println!("{}", result.stdout);
sandbox.stop().await?;
Ok(())
}Python SDK
Installation
pip install a3s-boxBoxSdk
from a3s_box import BoxSdk
# Default home directory (~/.a3s/)
sdk = BoxSdk()
# Custom home directory
sdk = BoxSdk(home_dir="/data/sandboxes")
# Get home directory
print(sdk.home_dir) # strSandboxOptions
from a3s_box import SandboxOptions, MountSpec, PortForward, WorkspaceConfig
options = SandboxOptions(
image="python:3.12-slim", # str, default: "alpine:latest"
cpus=2, # int, default: 1
memory_mb=1024, # int, default: 256
env={"KEY": "VALUE"}, # dict[str, str], default: {}
workdir="/app", # str | None
mounts=[ # list[MountSpec], default: []
MountSpec(host_path="./data", guest_path="/data", readonly=False)
],
network=True, # bool, default: True
tee=False, # bool, default: False
name="my-sandbox", # str | None
port_forwards=[ # list[PortForward], default: []
PortForward(guest_port=8080, host_port=0, protocol="tcp")
],
workspace=WorkspaceConfig( # WorkspaceConfig | None
name="my-project",
guest_path="/workspace"
),
)MountSpec / PortForward / WorkspaceConfig
MountSpec(host_path: str, guest_path: str, readonly: bool = False)
PortForward(guest_port: int, host_port: int = 0, protocol: str = "tcp")
WorkspaceConfig(name: str, guest_path: str = "/workspace")Sandbox
create
sandbox = sdk.create(options) # sync
sandbox = await sdk.create_async(options) # asyncexec
result = sandbox.exec("python", ["-c", "print('hello')"])
# result.stdout: str
# result.stderr: str
# result.exit_code: int
# result.metrics.duration_ms: int
# result.metrics.stdout_bytes: int
# result.metrics.stderr_bytes: intexec_stream
import sys
async for event in sandbox.exec_stream("bash", ["-c", "for i in 1 2 3; do echo $i; sleep 1; done"]):
if event.stdout:
sys.stdout.write(event.stdout)
elif event.stderr:
sys.stderr.write(event.stderr)
elif event.exit_code is not None:
print(f"exit: {event.exit_code}")upload / download
sandbox.upload("./input.csv", "/app/input.csv")
sandbox.download("/app/output.csv", "./output.csv")pause / resume / stop
sandbox.pause()
sandbox.resume()
sandbox.stop()Context manager
async with sdk.create(SandboxOptions(image="alpine:latest")) as sandbox:
result = sandbox.exec("echo", ["hello"])
print(result.stdout)
# sandbox.stop() called automaticallyComplete Example
import asyncio
from a3s_box import BoxSdk, SandboxOptions, MountSpec
async def main():
sdk = BoxSdk()
sandbox = sdk.create(SandboxOptions(
image="python:3.12-slim",
cpus=2,
memory_mb=1024,
env={"PYTHONPATH": "/app"},
mounts=[MountSpec(host_path="./src", guest_path="/app")],
))
# Upload a script
sandbox.upload("./script.py", "/app/script.py")
# Run it with streaming output
async for event in sandbox.exec_stream("python", ["/app/script.py"]):
if event.stdout:
print(event.stdout, end="")
# Download results
sandbox.download("/app/results.json", "./results.json")
sandbox.stop()
asyncio.run(main())TypeScript SDK
Installation
npm install @a3s-lab/boxBoxSdk
import { BoxSdk } from '@a3s-lab/box';
// Default home directory (~/.a3s/)
const sdk = new BoxSdk();
// Custom home directory
const sdk = new BoxSdk('/data/sandboxes');
// Get home directory
console.log(sdk.homeDir); // stringSandboxOptions
interface SandboxOptions {
image?: string; // default: "alpine:latest"
cpus?: number; // default: 1
memoryMb?: number; // default: 256
env?: Record<string, string>;
workdir?: string;
mounts?: MountSpec[];
network?: boolean; // default: true
tee?: boolean; // default: false
name?: string;
portForwards?: PortForward[];
workspace?: WorkspaceConfig;
}
interface MountSpec {
hostPath: string;
guestPath: string;
readonly?: boolean; // default: false
}
interface PortForward {
guestPort: number;
hostPort?: number; // default: 0 (auto-assign)
protocol?: string; // default: "tcp"
}
interface WorkspaceConfig {
name: string;
guestPath?: string; // default: "/workspace"
}Sandbox
create
const sandbox = await sdk.create({
image: 'node:20-slim',
cpus: 2,
memoryMb: 512,
});exec
const result = await sandbox.exec('node', ['-e', 'console.log("hello")']);
// result.stdout: string
// result.stderr: string
// result.exitCode: number
// result.metrics.durationMs: number
// result.metrics.stdoutBytes: number
// result.metrics.stderrBytes: numberexecStream
const stream = await sandbox.execStream('bash', [
'-c', 'for i in 1 2 3; do echo $i; sleep 1; done'
]);
for await (const event of stream) {
if (event.stdout) process.stdout.write(event.stdout);
if (event.stderr) process.stderr.write(event.stderr);
if (event.exitCode !== undefined) console.log(`exit: ${event.exitCode}`);
}upload / download
await sandbox.upload('./input.json', '/app/input.json');
await sandbox.download('/app/output.json', './output.json');pause / resume / stop
await sandbox.pause();
await sandbox.resume();
await sandbox.stop();Complete Example
import { BoxSdk } from '@a3s-lab/box';
const sdk = new BoxSdk();
const sandbox = await sdk.create({
image: 'node:20-slim',
cpus: 2,
memoryMb: 512,
env: { NODE_ENV: 'production' },
mounts: [{ hostPath: './app', guestPath: '/app' }],
portForwards: [{ guestPort: 3000, hostPort: 8080 }],
});
await sandbox.upload('./package.json', '/app/package.json');
const install = await sandbox.exec('npm', ['install', '--prefix', '/app']);
console.log(install.stdout);
const stream = await sandbox.execStream('node', ['/app/index.js']);
for await (const event of stream) {
if (event.stdout) process.stdout.write(event.stdout);
}
await sandbox.stop();Capabilities Summary
Prop
Type