Skip to main content
The Template class provides a fluent API for building custom VM templates. Templates allow you to pre-configure environments with packages, files, and settings that boot in under 100ms using memory snapshots.

Overview

Templates are built using a step-based approach similar to Dockerfiles. You define a series of steps (install packages, copy files, run commands) and the SDK handles the build process, file uploads, and progress tracking.

Installation

The Template builder is included in the main SDK:
pip install hopx-ai

Quick Start

from hopx_ai import Template
from hopx_ai.template.types import BuildOptions

# Define template with fluent API
template = (
    Template()
    .from_ubuntu_image("22.04")
    .apt_install("curl", "git", "build-essential")
    .pip_install("numpy", "pandas", "scikit-learn")
    .set_env("PYTHONUNBUFFERED", "1")
    .set_workdir("/workspace")
)

# Build it
result = await Template.build(
    template,
    BuildOptions(
        alias="my-ml-template",
        api_key="hopx_live_...",
        cpu=2,
        memory=2048,
        disk_gb=10
    )
)

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

Template Class

Creating a Template

from hopx_ai import Template

template = Template()

Base Images

Start your template from a base Docker image:
# Ubuntu
template.from_ubuntu_image("22.04")

# Python
template.from_python_image("3.11")

# Node.js
template.from_node_image("18")

# Custom image
template.from_image("my-registry/image:tag")

# Private registries
template.from_gcp_registry("gcr.io/project/image", gcp_auth)
template.from_aws_registry("123456789.dkr.ecr.us-east-1.amazonaws.com/image", aws_auth)

Package Installation

Install packages using helper methods:
# System packages (apt)
template.apt_install("curl", "git", "build-essential")

# Python packages (pip)
template.pip_install("numpy", "pandas", "scikit-learn")

# Node.js packages (npm)
template.npm_install("express", "axios")

# Go packages
template.go_install("github.com/gin-gonic/gin")

# Rust packages
template.cargo_install("cargo-watch")
Multiple argument styles supported:
# Style 1: Multiple arguments
.pip_install("numpy", "pandas", "scikit-learn")

# Style 2: List
.pip_install(["numpy", "pandas", "scikit-learn"])

# Style 3: Chained
.pip_install("numpy").pip_install("pandas")

File Operations

Copy files into the template:
# Single file
template.copy("config.json", "/workspace/config.json")

# Multiple files
template.copy(["file1.txt", "file2.txt"], "/workspace/")

# Directory
template.copy("src/", "/workspace/src/")

Commands

Execute shell commands:
template.run_cmd("apt-get update && apt-get install -y python3")
template.run_cmd("curl -fsSL https://bun.sh/install | bash")

Environment Variables

Set environment variables:
# Single variable
template.set_env("PYTHONUNBUFFERED", "1")

# Multiple variables
template.set_envs({
    "NODE_ENV": "production",
    "API_URL": "https://api.example.com"
})

Working Directory

Set the working directory:
template.set_workdir("/workspace")

User

Set the user for subsequent commands:
template.set_user("appuser")

Git Operations

Clone repositories:
template.git_clone("https://github.com/user/repo.git", "/workspace/repo")

Start Command

Set a command to run when sandbox starts:
# Simple command
template.set_start_cmd("python /app/main.py")

# With ready check (wait for port)
from hopx_ai.template.types import wait_for_port
template.set_start_cmd("python /app/main.py", wait_for_port(8000))

Cache Control

Skip cache for a step:
template.skip_cache()

Building Templates

BuildOptions

Configure the build process:
from hopx_ai.template.types import BuildOptions

options = BuildOptions(
    alias="my-template",           # Template name (required)
    api_key="hopx_live_...",       # API key (required)
    base_url="https://api.hopx.dev",  # API base URL
    cpu=2,                         # vCPUs (1-64)
    memory=2048,                   # Memory in MB
    disk_gb=10,                    # Disk in GB
    on_log=lambda log: print(log), # Log callback
    on_progress=lambda p: print(f"{p}%")  # Progress callback
)

