Python SDK

Integrate sandboxes into your Python web applications.

Getting Started with the StateSet Sandbox Python SDK

This guide walks you through integrating the StateSet Sandbox SDK into your Python web application to spin up isolated sandbox environments for code execution.

Prerequisites

  • Python 3.9 or later
  • A StateSet Sandbox API key (sign up here)
  • pip or poetry package manager

Installation

bash
pip install stateset-sandbox

Or with poetry:

bash
poetry add stateset-sandbox

Quick Start

python
from stateset_sandbox import StateSetSandbox
import os

# Initialize the client
client = StateSetSandbox(
    base_url="https://api.sandbox.stateset.app",
    auth_token=os.environ["STATESET_API_KEY"],
)

# Create a sandbox and run code
sandbox = client.create(
    cpus="1",
    memory="1Gi",
    timeout_seconds=300,
)
print(f"Sandbox created: {sandbox.sandbox_id}")

# Execute a command
result = client.execute(sandbox.sandbox_id, command='echo "Hello from the sandbox!"')
print("Output:", result.stdout)
print("Exit code:", result.exit_code)

# Clean up
client.stop(sandbox.sandbox_id)

Configuration Options

python
client = StateSetSandbox(
    # Required: API endpoint
    base_url="https://api.sandbox.stateset.app",

    # Required: API key or JWT token
    auth_token="sk_live_...",

    # Optional: request timeout in seconds (default: 30)
    timeout=60,
)

Creating Sandboxes

Basic Sandbox

python
sandbox = client.create()
print(sandbox.sandbox_id, sandbox.status, sandbox.expires_at)

Customized Sandbox

python
sandbox = client.create(
    cpus="2",
    memory="2Gi",
    timeout_seconds=600,
    env={
        "NODE_ENV": "production",
        "API_URL": "https://api.example.com",
    },
    isolation="gvisor",   # "container" | "gvisor" | "microvm"
)

if sandbox.startup_metrics:
    print(f"Startup time: {sandbox.startup_metrics.total_ms}ms")

Executing Commands

Simple Execution

python
result = client.execute(sandbox.sandbox_id, command="node --version")
print(result.stdout)   # v20.x.x
print(result.exit_code)  # 0

With Working Directory and Environment

python
result = client.execute(
    sandbox.sandbox_id,
    command=["npm", "install"],
    working_dir="/workspace/my-project",
    env={"NPM_CONFIG_REGISTRY": "https://registry.npmjs.org"},
)

Streaming Execution

For long-running commands, use streaming for real-time output:

python
def on_stdout(data: str):
    print(data, end="")

def on_stderr(data: str):
    print(data, end="", file=sys.stderr)

def on_exit(code: int):
    print(f"\nProcess exited with code: {code}")

client.execute_stream(
    sandbox.sandbox_id,
    command="npm test",
    on_stdout=on_stdout,
    on_stderr=on_stderr,
    on_exit=on_exit,
)

File Operations

Writing Files

python
import base64

# Write a single file
client.write_file(sandbox.sandbox_id, "/workspace/main.py", """
from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return {"message": "Hello World!"}
""")

# Write multiple files (content must be base64 encoded)
client.write_files(sandbox.sandbox_id, files=[
    {
        "path": "/workspace/requirements.txt",
        "content": base64.b64encode(b"flask>=3.0\ngunicorn>=21.2").decode(),
    },
    {
        "path": "/workspace/README.md",
        "content": base64.b64encode(b"# My App").decode(),
    },
])

Reading Files

python
# Read and decode a file
content = client.read_file_content(sandbox.sandbox_id, "/workspace/main.py")
print(content)

# Read with metadata
file = client.read_file(sandbox.sandbox_id, "/workspace/main.py")
print(f"Size: {file.size} bytes")
decoded = base64.b64decode(file.content).decode("utf-8")

Web Application Integration

FastAPI Example

python
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from stateset_sandbox import StateSetSandbox
import os

app = FastAPI()

sandbox_client = StateSetSandbox(
    base_url=os.environ["STATESET_API_URL"],
    auth_token=os.environ["STATESET_API_KEY"],
)

class RunRequest(BaseModel):
    code: str
    language: str = "python"

@app.post("/api/run-code")
async def run_code(req: RunRequest):
    sandbox_id = None
    try:
        sandbox = sandbox_client.create(
            cpus="0.5",
            memory="512Mi",
            timeout_seconds=30,
            isolation="gvisor",
        )
        sandbox_id = sandbox.sandbox_id

        filename = "main.py" if req.language == "python" else "main.js"
        sandbox_client.write_file(sandbox_id, f"/workspace/{filename}", req.code)

        command = f"python3 /workspace/{filename}" if req.language == "python" \
            else f"node /workspace/{filename}"

        result = sandbox_client.execute(sandbox_id, command=command)

        return {
            "success": result.exit_code == 0,
            "output": result.stdout,
            "error": result.stderr,
            "exit_code": result.exit_code,
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))
    finally:
        if sandbox_id:
            sandbox_client.stop(sandbox_id)

Flask Example

python
from flask import Flask, request, jsonify
from stateset_sandbox import StateSetSandbox
import os

app = Flask(__name__)

sandbox_client = StateSetSandbox(
    base_url=os.environ["STATESET_API_URL"],
    auth_token=os.environ["STATESET_API_KEY"],
)

