hopx-ai 0.5.0
Official Python SDK for HOPX.AI Sandboxes
License: MIT
Requires Python: >=3.8
Keywords: cloud, containers, hopx, hopx-ai, microvm, sandbox, vm

# Hopx Python SDK

[![Python Version](https://img.shields.io/badge/python-3.8%2B-blue.svg)](https://www.python.org/downloads/)
[![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
[![Version](https://img.shields.io/badge/version-0.3.0-blue.svg)](CHANGELOG.md)

Official Python SDK for [Hopx.ai](https://hopx.ai) - Cloud sandboxes for AI agents and code execution.

## What is Hopx.ai?

Hopx.ai provides secure, isolated cloud sandboxes that start in seconds. Each sandbox is a lightweight VM with root access, pre-installed development tools, and configurable network access.

**Use cases:**
- AI agent code execution
- Running untrusted code safely
- Integration testing
- Data processing and analysis
- Browser automation
- Educational coding environments

**Sandbox features:**
- Full root access
- Pre-installed development tools
- Configurable network access
- Persistent filesystem during session
- Automatic cleanup after timeout

## Installation

```bash
pip install hopx-ai
```

## Quick Start

### Basic Usage

```python
from hopx_ai import Sandbox

# Create sandbox
sandbox = Sandbox.create(
    template="code-interpreter",
    api_key="your-api-key"  # or set HOPX_API_KEY env var
)

# Execute code
result = sandbox.run_code("""
import sys
print(f"Python {sys.version}")
print("Hello from Hopx!")
""")

print(result.stdout)
# Output:
# Python 3.11.x
# Hello from Hopx!

# Clean up
sandbox.kill()
```

### Context Manager

The context manager handles cleanup automatically:

```python
from hopx_ai import Sandbox

with Sandbox.create(template="code-interpreter") as sandbox:
    result = sandbox.run_code("print(2 + 2)")
    print(result.stdout)  # "4"
```

### Async Support

```python
from hopx_ai import AsyncSandbox
import asyncio

async def main():
    async with AsyncSandbox.create(template="code-interpreter") as sandbox:
        result = await sandbox.run_code("print('Async!')")
        print(result.stdout)

asyncio.run(main())
```

## Examples

### AI Code Execution

Execute code generated by LLM agents:

```python
from hopx_ai import Sandbox

agent_code = """
import pandas as pd
df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
print(df.describe())
"""

sandbox = Sandbox.create(template="code-interpreter")
result = sandbox.run_code(agent_code)

if result.success:
    print(result.stdout)
else:
    print(f"Error: {result.error}")

sandbox.kill()
```

### Data Analysis with Charts

Capture matplotlib charts as base64-encoded PNG:

```python
code = """
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)
plt.plot(x, np.sin(x))
plt.title('Sine Wave')
plt.show()
"""

sandbox = Sandbox.create(template="code-interpreter")
result = sandbox.run_code(code)

# Access chart data
if result.rich_outputs:
    png_data = result.rich_outputs[0].data  # Base64 PNG

sandbox.kill()
```

### Multi-Step Workflow

Run commands sequentially in the same environment:

```python
from hopx_ai import Sandbox

sandbox = Sandbox.create(template="code-interpreter", timeout_seconds=600)

# Clone and install
sandbox.commands.run("git clone https://github.com/user/project.git /app")
sandbox.commands.run("cd /app && npm install")

# Run tests
result = sandbox.commands.run("cd /app && npm test")
print(f"Tests: {'PASSED' if result.exit_code == 0 else 'FAILED'}")

# Build
sandbox.commands.run("cd /app && npm run build")

# List artifacts
files = sandbox.files.list("/app/dist/")
for file in files:
    print(f"Built: {file.name} ({file.size} bytes)")

sandbox.kill()
```

### File Processing

Upload files, process data, and download results:

```python
sandbox = Sandbox.create(template="code-interpreter")

# Upload data
sandbox.files.write("/tmp/data.csv", csv_content)

# Process
result = sandbox.run_code("""
import pandas as pd
df = pd.read_csv('/tmp/data.csv')
result = df.groupby('category').sum()
result.to_csv('/tmp/output.csv')
print(f"Processed {len(df)} rows")
""")

# Download result
output = sandbox.files.read("/tmp/output.csv")
print(output)

sandbox.kill()
```

## Core Features

### Code Execution

Execute code in Python, JavaScript, or Bash:

```python
# Python
result = sandbox.run_code("print('Hello')", language="python")

# JavaScript
result = sandbox.run_code("console.log('Hello')", language="javascript")

# Bash
result = sandbox.run_code("echo 'Hello'", language="bash")

# With environment variables
result = sandbox.run_code(
    "import os; print(os.environ['API_KEY'])",
    env={"API_KEY": "secret"}
)
```

### File Operations

```python
# Write files
sandbox.files.write("/app/config.json", '{"key": "value"}')

# Read files
content = sandbox.files.read("/app/config.json")

# List directory
files = sandbox.files.list("/app/")
for file in files:
    print(f"{file.name}: {file.size} bytes")

# Delete files
sandbox.files.delete("/app/temp.txt")
```

### Commands

```python
# Run synchronously
result = sandbox.commands.run("ls -la /app")
print(result.stdout)
print(f"Exit code: {result.exit_code}")

# Run in background (returns immediately with process ID)
result = sandbox.commands.run(
    "python long_task.py",
    background=True,
    timeout=300  # 5 minutes
)
print(result.stdout)  # "Background process started: cmd_1234..."

# Check process status
processes = sandbox.list_system_processes()
```

### Environment Variables

```python
# Set during creation (recommended)
sandbox = Sandbox.create(
    template="code-interpreter",
    env_vars={
        "DATABASE_URL": "postgresql://...",
        "API_KEY": "key123",
        "DEBUG": "true"
    }
)

# Variables are immediately available
result = sandbox.run_code("import os; print(os.environ['API_KEY'])")

# Set after creation
sandbox.env.update({
    "NODE_ENV": "production"
})

# Get all variables
all_vars = sandbox.env.get_all()

# Get specific variable
value = sandbox.env.get("API_KEY")

# Delete variable
sandbox.env.delete("DEBUG")
```

### Accessing Sandbox Services

Hopx automatically exposes all ports from your sandbox, making it easy to access web apps, APIs, and other services running inside.

```python
# Create sandbox and run a web server
sandbox = Sandbox.create(template="code-interpreter")

# Start a simple HTTP server on port 8080
sandbox.run_code_background("""
from http.server import HTTPServer, BaseHTTPRequestHandler

class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        self.wfile.write(b'<h1>Hello from Hopx!</h1>')

HTTPServer(('0.0.0.0', 8080), Handler).serve_forever()
""", language="python")

# Get the preview URL for port 8080
url = sandbox.get_preview_url(8080)
print(f"Access your app at: {url}")
# Output: https://8080-sandbox123.eu-1001.vms.hopx.dev/

# Get the default agent URL (port 7777)
agent = sandbox.agent_url
print(f"Sandbox agent: {agent}")
# Output: https://7777-sandbox123.eu-1001.vms.hopx.dev/

# Access any port
api_url = sandbox.get_preview_url(3000)  # Your API on port 3000
websocket_url = sandbox.get_preview_url(5000)  # WebSocket server
```

The preview URLs follow the format: `https://{port}-{sandbox_id}.{region}.vms.hopx.dev/`

See `examples/preview_url_basic.py` for a complete working example.

### Template Building

Build custom sandbox environments with your dependencies:

```python
from hopx_ai import Template, wait_for_port
from hopx_ai.template import BuildOptions

# Define template
template = (
    Template()
    .from_python_image("3.11")
    .copy("requirements.txt", "/app/requirements.txt")
    .copy("src/", "/app/src/")
    .run("cd /app && pip install -r requirements.txt")
    .set_workdir("/app")
    .set_env("PORT", "8000")
    .set_start_cmd("python src/main.py", wait_for_port(8000))
)

# Build template
result = await Template.build(
    template,
    BuildOptions(
        name="my-python-app",
        api_key="your-api-key",
        on_log=lambda log: print(f"[{log['level']}] {log['message']}")
    )
)

print(f"Template ID: {result.template_id}")

# Create sandbox from template
sandbox = Sandbox.create(template_id=result.template_id)
```

## Authentication

Get your API key at [hopx.ai/dashboard](https://hopx.ai/dashboard)

Set via environment variable:

```bash
export HOPX_API_KEY="your-api-key"
```

Or pass directly to methods:

```python
sandbox = Sandbox.create(
    template="code-interpreter",
    api_key="your-api-key"
)
```

## Configuration

### Template Build Timeout

`Template.build()` waits for templates to reach "active" status before returning. Templates transition through: building → publishing → active. The publishing phase takes 60-120 seconds.

**Default timeout:** 2700 seconds (45 minutes)

**Environment variable:**
```bash
export HOPX_TEMPLATE_BAKE_SECONDS=2700
```

**BuildOptions parameter:**
```python
result = await Template.build(
    template,
    BuildOptions(
        name="my-template",
        api_key="...",
        template_activation_timeout=1800  # 1800 seconds = 30 minutes
    )
)
```

**Priority:** BuildOptions.template_activation_timeout > HOPX_TEMPLATE_BAKE_SECONDS > Default (2700s)

## Pre-built Templates

| Template | Description |
|----------|-------------|
| `python` | Python 3.11 with pip, numpy, pandas, requests |
| `nodejs` | Node.js 20 with npm, common packages |
| `code-interpreter` | Python with data science stack (pandas, numpy, matplotlib, seaborn, scikit-learn) |
| `go` | Go 1.21 |
| `rust` | Rust with Cargo |
| `java` | Java 17 with Maven |

Build custom templates with `Template.build()` for specific requirements.

## Advanced Features

### Rich Output Capture

Capture matplotlib charts and visualizations:

```python
result = sandbox.run_code("""
import matplotlib.pyplot as plt
plt.plot([1, 2, 3], [1, 4, 9])
plt.title('My Chart')
plt.show()
""")

# Access PNG data
for output in result.rich_outputs:
    if output.type == "image/png":
        import base64
        with open("chart.png", "wb") as f:
            f.write(base64.b64decode(output.data))
```

### Process Management

```python
# List processes
processes = sandbox.processes.list()
for proc in processes:
    print(f"{proc.pid}: {proc.name} (CPU: {proc.cpu_percent}%)")

# Kill process
sandbox.processes.kill(1234)
```

### Desktop Automation

Control sandboxes with graphical interfaces:

```python
# Get VNC connection info
vnc = sandbox.desktop.get_vnc_info()
print(f"Connect to: {vnc.url}")

# Take screenshot
screenshot = sandbox.desktop.screenshot()  # Returns PNG bytes

# Control mouse
sandbox.desktop.mouse_click(100, 200)

# Type text
sandbox.desktop.keyboard_type("Hello, World!")
```

### Health and Metrics

Monitor sandbox resource usage:

```python
# Check health
health = sandbox.get_health()
print(health.status)

# Get metrics
metrics = sandbox.get_metrics()
print(f"CPU: {metrics.cpu_percent}%")
print(f"Memory: {metrics.memory_mb}MB")
print(f"Disk: {metrics.disk_mb}MB")
```

## Error Handling

```python
from hopx_ai import (
    HopxError,
    AuthenticationError,
    CodeExecutionError,
    FileNotFoundError,
    RateLimitError
)

try:
    sandbox = Sandbox.create(template="code-interpreter")
    result = sandbox.run_code("1/0")

except AuthenticationError:
    print("Invalid API key")
except CodeExecutionError as e:
    print(f"Code execution failed: {e.stderr}")
except RateLimitError:
    print("Rate limit exceeded")
except HopxError as e:
    print(f"API error: {e.message}")
```

## Best Practices

**Resource management:**
- Use context managers for automatic cleanup
- Set `timeout_seconds` to prevent runaway sandboxes
- Call `.kill()` explicitly when not using context managers

**Error handling:**
- Wrap sandbox operations in try/except blocks
- Check `result.success` before accessing output
- Review `result.stderr` for error details

**Performance:**
- Use pre-built templates when possible (faster than custom builds)
- Group related operations to reduce API calls
- Monitor resource usage for long-running tasks

## Troubleshooting

**Sandbox creation fails:**
- Verify API key is valid
- Check network connectivity
- Review error message for specific issue

**Code execution errors:**
- Check `result.stderr` for error details
- Verify required packages are installed
- Confirm file paths are correct

**File not found errors:**
- Use absolute paths (e.g., `/app/file.txt`)
- Verify file upload completed successfully
- Check current working directory

## Documentation

- [Full Documentation](https://docs.hopx.ai)
- [API Reference](https://docs.hopx.ai/python/api)
- [Examples](https://github.com/hopx-ai/hopx/tree/main/python/examples)
- [Cookbook](https://github.com/hopx-ai/hopx/tree/main/cookbook/python)

## Support

- Email: support@hopx.ai
- Discord: [discord.gg/hopx](https://discord.gg/hopx)
- GitHub Issues: [github.com/hopx-ai/hopx/issues](https://github.com/hopx-ai/hopx/issues)

## License

MIT License - see [LICENSE](LICENSE) file for details.

## Links

- [Website](https://hopx.ai)
- [Dashboard](https://hopx.ai/dashboard)
- [GitHub](https://github.com/hopx-ai/hopx)
- [Discord](https://discord.gg/hopx)
- [Twitter](https://twitter.com/hopx_ai)