Building

Build the template:
result = await Template.build(template, options)

# Result contains:
# - template_id: ID of created template
# - build_id: Build job ID
# - status: Build status
# - duration: Build duration in milliseconds

Progress Tracking

Monitor build progress:
def on_log(log):
    level = log.get('level', 'INFO')
    message = log.get('message', '')
    print(f"[{level}] {message}")

def on_progress(progress):
    print(f"Progress: {progress}%")

result = await Template.build(
    template,
    BuildOptions(
        alias="my-template",
        api_key=api_key,
        on_log=on_log,
        on_progress=on_progress
    )
)

Complete Example

from hopx_ai import Template
from hopx_ai.template.types import BuildOptions, wait_for_port

async def create_ml_template():
    # Define template
    template = (
        Template()
        .from_ubuntu_image("22.04")
        .apt_install("python3-dev", "build-essential")
        .pip_install(
            "numpy==1.24.3",
            "pandas==2.0.3",
            "scikit-learn==1.3.0",
            "matplotlib==3.7.2"
        )
        .set_env("PYTHONUNBUFFERED", "1")
        .set_workdir("/workspace")
    )
    
    # Build template
    result = await Template.build(
        template,
        BuildOptions(
            alias="ml-template",
            api_key=os.getenv("HOPX_API_KEY"),
            cpu=4,
            memory=8192,
            disk_gb=20
        )
    )
    
    return result.template_id

# Use the template
template_id = await create_ml_template()
sandbox = Sandbox.create(template_id=template_id)

Validation

The SDK validates templates before building:
  • ✅ Must have a FROM step (base image)
  • ✅ Must have at least one build step (RUN, COPY, APT, etc.)
  • ❌ Cannot have only FROM + ENV/WORKDIR/USER

Error Handling

from hopx_ai.template.errors import TemplateBuildError

try:
    result = await Template.build(template, options)
except TemplateBuildError as e:
    print(f"Build failed: {e.message}")
    print(f"Build ID: {e.build_id}")

Best Practices

Pin versions for reproducibility:
.pip_install("numpy==1.24.3", "pandas==2.0.3")
Combine commands to reduce build time:
.run_cmd("apt-get update && apt-get install -y package1 package2")
Configure CPU, memory, and disk for your workload:
BuildOptions(
    alias="ml-template",
    cpu=4,
    memory=8192,
    disk_gb=50
)
Monitor long builds:
def on_progress(progress):
    print(f"Building: {progress}%")

BuildOptions(..., on_progress=on_progress)

API Reference

Template Methods

MethodDescriptionReturns
from_ubuntu_image(version)Start from Ubuntu base imageTemplate
from_python_image(version)Start from Python base imageTemplate
from_node_image(version)Start from Node.js base imageTemplate
from_image(image, auth?)Start from custom imageTemplate
apt_install(*packages)Install system packagesTemplate
pip_install(*packages)Install Python packagesTemplate
npm_install(*packages)Install Node.js packagesTemplate
go_install(*packages)Install Go packagesTemplate
cargo_install(*packages)Install Rust packagesTemplate
copy(src, dest, options?)Copy files/directoriesTemplate
run_cmd(command)Execute shell commandTemplate
set_env(key, value)Set environment variableTemplate
set_envs(vars)Set multiple environment variablesTemplate
set_workdir(path)Set working directoryTemplate
set_user(user)Set user for commandsTemplate
git_clone(url, dest)Clone git repositoryTemplate
set_start_cmd(cmd, ready?)Set start commandTemplate
skip_cache()Skip cache for next stepTemplate
get_steps()Get all stepsList[Step]

Template.build()

Static method to build a template:
@staticmethod
async def build(template: Template, options: BuildOptions) -> BuildResult
Parameters:
  • template: Template instance with steps defined
  • options: BuildOptions with alias, API key, and configuration
Returns: BuildResult with template_id, build_id, status, and duration

Next Steps