@app.post("/api/run-code")
def run_code():
    data = request.get_json()
    code = data["code"]
    language = data.get("language", "python")
    sandbox_id = None

    try:
        sandbox = sandbox_client.create(
            cpus="0.5",
            memory="512Mi",
            timeout_seconds=30,
            isolation="gvisor",
        )
        sandbox_id = sandbox.sandbox_id

        filename = "main.py" if language == "python" else "main.js"
        sandbox_client.write_file(sandbox_id, f"/workspace/{filename}", code)

        command = f"python3 /workspace/{filename}" if language == "python" \
            else f"node /workspace/{filename}"

        result = sandbox_client.execute(sandbox_id, command=command)

        return jsonify({
            "success": result.exit_code == 0,
            "output": result.stdout,
            "error": result.stderr,
            "exit_code": result.exit_code,
        })
    except Exception as e:
        return jsonify({"success": False, "error": str(e)}), 500
    finally:
        if sandbox_id:
            sandbox_client.stop(sandbox_id)

Error Handling

python
from stateset_sandbox import (
    StateSetSandbox,
    SandboxApiError,
    SandboxTimeoutError,
    SandboxNetworkError,
)

try:
    result = client.execute(sandbox_id, command="npm test")
except SandboxApiError as e:
    print(f"API Error [{e.code}]: {e.message}")
    print(f"Status: {e.status_code}")
    print(f"Request ID: {e.request_id}")
except SandboxTimeoutError as e:
    print(f"Timeout after {e.timeout}ms")
except SandboxNetworkError as e:
    print(f"Network error: {e}")

Checkpoints

Save and restore sandbox state. See the Checkpoints guide for full details.

python
# Create a checkpoint
checkpoint = client.create_checkpoint(
    sandbox_id,
    name="after-setup",
    description="Dependencies installed",
    include_paths=["/workspace"],
    exclude_paths=["/workspace/node_modules"],
)
print(f"Checkpoint: {checkpoint.id}")

# Restore a checkpoint
client.restore_checkpoint(sandbox_id, checkpoint.id)

Secrets

python
# Store a secret
client.create_secret(name="DATABASE_URL", value="postgresql://...")

# List secrets (values are never returned)
secrets = client.list_secrets()
for s in secrets:
    print(f"{s.name} (created {s.created_at})")

# Inject secrets into a sandbox
client.inject_secrets(sandbox_id, secrets=["DATABASE_URL"], as_env_vars=True)

Agent Sessions

Run long-lived AI agent loops. See the Agent Sessions guide for full details.

python
# Create and start a session
session = client.create_agent_session(
    name="code-review",
    budget={"cost_cap_cents": 500, "iteration_limit": 100},
    sandbox={"cpus": "2", "memory": "4Gi", "timeout_seconds": 3600},
)
client.start_agent_session(session.id)

# Execute inside the session
result = client.execute_in_agent_session(session.id, command=["python3", "run.py"])
print(result.stdout)

# Stop when done
client.stop_agent_session(session.id)

Best Practices

1. Always Clean Up Sandboxes

python
sandbox = client.create()
try:
    result = client.execute(sandbox.sandbox_id, command="python3 main.py")
finally:
    client.stop(sandbox.sandbox_id)

2. Use Appropriate Timeouts

python
# Quick task
quick = client.create(timeout_seconds=30, cpus="0.5", memory="256Mi")

# Long-running task
long = client.create(timeout_seconds=3600, cpus="2", memory="4Gi")

3. Use gVisor for Untrusted Code

python
sandbox = client.create(isolation="gvisor", cpus="1", memory="1Gi")

Complete Example: Code Playground API

python
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from stateset_sandbox import StateSetSandbox
import os

app = FastAPI()

sandbox_client = StateSetSandbox(
    base_url=os.environ["STATESET_API_URL"],
    auth_token=os.environ["STATESET_API_KEY"],
)

class PlaygroundRequest(BaseModel):
    code: str
    language: str = "python"  # "python" | "javascript" | "typescript"
    dependencies: list[str] = []

@app.post("/api/playground/run")
async def run_playground(req: PlaygroundRequest):
    sandbox_id = None
    try:
        sandbox = sandbox_client.create(
            cpus="1",
            memory="1Gi",
            timeout_seconds=120,
            isolation="gvisor",
        )
        sandbox_id = sandbox.sandbox_id

        # Install dependencies
        if req.dependencies:
            if req.language == "python":
                install_cmd = f"pip install {' '.join(req.dependencies)}"
            else:
                install_cmd = f"npm install {' '.join(req.dependencies)}"
            sandbox_client.execute(sandbox_id, command=install_cmd, working_dir="/workspace")

        # Write and run the code
        filenames = {"python": "main.py", "javascript": "main.js", "typescript": "main.ts"}
        commands = {
            "python": "python3 /workspace/main.py",
            "javascript": "node /workspace/main.js",
            "typescript": "npx tsx /workspace/main.ts",
        }

        filename = filenames[req.language]
        sandbox_client.write_file(sandbox_id, f"/workspace/{filename}", req.code)

        result = sandbox_client.execute(
            sandbox_id,
            command=commands[req.language],
            working_dir="/workspace",
        )

        return {
            "success": result.exit_code == 0,
            "output": result.stdout,
            "error": result.stderr,
            "exit_code": result.exit_code,
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))
    finally:
        if sandbox_id:
            sandbox_client.stop(sandbox_id)

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=3000)

Support