# API key Source: https://docs.hopx.ai/api-key How to obtain, manage, and use your HopX API keys for authentication. Complete guide to API key management, security best practices, and configuration for HopX SDK, CLI, and API access. Your API key is required to authenticate all requests to the HopX API. This guide shows you how to get your API key, configure it securely, and use it with the SDKs, CLI, or REST API. ## Get Your API key Sign up at [console.hopx.dev](https://console.hopx.dev) to get your free API key. After creating an account, you'll find your API key in the dashboard. Your API key is shown only once when created. Make sure to save it securely. If you lose your key, you'll need to create a new one. ## API key Format HopX API keys follow this format: ``` hopx_live_. ``` **Example:** ``` hopx_live_NXAXAV4sU3Ii.EXi3vR9kOJuhfbR5z42aFx5rhGjH1xnzFdjn9caAqps ``` Never share your API key publicly or commit it to version control. Treat it like a password. ## Setting Your API key You can provide your API key in several ways. The SDKs check these sources in order: ### Method 1: Environment Variable (Recommended) Set the `HOPX_API_KEY` environment variable. This is the most secure method and keeps your key out of your code. ```bash theme={null} # Linux/macOS export HOPX_API_KEY="hopx_live_..." # Windows (PowerShell) $env:HOPX_API_KEY="hopx_live_..." # Windows (Command Prompt) set HOPX_API_KEY=hopx_live_... ``` Then use the SDK without specifying the key: ```python theme={null} from hopx_ai import Sandbox # API key is automatically read from HOPX_API_KEY environment variable sandbox = Sandbox.create(template="code-interpreter") ``` ```bash theme={null} # Linux/macOS export HOPX_API_KEY="hopx_live_..." # Windows (PowerShell) $env:HOPX_API_KEY="hopx_live_..." # Windows (Command Prompt) set HOPX_API_KEY=hopx_live_... ``` Then use the SDK without specifying the key: ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // API key is automatically read from HOPX_API_KEY environment variable const sandbox = await Sandbox.create({ template: 'code-interpreter' }); ``` ### Method 2: Pass Directly to SDK You can pass the API key directly when creating a sandbox: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create( template="code-interpreter", api_key="hopx_live_..." # Pass directly ) ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter', apiKey: 'hopx_live_...' // Pass directly }); ``` Avoid hardcoding API keys in your source code. Use environment variables or secure secret management systems instead. ### Method 3: Configuration File You can use configuration files or secret management systems: ```bash theme={null} # .env file HOPX_API_KEY=hopx_live_... ``` ```python theme={null} # Install python-dotenv: pip install python-dotenv from dotenv import load_dotenv load_dotenv() from hopx_ai import Sandbox # API key is automatically loaded from .env sandbox = Sandbox.create(template="code-interpreter") ``` ```bash theme={null} # .env file HOPX_API_KEY=hopx_live_... ``` ```javascript theme={null} // Install dotenv: npm install dotenv import 'dotenv/config'; import { Sandbox } from '@hopx-ai/sdk'; // API key is automatically loaded from .env const sandbox = await Sandbox.create({ template: 'code-interpreter' }); ``` The CLI automatically uses the `HOPX_API_KEY` environment variable. You can also configure it via: ```bash theme={null} # Set environment variable export HOPX_API_KEY="hopx_live_..." # Or use CLI login (interactive) hopx auth login # Or set via CLI config hopx config set api_key "hopx_live_..." ``` See [CLI Authentication](/cli/commands/auth) for more options. ## Using API Keys with Direct API Calls When making direct HTTP requests to the HopX API, include your API key in the request headers: ### Header Format You can use either of these header formats: ```bash theme={null} # Option 1: Authorization header (recommended) Authorization: Bearer hopx_live_... # Option 2: X-API-Key header X-API-Key: hopx_live_... ``` ### Example: Creating a Sandbox ```bash theme={null} curl -X POST https://api.hopx.dev/v1/sandboxes \ -H "Authorization: Bearer hopx_live_..." \ -H "Content-Type: application/json" \ -d '{ "template_id": "code-interpreter" }' ``` ### Example: Listing Sandboxes ```bash theme={null} curl https://api.hopx.dev/v1/sandboxes \ -H "Authorization: Bearer hopx_live_..." ``` ## Security Best Practices Never commit API keys to version control. Use environment variables, secret management services (AWS Secrets Manager, HashiCorp Vault), or secure configuration files. Periodically rotate your API keys, especially if you suspect they may have been compromised. Create new keys in the console and update your applications. Use separate API keys for development, staging, and production environments. This allows you to revoke access to specific environments without affecting others. Regularly review your API key usage in the console to detect any unauthorized access or unusual activity. If your organization supports it, create API keys with limited permissions for specific use cases (e.g., read-only keys for monitoring). ## Testing Your API key You can test your API key by making a simple API call: ```python theme={null} from hopx_ai import Sandbox try: # Try to list templates (requires valid API key) templates = Sandbox.list_templates() print(f"✅ API key is valid! Found {len(templates)} templates.") except Exception as e: print(f"❌ API key error: {e}") ``` **Expected Output:** ``` ✅ API key is valid! Found 15 templates. ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; try { // Try to list templates (requires valid API key) const templates = await Sandbox.listTemplates(); console.log(`✅ API key is valid! Found ${templates.length} templates.`); } catch (error) { console.error(`❌ API key error: ${error.message}`); } ``` **Expected Output:** ``` ✅ API key is valid! Found 15 templates. ``` ```bash theme={null} curl https://api.hopx.dev/v1/templates \ -H "Authorization: Bearer hopx_live_..." ``` If your key is valid, you'll receive a JSON response with available templates. If invalid, you'll get a `401 Unauthorized` error. ## Troubleshooting ### Invalid API key Error If you receive an authentication error: 1. **Verify the key format**: Ensure your key starts with `hopx_live_` and contains both the key ID and secret separated by a dot. 2. **Check for extra spaces**: Make sure there are no leading or trailing spaces when copying the key. 3. **Verify environment variable**: If using environment variables, confirm it's set correctly: ```bash theme={null} echo $HOPX_API_KEY # Linux/macOS echo %HOPX_API_KEY% # Windows ``` 4. **Check key status**: Log into [console.hopx.dev](https://console.hopx.dev) to verify your key is active and not revoked. ### Key Not Found If the SDK can't find your API key: 1. **Check environment variable name**: Ensure it's exactly `HOPX_API_KEY` (case-sensitive on some systems). 2. **Restart your terminal/IDE**: Environment variables may not be loaded in your current session. 3. **Verify the key is set**: Use the troubleshooting commands above to confirm the variable is set. ### Rate Limiting If you receive rate limit errors: * Your API key has usage limits based on your plan * Wait a few moments and retry your request * Consider implementing exponential backoff in your application * Upgrade your plan if you need higher rate limits ## Related * **[API Authentication](/api/authentication)** - Learn about API authentication * **[Python SDK Quickstart](/sdk/python/quickstart)** - Get started with the Python SDK * **[JavaScript SDK Quickstart](/sdk/javascript/quickstart)** - Get started with the JavaScript SDK * **[API Quickstart](/api/quickstart)** - Make your first API request ## Next Steps * Follow the [Quickstart Guide](/quickstart) to create your first sandbox * Learn about [Supported Languages](/supported-languages) for code execution * Explore [MCP Integration](/guides/integrations/mcp-integration) for AI assistant integration # Authentication Source: https://docs.hopx.ai/api/authentication Learn how to authenticate requests to the HopX API using API keys. Secure your API requests with authentication headers, manage API keys, and understand authentication best practices. Essential for accessing HopX Control Plane and VM Agent APIs. Includes authentication examples, security guidelines, and API key management. All requests to the HopX API require authentication using an API key. This guide shows you how to get your API key, configure it securely, and use it in API requests. ## Get Your API key Sign up at [console.hopx.dev](https://console.hopx.dev) to get your free API key. After creating an account, navigate to the API Keys section in your dashboard to create and manage keys. Your API key is shown only once when created. Make sure to save it securely. If you lose your key, you'll need to create a new one from the dashboard. ## API key Format HopX API keys follow this format: ``` hopx_live_. ``` **Example:** ``` hopx_live_NXAXAV4sU3Ii.EXi3vR9kOJuhfbR5z42aFx5rhGjH1xnzFdjn9caAqps ``` The key consists of: * **Prefix**: `hopx_live_` (indicates a live/production key) * **Key ID**: 12-character alphanumeric identifier (public, used for identification) * **Secret**: 32-byte cryptographically random secret (base64url encoded) Never share your API key publicly or commit it to version control. Treat it like a password. If your key is exposed, revoke it immediately and create a new one. ## Authentication Methods The HopX API supports two authentication header formats: ### Method 1: Authorization Header (Recommended) Include your API key in the `Authorization` header using Bearer authentication: ```bash theme={null} curl -H "Authorization: Bearer $HOPX_API_KEY" \ https://api.hopx.dev/v1/sandboxes ``` Replace `$HOPX_API_KEY` with your actual API key from [console.hopx.dev](https://console.hopx.dev), or set it as an environment variable: `export HOPX_API_KEY="your-API key-here"` ### Method 2: X-API key Header Alternatively, use the `X-API key` header: ```bash theme={null} curl -H "X-API key: $HOPX_API_KEY" \ https://api.hopx.dev/v1/sandboxes ``` Replace `$HOPX_API_KEY` with your actual API key from [console.hopx.dev](https://console.hopx.dev), or set it as an environment variable: `export HOPX_API_KEY="your-API key-here"` Both methods are equivalent. Use whichever is more convenient for your setup. ## Complete Request Example Here's a complete authenticated request to create a sandbox: ```bash theme={null} curl -X POST https://api.hopx.dev/v1/sandboxes \ -H "Authorization: Bearer hopx_live_NXAXAV4sU3Ii.EXi3vR9kOJuhfbR5z42aFx5rhGjH1xnzFdjn9caAqps" \ -H "Content-Type: application/json" \ -d '{ "template_id": "73", "timeout_seconds": 3600 }' ``` ## Security Best Practices ### 1. Use Environment Variables Store your API key in an environment variable rather than hardcoding it: ```bash theme={null} # Set environment variable export HOPX_API_KEY="hopx_live_NXAXAV4sU3Ii.EXi3vR9kOJuhfbR5z42aFx5rhGjH1xnzFdjn9caAqps" # Use in request curl -H "Authorization: Bearer $HOPX_API_KEY" \ https://api.hopx.dev/v1/sandboxes ``` ### 2. Use Least Privilege Only grant API keys the minimum permissions needed for your use case. If you're only reading sandbox information, don't use a key with full write access. ### 3. Rotate Keys Regularly Periodically rotate your API keys, especially if you suspect they may have been compromised. Create new keys in the dashboard and update your applications. ### 4. Monitor Key Usage Review API key usage in your dashboard to detect any unauthorized access. If you see unexpected activity, revoke the key immediately. ## Authentication Errors ### 401 Unauthorized If your API key is missing, invalid, or expired, you'll receive a 401 error: ```json theme={null} { "error": "Unauthorized", "code": "AUTHENTICATION_REQUIRED", "request_id": "req_abc123" } ``` **Common causes:** * Missing `Authorization` or `X-API key` header * Invalid API key format * Revoked or expired API key **Fix:** * Verify your API key is correct * Check that the key hasn't been revoked in your dashboard * Ensure you're using the correct header format ### 403 Forbidden If your API key doesn't have permission for the requested operation: ```json theme={null} { "error": "Forbidden", "code": "INSUFFICIENT_PERMISSIONS", "request_id": "req_abc123" } ``` **Fix:** * Verify your API key has the required permissions * Check your account's access level in the dashboard ## Public Endpoints The following endpoints do **not** require authentication: * `GET /health` - Health check endpoint All other endpoints require a valid API key. ## Related * **\[API key Management]\(/API key)** - Manage API keys in the dashboard * **[Python SDK Quickstart](/sdk/python/quickstart)** - Get started with the Python SDK * **[JavaScript SDK Quickstart](/sdk/javascript/quickstart)** - Get started with the JavaScript SDK * **[API Quickstart](/api/quickstart)** - Make your first API request * [CLI Reference](/cli/introduction) - Command-line interface ## Next Steps * **[Quickstart](/api/quickstart)** - Create your first sandbox with a complete example * **[Control Plane API](/api/control-plane/overview)** - Learn about sandbox management endpoints * **\[Get API key]\(/API key)** - Detailed guide on obtaining and managing API keys # Data Model Source: https://docs.hopx.ai/api/concepts/data-model Core resources and data structures in the HopX API. Understand sandbox objects, template structures, execution results, file metadata, and other data models used throughout the HopX API. Essential for working with API responses and building integrations. Includes data model reference and field descriptions. The HopX API uses a consistent data model across all endpoints. Understanding these core resources and their relationships is essential for effective API usage. ## Core Resources ### Sandbox A sandbox is an isolated virtual machine environment for code execution. Each sandbox has: | Field | Type | Description | | ------------------ | ------- | ----------------------------------- | | `id` | string | Unique sandbox identifier | | `status` | string | Current status (see statuses below) | | `template_id` | string | Template ID used to create sandbox | | `template_name` | string | Template name | | `region` | string | Deployment region | | `resources` | object | Allocated vCPU, memory, disk | | `auth_token` | string | JWT token for VM Agent API access | | `token_expires_at` | string | JWT token expiration (ISO 8601) | | `public_host` | string | VM Agent API base URL | | `timeout_seconds` | integer | Auto-shutdown timeout | | `created_at` | string | Creation timestamp (ISO 8601) | | `updated_at` | string | Last update timestamp (ISO 8601) | #### Sandbox Statuses | Status | Description | | ---------- | ------------------------------------- | | `creating` | Sandbox is being created | | `running` | Sandbox is active and ready | | `stopped` | Sandbox is stopped (can be restarted) | | `paused` | Sandbox is paused (RAM preserved) | | `error` | Sandbox creation or operation failed | | `deleted` | Sandbox has been deleted | #### Sandbox Lifecycle ``` creating → running ⟷ stopped ↓ paused → running ↓ deleted ``` ### Template A template defines the base image and resources for creating sandboxes: | Field | Type | Description | | ------------------- | ------- | ------------------------------------------------ | | `id` | string | Unique template identifier | | `name` | string | Template name (unique, used as identifier) | | `display_name` | string | Human-readable name | | `description` | string | Template description | | `category` | string | Template category (python, nodejs, ubuntu, etc.) | | `language` | string | Primary programming language | | `default_resources` | object | Default vCPU, memory, disk allocation | | `features` | array | Supported features | | `is_public` | boolean | Whether template is publicly available | | `is_active` | boolean | Whether template is ready for use | | `status` | string | Template status (active, building, failed) | #### Template Categories * **python** - Python environments (various versions) * **nodejs** - Node.js environments * **ubuntu** - Ubuntu base images * **code-interpreter** - Multi-language execution environments * **custom** - Custom organization templates ### Execution Result Result from code execution or command: | Field | Type | Description | | ---------------- | ------- | --------------------------- | | `success` | boolean | Whether execution succeeded | | `stdout` | string | Standard output | | `stderr` | string | Standard error | | `exit_code` | integer | Exit code (0 = success) | | `execution_time` | number | Execution time in seconds | For rich output capture, additional fields: | Field | Type | Description | | -------------- | ----- | ---------------------------- | | `rich_outputs` | array | Array of rich output objects | Each rich output object: | Field | Type | Description | | ---------- | ------ | -------------------------------------- | | `type` | string | MIME type (image/png, text/html, etc.) | | `format` | string | Data format (base64, text) | | `data` | string | Output data | | `metadata` | object | Additional metadata | ### Process Background execution process: | Field | Type | Description | | -------------- | ------- | --------------------------------------------------- | | `process_id` | string | Unique process identifier | | `execution_id` | string | Execution ID | | `name` | string | Process name (optional) | | `status` | string | Process status (queued, running, completed, failed) | | `language` | string | Programming language | | `started_at` | string | Start timestamp (ISO 8601) | | `completed_at` | string | Completion timestamp (ISO 8601, if complete) | | `stdout` | string | Standard output | | `stderr` | string | Standard error | | `exit_code` | integer | Exit code (null if still running) | ## Object Types All API responses include an `object` field identifying the resource type: | Object Type | Description | | ----------- | --------------------------------- | | `sandbox` | Sandbox resource | | `template` | Template resource | | `list` | List of resources with pagination | | `error` | Error response | ## List Objects List endpoints return a consistent structure: ```json theme={null} { "object": "list", "data": [...], "has_more": false, "next_cursor": null, "url": "/v1/sandboxes", "request_id": "req_abc123" } ``` | Field | Type | Description | | ------------- | ------- | ----------------------------------- | | `object` | string | Always "list" | | `data` | array | Array of resource objects | | `has_more` | boolean | Whether more results exist | | `next_cursor` | string | Cursor for next page (if has\_more) | | `url` | string | Endpoint URL | | `request_id` | string | Request ID for debugging | ## Timestamps All timestamps use ISO 8601 format with UTC timezone: ``` 2025-01-28T00:00:00Z ``` Example timestamps: * `created_at` - Resource creation time * `updated_at` - Last modification time * `completed_at` - Task completion time * `expires_at` - Expiration time * `token_expires_at` - JWT token expiration ## Identifiers ### Format Identifiers follow consistent patterns: | Prefix | Resource Type | Example | | ----------- | -------------- | ------------------- | | `sandbox_` | Sandbox | `sandbox_abc123xyz` | | `template_` | Template | `template_xyz789` | | `proc_` | Process | `proc_abc123` | | `exec_` | Execution | `exec_xyz789` | | `req_` | Request | `req_abc123` | | `build_` | Template Build | `build_abc123` | ### Usage * Identifiers are **case-sensitive** * Store identifiers as returned by the API * Use template `name` or `id` when creating sandboxes ## Resource Relationships ``` Template (1) ──creates──> (N) Sandbox │ ├──has──> (1) JWT Token │ └──runs──> (N) Process/Execution ``` * One template can create multiple sandboxes * Each sandbox has one JWT token (refreshable) * Each sandbox can have multiple concurrent processes/executions ## Common Patterns ### Create → Poll → Use ```bash theme={null} # 1. Create resource RESPONSE=$(curl -X POST https://api.hopx.dev/v1/sandboxes \ -H "Authorization: Bearer $HOPX_API_KEY" \ -H "Content-Type: application/json" \ -d '{"template_id": "code-interpreter"}') SANDBOX_ID=$(echo "$RESPONSE" | jq -r '.id') # 2. Poll until ready (status: running) while true; do STATUS=$(curl -s "https://api.hopx.dev/v1/sandboxes/$SANDBOX_ID" \ -H "Authorization: Bearer $HOPX_API_KEY" | jq -r '.status') [ "$STATUS" == "running" ] && break sleep 2 done # 3. Use resource JWT_TOKEN=$(curl -s "https://api.hopx.dev/v1/sandboxes/$SANDBOX_ID" \ -H "Authorization: Bearer $HOPX_API_KEY" | jq -r '.auth_token') curl -X POST "https://$SANDBOX_ID.hopx.dev/execute" \ -H "Authorization: Bearer $JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{"code": "print(\"Hello World\")", "language": "python"}' ``` ## Related * **[API Introduction](/api/introduction)** - Learn about the HopX API * **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Learn about sandbox creation * **[Managing Sandbox State](/core-concepts/sandboxes/managing-state)** - Control sandbox lifecycle * **[Control Plane API Overview](/api/control-plane/overview)** - Manage sandboxes via API * **[VM Agent API Overview](/api/vm-agent/overview)** - Execute code via API * [CLI Reference](/cli/introduction) - Command-line interface ## Next Steps * **[Errors](/api/concepts/errors)** - Error handling and codes * **[Rate Limits](/api/concepts/rate-limits)** - Request rate limits * **[Pagination](/api/concepts/pagination)** - Paginating list results # Error Handling Source: https://docs.hopx.ai/api/concepts/errors Error handling, error codes, and troubleshooting in the HopX API. Understand API error responses, HTTP status codes, error message formats, and how to handle errors gracefully in your applications. Essential for building robust integrations with HopX APIs. Includes error code reference and troubleshooting guides. The HopX API uses conventional HTTP status codes and returns detailed error responses to help you troubleshoot issues. ## Error Response Format All errors return a JSON response with this structure: ```json theme={null} { "error": "Error message describing what went wrong", "code": "ERROR_CODE", "request_id": "req_abc123" } ``` | Field | Type | Description | | ------------ | ------ | -------------------------------- | | `error` | string | Human-readable error message | | `code` | string | Machine-readable error code | | `request_id` | string | Request ID for support/debugging | ## HTTP Status Codes | Code | Meaning | Description | | ---- | --------------------- | ---------------------------------------- | | 200 | OK | Request succeeded | | 202 | Accepted | Request accepted (async operation) | | 204 | No Content | Request succeeded, no response body | | 400 | Bad Request | Invalid request parameters | | 401 | Unauthorized | Authentication failed or missing | | 403 | Forbidden | Access denied | | 404 | Not Found | Resource not found | | 408 | Request Timeout | Request exceeded timeout | | 409 | Conflict | Resource conflict (e.g., already exists) | | 429 | Too Many Requests | Rate limit exceeded | | 500 | Internal Server Error | Server error | | 503 | Service Unavailable | Service temporarily unavailable | ## Error Codes ### Authentication Errors #### AUTHENTICATION\_REQUIRED (401) ```json theme={null} { "error": "Authentication required", "code": "AUTHENTICATION_REQUIRED", "request_id": "req_abc123" } ``` **Cause:** No API key or JWT token provided. **Fix:** Include `Authorization: Bearer $HOPX_API_KEY` header. #### INVALID\_TOKEN (401) ```json theme={null} { "error": "Invalid or expired token", "code": "INVALID_TOKEN", "request_id": "req_abc123" } ``` **Cause:** JWT token is invalid or expired. **Fix:** Refresh the JWT token using the Control Plane API. ### Request Errors #### INVALID\_REQUEST (400) ```json theme={null} { "error": "Invalid request: missing required field 'code'", "code": "INVALID_REQUEST", "request_id": "req_abc123" } ``` **Cause:** Missing required parameters or invalid request format. **Fix:** Check the request body and ensure all required fields are present. #### RESOURCE\_NOT\_FOUND (404) ```json theme={null} { "error": "Sandbox not found", "code": "RESOURCE_NOT_FOUND", "request_id": "req_abc123" } ``` **Cause:** The requested resource doesn't exist. **Fix:** Verify the resource ID is correct. #### CONFLICT (409) ```json theme={null} { "error": "Template already exists. Set update=true to update it.", "code": "CONFLICT", "request_id": "req_abc123" } ``` **Cause:** Resource already exists. **Fix:** Use a different name or set `update=true`. ### Execution Errors #### EXECUTION\_TIMEOUT (408) ```json theme={null} { "error": "Execution timeout after 60 seconds", "code": "EXECUTION_TIMEOUT", "request_id": "req_abc123" } ``` **Cause:** Code execution exceeded the timeout limit. **Fix:** Increase the timeout or optimize your code. #### CODE\_EXECUTION\_ERROR (500) ```json theme={null} { "success": false, "stdout": "", "stderr": "NameError: name 'x' is not defined\n", "exit_code": 1, "execution_time": 0.05 } ``` **Cause:** Code execution failed (syntax error, runtime error, etc.). **Fix:** Check the `stderr` field for error details and fix your code. ### Resource Errors #### PAYMENT\_REQUIRED (402) ```json theme={null} { "error": "Payment required: credit limit exceeded", "code": "PAYMENT_REQUIRED", "request_id": "req_abc123" } ``` **Cause:** Account credit limit reached or payment method required. **Fix:** Add payment method or increase credit limit. #### RESOURCE\_LIMIT\_ERROR (429) ```json theme={null} { "error": "Sandbox limit reached (10/10)", "code": "RESOURCE_LIMIT_ERROR", "request_id": "req_abc123" } ``` **Cause:** Account resource limit reached. **Fix:** Delete unused sandboxes or upgrade your plan. #### FORBIDDEN (403) ```json theme={null} { "error": "Path not allowed: /etc/passwd", "code": "FORBIDDEN", "request_id": "req_abc123" } ``` **Cause:** Access to resource or path is forbidden. **Fix:** Only access allowed paths (e.g., `/workspace`, `/tmp`). ### Rate Limiting #### RATE\_LIMIT\_EXCEEDED (429) ```json theme={null} { "error": "Rate limit exceeded: 100 requests per minute", "code": "RATE_LIMIT_EXCEEDED", "request_id": "req_abc123", "retry_after": 30 } ``` **Cause:** Too many requests in a short time. **Fix:** Wait and retry. Use exponential backoff. See [Rate Limits](/api/concepts/rate-limits) for details. ### Service Errors #### SERVICE\_UNAVAILABLE (503) ```json theme={null} { "error": "Service temporarily unavailable", "code": "SERVICE_UNAVAILABLE", "request_id": "req_abc123" } ``` **Cause:** Service is temporarily down or overloaded. **Fix:** Retry with exponential backoff. #### INTERNAL\_ERROR (500) ```json theme={null} { "error": "Internal server error", "code": "INTERNAL_ERROR", "request_id": "req_abc123" } ``` **Cause:** Unexpected server error. **Fix:** Retry the request. Contact support with `request_id` if issue persists. ## Error Handling Best Practices ### 1. Check Status Codes ```bash theme={null} RESPONSE=$(curl -s -w "\n%{http_code}" https://api.hopx.dev/v1/sandboxes \ -H "Authorization: Bearer $HOPX_API_KEY") HTTP_CODE=$(echo "$RESPONSE" | tail -n1) BODY=$(echo "$RESPONSE" | sed '$d') if [ "$HTTP_CODE" -ge 400 ]; then echo "Error: $BODY" exit 1 fi ``` ### 2. Parse Error Responses ```python theme={null} import requests response = requests.post( "https://api.hopx.dev/v1/sandboxes", headers={"Authorization": "Bearer $HOPX_API_KEY"}, json={"template_id": "code-interpreter"} ) if response.status_code >= 400: error = response.json() print(f"Error: {error['error']}") print(f"Code: {error['code']}") print(f"Request ID: {error['request_id']}") exit(1) ``` ### 3. Implement Retry Logic ```python theme={null} import time import requests def create_sandbox_with_retry(max_retries=3): for attempt in range(max_retries): try: response = requests.post( "https://api.hopx.dev/v1/sandboxes", headers={"Authorization": "Bearer $HOPX_API_KEY"}, json={"template_id": "code-interpreter"}, timeout=30 ) if response.status_code == 200: return response.json() # Retry on 5xx errors or rate limits if response.status_code >= 500 or response.status_code == 429: wait_time = 2 ** attempt # Exponential backoff print(f"Retry {attempt + 1}/{max_retries} after {wait_time}s") time.sleep(wait_time) continue # Don't retry on 4xx errors (except 429) response.raise_for_status() except requests.exceptions.RequestException as e: if attempt == max_retries - 1: raise time.sleep(2 ** attempt) raise Exception("Max retries exceeded") ``` ### 4. Handle Specific Errors ```python theme={null} response = requests.post(url, headers=headers, json=payload) if response.status_code == 401: # Refresh token and retry refresh_token() response = requests.post(url, headers=headers, json=payload) elif response.status_code == 404: # Resource not found - create it create_resource() elif response.status_code == 429: # Rate limited - wait and retry time.sleep(60) response = requests.post(url, headers=headers, json=payload) ``` ## Getting Support When contacting support, always include: 1. **Request ID** - From the error response 2. **Timestamp** - When the error occurred 3. **API endpoint** - The URL you called 4. **HTTP status code** - The response status 5. **Error message** - The full error response Example support request: ``` Request ID: req_abc123 Timestamp: 2025-01-28T00:00:00Z Endpoint: POST /v1/sandboxes Status: 500 Error: Internal server error ``` ## Related * **[API Introduction](/api/introduction)** - Learn about the HopX API * **[Rate Limits](/api/concepts/rate-limits)** - Understand rate limit errors * **[Troubleshooting](/api/concepts/troubleshooting)** - Debug common issues * **[Data Model](/api/concepts/data-model)** - Learn about API resources * **[Python SDK Quickstart](/sdk/python/quickstart)** - Use the Python SDK (handles errors automatically) * [CLI Reference](/cli/introduction) - Command-line interface ## Next Steps * **[Rate Limits](/api/concepts/rate-limits)** - Understand rate limiting * **[Data Model](/api/concepts/data-model)** - Core resources and data structures * **[Troubleshooting](/api/concepts/troubleshooting)** - Common issues and solutions # Pagination Source: https://docs.hopx.ai/api/concepts/pagination Paginating HopX API list results using cursor-based pagination. Navigate through large result sets efficiently using cursor-based pagination. Learn how to use pagination parameters, handle page boundaries, and iterate through all results. Essential for listing sandboxes, templates, and other resources. Includes pagination examples and best practices. The HopX API uses cursor-based pagination for list endpoints. This provides consistent, efficient pagination even when data is being added or removed. ## List Response Format All list endpoints return a consistent structure: ```json theme={null} { "object": "list", "data": [ {"id": "sandbox_1", ...}, {"id": "sandbox_2", ...} ], "has_more": true, "next_cursor": "cursor_abc123", "url": "/v1/sandboxes", "request_id": "req_abc123" } ``` | Field | Type | Description | | ------------- | ------- | ---------------------------------------------- | | `object` | string | Always "list" | | `data` | array | Array of resource objects | | `has_more` | boolean | Whether more results exist | | `next_cursor` | string | Cursor for next page (null if no more results) | | `url` | string | Endpoint URL | | `request_id` | string | Request ID | ## Pagination Parameters ### cursor Use the `cursor` query parameter to fetch the next page: ```bash theme={null} # First page curl "https://api.hopx.dev/v1/sandboxes" \ -H "Authorization: Bearer $HOPX_API_KEY" # Next page (using cursor from previous response) curl "https://api.hopx.dev/v1/sandboxes?cursor=cursor_abc123" \ -H "Authorization: Bearer $HOPX_API_KEY" ``` ### limit Control the number of results per page with the `limit` parameter: ```bash theme={null} curl "https://api.hopx.dev/v1/sandboxes?limit=50" \ -H "Authorization: Bearer $HOPX_API_KEY" ``` Default limits vary by endpoint: * Sandboxes: 20 per page * Templates: 50 per page Maximum limit: 100 per page ## Paginating Through Results ### Example: Fetch All Sandboxes ```python theme={null} import requests def get_all_sandboxes(api_key): url = "https://api.hopx.dev/v1/sandboxes" headers = {"Authorization": f"Bearer {api_key}"} all_sandboxes = [] cursor = None while True: params = {"limit": 100} if cursor: params["cursor"] = cursor response = requests.get(url, headers=headers, params=params) data = response.json() all_sandboxes.extend(data["data"]) if not data["has_more"]: break cursor = data["next_cursor"] return all_sandboxes sandboxes = get_all_sandboxes("$HOPX_API_KEY") print(f"Total sandboxes: {len(sandboxes)}") ``` ### Example: Fetch with Progress ```python theme={null} def get_all_sandboxes_with_progress(api_key): url = "https://api.hopx.dev/v1/sandboxes" headers = {"Authorization": f"Bearer {api_key}"} all_sandboxes = [] cursor = None page = 1 while True: params = {"limit": 50} if cursor: params["cursor"] = cursor response = requests.get(url, headers=headers, params=params) data = response.json() page_sandboxes = data["data"] all_sandboxes.extend(page_sandboxes) print(f"Page {page}: Fetched {len(page_sandboxes)} sandboxes (total: {len(all_sandboxes)})") if not data["has_more"]: print("No more results") break cursor = data["next_cursor"] page += 1 return all_sandboxes ``` ## Cursor-Based Pagination Benefits ### Consistent Results Cursor-based pagination provides consistent results even when data changes: ```python theme={null} # Offset-based (bad) - can miss or duplicate items if data changes response1 = get("/sandboxes?offset=0&limit=10") # New sandbox created here response2 = get("/sandboxes?offset=10&limit=10") # Might miss items! # Cursor-based (good) - consistent results response1 = get("/sandboxes?limit=10") cursor = response1["next_cursor"] # New sandbox created here response2 = get(f"/sandboxes?cursor={cursor}&limit=10") # No duplicates or misses ``` ### Performance Cursor-based pagination is more efficient for large datasets: * O(1) lookups using the cursor * No need to count or skip rows * Works well with databases ## Filtering with Pagination Combine filters with pagination: ```bash theme={null} # List running sandboxes with pagination curl "https://api.hopx.dev/v1/sandboxes?status=running&limit=50" \ -H "Authorization: Bearer $HOPX_API_KEY" # Next page curl "https://api.hopx.dev/v1/sandboxes?status=running&limit=50&cursor=cursor_abc123" \ -H "Authorization: Bearer $HOPX_API_KEY" ``` Example with filters: ```python theme={null} def get_running_sandboxes(api_key): url = "https://api.hopx.dev/v1/sandboxes" headers = {"Authorization": f"Bearer {api_key}"} running_sandboxes = [] cursor = None while True: params = { "status": "running", "limit": 50 } if cursor: params["cursor"] = cursor response = requests.get(url, headers=headers, params=params) data = response.json() running_sandboxes.extend(data["data"]) if not data["has_more"]: break cursor = data["next_cursor"] return running_sandboxes ``` ## Endpoints with Pagination All list endpoints support pagination: | Endpoint | Default Limit | Max Limit | | ------------------- | ------------- | --------- | | `GET /v1/sandboxes` | 20 | 100 | | `GET /v1/templates` | 50 | 100 | ## Best Practices ### 1. Use Reasonable Page Sizes ```python theme={null} # Good: Fetch manageable chunks response = get("/v1/sandboxes?limit=50") # Bad: Fetching too many at once response = get("/v1/sandboxes?limit=1000") # Over max limit (100) ``` ### 2. Store and Reuse Cursors ```python theme={null} # Save cursor for resuming later last_cursor = None for page in range(5): params = {"limit": 20} if last_cursor: params["cursor"] = last_cursor response = get("/v1/sandboxes", params=params) data = response.json() process_sandboxes(data["data"]) if not data["has_more"]: break last_cursor = data["next_cursor"] # Resume later with last_cursor ``` ### 3. Handle Empty Results ```python theme={null} response = requests.get(url, headers=headers) data = response.json() if not data["data"]: print("No results found") elif not data["has_more"]: print("This is the last page") ``` ## Shell Script Example ```bash theme={null} #!/bin/bash API_KEY="$HOPX_API_KEY" URL="https://api.hopx.dev/v1/sandboxes" CURSOR="" PAGE=1 while true; do # Build URL with cursor if available if [ -z "$CURSOR" ]; then REQUEST_URL="$URL?limit=50" else REQUEST_URL="$URL?limit=50&cursor=$CURSOR" fi # Fetch page RESPONSE=$(curl -s "$REQUEST_URL" -H "Authorization: Bearer $API_KEY") # Extract data COUNT=$(echo "$RESPONSE" | jq '.data | length') HAS_MORE=$(echo "$RESPONSE" | jq -r '.has_more') echo "Page $PAGE: $COUNT sandboxes" # Check if more pages exist if [ "$HAS_MORE" != "true" ]; then echo "No more results" break fi # Get next cursor CURSOR=$(echo "$RESPONSE" | jq -r '.next_cursor') PAGE=$((PAGE + 1)) done ``` ## Related * **[API Introduction](/api/introduction)** - Learn about the HopX API * **[Rate Limits](/api/concepts/rate-limits)** - Understand API rate limits * **[Data Model](/api/concepts/data-model)** - Learn about API resources * **[Python SDK Quickstart](/sdk/python/quickstart)** - Use the Python SDK (handles pagination automatically) * [CLI Reference](/cli/introduction) - Command-line interface ## Next Steps * **[Data Model](/api/concepts/data-model)** - Core resources and data structures * **[Rate Limits](/api/concepts/rate-limits)** - Request rate limits * **[Errors](/api/concepts/errors)** - Error handling and codes # Rate Limits Source: https://docs.hopx.ai/api/concepts/rate-limits API rate limits, headers, and best practices for the HopX API. Understand rate limit policies, check rate limit headers, handle rate limit errors, and implement best practices for high-volume API usage. Essential for building scalable applications with HopX APIs. Includes rate limit examples and optimization strategies. The HopX API implements rate limiting to ensure fair usage and system stability. Rate limits vary by endpoint and account plan. ## Rate Limit Tiers ### Default Limits | Endpoint Type | Limit | Window | | ----------------- | ------------ | ---------- | | Control Plane API | 100 requests | per minute | | VM Agent API | 300 requests | per minute | | Template Builds | 10 builds | per hour | | Sandbox Creation | 20 sandboxes | per minute | ### Plan-Based Limits Rate limits may vary based on your account plan: * **Free Tier** - Default limits * **Pro Tier** - 2x default limits * **Enterprise** - Custom limits ## Rate Limit Headers Every API response includes rate limit headers: ``` X-RateLimit-Limit: 100 X-RateLimit-Remaining: 95 X-RateLimit-Reset: 1706400060 ``` | Header | Description | | ----------------------- | -------------------------------------- | | `X-RateLimit-Limit` | Maximum requests allowed in the window | | `X-RateLimit-Remaining` | Requests remaining in current window | | `X-RateLimit-Reset` | Unix timestamp when the limit resets | ## Rate Limit Exceeded When you exceed the rate limit, you'll receive a `429 Too Many Requests` response: ```json theme={null} { "error": "Rate limit exceeded: 100 requests per minute", "code": "RATE_LIMIT_EXCEEDED", "request_id": "req_abc123", "retry_after": 30 } ``` The `retry_after` field indicates how many seconds to wait before retrying. ## Best Practices ### 1. Monitor Rate Limit Headers ```python theme={null} import requests response = requests.get( "https://api.hopx.dev/v1/sandboxes", headers={"Authorization": "Bearer $HOPX_API_KEY"} ) remaining = int(response.headers.get('X-RateLimit-Remaining', 0)) limit = int(response.headers.get('X-RateLimit-Limit', 0)) print(f"Rate limit: {remaining}/{limit}") if remaining < 10: print("Warning: Approaching rate limit") ``` ### 2. Implement Exponential Backoff ```python theme={null} import time import requests def make_request_with_backoff(url, headers, max_retries=5): for attempt in range(max_retries): response = requests.get(url, headers=headers) if response.status_code != 429: return response # Rate limited - wait and retry retry_after = int(response.headers.get('Retry-After', 2 ** attempt)) print(f"Rate limited. Retrying after {retry_after}s") time.sleep(retry_after) raise Exception("Max retries exceeded") ``` ### 3. Batch Operations Instead of making many individual requests, batch operations when possible: ```python theme={null} # Bad: One request per sandbox for sandbox_id in sandbox_ids: response = requests.get( f"https://api.hopx.dev/v1/sandboxes/{sandbox_id}", headers=headers ) process(response.json()) # Good: One request for all sandboxes response = requests.get( "https://api.hopx.dev/v1/sandboxes", headers=headers ) sandboxes = response.json()["data"] for sandbox in sandboxes: process(sandbox) ``` ### 4. Cache Responses Cache responses that don't change frequently: ```python theme={null} import time from functools import lru_cache @lru_cache(maxsize=100) def get_template(template_id, cache_time): response = requests.get( f"https://api.hopx.dev/v1/templates/{template_id}", headers={"Authorization": "Bearer $HOPX_API_KEY"} ) return response.json() # Cache for 5 minutes cache_key = int(time.time() // 300) template = get_template("code-interpreter", cache_key) ``` ### 5. Distribute Requests Over Time ```python theme={null} import time sandboxes_to_create = 50 rate_limit_per_minute = 20 delay = 60 / rate_limit_per_minute # 3 seconds for i in range(sandboxes_to_create): create_sandbox() if i < sandboxes_to_create - 1: time.sleep(delay) ``` ## Rate Limit Strategies ### Sliding Window Rate limits use a sliding window algorithm, not a fixed window. This means: * Limits are enforced per 60-second rolling window * Request counts decay as time passes * Burst traffic is allowed up to the limit ### Per-Endpoint Limits Some endpoints have separate rate limits: | Endpoint | Limit | Reason | | ---------------------- | ---------- | ---------------------------- | | `/v1/templates/build` | 10/hour | Resource-intensive operation | | `/v1/sandboxes` (POST) | 20/minute | Prevent abuse | | `/v1/sandboxes` (GET) | 100/minute | Standard limit | ## Handling Rate Limits in Production ### Production-Ready Handler ```python theme={null} import time import requests from typing import Optional class RateLimitedClient: def __init__(self, api_key: str): self.api_key = api_key self.base_url = "https://api.hopx.dev" self.headers = {"Authorization": f"Bearer {api_key}"} def request(self, method: str, path: str, **kwargs) -> requests.Response: max_retries = 5 for attempt in range(max_retries): response = requests.request( method, f"{self.base_url}{path}", headers=self.headers, **kwargs ) # Success if response.status_code < 400: return response # Rate limited if response.status_code == 429: retry_after = int(response.headers.get('Retry-After', 2 ** attempt)) print(f"Rate limited. Waiting {retry_after}s (attempt {attempt + 1}/{max_retries})") time.sleep(retry_after) continue # Other errors - don't retry response.raise_for_status() raise Exception("Max retries exceeded due to rate limiting") def get(self, path: str, **kwargs) -> requests.Response: return self.request("GET", path, **kwargs) def post(self, path: str, **kwargs) -> requests.Response: return self.request("POST", path, **kwargs) # Usage client = RateLimitedClient("$HOPX_API_KEY") response = client.get("/v1/sandboxes") sandboxes = response.json() ``` ## Increasing Rate Limits If you need higher rate limits: 1. **Upgrade Your Plan** - Higher tiers include increased limits 2. **Contact Support** - Request custom limits for your use case 3. **Optimize Your Code** - Reduce unnecessary API calls ## Monitoring Usage Check your current usage via the API: ```bash theme={null} curl https://api.hopx.dev/v1/account/usage \ -H "Authorization: Bearer $HOPX_API_KEY" ``` Response: ```json theme={null} { "rate_limits": { "control_plane": { "limit": 100, "remaining": 85, "reset_at": "2025-01-28T00:01:00Z" }, "vm_agent": { "limit": 300, "remaining": 250, "reset_at": "2025-01-28T00:01:00Z" } } } ``` ## Related * **[API Introduction](/api/introduction)** - Learn about the HopX API * **[Error Handling](/api/concepts/errors)** - Handle rate limit errors * **[Pagination](/api/concepts/pagination)** - Paginate list results * **[Troubleshooting](/api/concepts/troubleshooting)** - Debug API issues * [CLI Reference](/cli/introduction) - Command-line interface ## Next Steps * **[Errors](/api/concepts/errors)** - Error handling and codes * **[Pagination](/api/concepts/pagination)** - Paginating list results * **[Troubleshooting](/api/concepts/troubleshooting)** - Common issues and solutions # Troubleshooting Source: https://docs.hopx.ai/api/concepts/troubleshooting Common issues, solutions, and debugging tips for the HopX API. Resolve authentication errors, handle API errors, debug connection issues, and troubleshoot common problems when using HopX APIs. Essential for building reliable integrations. Includes troubleshooting guides, error solutions, and debugging strategies. This guide covers common issues you might encounter when using the HopX API and how to resolve them. ## Authentication Issues ### Invalid API key **Problem:** Receiving `401 Unauthorized` errors. ```json theme={null} { "error": "Invalid API key", "code": "AUTHENTICATION_REQUIRED" } ``` **Solutions:** 1. Verify your API key is correct 2. Check the `Authorization` header format: `Authorization: Bearer $HOPX_API_KEY` 3. Ensure no extra spaces or newlines in the API key 4. Generate a new API key from the dashboard ```bash theme={null} # Correct curl https://api.hopx.dev/v1/sandboxes \ -H "Authorization: Bearer sk-live-abc123xyz" # Wrong - missing "Bearer" curl https://api.hopx.dev/v1/sandboxes \ -H "Authorization: sk-live-abc123xyz" ``` ### Expired JWT Token **Problem:** VM Agent API returns `401` with expired token error. **Solution:** Refresh the JWT token using the Control Plane API: ```bash theme={null} curl -X POST https://api.hopx.dev/v1/sandboxes/{sandbox_id}/refresh \ -H "Authorization: Bearer $HOPX_API_KEY" ``` ## Sandbox Creation Issues ### Sandbox Stuck in "Creating" Status **Problem:** Sandbox status remains "creating" for more than 2 minutes. **Solutions:** 1. Wait up to 5 minutes for large templates 2. Check template status - ensure it's "active" 3. Try a different region if available 4. Delete and recreate the sandbox ```bash theme={null} # Check sandbox status curl https://api.hopx.dev/v1/sandboxes/{sandbox_id} \ -H "Authorization: Bearer $HOPX_API_KEY" | jq '.status' # If stuck, delete and recreate curl -X DELETE https://api.hopx.dev/v1/sandboxes/{sandbox_id} \ -H "Authorization: Bearer $HOPX_API_KEY" ``` ### Template Not Found **Problem:** `404 Template not found` when creating sandbox. ```json theme={null} { "error": "Template not found", "code": "RESOURCE_NOT_FOUND" } ``` **Solutions:** 1. List available templates to find valid IDs 2. Use template `name` instead of ID 3. Check if template is active ```bash theme={null} # List available templates curl https://api.hopx.dev/v1/templates \ -H "Authorization: Bearer $HOPX_API_KEY" | jq '.data[] | {id, name, is_active}' # Use name instead of ID curl -X POST https://api.hopx.dev/v1/sandboxes \ -H "Authorization: Bearer $HOPX_API_KEY" \ -H "Content-Type: application/json" \ -d '{"template_id": "code-interpreter"}' ``` ### Resource Limits Exceeded **Problem:** Cannot create more sandboxes. ```json theme={null} { "error": "Sandbox limit reached (10/10)", "code": "RESOURCE_LIMIT_ERROR" } ``` **Solutions:** 1. Delete unused sandboxes 2. Upgrade your plan for higher limits 3. Use sandbox pooling/reuse ```bash theme={null} # List all sandboxes curl https://api.hopx.dev/v1/sandboxes \ -H "Authorization: Bearer $HOPX_API_KEY" # Delete stopped sandboxes for ID in $(curl -s https://api.hopx.dev/v1/sandboxes \ -H "Authorization: Bearer $HOPX_API_KEY" | \ jq -r '.data[] | select(.status == "stopped") | .id'); do curl -X DELETE "https://api.hopx.dev/v1/sandboxes/$ID" \ -H "Authorization: Bearer $HOPX_API_KEY" done ``` ## Code Execution Issues ### Execution Timeout **Problem:** Code execution times out. ```json theme={null} { "error": "Execution timeout after 60 seconds", "code": "EXECUTION_TIMEOUT" } ``` **Solutions:** 1. Increase the timeout parameter 2. Optimize your code 3. Use background execution for long tasks ```bash theme={null} # Increase timeout curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \ -H "Authorization: Bearer JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "code": "import time; time.sleep(120)", "language": "python", "timeout": 180 }' # Or use background execution curl -X POST https://sandbox_abc123xyz.hopx.dev/execute/background \ -H "Authorization: Bearer JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "code": "import time; time.sleep(600)", "language": "python", "timeout": 900 }' ``` ### Import/Module Errors **Problem:** Python packages not found. ``` ModuleNotFoundError: No module named 'requests' ``` **Solutions:** 1. Install packages before use 2. Use a template with pre-installed packages 3. Check package spelling ```bash theme={null} # Install package first curl -X POST https://sandbox_abc123xyz.hopx.dev/commands/run \ -H "Authorization: Bearer JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "command": "pip install requests numpy pandas", "timeout": 120 }' # Then use it curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \ -H "Authorization: Bearer JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "code": "import requests; print(requests.__version__)", "language": "python" }' ``` ## File Operation Issues ### Path Not Allowed **Problem:** `403 Forbidden` when accessing files. ```json theme={null} { "error": "Path not allowed: /etc/passwd", "code": "FORBIDDEN" } ``` **Solutions:** 1. Only access allowed paths: `/workspace`, `/tmp` 2. Use relative paths from allowed directories ```bash theme={null} # Good - allowed paths curl "https://sandbox_abc123xyz.hopx.dev/files/read?path=/workspace/data.txt" \ -H "Authorization: Bearer JWT_TOKEN" # Bad - forbidden path curl "https://sandbox_abc123xyz.hopx.dev/files/read?path=/etc/passwd" \ -H "Authorization: Bearer JWT_TOKEN" ``` ### File Not Found **Problem:** File doesn't exist when trying to read. **Solutions:** 1. Check if file exists first 2. Create the file before reading 3. Verify the file path ```bash theme={null} # Check if file exists EXISTS=$(curl -s "https://sandbox_abc123xyz.hopx.dev/files/exists?path=/workspace/data.txt" \ -H "Authorization: Bearer JWT_TOKEN" | jq -r '.exists') if [ "$EXISTS" == "true" ]; then # File exists, read it curl "https://sandbox_abc123xyz.hopx.dev/files/read?path=/workspace/data.txt" \ -H "Authorization: Bearer JWT_TOKEN" else # File doesn't exist, create it curl -X POST https://sandbox_abc123xyz.hopx.dev/files/write \ -H "Authorization: Bearer JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "path": "/workspace/data.txt", "content": "Initial content" }' fi ``` ## Connection Issues ### Network Timeout **Problem:** Requests timing out. **Solutions:** 1. Increase client timeout 2. Check network connectivity 3. Use retry logic with exponential backoff ```python theme={null} import requests from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry # Configure retries session = requests.Session() retries = Retry( total=5, backoff_factor=1, status_forcelist=[502, 503, 504] ) session.mount('https://', HTTPAdapter(max_retries=retries)) # Make request with retries response = session.post( "https://api.hopx.dev/v1/sandboxes", headers={"Authorization": "Bearer $HOPX_API_KEY"}, json={"template_id": "code-interpreter"}, timeout=30 ) ``` ### SSL Certificate Errors **Problem:** SSL verification failures. **Solutions:** 1. Update your SSL certificates 2. Update your HTTP client library 3. Check system time (certificate validation depends on correct time) ```bash theme={null} # Update certificates (Ubuntu/Debian) sudo apt-get update sudo apt-get install ca-certificates # Update Python certifi pip install --upgrade certifi ``` ## Rate Limiting ### Rate Limit Exceeded **Problem:** `429 Too Many Requests` errors. ```json theme={null} { "error": "Rate limit exceeded: 100 requests per minute", "code": "RATE_LIMIT_EXCEEDED", "retry_after": 30 } ``` **Solutions:** 1. Implement exponential backoff 2. Respect the `retry_after` header 3. Distribute requests over time 4. Cache responses when possible ```python theme={null} import time import requests def make_request_with_rate_limiting(url, headers): max_retries = 5 for attempt in range(max_retries): response = requests.get(url, headers=headers) if response.status_code != 429: return response # Get retry_after from header or response body retry_after = int(response.headers.get('Retry-After', 0)) if retry_after == 0: error_data = response.json() retry_after = error_data.get('retry_after', 2 ** attempt) print(f"Rate limited. Waiting {retry_after}s") time.sleep(retry_after) raise Exception("Max retries exceeded") ``` ## Debugging Tips ### Enable Verbose Logging ```bash theme={null} # cURL with verbose output curl -v https://api.hopx.dev/v1/sandboxes \ -H "Authorization: Bearer $HOPX_API_KEY" # Python with logging import logging import requests logging.basicConfig(level=logging.DEBUG) response = requests.get( "https://api.hopx.dev/v1/sandboxes", headers={"Authorization": "Bearer $HOPX_API_KEY"} ) ``` ### Check Request ID Every response includes a `request_id` for debugging: ```bash theme={null} curl -i https://api.hopx.dev/v1/sandboxes \ -H "Authorization: Bearer $HOPX_API_KEY" | grep request_id ``` Include the `request_id` when contacting support. ### Inspect Full Response ```bash theme={null} # Save full response for debugging curl -i https://api.hopx.dev/v1/sandboxes \ -H "Authorization: Bearer $HOPX_API_KEY" \ > response.txt ``` ### Test with cURL First Before implementing in your application, test with cURL: ```bash theme={null} # Test sandbox creation curl -X POST https://api.hopx.dev/v1/sandboxes \ -H "Authorization: Bearer $HOPX_API_KEY" \ -H "Content-Type: application/json" \ -d '{"template_id": "code-interpreter"}' | jq '.' ``` ## Getting Help If you're still experiencing issues: 1. **Check Status Page** - [https://status.hopx.dev](https://status.hopx.dev) 2. **Review Documentation** - Complete API reference 3. **Contact Support** - Include: * Request ID * Timestamp * Full error message * Code snippet (remove sensitive data) * Expected vs actual behavior ## Common Patterns ### Healthcheck Pattern ```python theme={null} def check_sandbox_health(sandbox_id, jwt_token): """Check if sandbox is ready for use""" try: response = requests.get( f"https://{sandbox_id}.hopx.dev/health", headers={"Authorization": f"Bearer {jwt_token}"}, timeout=5 ) return response.status_code == 200 except: return False ``` ### Cleanup Pattern ```python theme={null} def cleanup_old_sandboxes(api_key, hours=24): """Delete sandboxes older than specified hours""" from datetime import datetime, timedelta response = requests.get( "https://api.hopx.dev/v1/sandboxes", headers={"Authorization": f"Bearer {api_key}"} ) cutoff = datetime.utcnow() - timedelta(hours=hours) for sandbox in response.json()["data"]: created_at = datetime.fromisoformat(sandbox["created_at"].replace('Z', '+00:00')) if created_at < cutoff: print(f"Deleting old sandbox: {sandbox['id']}") requests.delete( f"https://api.hopx.dev/v1/sandboxes/{sandbox['id']}", headers={"Authorization": f"Bearer {api_key}"} ) ``` ## Related * **[Error Handling](/api/concepts/errors)** - Understand error codes and responses * **[Rate Limits](/api/concepts/rate-limits)** - Handle rate limit issues * **[Authentication](/api/authentication)** - Fix authentication problems * **[API Introduction](/api/introduction)** - Learn about the HopX API * **[Python SDK Quickstart](/sdk/python/quickstart)** - Use the Python SDK (simpler error handling) * [CLI Reference](/cli/introduction) - Command-line interface ## Next Steps * **[Errors](/api/concepts/errors)** - Complete error reference * **[Rate Limits](/api/concepts/rate-limits)** - Rate limiting details * **[Data Model](/api/concepts/data-model)** - Core resources # Build Template Source: https://docs.hopx.ai/api/control-plane/build-template Create a custom template from a Docker image with build steps using the HopX Control Plane API. Build custom sandbox templates with specific configurations, dependencies, and resources. Learn how to use POST /v1/templates/build endpoint to create templates from Docker images. Includes request examples and template configuration. Build a custom template from a Docker image. Define the base image, build steps, resources, and ready checks. The API will build and cache your template for creating sandboxes. ## Endpoint ``` POST /v1/templates/build ``` ## Request ### Headers ``` Authorization: Bearer $HOPX_API_KEY Content-Type: application/json ``` ### Body Parameters | Parameter | Type | Required | Description | | ---------------------- | ------- | -------- | ------------------------------------------------------------ | | `name` | string | Yes | Unique template name | | `from_image` | string | Yes | Base Docker image (e.g., `ubuntu:22.04`, `python:3.11-slim`) | | `cpu` | integer | Yes | Number of vCPUs (min/max from your plan) | | `memory` | integer | Yes | Memory in MB (min: 512, max: 64000) | | `diskGB` | integer | Yes | Disk size in GB (min: 1, max: 250) | | `steps` | array | No | Build steps (RUN, COPY, ENV, WORKDIR, USER, CMD) | | `startCmd` | string | No | Command to run on sandbox start | | `readyCmd` | object | No | Ready check configuration | | `skipCache` | boolean | No | Skip build cache (default: false) | | `registry_credentials` | object | No | Private registry authentication | | `update` | boolean | No | Update existing template (default: false) | **Alpine Linux is not supported.** Use glibc-based images like `ubuntu:*`, `debian:*`, `python:*-slim`, `node:*-slim`. ### Example Request Build a Python template: ```bash theme={null} curl -X POST https://api.hopx.dev/v1/templates/build \ -H "Authorization: Bearer $HOPX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "my-python-template", "from_image": "python:3.11-slim", "cpu": 2, "memory": 4096, "diskGB": 10, "steps": [ { "type": "RUN", "args": ["pip install pandas numpy matplotlib"] }, { "type": "WORKDIR", "args": ["/workspace"] }, { "type": "ENV", "args": ["PYTHONUNBUFFERED=1"] } ] }' ``` Build a Node.js template: ```bash theme={null} curl -X POST https://api.hopx.dev/v1/templates/build \ -H "Authorization: Bearer $HOPX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "my-nodejs-template", "from_image": "node:18-slim", "cpu": 1, "memory": 2048, "diskGB": 5, "steps": [ { "type": "RUN", "args": ["npm install -g typescript ts-node"] }, { "type": "WORKDIR", "args": ["/app"] } ] }' ``` ## Response ### Success (202 Accepted) ```json theme={null} { "build_id": "build_abc123", "template_id": "template_xyz789", "status": "building", "logs_url": "https://api.hopx.dev/v1/templates/build/build_abc123/logs", "request_id": "req_abc123" } ``` ### Response Fields | Field | Type | Description | | ------------- | ------ | --------------------------------------------- | | `build_id` | string | Build ID (same as template\_id) | | `template_id` | string | Template ID | | `status` | string | Build status (`building`, `active`, `failed`) | | `logs_url` | string | URL to stream build logs | | `request_id` | string | Request ID for debugging | ## Status Codes | Code | Description | | ----- | ------------------------------------------------- | | `202` | Build triggered (accepted) | | `400` | Invalid request (Alpine, invalid resources, etc.) | | `401` | Authentication required | | `404` | Template not found (when `update=true`) | | `409` | Template exists (when `update=false`) | | `503` | Service unavailable (no available nodes) | ## Build Steps ### Supported Step Types | Type | Description | Example | | --------- | --------------------------------- | -------------------------------------------------------------- | | `RUN` | Run a shell command | `{"type": "RUN", "args": ["apt-get update"]}` | | `COPY` | Copy files (requires file upload) | `{"type": "COPY", "args": ["/app"], "filesHash": "sha256..."}` | | `ENV` | Set environment variable | `{"type": "ENV", "args": ["KEY=value"]}` | | `WORKDIR` | Set working directory | `{"type": "WORKDIR", "args": ["/workspace"]}` | | `USER` | Set user | `{"type": "USER", "args": ["1000"]}` | | `CMD` | Set default command | `{"type": "CMD", "args": ["python", "app.py"]}` | ### RUN Steps ```json theme={null} { "type": "RUN", "args": ["pip install pandas numpy"] } ``` ### ENV Steps ```json theme={null} { "type": "ENV", "args": ["PYTHONUNBUFFERED=1", "DEBUG=true"] } ``` ### WORKDIR Steps ```json theme={null} { "type": "WORKDIR", "args": ["/workspace"] } ``` ## Errors ### Alpine Not Supported (400) ```json theme={null} { "error": "Alpine Linux is not supported. Use glibc-based images like ubuntu, debian, python-slim, node-slim", "code": "INVALID_REQUEST", "request_id": "req_abc123" } ``` **Cause:** The base image is Alpine Linux, which is not supported. **Fix:** Use a glibc-based image like `ubuntu:22.04`, `python:3.11-slim`, or `node:18-slim`. ### Template Exists (409) ```json theme={null} { "error": "Template already exists. Set update=true to update it.", "code": "CONFLICT", "request_id": "req_abc123" } ``` **Cause:** A template with the same name already exists and `update` is false. **Fix:** Either: * Use a different template name * Set `"update": true` to update the existing template ### Invalid Resources (400) ```json theme={null} { "error": "Invalid memory: must be between 512 and 64000 MB", "code": "INVALID_REQUEST", "request_id": "req_abc123" } ``` **Cause:** Resource values are outside allowed limits. **Fix:** Ensure: * `cpu`: 1-8 (depends on your plan) * `memory`: 512-64000 MB * `diskGB`: 1-250 GB ## Monitor Build Progress After triggering a build, monitor its progress: ```bash theme={null} # Get build status curl https://api.hopx.dev/v1/templates/build/build_abc123/status \ -H "Authorization: Bearer $HOPX_API_KEY" # Stream build logs curl https://api.hopx.dev/v1/templates/build/build_abc123/logs \ -H "Authorization: Bearer $HOPX_API_KEY" ``` ## Use Cases ### Create Data Science Template ```bash theme={null} curl -X POST https://api.hopx.dev/v1/templates/build \ -H "Authorization: Bearer $HOPX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "data-science", "from_image": "python:3.11-slim", "cpu": 4, "memory": 8192, "diskGB": 20, "steps": [ { "type": "RUN", "args": ["pip install pandas numpy matplotlib scikit-learn jupyter"] }, { "type": "WORKDIR", "args": ["/workspace"] }, { "type": "ENV", "args": ["PYTHONUNBUFFERED=1"] } ] }' ``` ### Update Existing Template ```bash theme={null} curl -X POST https://api.hopx.dev/v1/templates/build \ -H "Authorization: Bearer $HOPX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "my-template", "from_image": "python:3.11-slim", "cpu": 2, "memory": 4096, "diskGB": 10, "update": true, "steps": [ { "type": "RUN", "args": ["pip install --upgrade pandas"] } ] }' ``` ## Related * **[Building Templates](/core-concepts/templates/building)** - Learn about template building * **[Template Configuration](/core-concepts/templates/configuration)** - Configure template resources * **[Template Caching](/core-concepts/templates/caching)** - Optimize build performance * **[Get Template](/api/control-plane/get-template)** - Check template details after build * [CLI Template Commands](/cli/commands/template) - Template management from CLI ## Next Steps * **[Get Template](/api/control-plane/get-template)** - Check template details after build * **[Stream Build Logs](/api/control-plane/stream-logs)** - Monitor build progress * **[Create Sandbox](/api/control-plane/create-sandbox)** - Use your new template # Create Sandbox Source: https://docs.hopx.ai/api/control-plane/create-sandbox Create a new sandbox from a template using the HopX Control Plane API. Provision isolated cloud environments with custom configuration, resources, and environment variables. Learn how to use POST /v1/sandboxes endpoint with Python and JavaScript SDK examples. Create a new sandbox from a template. The sandbox will be provisioned with resources (vCPU, memory, disk) defined by the template. ## Endpoint ``` POST /v1/sandboxes ``` ## Request ### Headers ``` Authorization: Bearer $HOPX_API_KEY Content-Type: application/json ``` ### Body Parameters | Parameter | Type | Required | Description | | ----------------- | ----------------- | -------- | --------------------------------------------- | | `template_id` | string or integer | Yes\* | Template ID to use | | `template_name` | string | Yes\* | Template name (alternative to `template_id`) | | `region` | string | No | Preferred region (e.g., `us-east`, `eu-west`) | | `timeout_seconds` | integer | No | Auto-kill timeout in seconds | | `internet_access` | boolean | No | Enable internet access (default: `true`) | | `env_vars` | object | No | Environment variables to set in sandbox | Either `template_id` or `template_name` must be provided. Resources (vcpu, memory, disk) are **always loaded from the template** - you cannot specify custom resources. ### Example Request ```bash theme={null} curl -X POST https://api.hopx.dev/v1/sandboxes \ -H "Authorization: Bearer $HOPX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "template_id": "73", "timeout_seconds": 3600, "internet_access": true, "env_vars": { "MY_VAR": "my_value", "API_KEY": "secret123" } }' ``` Replace `$HOPX_API_KEY` with your actual API key from [console.hopx.dev](https://console.hopx.dev), or set it as an environment variable: `export HOPX_API_KEY="your-API key-here"` Or using template name: ```bash theme={null} curl -X POST https://api.hopx.dev/v1/sandboxes \ -H "Authorization: Bearer $HOPX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "template_name": "code-interpreter", "timeout_seconds": 3600 }' ``` Replace `$HOPX_API_KEY` with your actual API key from [console.hopx.dev](https://console.hopx.dev), or set it as an environment variable: `export HOPX_API_KEY="your-API key-here"` ## Response ### Success (201 Created) ```json theme={null} { "id": "sandbox_abc123xyz", "object": "sandbox", "status": "running", "public_host": "https://sandbox_abc123xyz.hopx.dev", "direct_url": "https://sandbox_abc123xyz.hopx.dev", "template_id": "73", "template_name": "code-interpreter", "organization_id": 123, "node_id": "node_xyz789", "region": "us-east", "resources": { "vcpu": 2, "memory_mb": 4096, "disk_mb": 10240 }, "internet_access": true, "timeout_seconds": 3600, "expires_at": "2025-01-29T00:00:00Z", "created_at": "2025-01-28T00:00:00Z", "auth_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "token_expires_at": "2025-01-28T01:00:00Z", "request_id": "req_abc123" } ``` ### Response Fields | Field | Type | Description | | ------------------ | ------ | ---------------------------------------------------- | | `id` | string | Sandbox ID (use for all subsequent operations) | | `status` | string | Current sandbox status (`creating`, `running`, etc.) | | `public_host` | string | VM Agent API base URL for this sandbox | | `direct_url` | string | Alternative VM Agent API URL (same as `public_host`) | | `template_id` | string | Template ID used to create sandbox | | `template_name` | string | Template name | | `resources` | object | Allocated resources (from template) | | `auth_token` | string | JWT token for VM Agent API authentication | | `token_expires_at` | string | ISO 8601 timestamp when token expires | ## Status Codes | Code | Description | | ----- | --------------------------------------------------------- | | `201` | Sandbox created successfully | | `400` | Invalid request (missing template, invalid timeout, etc.) | | `401` | Authentication required | | `402` | Payment required (insufficient balance) | | `404` | Template not found | | `503` | Service unavailable (no available nodes) | ## Errors ### Template Not Found (404) ```json theme={null} { "error": "Template not found", "code": "RESOURCE_NOT_FOUND", "request_id": "req_abc123" } ``` **Cause:** The specified `template_id` or `template_name` doesn't exist. **Fix:** List available templates using `GET /v1/templates` to find valid template IDs or names. ### Invalid Request (400) ```json theme={null} { "error": "Invalid request: timeout_seconds must be positive", "code": "INVALID_REQUEST", "request_id": "req_abc123" } ``` **Cause:** Invalid parameter value (e.g., negative timeout, missing template). **Fix:** Verify all parameters meet requirements: * `timeout_seconds` must be positive * Either `template_id` or `template_name` must be provided * `env_vars` must be a valid object ### Service Unavailable (503) ```json theme={null} { "error": "Service unavailable: no available nodes", "code": "SERVICE_UNAVAILABLE", "request_id": "req_abc123" } ``` **Cause:** No compute nodes are available to provision the sandbox. **Fix:** Retry the request after a few moments. This is usually temporary. ## Use Cases ### Quick Code Execution Create a sandbox for quick code execution: ```bash theme={null} curl -X POST https://api.hopx.dev/v1/sandboxes \ -H "Authorization: Bearer $HOPX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "template_name": "code-interpreter", "timeout_seconds": 300 }' ``` ### Long-Running Job Create a sandbox for a long-running task: ```bash theme={null} curl -X POST https://api.hopx.dev/v1/sandboxes \ -H "Authorization: Bearer $HOPX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "template_id": "73", "timeout_seconds": 7200, "env_vars": { "DATABASE_URL": "postgres://...", "API_KEY": "secret" } }' ``` ### Region-Specific Deployment Create a sandbox in a specific region: ```bash theme={null} curl -X POST https://api.hopx.dev/v1/sandboxes \ -H "Authorization: Bearer $HOPX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "template_name": "code-interpreter", "region": "eu-west" }' ``` ## Related * **SDK**: [Sandbox.create()](/sdk/python/sandbox#create) - Python SDK method * **[Get Sandbox](/api/control-plane/get-sandbox)** - Retrieve sandbox information * **[List Sandboxes](/api/control-plane/list-sandboxes)** - Query all your sandboxes * **[VM Agent API](/api/vm-agent/overview)** - Execute code in your new sandbox * [CLI Sandbox Commands](/cli/commands/sandbox) - Manage sandboxes from CLI ## Next Steps * **[Get Sandbox](/api/control-plane/get-sandbox)** - Retrieve sandbox information * **[List Sandboxes](/api/control-plane/list-sandboxes)** - Query all your sandboxes * **[VM Agent API](/api/vm-agent/overview)** - Execute code in your new sandbox # Delete Sandbox Source: https://docs.hopx.ai/api/control-plane/delete-sandbox Permanently delete a sandbox and free its resources using the HopX Control Plane API. Remove sandboxes when no longer needed to free up resources and manage costs. Learn how to use DELETE /v1/sandboxes/:id endpoint to permanently delete sandboxes and clean up resources. Includes request examples and cleanup best practices. Delete a sandbox to permanently destroy it and free all allocated resources. This action cannot be undone. ## Endpoint ``` DELETE /v1/sandboxes/:id ``` ## Request ### Headers ``` Authorization: Bearer $HOPX_API_KEY ``` ### Path Parameters | Parameter | Type | Description | | --------- | ------ | -------------------- | | `id` | string | Sandbox ID to delete | ### Example Request ```bash theme={null} curl -X DELETE https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz \ -H "Authorization: Bearer $HOPX_API_KEY" ``` ## Response ### Success (200 OK) ```json theme={null} { "status": "deleted", "id": "sandbox_abc123xyz", "request_id": "req_abc123" } ``` ### Response Fields | Field | Type | Description | | ------------ | ------ | ------------------------ | | `status` | string | Always `"deleted"` | | `id` | string | Deleted sandbox ID | | `request_id` | string | Request ID for debugging | ## Status Codes | Code | Description | | ----- | ---------------------------- | | `200` | Sandbox deleted successfully | | `401` | Authentication required | | `404` | Sandbox not found | ## Errors ### Sandbox Not Found (404) ```json theme={null} { "error": "Sandbox not found", "code": "RESOURCE_NOT_FOUND", "request_id": "req_abc123" } ``` **Cause:** The sandbox ID doesn't exist or belongs to another organization. **Fix:** Verify the sandbox ID is correct. List your sandboxes using `GET /v1/sandboxes` to find valid IDs. ## Important Notes Deleting a sandbox is **permanent and irreversible**. All data, files, and state in the sandbox will be lost. Make sure to save any important data before deleting. * **Immediate deletion** - The sandbox is destroyed immediately upon successful deletion * **Resource cleanup** - All allocated resources (vCPU, memory, disk) are freed * **VM Agent API** - The sandbox's VM Agent API endpoint becomes unavailable immediately * **No recovery** - Deleted sandboxes cannot be recovered ## Use Cases ### Clean Up After Task Completion ```bash theme={null} # Execute your task # ... code execution ... # Delete when done curl -X DELETE https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz \ -H "Authorization: Bearer $HOPX_API_KEY" ``` ### Delete All Stopped Sandboxes ```bash theme={null} #!/bin/bash # Get all stopped sandboxes STOPPED=$(curl -s "https://api.hopx.dev/v1/sandboxes?status=stopped" \ -H "Authorization: Bearer $HOPX_API_KEY" | \ jq -r '.data[].id') # Delete each one for ID in $STOPPED; do curl -X DELETE "https://api.hopx.dev/v1/sandboxes/$ID" \ -H "Authorization: Bearer $HOPX_API_KEY" echo "Deleted $ID" done ``` ### Delete Sandbox with Verification ```bash theme={null} #!/bin/bash SANDBOX_ID="sandbox_abc123xyz" # Verify sandbox exists STATUS=$(curl -s "https://api.hopx.dev/v1/sandboxes/$SANDBOX_ID" \ -H "Authorization: Bearer $HOPX_API_KEY" | jq -r '.status') if [ "$STATUS" != "null" ]; then # Delete it curl -X DELETE "https://api.hopx.dev/v1/sandboxes/$SANDBOX_ID" \ -H "Authorization: Bearer $HOPX_API_KEY" echo "Sandbox $SANDBOX_ID deleted" else echo "Sandbox not found" fi ``` ## Related * **SDK**: [sandbox.kill()](/sdk/python/sandbox#kill) - Python SDK method * [CLI Sandbox Commands](/cli/commands/sandbox) - Manage sandboxes from CLI ## Next Steps * **[List Sandboxes](/api/control-plane/list-sandboxes)** - View all your sandboxes * **[Create Sandbox](/api/control-plane/create-sandbox)** - Create a new sandbox * **[Get Sandbox](/api/control-plane/get-sandbox)** - Retrieve sandbox information # Get Sandbox Source: https://docs.hopx.ai/api/control-plane/get-sandbox Retrieve information about a specific sandbox using the HopX Control Plane API. Get sandbox details including status, resources, connection information, and metadata. Learn how to use GET /v1/sandboxes/:id endpoint to connect to existing sandboxes and retrieve their current state. Get detailed information about a sandbox, including its current status, resources, and configuration. ## Endpoint ``` GET /v1/sandboxes/:id ``` ## Request ### Headers ``` Authorization: Bearer $HOPX_API_KEY ``` ### Path Parameters | Parameter | Type | Description | | --------- | ------ | ----------- | | `id` | string | Sandbox ID | ### Example Request ```bash theme={null} curl https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz \ -H "Authorization: Bearer $HOPX_API_KEY" ``` ## Response ### Success (200 OK) ```json theme={null} { "id": "sandbox_abc123xyz", "object": "sandbox", "status": "running", "public_host": "https://sandbox_abc123xyz.hopx.dev", "direct_url": "https://sandbox_abc123xyz.hopx.dev", "template_id": "73", "template_name": "code-interpreter", "organization_id": 123, "node_id": "node_xyz789", "region": "us-east", "resources": { "vcpu": 2, "memory_mb": 4096, "disk_mb": 10240 }, "internet_access": true, "timeout_seconds": 3600, "expires_at": "2025-01-29T00:00:00Z", "created_at": "2025-01-28T00:00:00Z" } ``` ### Response Fields | Field | Type | Description | | ----------------- | ------- | ----------------------------------------------------------- | | `id` | string | Sandbox ID | | `status` | string | Current status (`running`, `stopped`, `paused`, `creating`) | | `public_host` | string | VM Agent API base URL | | `template_id` | string | Template ID used to create sandbox | | `resources` | object | Allocated resources (vcpu, memory\_mb, disk\_mb) | | `timeout_seconds` | integer | Auto-kill timeout in seconds | | `expires_at` | string | ISO 8601 timestamp when sandbox expires | ## Status Codes | Code | Description | | ----- | ----------------------- | | `200` | Success | | `401` | Authentication required | | `404` | Sandbox not found | ## Errors ### Sandbox Not Found (404) ```json theme={null} { "error": "Sandbox not found", "code": "RESOURCE_NOT_FOUND", "request_id": "req_abc123" } ``` **Cause:** The sandbox ID doesn't exist or belongs to another organization. **Fix:** Verify the sandbox ID is correct. List your sandboxes using `GET /v1/sandboxes` to find valid IDs. ## Use Cases ### Check Sandbox Status Monitor sandbox status before executing code: ```bash theme={null} curl https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz \ -H "Authorization: Bearer $HOPX_API_KEY" | jq '.status' ``` ### Verify Resources Confirm allocated resources match expectations: ```bash theme={null} curl https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz \ -H "Authorization: Bearer $HOPX_API_KEY" | jq '.resources' ``` ## Related * **SDK**: [Sandbox.connect()](/sdk/python/sandbox#connect) - Python SDK method * **SDK**: [sandbox.get\_info()](/sdk/python/sandbox#get_info) - Python SDK method * [CLI Sandbox Commands](/cli/commands/sandbox) - Manage sandboxes from CLI ## Next Steps * **[List Sandboxes](/api/control-plane/list-sandboxes)** - Query all your sandboxes * **[Update Sandbox](/api/control-plane/set-timeout)** - Modify sandbox configuration * **[Delete Sandbox](/api/control-plane/delete-sandbox)** - Clean up resources # Get Template Source: https://docs.hopx.ai/api/control-plane/get-template Get detailed information about a specific template using the HopX Control Plane API. Retrieve template configuration, resources, build steps, and metadata for pre-built or custom templates. Learn how to use GET /v1/templates/:name endpoint to view template details before creating sandboxes. Includes request examples and response formats. Get detailed information about a specific template, including its configuration, resources, features, and availability. ## Endpoint ``` GET /v1/templates/:name ``` ## Request ### Headers ``` Authorization: Bearer $HOPX_API_KEY ``` ### Path Parameters | Parameter | Type | Description | | --------- | ------ | ------------------- | | `name` | string | Template name or ID | ### Example Request Get by template name: ```bash theme={null} curl https://api.hopx.dev/v1/templates/code-interpreter \ -H "Authorization: Bearer $HOPX_API_KEY" ``` Get by template ID: ```bash theme={null} curl https://api.hopx.dev/v1/templates/73 \ -H "Authorization: Bearer $HOPX_API_KEY" ``` ## Response ### Success (200 OK) ```json theme={null} { "id": "73", "object": "template", "name": "code-interpreter", "display_name": "Code Interpreter", "description": "Pre-built environment for Python, JavaScript, and Bash execution with common packages pre-installed", "category": "python", "language": "python", "icon": "python", "default_resources": { "vcpu": 2, "memory_mb": 4096, "disk_gb": 10 }, "min_resources": { "vcpu": 1, "memory_mb": 512, "disk_gb": 1 }, "max_resources": { "vcpu": 8, "memory_mb": 16384, "disk_gb": 100 }, "features": [ "python", "javascript", "bash", "desktop", "internet" ], "tags": [ "code-execution", "multi-language", "data-science" ], "popularity_score": 950, "docs_url": "https://docs.hopx.dev/templates/code-interpreter", "is_active": true, "status": "active", "build_id": "build_abc123", "is_public": true, "created_at": "2025-01-01T00:00:00Z", "updated_at": "2025-01-15T00:00:00Z", "request_id": "req_abc123" } ``` ### Response Fields | Field | Type | Description | | ------------------- | ------- | ------------------------------------------------ | | `id` | string | Template ID | | `name` | string | Template name (unique identifier) | | `display_name` | string | Human-readable name | | `description` | string | Template description | | `category` | string | Template category | | `language` | string | Primary programming language | | `default_resources` | object | Default resource allocation | | `min_resources` | object | Minimum resource requirements | | `max_resources` | object | Maximum resource limits | | `features` | array | Supported features | | `tags` | array | Template tags for categorization | | `is_active` | boolean | Whether template is ready for use | | `status` | string | Template status (`active`, `building`, `failed`) | | `is_public` | boolean | Whether template is publicly available | ## Status Codes | Code | Description | | ----- | ----------------------- | | `200` | Success | | `401` | Authentication required | | `404` | Template not found | ## Errors ### Template Not Found (404) ```json theme={null} { "error": "Template not found", "code": "RESOURCE_NOT_FOUND", "request_id": "req_abc123" } ``` **Cause:** The template name or ID doesn't exist or is not accessible to your organization. **Fix:** List available templates using `GET /v1/templates` to find valid template names or IDs. ## Template Features Common template features: * **`python`** - Python runtime available * **`javascript`** - JavaScript/Node.js runtime available * **`bash`** - Bash shell available * **`desktop`** - Desktop environment with VNC support * **`internet`** - Internet access enabled * **`gpu`** - GPU support (for ML/AI workloads) ## Use Cases ### Check Template Resources ```bash theme={null} curl https://api.hopx.dev/v1/templates/code-interpreter \ -H "Authorization: Bearer $HOPX_API_KEY" | \ jq '.default_resources' ``` ### Verify Template Status ```bash theme={null} STATUS=$(curl -s https://api.hopx.dev/v1/templates/my-custom-template \ -H "Authorization: Bearer $HOPX_API_KEY" | jq -r '.status') if [ "$STATUS" == "active" ]; then echo "Template is ready" else echo "Template is not ready: $STATUS" fi ``` ### Check Template Features ```bash theme={null} curl https://api.hopx.dev/v1/templates/code-interpreter \ -H "Authorization: Bearer $HOPX_API_KEY" | \ jq '.features[]' ``` ### Compare Template Resources ```bash theme={null} #!/bin/bash TEMPLATES=("code-interpreter" "python-3.11" "nodejs-18") for TEMPLATE in "${TEMPLATES[@]}"; do echo "=== $TEMPLATE ===" curl -s "https://api.hopx.dev/v1/templates/$TEMPLATE" \ -H "Authorization: Bearer $HOPX_API_KEY" | \ jq '{name: .name, resources: .default_resources}' done ``` ## Related * **SDK**: [Sandbox.get\_template()](/sdk/python/sandbox#get_template) - Python SDK method * [CLI Template Commands](/cli/commands/template) - Template management from CLI ## Next Steps * **[List Templates](/api/control-plane/list-templates)** - Browse all available templates * **[Build Template](/api/control-plane/build-template)** - Create a custom template * **[Create Sandbox](/api/control-plane/create-sandbox)** - Create a sandbox from this template # Kill Sandbox Source: https://docs.hopx.ai/api/control-plane/kill-sandbox Forcefully terminate a sandbox immediately using the HopX Control Plane API. Immediately stop a sandbox and free all resources without waiting for graceful shutdown. Learn how to use POST /v1/sandboxes/:id/kill endpoint to force-terminate sandboxes. Includes request examples and termination behavior. Kill a sandbox to forcefully terminate it immediately. This is similar to delete but may be used when a sandbox is unresponsive. The sandbox is destroyed and cannot be recovered. ## Endpoint ``` POST /v1/sandboxes/:id/kill ``` ## Request ### Headers ``` Authorization: Bearer $HOPX_API_KEY ``` ### Path Parameters | Parameter | Type | Description | | --------- | ------ | ------------------ | | `id` | string | Sandbox ID to kill | ### Example Request ```bash theme={null} curl -X POST https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/kill \ -H "Authorization: Bearer $HOPX_API_KEY" ``` ## Response ### Success (200 OK) ```json theme={null} { "id": "sandbox_abc123xyz", "status": "killed", "request_id": "req_abc123" } ``` ### Response Fields | Field | Type | Description | | ------------ | ------ | ------------------------ | | `id` | string | Sandbox ID | | `status` | string | New status (`killed`) | | `request_id` | string | Request ID for debugging | ## Status Codes | Code | Description | | ----- | --------------------------- | | `200` | Sandbox killed successfully | | `401` | Authentication required | | `404` | Sandbox not found | ## Errors ### Sandbox Not Found (404) ```json theme={null} { "error": "Sandbox not found", "code": "RESOURCE_NOT_FOUND", "request_id": "req_abc123" } ``` **Cause:** The sandbox ID doesn't exist or belongs to another organization. **Fix:** Verify the sandbox ID is correct. List your sandboxes using `GET /v1/sandboxes` to find valid IDs. ## Important Notes Killing a sandbox is **permanent and irreversible**. All data, files, and state in the sandbox will be lost. This action forcefully terminates the sandbox even if it's unresponsive. * **Immediate termination** - The sandbox is forcefully terminated immediately * **No graceful shutdown** - Running processes are killed without cleanup * **Resource cleanup** - All allocated resources are freed * **VM Agent API** - The sandbox's VM Agent API endpoint becomes unavailable immediately * **No recovery** - Killed sandboxes cannot be recovered ## Use Cases ### Kill Unresponsive Sandbox ```bash theme={null} # Kill a sandbox that's not responding curl -X POST https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/kill \ -H "Authorization: Bearer $HOPX_API_KEY" ``` ### Force Cleanup ```bash theme={null} # Kill instead of delete when sandbox is stuck curl -X POST https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/kill \ -H "Authorization: Bearer $HOPX_API_KEY" ``` ## Difference from Delete * **Kill** - Forcefully terminates the sandbox immediately, even if unresponsive * **Delete** - Gracefully deletes the sandbox (may fail if sandbox is stuck) Use `kill` when a sandbox is unresponsive and `delete` doesn't work. ## Related * **[Managing Sandbox State](/core-concepts/sandboxes/managing-state)** - Learn about sandbox lifecycle * **[Delete Sandbox](/api/control-plane/delete-sandbox)** - Gracefully delete a sandbox * **[Stop Sandbox](/api/control-plane/stop-sandbox)** - Stop instead of killing * **SDK**: [sandbox.kill()](/sdk/python/sandbox#kill) - Python SDK method * [CLI Sandbox Commands](/cli/commands/sandbox) - Manage sandboxes from CLI ## Next Steps * **[Delete Sandbox](/api/control-plane/delete-sandbox)** - Gracefully delete a sandbox * **[Stop Sandbox](/api/control-plane/stop-sandbox)** - Stop instead of killing * **[Get Sandbox](/api/control-plane/get-sandbox)** - Check sandbox status # List Sandboxes Source: https://docs.hopx.ai/api/control-plane/list-sandboxes List and filter all your sandboxes with pagination support using the HopX Control Plane API. Query sandboxes by status, region, template, or other criteria. Learn how to use GET /v1/sandboxes endpoint with filtering, pagination, and sorting options. Includes Python and JavaScript SDK examples. List all sandboxes in your organization. Filter by status, region, or use pagination to handle large result sets. ## Endpoint ``` GET /v1/sandboxes ``` ## Request ### Headers ``` Authorization: Bearer $HOPX_API_KEY ``` ### Query Parameters | Parameter | Type | Required | Description | | --------- | ------- | -------- | ------------------------------------------------------------ | | `limit` | integer | No | Maximum number of results (default: 100, max: 1000) | | `status` | string | No | Filter by status: `running`, `stopped`, `paused`, `creating` | | `region` | string | No | Filter by region (e.g., `us-east`, `eu-west`) | | `cursor` | string | No | Pagination cursor for next page | ### Example Request List all running sandboxes: ```bash theme={null} curl "https://api.hopx.dev/v1/sandboxes?status=running&limit=10" \ -H "Authorization: Bearer $HOPX_API_KEY" ``` Filter by region: ```bash theme={null} curl "https://api.hopx.dev/v1/sandboxes?region=us-east" \ -H "Authorization: Bearer $HOPX_API_KEY" ``` Paginated request: ```bash theme={null} curl "https://api.hopx.dev/v1/sandboxes?limit=20&cursor=abc123" \ -H "Authorization: Bearer $HOPX_API_KEY" ``` ## Response ### Success (200 OK) ```json theme={null} { "object": "list", "data": [ { "id": "sandbox_abc123", "object": "sandbox", "status": "running", "public_host": "https://sandbox_abc123.hopx.dev", "template_name": "code-interpreter", "region": "us-east", "created_at": "2025-01-28T00:00:00Z" }, { "id": "sandbox_xyz789", "object": "sandbox", "status": "stopped", "public_host": "https://sandbox_xyz789.hopx.dev", "template_name": "python", "region": "eu-west", "created_at": "2025-01-27T12:00:00Z" } ], "has_more": true, "next_cursor": "def456", "request_id": "req_abc123" } ``` ### Response Fields | Field | Type | Description | | ------------- | ------- | ------------------------------------------------ | | `object` | string | Always `"list"` | | `data` | array | Array of sandbox objects | | `has_more` | boolean | Whether more results are available | | `next_cursor` | string | Cursor for the next page (if `has_more` is true) | | `request_id` | string | Request ID for debugging | Each sandbox object in `data` includes: * `id` - Sandbox ID * `status` - Current status * `public_host` - VM Agent API URL * `template_name` - Template used * `region` - Deployment region * `created_at` - Creation timestamp ## Status Codes | Code | Description | | ----- | ------------------------ | | `200` | Success | | `401` | Authentication required | | `400` | Invalid query parameters | ## Pagination Use cursor-based pagination to retrieve large result sets: 1. **First request** - Omit `cursor` parameter: ```bash theme={null} curl "https://api.hopx.dev/v1/sandboxes?limit=10" \ -H "Authorization: Bearer $HOPX_API_KEY" ``` 2. **Check for more** - If `has_more` is `true`, use `next_cursor`: ```bash theme={null} curl "https://api.hopx.dev/v1/sandboxes?limit=10&cursor=def456" \ -H "Authorization: Bearer $HOPX_API_KEY" ``` 3. **Repeat** - Continue until `has_more` is `false` ## Filtering ### Filter by Status ```bash theme={null} # Only running sandboxes curl "https://api.hopx.dev/v1/sandboxes?status=running" \ -H "Authorization: Bearer $HOPX_API_KEY" # Only stopped sandboxes curl "https://api.hopx.dev/v1/sandboxes?status=stopped" \ -H "Authorization: Bearer $HOPX_API_KEY" ``` ### Filter by Region ```bash theme={null} curl "https://api.hopx.dev/v1/sandboxes?region=us-east" \ -H "Authorization: Bearer $HOPX_API_KEY" ``` ### Combine Filters ```bash theme={null} curl "https://api.hopx.dev/v1/sandboxes?status=running®ion=us-east&limit=50" \ -H "Authorization: Bearer $HOPX_API_KEY" ``` ## Use Cases ### Count Running Sandboxes ```bash theme={null} curl "https://api.hopx.dev/v1/sandboxes?status=running" \ -H "Authorization: Bearer $HOPX_API_KEY" | jq '.data | length' ``` ### List All Sandboxes (Paginated) ```bash theme={null} #!/bin/bash CURSOR="" while true; do if [ -z "$CURSOR" ]; then RESPONSE=$(curl -s "https://api.hopx.dev/v1/sandboxes?limit=100" \ -H "Authorization: Bearer $HOPX_API_KEY") else RESPONSE=$(curl -s "https://api.hopx.dev/v1/sandboxes?limit=100&cursor=$CURSOR" \ -H "Authorization: Bearer $HOPX_API_KEY") fi echo "$RESPONSE" | jq '.data[]' HAS_MORE=$(echo "$RESPONSE" | jq -r '.has_more') if [ "$HAS_MORE" != "true" ]; then break fi CURSOR=$(echo "$RESPONSE" | jq -r '.next_cursor') done ``` ### Find Sandboxes by Template ```bash theme={null} curl "https://api.hopx.dev/v1/sandboxes" \ -H "Authorization: Bearer $HOPX_API_KEY" | \ jq '.data[] | select(.template_name == "code-interpreter")' ``` ## Related * **SDK**: [Sandbox.list()](/sdk/python/sandbox#list) - Python SDK method * **SDK**: [Sandbox.iter()](/sdk/python/sandbox#iter) - Python SDK method * [CLI Sandbox Commands](/cli/commands/sandbox) - Manage sandboxes from CLI ## Next Steps * **[Get Sandbox](/api/control-plane/get-sandbox)** - Get details for a specific sandbox * **[Create Sandbox](/api/control-plane/create-sandbox)** - Create a new sandbox * **[Delete Sandbox](/api/control-plane/delete-sandbox)** - Clean up unused sandboxes # List Templates Source: https://docs.hopx.ai/api/control-plane/list-templates List all available sandbox templates using the HopX Control Plane API. Browse pre-built and custom templates, filter by category or language, and view template configurations. Learn how to use GET /v1/templates endpoint with filtering options to discover templates for your sandbox needs. Includes request examples and response formats. List all available templates that can be used to create sandboxes. This includes both public pre-built templates and your organization's custom templates. ## Endpoint ``` GET /v1/templates ``` ## Request ### Headers ``` Authorization: Bearer $HOPX_API_KEY ``` ### Query Parameters | Parameter | Type | Required | Description | | ---------- | ------ | -------- | ------------------------------------------------------- | | `category` | string | No | Filter by category (e.g., `python`, `nodejs`, `ubuntu`) | | `language` | string | No | Filter by language (e.g., `python`, `javascript`) | ### Example Request List all templates: ```bash theme={null} curl https://api.hopx.dev/v1/templates \ -H "Authorization: Bearer $HOPX_API_KEY" ``` Filter by category: ```bash theme={null} curl "https://api.hopx.dev/v1/templates?category=python" \ -H "Authorization: Bearer $HOPX_API_KEY" ``` Filter by language: ```bash theme={null} curl "https://api.hopx.dev/v1/templates?language=javascript" \ -H "Authorization: Bearer $HOPX_API_KEY" ``` ## Response ### Success (200 OK) ```json theme={null} { "object": "list", "data": [ { "id": "73", "name": "code-interpreter", "display_name": "Code Interpreter", "description": "Pre-built environment for Python, JavaScript, and Bash execution", "category": "python", "language": "python", "is_public": true, "is_active": true, "default_resources": { "vcpu": 2, "memory_mb": 4096, "disk_gb": 10 } }, { "id": "74", "name": "python-3.11", "display_name": "Python 3.11", "description": "Python 3.11 environment with pip and common packages", "category": "python", "language": "python", "is_public": true, "is_active": true, "default_resources": { "vcpu": 1, "memory_mb": 2048, "disk_gb": 5 } } ], "has_more": false, "url": "/v1/templates", "request_id": "req_abc123" } ``` ### Response Fields | Field | Type | Description | | ------------ | ------- | ---------------------------------- | | `object` | string | Always `"list"` | | `data` | array | Array of template objects | | `has_more` | boolean | Whether more results are available | | `url` | string | Endpoint URL | | `request_id` | string | Request ID for debugging | Each template object includes: * `id` - Template ID (use for creating sandboxes) * `name` - Template name (alternative identifier) * `display_name` - Human-readable name * `description` - Template description * `category` - Template category * `language` - Primary language (if applicable) * `is_public` - Whether template is publicly available * `is_active` - Whether template is active and ready for use * `default_resources` - Default vCPU, memory, and disk allocation ## Status Codes | Code | Description | | ----- | ----------------------- | | `200` | Success | | `401` | Authentication required | ## Template Categories Common template categories: * **`python`** - Python environments (various versions) * **`nodejs`** - Node.js environments * **`ubuntu`** - Ubuntu base images * **`code-interpreter`** - Multi-language code execution * **`custom`** - Custom templates created by your organization ## Use Cases ### Find Python Templates ```bash theme={null} curl "https://api.hopx.dev/v1/templates?category=python" \ -H "Authorization: Bearer $HOPX_API_KEY" | jq '.data[]' ``` ### List Only Custom Templates ```bash theme={null} curl https://api.hopx.dev/v1/templates \ -H "Authorization: Bearer $HOPX_API_KEY" | \ jq '.data[] | select(.is_public == false)' ``` ### Find Template ID by Name ```bash theme={null} curl https://api.hopx.dev/v1/templates \ -H "Authorization: Bearer $HOPX_API_KEY" | \ jq '.data[] | select(.name == "code-interpreter") | .id' ``` ### Check Template Resources ```bash theme={null} curl https://api.hopx.dev/v1/templates \ -H "Authorization: Bearer $HOPX_API_KEY" | \ jq '.data[] | {name: .name, resources: .default_resources}' ``` ## Related * **SDK**: [Sandbox.list\_templates()](/sdk/python/sandbox#list_templates) - Python SDK method * [CLI Template Commands](/cli/commands/template) - Template management from CLI ## Next Steps * **[Get Template](/api/control-plane/get-template)** - Get detailed template information * **[Build Template](/api/control-plane/build-template)** - Create a custom template * **[Create Sandbox](/api/control-plane/create-sandbox)** - Create a sandbox from a template # Overview Source: https://docs.hopx.ai/api/control-plane/overview Manage sandboxes, templates, and monitor resources with the HopX Control Plane API. Create and manage sandbox lifecycle, list and build templates, monitor resources, and stream real-time events. Complete reference for all Control Plane API endpoints with authentication, request formats, and response handling. The Control Plane API (`https://api.hopx.dev`) manages the lifecycle of sandboxes and templates. Use it to create, list, manage, and monitor your cloud sandboxes. ## Base URL ``` https://api.hopx.dev ``` All endpoints are prefixed with `/v1/`: ``` https://api.hopx.dev/v1/sandboxes https://api.hopx.dev/v1/templates ``` ## Authentication All Control Plane API requests require an API key. Include it in the `Authorization` header: ```bash theme={null} curl -H "Authorization: Bearer $HOPX_API_KEY" \ https://api.hopx.dev/v1/sandboxes ``` See the [Authentication guide](/api/authentication) for details. ## What You Can Do ### Sandbox Lifecycle * **Create sandboxes** - Spin up isolated environments from templates * **List and filter** - Query sandboxes by status, region, or other criteria * **Manage state** - Start, stop, pause, resume, and delete sandboxes * **Set timeouts** - Configure auto-shutdown timers * **Refresh tokens** - Renew JWT tokens for VM Agent API access ### Template Management * **List templates** - Browse available pre-built and custom templates * **Get template details** - View template configuration and resources * **Build templates** - Create custom templates from Docker images * **Delete templates** - Remove custom templates (when not in use) ### Real-Time Monitoring * **Stream sandbox events** - Server-Sent Events (SSE) for sandbox lifecycle changes * **Stream metrics** - Real-time VM metrics for running sandboxes * **Stream template updates** - Real-time template list changes ## API Endpoints ### Sandbox Lifecycle | Endpoint | Method | Description | | --------------------------------- | ------ | ----------------------------- | | `/v1/sandboxes` | POST | Create a new sandbox | | `/v1/sandboxes` | GET | List all sandboxes | | `/v1/sandboxes/:id` | GET | Get sandbox details | | `/v1/sandboxes/:id` | DELETE | Delete a sandbox | | `/v1/sandboxes/:id/start` | POST | Start a stopped sandbox | | `/v1/sandboxes/:id/stop` | POST | Stop a running sandbox | | `/v1/sandboxes/:id/pause` | POST | Pause a running sandbox | | `/v1/sandboxes/:id/resume` | POST | Resume a paused sandbox | | `/v1/sandboxes/:id/timeout` | PUT | Set or extend sandbox timeout | | `/v1/sandboxes/:id/token/refresh` | POST | Refresh JWT token | ### Templates | Endpoint | Method | Description | | --------------------------- | ------ | ------------------------ | | `/v1/templates` | GET | List available templates | | `/v1/templates/:name` | GET | Get template details | | `/v1/templates/:templateID` | DELETE | Delete a custom template | ### Template Building | Endpoint | Method | Description | | ------------------------------------- | ------ | ---------------------------------- | | `/v1/templates/files/upload-link` | POST | Get presigned URL for file uploads | | `/v1/templates/build` | POST | Trigger template build | | `/v1/templates/build/:buildID/status` | GET | Get build status | | `/v1/templates/build/:buildID/logs` | GET | Stream build logs | ### Streaming | Endpoint | Method | Description | | ---------------------------------- | ------ | ---------------------------- | | `/v1/sandboxes/stream` | GET | Stream sandbox events (SSE) | | `/v1/sandboxes/:id/metrics/stream` | GET | Stream sandbox metrics (SSE) | | `/v1/templates/stream` | GET | Stream template events (SSE) | ## Response Format All responses use JSON with a consistent structure: ### Success Response ```json theme={null} { "id": "sandbox_abc123", "object": "sandbox", "status": "running", ... } ``` ### List Response ```json theme={null} { "object": "list", "data": [...], "has_more": false, "next_cursor": null, "request_id": "req_abc123" } ``` ### Error Response ```json theme={null} { "error": "Error message", "code": "ERROR_CODE", "request_id": "req_abc123" } ``` ## Status Codes | Code | Description | | ---- | --------------------------- | | 200 | Success | | 201 | Created | | 202 | Accepted (async operations) | | 400 | Bad Request | | 401 | Unauthorized | | 403 | Forbidden | | 404 | Not Found | | 409 | Conflict | | 402 | Payment Required | | 503 | Service Unavailable | ## Rate Limits The Control Plane API has rate limits to ensure fair usage. Rate limit headers are included in responses: ``` X-RateLimit-Limit: 100 X-RateLimit-Remaining: 95 X-RateLimit-Reset: 1640995200 ``` If you exceed the rate limit, you'll receive a `429 Too Many Requests` response. ## Related * **[VM Agent API Overview](/api/vm-agent/overview)** - Execute code and manage sandbox resources * **[Python SDK Quickstart](/sdk/python/quickstart)** - Use the Python SDK instead * **[JavaScript SDK Quickstart](/sdk/javascript/quickstart)** - Use the JavaScript SDK instead * **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Learn about sandbox creation * **[Managing Sandbox State](/core-concepts/sandboxes/managing-state)** - Control sandbox lifecycle * [CLI Reference](/cli/introduction) - Command-line interface ## Next Steps * **[Create Sandbox](/api/control-plane/create-sandbox)** - Create your first sandbox * **[List Sandboxes](/api/control-plane/list-sandboxes)** - Query and filter sandboxes * **[Manage Sandboxes](/api/control-plane/get-sandbox)** - Get, update, and delete sandboxes * **[Templates](/api/control-plane/list-templates)** - Work with templates # Pause Sandbox Source: https://docs.hopx.ai/api/control-plane/pause-sandbox Pause a running sandbox to temporarily suspend execution using the HopX Control Plane API. Temporarily stop sandbox execution while preserving filesystem and state. Learn how to use POST /v1/sandboxes/:id/pause endpoint to pause sandboxes, free resources, and resume later. Includes request examples and state management. Pause a running sandbox to temporarily suspend all execution. The sandbox will transition from `running` to `paused` status. You can resume it later to continue where it left off. ## Endpoint ``` POST /v1/sandboxes/:id/pause ``` ## Request ### Headers ``` Authorization: Bearer $HOPX_API_KEY ``` ### Path Parameters | Parameter | Type | Description | | --------- | ------ | ------------------- | | `id` | string | Sandbox ID to pause | ### Example Request ```bash theme={null} curl -X POST https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/pause \ -H "Authorization: Bearer $HOPX_API_KEY" ``` ## Response ### Success (200 OK) ```json theme={null} { "id": "sandbox_abc123xyz", "status": "paused", "request_id": "req_abc123" } ``` ### Response Fields | Field | Type | Description | | ------------ | ------ | ------------------------ | | `id` | string | Sandbox ID | | `status` | string | New status (`paused`) | | `request_id` | string | Request ID for debugging | ## Status Codes | Code | Description | | ----- | --------------------------- | | `200` | Sandbox paused successfully | | `401` | Authentication required | | `404` | Sandbox not found | ## Errors ### Sandbox Not Found (404) ```json theme={null} { "error": "Sandbox not found", "code": "RESOURCE_NOT_FOUND", "request_id": "req_abc123" } ``` **Cause:** The sandbox ID doesn't exist or belongs to another organization. **Fix:** Verify the sandbox ID is correct. List your sandboxes using `GET /v1/sandboxes` to find valid IDs. ## Important Notes * **Execution suspended** - All running processes are paused * **State preserved** - Memory state and files are retained * **Can be resumed** - Use [Resume Sandbox](/api/control-plane/resume-sandbox) to continue * **VM Agent API** - VM Agent API endpoints are unavailable while paused ## Use Cases ### Pause Long-Running Task ```bash theme={null} # Pause a sandbox running a long computation curl -X POST https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/pause \ -H "Authorization: Bearer $HOPX_API_KEY" ``` ### Temporarily Free Resources ```bash theme={null} # Pause to free resources temporarily curl -X POST https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/pause \ -H "Authorization: Bearer $HOPX_API_KEY" # ... later, resume ... curl -X POST https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/resume \ -H "Authorization: Bearer $HOPX_API_KEY" ``` ## Related * **SDK**: [sandbox.pause()](/sdk/python/sandbox#pause) - Python SDK method * [CLI Sandbox Commands](/cli/commands/sandbox) - Manage sandboxes from CLI ## Next Steps * **[Resume Sandbox](/api/control-plane/resume-sandbox)** - Resume a paused sandbox * **[Stop Sandbox](/api/control-plane/stop-sandbox)** - Stop instead of pausing * **[Get Sandbox](/api/control-plane/get-sandbox)** - Check sandbox status # Resume Sandbox Source: https://docs.hopx.ai/api/control-plane/resume-sandbox Resume a paused sandbox to continue execution using the HopX Control Plane API. Restart a previously paused sandbox to continue work where you left off. Learn how to use POST /v1/sandboxes/:id/resume endpoint to resume paused sandboxes and restore execution state. Includes request examples and state transitions. Resume a paused sandbox to continue execution from where it was paused. The sandbox will transition from `paused` to `running` status. ## Endpoint ``` POST /v1/sandboxes/:id/resume ``` ## Request ### Headers ``` Authorization: Bearer $HOPX_API_KEY ``` ### Path Parameters | Parameter | Type | Description | | --------- | ------ | -------------------- | | `id` | string | Sandbox ID to resume | ### Example Request ```bash theme={null} curl -X POST https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/resume \ -H "Authorization: Bearer $HOPX_API_KEY" ``` ## Response ### Success (200 OK) ```json theme={null} { "id": "sandbox_abc123xyz", "status": "running", "request_id": "req_abc123" } ``` ### Response Fields | Field | Type | Description | | ------------ | ------ | ------------------------ | | `id` | string | Sandbox ID | | `status` | string | New status (`running`) | | `request_id` | string | Request ID for debugging | ## Status Codes | Code | Description | | ----- | ---------------------------- | | `200` | Sandbox resumed successfully | | `401` | Authentication required | | `404` | Sandbox not found | ## Errors ### Sandbox Not Found (404) ```json theme={null} { "error": "Sandbox not found", "code": "RESOURCE_NOT_FOUND", "request_id": "req_abc123" } ``` **Cause:** The sandbox ID doesn't exist or belongs to another organization. **Fix:** Verify the sandbox ID is correct. List your sandboxes using `GET /v1/sandboxes` to find valid IDs. ## Important Notes * **Execution continues** - All paused processes resume from where they were paused * **State preserved** - Memory state and files remain intact * **VM Agent API** - VM Agent API endpoints become available again ## Use Cases ### Resume After Pausing ```bash theme={null} # Pause a sandbox curl -X POST https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/pause \ -H "Authorization: Bearer $HOPX_API_KEY" # ... later, resume it ... curl -X POST https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/resume \ -H "Authorization: Bearer $HOPX_API_KEY" ``` ### Resume All Paused Sandboxes ```bash theme={null} #!/bin/bash # Get all paused sandboxes PAUSED=$(curl -s "https://api.hopx.dev/v1/sandboxes?status=paused" \ -H "Authorization: Bearer $HOPX_API_KEY" | \ jq -r '.data[].id') # Resume each one for ID in $PAUSED; do curl -X POST "https://api.hopx.dev/v1/sandboxes/$ID/resume" \ -H "Authorization: Bearer $HOPX_API_KEY" echo "Resumed $ID" done ``` ## Related * **SDK**: [sandbox.resume()](/sdk/python/sandbox#resume) - Python SDK method * [CLI Sandbox Commands](/cli/commands/sandbox) - Manage sandboxes from CLI ## Next Steps * **[Pause Sandbox](/api/control-plane/pause-sandbox)** - Pause a running sandbox * **[Get Sandbox](/api/control-plane/get-sandbox)** - Check sandbox status * **[Stop Sandbox](/api/control-plane/stop-sandbox)** - Stop instead of pausing description: Resume a paused sandbox to continue execution *** Resume a paused sandbox to continue execution from where it was paused. The sandbox will transition from `paused` to `running` status. ## Endpoint ``` POST /v1/sandboxes/:id/resume ``` ## Request ### Headers ``` Authorization: Bearer $HOPX_API_KEY ``` ### Path Parameters | Parameter | Type | Description | | --------- | ------ | -------------------- | | `id` | string | Sandbox ID to resume | ### Example Request ```bash theme={null} curl -X POST https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/resume \ -H "Authorization: Bearer $HOPX_API_KEY" ``` ## Response ### Success (200 OK) ```json theme={null} { "id": "sandbox_abc123xyz", "status": "running", "request_id": "req_abc123" } ``` ### Response Fields | Field | Type | Description | | ------------ | ------ | ------------------------ | | `id` | string | Sandbox ID | | `status` | string | New status (`running`) | | `request_id` | string | Request ID for debugging | ## Status Codes | Code | Description | | ----- | ---------------------------- | | `200` | Sandbox resumed successfully | | `401` | Authentication required | | `404` | Sandbox not found | ## Errors ### Sandbox Not Found (404) ```json theme={null} { "error": "Sandbox not found", "code": "RESOURCE_NOT_FOUND", "request_id": "req_abc123" } ``` **Cause:** The sandbox ID doesn't exist or belongs to another organization. **Fix:** Verify the sandbox ID is correct. List your sandboxes using `GET /v1/sandboxes` to find valid IDs. ## Important Notes * **Execution continues** - All paused processes resume from where they were paused * **State preserved** - Memory state and files remain intact * **VM Agent API** - VM Agent API endpoints become available again ## Use Cases ### Resume After Pausing ```bash theme={null} # Pause a sandbox curl -X POST https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/pause \ -H "Authorization: Bearer $HOPX_API_KEY" # ... later, resume it ... curl -X POST https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/resume \ -H "Authorization: Bearer $HOPX_API_KEY" ``` ### Resume All Paused Sandboxes ```bash theme={null} #!/bin/bash # Get all paused sandboxes PAUSED=$(curl -s "https://api.hopx.dev/v1/sandboxes?status=paused" \ -H "Authorization: Bearer $HOPX_API_KEY" | \ jq -r '.data[].id') # Resume each one for ID in $PAUSED; do curl -X POST "https://api.hopx.dev/v1/sandboxes/$ID/resume" \ -H "Authorization: Bearer $HOPX_API_KEY" echo "Resumed $ID" done ``` ## Next Steps * **[Pause Sandbox](/api/control-plane/pause-sandbox)** - Pause a running sandbox * **[Get Sandbox](/api/control-plane/get-sandbox)** - Check sandbox status * **[Stop Sandbox](/api/control-plane/stop-sandbox)** - Stop instead of pausing # Set Sandbox Timeout Source: https://docs.hopx.ai/api/control-plane/set-timeout Set or extend the auto-shutdown timeout for a sandbox using the HopX Control Plane API. Configure when sandboxes are automatically destroyed to manage resources and costs. Learn how to use PUT /v1/sandboxes/:id/timeout endpoint to set initial timeouts or extend existing timeouts for long-running tasks. Includes request examples and timeout management. Set or extend the auto-shutdown timeout for a sandbox. When the timeout expires, the sandbox will be automatically deleted. ## Endpoint ``` PUT /v1/sandboxes/:id/timeout ``` ## Request ### Headers ``` Authorization: Bearer $HOPX_API_KEY Content-Type: application/json ``` ### Path Parameters | Parameter | Type | Description | | --------- | ------ | ----------- | | `id` | string | Sandbox ID | ### Body Parameters | Parameter | Type | Required | Description | | ----------------- | ------- | -------- | ---------------------------------------- | | `timeout_seconds` | integer | Yes | New timeout duration in seconds from now | ### Example Request Set timeout to 1 hour (3600 seconds): ```bash theme={null} curl -X PUT https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/timeout \ -H "Authorization: Bearer $HOPX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "timeout_seconds": 3600 }' ``` Extend timeout by 2 hours: ```bash theme={null} curl -X PUT https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/timeout \ -H "Authorization: Bearer $HOPX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "timeout_seconds": 7200 }' ``` ## Response ### Success (200 OK) ```json theme={null} { "id": "sandbox_abc123xyz", "timeout_seconds": 3600, "expires_at": "2025-01-28T01:00:00Z", "request_id": "req_abc123" } ``` ### Response Fields | Field | Type | Description | | ----------------- | ------- | ------------------------------------------- | | `id` | string | Sandbox ID | | `timeout_seconds` | integer | New timeout duration in seconds | | `expires_at` | string | ISO 8601 timestamp when sandbox will expire | | `request_id` | string | Request ID for debugging | ## Status Codes | Code | Description | | ----- | ---------------------------- | | `200` | Timeout updated successfully | | `400` | Invalid timeout value | | `401` | Authentication required | | `404` | Sandbox not found | ## Errors ### Invalid Timeout (400) ```json theme={null} { "error": "Invalid timeout value: must be positive", "code": "INVALID_REQUEST", "request_id": "req_abc123" } ``` **Cause:** The `timeout_seconds` value is negative, zero, or invalid. **Fix:** Ensure `timeout_seconds` is a positive integer. ### Sandbox Not Found (404) ```json theme={null} { "error": "Sandbox not found", "code": "RESOURCE_NOT_FOUND", "request_id": "req_abc123" } ``` **Cause:** The sandbox ID doesn't exist or belongs to another organization. **Fix:** Verify the sandbox ID is correct. ## Important Notes * **Absolute timeout** - The timeout is set from the current time, not relative to the previous timeout * **Auto-deletion** - When the timeout expires, the sandbox is automatically deleted * **Can be extended** - You can extend the timeout multiple times * **No maximum** - There's no maximum timeout limit (subject to your plan) ## Use Cases ### Extend Timeout for Long-Running Task ```bash theme={null} # Check current expiration curl https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz \ -H "Authorization: Bearer $HOPX_API_KEY" | jq '.expires_at' # Extend by 2 hours curl -X PUT https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/timeout \ -H "Authorization: Bearer $HOPX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "timeout_seconds": 7200 }' ``` ### Set Timeout on Creation ```bash theme={null} # Create sandbox with 1 hour timeout curl -X POST https://api.hopx.dev/v1/sandboxes \ -H "Authorization: Bearer $HOPX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "template_id": "73", "timeout_seconds": 3600 }' ``` ### Keep Sandbox Alive Indefinitely ```bash theme={null} # Set a very long timeout (e.g., 30 days) curl -X PUT https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/timeout \ -H "Authorization: Bearer $HOPX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "timeout_seconds": 2592000 }' ``` ## Related * **SDK**: [sandbox.set\_timeout()](/sdk/python/sandbox#set_timeout) - Python SDK method * [CLI Reference](/cli/introduction) - Command-line interface ## Next Steps * **[Get Sandbox](/api/control-plane/get-sandbox)** - Check current timeout and expiration * **[Create Sandbox](/api/control-plane/create-sandbox)** - Set timeout on creation * **[Delete Sandbox](/api/control-plane/delete-sandbox)** - Manually delete before timeout # Overview Source: https://docs.hopx.ai/api/introduction Learn what the HopX REST API does, its main resources, and who uses it. The HopX API provides two interfaces: Control Plane API for sandbox lifecycle management and VM Agent API for code execution, file operations, and desktop automation. Get started with authentication, endpoints, and API best practices. For SDK or CLI usage, see the SDK Reference or CLI Reference sections. The HopX REST API enables you to create, manage, and interact with cloud sandboxes programmatically. Use the API to build automation workflows, integrate sandbox execution into your applications, or create custom tooling on top of HopX. ## What the API Does The HopX API provides two main interfaces: ### Control Plane API The **Control Plane API** (`https://api.hopx.dev`) manages sandbox lifecycle and templates: * **Create and manage sandboxes** - Spin up isolated cloud environments from templates * **Template management** - List, view, and build custom templates * **Real-time monitoring** - Stream sandbox events and metrics via Server-Sent Events (SSE) * **Resource management** - Start, stop, pause, resume, and delete sandboxes ### VM Agent API The **VM Agent API** (sandbox-specific URLs) executes code and manages sandbox resources: * **Code execution** - Run Python, JavaScript, Bash, and Go code synchronously or asynchronously * **File operations** - Read, write, list, upload, and download files * **Command execution** - Run shell commands in the sandbox environment * **Desktop automation** - Control VNC, mouse, keyboard, screenshots, and screen recording * **Observability** - Monitor processes, metrics, cache, and terminal access ## Main Resources ### Sandboxes Sandboxes are isolated cloud environments created from templates. Each sandbox has: * **Unique ID** - Identifier for all operations * **Status** - `running`, `stopped`, `paused`, `creating` * **Resources** - vCPU, memory, and disk allocated from template * **Public URL** - Accessible endpoint for VM Agent API * **JWT Token** - Authentication token for VM Agent API calls ### Templates Templates define the base environment for sandboxes: * **Pre-built templates** - Python, Node.js, Ubuntu, and more * **Custom templates** - Build your own with Docker images and build steps * **Resource specifications** - vCPU, memory, and disk limits * **Features** - Desktop support, internet access, pre-installed packages ## When to Use the API vs SDK vs CLI ### Use the REST API when: * ✅ You're building in a language without an official SDK * ✅ You need fine-grained control over HTTP requests * ✅ You're integrating with existing HTTP client libraries * ✅ You need custom retry logic or connection pooling * ✅ You're building serverless functions or edge workers ### Use the SDK when: * ✅ You're building Python or JavaScript/TypeScript applications * ✅ You want type safety and IDE autocomplete * ✅ You prefer language-native error handling * ✅ You want automatic resource management ### Use the CLI when: * ✅ You prefer command-line workflows * ✅ You're scripting or automating from shell * ✅ You want quick one-off operations * ✅ You're working in CI/CD pipelines ## Typical Consumers The HopX API is used by: * **Backend developers** - Integrating sandbox execution into applications * **DevOps engineers** - Automating infrastructure and testing workflows * **AI/ML engineers** - Running model training and inference in isolated environments * **CI/CD pipelines** - Executing tests and builds in clean sandboxes * **Automation tools** - Building custom tooling and workflows ## Base URLs ### Control Plane API ``` https://api.hopx.dev ``` All Control Plane endpoints are prefixed with `/v1/`: ``` https://api.hopx.dev/v1/sandboxes https://api.hopx.dev/v1/templates ``` ### VM Agent API Each sandbox has its own VM Agent API endpoint: ``` https://{sandbox_id}.hopx.dev ``` Or using the direct URL format: ``` https://{port}-{vmId}.{serverId}.hopx.dev ``` The VM Agent base URL is returned in the `public_host` or `direct_url` field when creating a sandbox. ## API Specification The HopX API follows RESTful principles: * **HTTP methods** - GET, POST, PUT, DELETE for resource operations * **JSON request/response** - All request bodies and responses use JSON * **Standard status codes** - 200, 201, 400, 401, 404, 503, etc. * **Error format** - Consistent error response structure with codes and messages An OpenAPI specification is available for the Control Plane API. The spec is kept in sync with the API implementation and can be used to generate client SDKs or mock servers. ## Related * **[API Quickstart](/api/quickstart)** - Get started with the API * **[Authentication](/api/authentication)** - Learn about API authentication * **[Python SDK Quickstart](/sdk/python/quickstart)** - Use the Python SDK instead * **[JavaScript SDK Quickstart](/sdk/javascript/quickstart)** - Use the JavaScript SDK instead * **[VM Agent API Overview](/api/vm-agent/overview)** - Learn about the VM Agent API * [CLI Reference](/cli/introduction) - Command-line interface ## Next Steps * **[Authentication](/api/authentication)** - Learn how to authenticate API requests * **[Quickstart](/api/quickstart)** - Get your first sandbox running in minutes * **[Control Plane API](/api/control-plane/overview)** - Manage sandboxes and templates * **[VM Agent API](/api/vm-agent/overview)** - Execute code and manage sandbox resources # Quickstart Source: https://docs.hopx.ai/api/quickstart Get your first sandbox running with the HopX API in minutes. Complete quickstart guide for using the HopX REST API to create sandboxes, execute code, manage files, and clean up resources. Learn authentication, make your first API call, and understand API response formats. Includes curl examples and response handling. Get up and running with the HopX API in minutes. This quickstart walks you through creating your first sandbox, executing code, and cleaning up. ## What You'll Learn In this quickstart, you'll learn how to: * Authenticate with the HopX API using API keys * Create sandboxes using the Control Plane API * Execute code using the VM Agent API * Handle API responses and extract results * Delete sandboxes to free resources * Use common API patterns and variations ## Prerequisites Before you begin, you'll need: * An API key from [console.hopx.dev](https://console.hopx.dev) * `curl` installed (or any HTTP client) * Basic familiarity with REST APIs ## Step 1: Set Your API key Set your API key as an environment variable: ```bash theme={null} export HOPX_API_KEY="hopx_live_YOUR_KEY_ID.YOUR_SECRET" ``` Replace `YOUR_KEY_ID` and `YOUR_SECRET` with your actual API key from the dashboard. ## Step 2: Create a Sandbox Create a sandbox from a pre-built template: ```bash theme={null} curl -X POST https://api.hopx.dev/v1/sandboxes \ -H "Authorization: Bearer $HOPX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "template_id": "73", "timeout_seconds": 3600 }' ``` **Response:** ```json theme={null} { "id": "sandbox_abc123xyz", "object": "sandbox", "status": "running", "public_host": "https://sandbox_abc123xyz.hopx.dev", "direct_url": "https://sandbox_abc123xyz.hopx.dev", "template_id": "73", "template_name": "code-interpreter", "organization_id": 123, "region": "us-east", "resources": { "vcpu": 2, "memory_mb": 4096, "disk_mb": 10240 }, "internet_access": true, "timeout_seconds": 3600, "created_at": "2025-01-28T00:00:00Z", "auth_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "token_expires_at": "2025-01-28T01:00:00Z", "request_id": "req_abc123" } ``` Save the `id` and `auth_token` from the response. You'll need them for the next steps. ## Step 3: Execute Code Execute Python code in your sandbox using the VM Agent API: ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \ -H "Content-Type: application/json" \ -d '{ "code": "print(\"Hello from HopX!\")", "language": "python" }' ``` **Response:** ```json theme={null} { "success": true, "stdout": "Hello from HopX!\n", "stderr": "", "exit_code": 0, "execution_time": 0.15 } ``` 🎉 **Success!** You've executed your first code in a HopX sandbox. The output shows "Hello from HopX!" was printed successfully. ## Step 4: Clean Up Delete the sandbox when you're done: ```bash theme={null} curl -X DELETE https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz \ -H "Authorization: Bearer $HOPX_API_KEY" ``` **Response:** ```json theme={null} { "status": "deleted", "id": "sandbox_abc123xyz", "request_id": "req_abc123" } ``` ## What Just Happened? 1. **Created a sandbox** - You spun up an isolated cloud environment from the `code-interpreter` template 2. **Executed code** - You ran Python code in the sandbox and received the output 3. **Cleaned up** - You deleted the sandbox to free resources The sandbox was completely isolated - any code you run can't access your local system or other sandboxes. ## Related * **[Python SDK Quickstart](/sdk/python/quickstart)** - Get started with the Python SDK * **[JavaScript SDK Quickstart](/sdk/javascript/quickstart)** - Get started with the JavaScript SDK * **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Learn more about sandbox creation * **[Code Execution](/core-concepts/code-execution/synchronous)** - Understand code execution concepts * [CLI Reference](/cli/introduction) - Command-line interface ## Next Steps * **[Control Plane API](/api/control-plane/overview)** - Learn about all sandbox management endpoints * **[VM Agent API](/api/vm-agent/overview)** - Explore code execution, file operations, and more * **[Authentication](/api/authentication)** - Deep dive into API key management and security * **[SDK Quickstart](/sdk/python/quickstart)** - Use the Python or JavaScript SDK for easier integration ## Common Variations ### Create Sandbox with Environment Variables ```bash theme={null} curl -X POST https://api.hopx.dev/v1/sandboxes \ -H "Authorization: Bearer $HOPX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "template_id": "73", "env_vars": { "MY_VAR": "my_value", "API_KEY": "secret123" } }' ``` ### Execute JavaScript Code ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \ -H "Authorization: Bearer $AUTH_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "code": "console.log(\"Hello from JavaScript!\");", "language": "javascript" }' ``` ### List All Sandboxes ```bash theme={null} curl https://api.hopx.dev/v1/sandboxes \ -H "Authorization: Bearer $HOPX_API_KEY" ``` ## Troubleshooting ### Error: 401 Unauthorized Your API key is missing or invalid. Verify: * The `HOPX_API_KEY` environment variable is set correctly * You're using the `Authorization: Bearer` header format * Your API key hasn't been revoked in the dashboard ### Error: 404 Template Not Found The template ID doesn't exist. Try: * Listing available templates: `GET /v1/templates` * Using a template name instead: `"template_name": "code-interpreter"` ### Error: 503 Service Unavailable No sandboxes are available at the moment. This is usually temporary. Try again in a few moments. For more help, see the [Errors & Troubleshooting](/api/errors) guide. # Clear Execution Cache Source: https://docs.hopx.ai/api/vm-agent/clear-cache Clear the sandbox execution result cache to free memory using the HopX VM Agent API. Remove cached execution results to free resources, force re-execution, or reset cache statistics. Learn how to use POST /cache/clear endpoint to clear all cached results. Includes request examples and cache management. Clear the execution result cache to free memory or force re-execution of previously cached code. ## Endpoint ``` POST /cache/clear ``` ## Request ### Headers ``` Authorization: Bearer YOUR_JWT_TOKEN ``` ### Example Request ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/cache/clear \ -H "Authorization: Bearer YOUR_JWT_TOKEN" ``` ## Response ### Success (200 OK) ```json theme={null} { "message": "Cache cleared successfully", "cleared_entries": 25, "freed_bytes": 512000 } ``` ## Status Codes | Code | Description | | ---- | ------------- | | 200 | Cache cleared | | 401 | Unauthorized | ## Use Cases ### Force Code Re-execution ```bash theme={null} # Clear cache curl -X POST https://sandbox_abc123xyz.hopx.dev/cache/clear \ -H "Authorization: Bearer YOUR_JWT_TOKEN" # Execute code (will not use cache) curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "code": "print(\"Fresh execution\")", "language": "python" }' ``` ## Related * **SDK**: [sandbox.cache.clear()](/sdk/python/cache#clear) - Python SDK method * [CLI System Commands](/cli/commands/system) - System operations from CLI ## Next Steps * **[Get Cache Statistics](/api/vm-agent/get-cache-stats)** - View cache metrics * **[Execute Code](/api/vm-agent/execute)** - Execute code # Clear Environment Variables Source: https://docs.hopx.ai/api/vm-agent/clear-env Remove all global environment variables from the sandbox using the HopX VM Agent API. Clear all environment variables to reset configuration or start fresh. Learn how to use DELETE /env endpoint to remove all variables at once. Includes request examples and cleanup best practices. Remove all custom environment variables from the sandbox. System environment variables may be preserved. This removes ALL custom environment variables. This operation cannot be undone. ## Endpoint ``` DELETE /env ``` ## Request ### Headers ``` Authorization: Bearer YOUR_JWT_TOKEN ``` ### Example Request ```bash theme={null} curl -X DELETE https://sandbox_abc123xyz.hopx.dev/env \ -H "Authorization: Bearer YOUR_JWT_TOKEN" ``` ## Response ### Success (204 No Content) Empty response on success. ## Status Codes | Code | Description | | ---- | ------------------------------ | | 204 | Variables cleared successfully | | 401 | Unauthorized | ## Use Cases ### Reset Environment ```bash theme={null} curl -X DELETE https://sandbox_abc123xyz.hopx.dev/env \ -H "Authorization: Bearer YOUR_JWT_TOKEN" ``` ## Related * **SDK**: [sandbox.env.clear()](/sdk/python/environment-variables#clear) - Python SDK method * [CLI Environment Variables](/cli/commands/env) - Environment variables from CLI ## Next Steps * **[Get Environment Variables](/api/vm-agent/get-env)** - View all variables * **[Set Environment Variables](/api/vm-agent/set-env)** - Set new variables # Execute Code Source: https://docs.hopx.ai/api/vm-agent/execute Execute code synchronously in a sandbox and get results. Run Python, JavaScript, Bash, or Go code in isolated cloud environments using the HopX VM Agent API. Learn how to use POST /execute endpoint with code examples, error handling, and result processing. Execute code synchronously in the sandbox. The request waits until execution completes and returns the output. ## Endpoint ``` POST /execute ``` ## Request ### Headers ``` Authorization: Bearer YOUR_JWT_TOKEN Content-Type: application/json ``` ### Body Parameters | Parameter | Type | Required | Description | | ------------- | ------- | -------- | ------------------------------------------------------------------ | | `code` | string | Yes | Code to execute | | `language` | string | No | Language: `python`, `javascript`, `bash`, `go` (default: `python`) | | `timeout` | integer | No | Execution timeout in seconds (default: 60, max: 300) | | `working_dir` | string | No | Working directory (default: `/workspace`) | | `env` | object | No | Environment variables for this execution only | ### Example Request Execute Python code: ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "code": "print(\"Hello from HopX!\")", "language": "python" }' ``` Execute JavaScript code: ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "code": "console.log(\"Hello from Node.js!\");", "language": "javascript" }' ``` Execute with custom environment: ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "code": "import os; print(os.getenv(\"MY_VAR\"))", "language": "python", "env": { "MY_VAR": "my_value" } }' ``` ## Response ### Success (200 OK) ```json theme={null} { "success": true, "stdout": "Hello from HopX!\n", "stderr": "", "exit_code": 0, "execution_time": 0.15 } ``` ### Response Fields | Field | Type | Description | | ---------------- | ------- | ---------------------------------------- | | `success` | boolean | Whether execution completed successfully | | `stdout` | string | Standard output | | `stderr` | string | Standard error | | `exit_code` | integer | Exit code (0 = success) | | `execution_time` | number | Execution time in seconds | ## Status Codes | Code | Description | | ---- | ------------------------------------------------ | | 200 | Execution completed | | 400 | Invalid request (missing code, invalid language) | | 401 | Unauthorized (invalid or expired JWT) | | 408 | Execution timeout | | 500 | Execution failed | ## Supported Languages ### Python ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "code": "import pandas as pd\ndf = pd.DataFrame({\"a\": [1,2,3]})\nprint(df)", "language": "python" }' ``` ### JavaScript (Node.js) ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "code": "const fs = require(\"fs\");\nconsole.log(fs.readdirSync(\".\"));", "language": "javascript" }' ``` ### Bash ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "code": "ls -la /workspace", "language": "bash" }' ``` ## Errors ### Timeout (408) ```json theme={null} { "error": "Execution timeout after 60 seconds", "code": "EXECUTION_TIMEOUT" } ``` **Cause:** Code execution exceeded the timeout limit. **Fix:** Increase the timeout or optimize your code. ### Invalid Language (400) ```json theme={null} { "error": "Invalid language: ruby", "code": "INVALID_REQUEST" } ``` **Cause:** Unsupported language specified. **Fix:** Use one of the supported languages: `python`, `javascript`, `bash`, `go`. ### Execution Failed (500) ```json theme={null} { "success": false, "stdout": "", "stderr": "NameError: name 'x' is not defined\n", "exit_code": 1, "execution_time": 0.05 } ``` **Cause:** Code execution failed (syntax error, runtime error, etc.). **Fix:** Check the `stderr` field for error details. ## Use Cases ### Data Analysis ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "code": "import pandas as pd\nimport numpy as np\n\ndata = {\"sales\": [100, 150, 200, 180, 220]}\ndf = pd.DataFrame(data)\n\nprint(f\"Mean: ${df[\"sales\"].mean():.2f}\")\nprint(f\"Median: ${df[\"sales\"].median():.2f}\")", "language": "python" }' ``` ### File Processing ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "code": "with open(\"/workspace/data.txt\", \"r\") as f:\n lines = f.readlines()\n print(f\"File has {len(lines)} lines\")", "language": "python" }' ``` ### System Information ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "code": "import platform\nimport os\n\nprint(f\"OS: {platform.system()}\")\nprint(f\"Python: {platform.python_version()}\")\nprint(f\"CPU Count: {os.cpu_count()}\")", "language": "python" }' ``` ## Related * **SDK**: [sandbox.run\_code()](/sdk/python/sandbox#run_code) - Python SDK method * [CLI Code Execution](/cli/commands/run) - Execute code from CLI ## Next Steps * **[Rich Output](/api/vm-agent/execute-rich)** - Capture plots and visualizations * **[Background Execution](/api/vm-agent/execute-background)** - Run long-running tasks * **[Async Execution](/api/vm-agent/execute-async)** - Execute with webhook callbacks # Async Code Execution with Webhooks Source: https://docs.hopx.ai/api/vm-agent/execute-async Execute very long-running code and receive results via webhook callback using the HopX VM Agent API. Run code asynchronously for long-running tasks and receive execution results via webhook when complete. Learn how to use POST /execute/async endpoint with webhook configuration. Includes request examples and webhook setup. Execute very long-running code (>5 minutes) and receive results via webhook callback when complete. Perfect for tasks that take hours or need to run independently of your connection. ## Endpoint ``` POST /execute/async ``` ## Request ### Headers ``` Authorization: Bearer YOUR_JWT_TOKEN Content-Type: application/json ``` ### Body Parameters | Parameter | Type | Required | Description | | --------------------------- | ------- | -------- | --------------------------------------------- | | `code` | string | Yes | Code to execute | | `callback_url` | string | Yes | URL to POST results to when complete | | `language` | string | No | Language (default: `python`) | | `timeout` | integer | No | Max execution time in seconds (default: 3600) | | `working_dir` | string | No | Working directory | | `env` | object | No | Environment variables | | `callback_headers` | object | No | Custom headers for callback request | | `callback_signature_secret` | string | No | Secret to sign callback payload (HMAC-SHA256) | ### Example Request ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/execute/async \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "code": "import time\nfor i in range(3600):\n if i % 60 == 0:\n print(f\"Progress: {i//60} minutes\")\n time.sleep(1)\nprint(\"Complete!\")", "callback_url": "https://your-server.com/webhook", "language": "python", "timeout": 7200, "callback_signature_secret": "your-secret-key" }' ``` ## Response ### Success (200 OK) ```json theme={null} { "execution_id": "exec_abc123", "status": "queued", "callback_url": "https://your-server.com/webhook" } ``` ### Response Fields | Field | Type | Description | | -------------- | ------ | ------------------------------------- | | `execution_id` | string | Execution ID for tracking | | `status` | string | Initial status (`queued`) | | `callback_url` | string | Webhook URL that will receive results | ## Callback Behavior When execution completes, the API POSTs results to your `callback_url`: ### Callback Request ``` POST https://your-server.com/webhook Content-Type: application/json X-HopX-Signature: sha256=abc123... X-HopX-Timestamp: 1706400000 ``` ### Callback Payload ```json theme={null} { "execution_id": "exec_abc123", "status": "completed", "success": true, "stdout": "Progress: 0 minutes\nProgress: 1 minutes\n...\nComplete!\n", "stderr": "", "exit_code": 0, "execution_time": 3600.5, "started_at": "2025-01-28T00:00:00Z", "completed_at": "2025-01-28T01:00:00Z" } ``` ### Callback Headers | Header | Description | | ------------------ | ----------------------------------------------------- | | `X-HopX-Signature` | HMAC-SHA256 signature of payload (if secret provided) | | `X-HopX-Timestamp` | Unix timestamp of callback | | Custom headers | From `callback_headers` in request | ## Status Codes | Code | Description | | ---- | ---------------------------------------------------- | | 200 | Execution queued | | 400 | Invalid request (missing callback\_url, invalid URL) | | 401 | Unauthorized | | 500 | Failed to queue execution | ## Verify Webhook Signature To verify the webhook signature: ### Python ```python theme={null} import hmac import hashlib import json def verify_webhook(payload_bytes, signature, secret): """Verify HMAC-SHA256 signature""" expected_signature = hmac.new( secret.encode('utf-8'), payload_bytes, hashlib.sha256 ).hexdigest() # Remove 'sha256=' prefix if present if signature.startswith('sha256='): signature = signature[7:] return hmac.compare_digest(signature, expected_signature) # In your webhook handler @app.route('/webhook', methods=['POST']) def webhook(): signature = request.headers.get('X-HopX-Signature') timestamp = request.headers.get('X-HopX-Timestamp') payload_bytes = request.get_data() if not verify_webhook(payload_bytes, signature, 'your-secret-key'): return 'Invalid signature', 401 data = json.loads(payload_bytes) print(f"Execution {data['execution_id']}: {data['status']}") return 'OK', 200 ``` ### JavaScript ```javascript theme={null} const crypto = require('crypto'); function verifyWebhook(payloadString, signature, secret) { const expectedSignature = crypto .createHmac('sha256', secret) .update(payloadString) .digest('hex'); // Remove 'sha256=' prefix if present const actualSignature = signature.startsWith('sha256=') ? signature.slice(7) : signature; return crypto.timingSafeEqual( Buffer.from(actualSignature), Buffer.from(expectedSignature) ); } // In your webhook endpoint app.post('/webhook', express.raw({type: 'application/json'}), (req, res) => { const signature = req.headers['x-HopX-signature']; const timestamp = req.headers['x-HopX-timestamp']; const payloadString = req.body.toString('utf8'); if (!verifyWebhook(payloadString, signature, 'your-secret-key')) { return res.status(401).send('Invalid signature'); } const data = JSON.parse(payloadString); console.log(`Execution ${data.execution_id}: ${data.status}`); res.send('OK'); }); ``` ## Use Cases ### Long-Running Model Training ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/execute/async \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "code": "import tensorflow as tf\nimport time\n\nprint(\"Starting model training...\")\nmodel = tf.keras.Sequential([...])\nmodel.fit(X_train, y_train, epochs=100, batch_size=32)\nmodel.save(\"/workspace/trained_model.h5\")\nprint(\"Training complete!\")", "callback_url": "https://your-server.com/training-complete", "language": "python", "timeout": 14400, "callback_signature_secret": "your-secret-key" }' ``` ### Batch Data Processing ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/execute/async \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "code": "import pandas as pd\nimport glob\n\nprint(\"Processing batch files...\")\nall_files = glob.glob(\"/workspace/data/*.csv\")\ndfs = [pd.read_csv(f) for f in all_files]\ncombined = pd.concat(dfs, ignore_index=True)\ncombined.to_csv(\"/workspace/combined_result.csv\")\nprint(f\"Processed {len(all_files)} files\")", "callback_url": "https://your-server.com/batch-complete", "language": "python", "timeout": 7200 }' ``` ### Custom Callback Headers ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/execute/async \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "code": "print(\"Task complete\")", "callback_url": "https://your-server.com/webhook", "language": "python", "callback_headers": { "X-Custom-Header": "my-value", "X-Task-ID": "task-123" } }' ``` ## Related * **[Async Execution with Webhooks](/core-concepts/code-execution/async-webhooks)** - Learn about async execution * **[Background Execution](/api/vm-agent/execute-background)** - Shorter background tasks * **[List Processes](/api/vm-agent/list-processes)** - Check process status * **SDK**: [sandbox.run\_code\_async()](/sdk/python/sandbox#run_code_async) - Python SDK method * [CLI Code Execution](/cli/commands/run) - Execute code from CLI ## Next Steps * **[Background Execution](/api/vm-agent/execute-background)** - Shorter background tasks * **[List Processes](/api/vm-agent/list-processes)** - Check process status * **[Execute Code](/api/vm-agent/execute)** - Simple synchronous execution # Background Execution Source: https://docs.hopx.ai/api/vm-agent/execute-background Execute code in the background and return immediately with a process ID using the HopX VM Agent API. Run long-running code without blocking, monitor process status, and retrieve results when complete. Learn how to use POST /execute/background endpoint for asynchronous code execution. Includes request examples and process management. Execute code in the background and return immediately. The code continues running asynchronously, and you can check its status using the process ID. ## Endpoint ``` POST /execute/background ``` ## Request ### Headers ``` Authorization: Bearer YOUR_JWT_TOKEN Content-Type: application/json ``` ### Body Parameters | Parameter | Type | Required | Description | | ------------- | ------- | -------- | -------------------------------------------- | | `code` | string | Yes | Code to execute | | `language` | string | No | Language (default: `python`) | | `timeout` | integer | No | Max execution time in seconds (default: 300) | | `working_dir` | string | No | Working directory | | `env` | object | No | Environment variables | | `name` | string | No | Process name for identification | ### Example Request ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/execute/background \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "code": "import time\nfor i in range(10):\n print(f\"Step {i+1}/10\")\n time.sleep(1)\nprint(\"Done!\")", "language": "python", "name": "long-task" }' ``` ## Response ### Success (200 OK) ```json theme={null} { "process_id": "proc_abc123", "execution_id": "exec_xyz789", "status": "running" } ``` ### Response Fields | Field | Type | Description | | -------------- | ------ | ---------------------------------------- | | `process_id` | string | Process ID (use to check status or kill) | | `execution_id` | string | Execution ID | | `status` | string | Initial status (`queued` or `running`) | ## Status Codes | Code | Description | | ---- | ----------------------- | | 200 | Process started | | 400 | Invalid request | | 401 | Unauthorized | | 500 | Failed to start process | ## Check Process Status Use the List Processes endpoint to check status: ```bash theme={null} curl https://sandbox_abc123xyz.hopx.dev/execute/processes \ -H "Authorization: Bearer YOUR_JWT_TOKEN" ``` Response: ```json theme={null} { "processes": [ { "process_id": "proc_abc123", "execution_id": "exec_xyz789", "name": "long-task", "status": "running", "language": "python", "started_at": "2025-01-28T00:00:00Z", "stdout": "Step 1/10\nStep 2/10\n", "stderr": "", "exit_code": null } ], "count": 1 } ``` ## Kill Background Process Use the Kill Process endpoint to terminate: ```bash theme={null} curl -X DELETE https://sandbox_abc123xyz.hopx.dev/execute/kill \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "process_id": "proc_abc123" }' ``` ## Use Cases ### Long-Running Data Processing ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/execute/background \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "code": "import pandas as pd\nimport time\n\nprint(\"Processing large dataset...\")\ntime.sleep(30)\ndf = pd.read_csv(\"/workspace/large_file.csv\")\nresult = df.groupby(\"category\").sum()\nresult.to_csv(\"/workspace/result.csv\")\nprint(\"Processing complete!\")", "language": "python", "timeout": 600, "name": "data-processing" }' ``` ### Model Training ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/execute/background \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "code": "from sklearn.ensemble import RandomForestClassifier\nimport numpy as np\nimport time\n\nprint(\"Training model...\")\nX = np.random.rand(10000, 20)\ny = np.random.randint(0, 2, 10000)\n\nmodel = RandomForestClassifier(n_estimators=100)\nmodel.fit(X, y)\n\nprint(f\"Model accuracy: {model.score(X, y):.2f}\")\nprint(\"Training complete!\")", "language": "python", "timeout": 1800, "name": "model-training" }' ``` ### Monitoring Background Process ```bash theme={null} #!/bin/bash PROCESS_ID="proc_abc123" while true; do STATUS=$(curl -s https://sandbox_abc123xyz.hopx.dev/execute/processes \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | \ jq -r ".processes[] | select(.process_id == \"$PROCESS_ID\") | .status") echo "Status: $STATUS" if [ "$STATUS" == "completed" ] || [ "$STATUS" == "failed" ]; then echo "Process finished" break fi sleep 5 done ``` ### Parallel Execution ```bash theme={null} #!/bin/bash # Start multiple background tasks for i in {1..5}; do curl -X POST https://sandbox_abc123xyz.hopx.dev/execute/background \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d "{ \"code\": \"import time\\ntime.sleep(10)\\nprint('Task $i complete')\", \"language\": \"python\", \"name\": \"task-$i\" }" echo "Started task $i" done echo "All tasks started, check status:" curl https://sandbox_abc123xyz.hopx.dev/execute/processes \ -H "Authorization: Bearer YOUR_JWT_TOKEN" ``` ## Related * **SDK**: [sandbox.run\_code\_background()](/sdk/python/sandbox#run_code_background) - Python SDK method * [CLI Code Execution](/cli/commands/run) - Execute code from CLI ## Next Steps * **[List Processes](/api/vm-agent/list-processes)** - Check background process status * **[Kill Process](/api/vm-agent/kill-process)** - Terminate a background process * **[Async Execution](/api/vm-agent/execute-async)** - Execute with webhook callbacks # Check File Exists Source: https://docs.hopx.ai/api/vm-agent/file-exists Check if a file or directory exists in the sandbox using the HopX VM Agent API. Verify file existence before reading or writing, check directory presence, and handle missing files gracefully. Learn how to use GET /files/exists endpoint to check file existence. Includes request examples and error handling. Check if a file or directory exists before reading or writing. Useful for conditional logic and error prevention. ## Endpoint ``` GET /files/exists ``` ## Request ### Headers ``` Authorization: Bearer YOUR_JWT_TOKEN ``` ### Query Parameters | Parameter | Type | Required | Description | | --------- | ------ | -------- | ------------- | | `path` | string | Yes | Path to check | ### Example Request ```bash theme={null} curl "https://sandbox_abc123xyz.hopx.dev/files/exists?path=/workspace/data.txt" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" ``` ## Response ### Success (200 OK) ```json theme={null} { "exists": true, "path": "/workspace/data.txt" } ``` ## Status Codes | Code | Description | | ---- | --------------------------------- | | 200 | Success (exists is true or false) | | 401 | Unauthorized | ## Use Cases ### Conditional Read ```bash theme={null} #!/bin/bash EXISTS=$(curl -s "https://sandbox_abc123xyz.hopx.dev/files/exists?path=/workspace/config.json" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | jq -r '.exists') if [ "$EXISTS" == "true" ]; then curl "https://sandbox_abc123xyz.hopx.dev/files/read?path=/workspace/config.json" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" else echo "Config file not found" fi ``` ## Related * **SDK**: [sandbox.files.exists()](/sdk/python/files#exists) - Python SDK method * [CLI File Operations](/cli/commands/files) - File operations from CLI ## Next Steps * **[Read File](/api/vm-agent/read-file)** - Read file if exists * **[Write File](/api/vm-agent/write-file)** - Create file # Get Cache Statistics Source: https://docs.hopx.ai/api/vm-agent/get-cache-stats Get cache hit rate and usage statistics for sandbox code execution results using the HopX VM Agent API. Monitor cache performance, view hit rates, and track cached items to optimize execution speed. Learn how to use GET /cache/stats endpoint to retrieve cache statistics. Includes request examples and performance metrics. Get the VM agent status, version, and basic health information. This endpoint provides agent metadata rather than cache statistics. For clearing the execution cache, use the [Clear Cache](/api/vm-agent/clear-cache) endpoint. ## Endpoint ``` GET /cache ``` ## Request ### Headers ``` Authorization: Bearer YOUR_JWT_TOKEN ``` ### Example Request ```bash theme={null} curl https://sandbox_abc123xyz.hopx.dev/cache \ -H "Authorization: Bearer YOUR_JWT_TOKEN" ``` ## Response ### Success (200 OK) ```json theme={null} { "agent": "HopX VM Agent (Go)", "status": "running", "version": "3.2.8", "vm_id": "17633354502w4l8eiy", "message": "success", "timestamp": "2025-11-16T23:25:45Z" } ``` ### Response Fields | Field | Type | Description | | ----------- | ------ | ------------------------------- | | `agent` | string | Agent name and runtime | | `status` | string | Agent status (running, stopped) | | `version` | string | Agent version | | `vm_id` | string | Sandbox/VM identifier | | `message` | string | Status message | | `timestamp` | string | Response timestamp (ISO 8601) | ## Status Codes | Code | Description | | ---- | ------------ | | 200 | Success | | 401 | Unauthorized | ## Use Cases ### Check Agent Status ```bash theme={null} curl https://sandbox_abc123xyz.hopx.dev/cache \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | \ jq '{agent, status, version}' ``` ### Verify Agent Version ```bash theme={null} VERSION=$(curl -s https://sandbox_abc123xyz.hopx.dev/cache \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | jq -r '.version') echo "Agent version: $VERSION" ``` ### Monitor Agent Health ```bash theme={null} STATUS=$(curl -s https://sandbox_abc123xyz.hopx.dev/cache \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | jq -r '.status') if [ "$STATUS" == "running" ]; then echo "✅ Agent is healthy" else echo "⚠️ Agent status: $STATUS" fi ``` ## Related * **SDK**: [sandbox.cache.stats()](/sdk/python/cache#stats) - Python SDK method * [CLI System Commands](/cli/commands/system) - System operations from CLI ## Next Steps * **[Clear Cache](/api/vm-agent/clear-cache)** - Clear execution cache * **[Get System Metrics](/api/vm-agent/get-system-metrics)** - View resource usage # Get Environment Variables Source: https://docs.hopx.ai/api/vm-agent/get-env Get all global environment variables in the sandbox using the HopX VM Agent API. Retrieve environment variable values for configuration, debugging, or processing. Learn how to use GET /env endpoint to access all environment variables, handle sensitive values, and process environment data. Includes request examples and response formats. Retrieve all global environment variables set in the sandbox. Sensitive values (containing KEY, SECRET, PASSWORD, TOKEN) are masked for security. ## Endpoint ``` GET /env ``` ## Request ### Headers ``` Authorization: Bearer YOUR_JWT_TOKEN ``` ### Example Request ```bash theme={null} curl https://sandbox_abc123xyz.hopx.dev/env \ -H "Authorization: Bearer YOUR_JWT_TOKEN" ``` ## Response ### Success (200 OK) ```json theme={null} { "env_vars": { "PATH": "/usr/local/bin:/usr/bin:/bin", "HOME": "/root", "DATABASE_URL": "postgres://localhost/mydb", "API_KEY": "***MASKED***", "SECRET_TOKEN": "***MASKED***" } } ``` ## Status Codes | Code | Description | | ---- | ------------ | | 200 | Success | | 401 | Unauthorized | ## Use Cases ### View All Variables ```bash theme={null} curl https://sandbox_abc123xyz.hopx.dev/env \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | jq '.env_vars' ``` ### Check Specific Variable ```bash theme={null} curl https://sandbox_abc123xyz.hopx.dev/env \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | jq -r '.env_vars.DATABASE_URL' ``` ## Related * **SDK**: [sandbox.env.get()](/sdk/python/environment-variables#get) - Python SDK method * [CLI Environment Variables](/cli/commands/env) - Environment variables from CLI ## Next Steps * **[Set Environment Variables](/api/vm-agent/set-env)** - Replace all variables * **[Update Environment Variables](/api/vm-agent/update-env)** - Merge variables # Get System Metrics Source: https://docs.hopx.ai/api/vm-agent/get-system-metrics Get current CPU, memory, and disk usage metrics for HopX sandboxes using the HopX VM Agent API. Monitor system resources in real-time, track performance metrics, and use data for optimization and troubleshooting. Learn how to use GET /system/metrics endpoint to retrieve comprehensive system information. Includes request examples and response formats. Get current system metrics for the sandbox including CPU, memory, and disk usage. ## Endpoint ``` GET /system ``` ## Request ### Headers ``` Authorization: Bearer YOUR_JWT_TOKEN ``` ### Example Request ```bash theme={null} curl https://sandbox_abc123xyz.hopx.dev/system \ -H "Authorization: Bearer YOUR_JWT_TOKEN" ``` ## Response ### Success (200 OK) ```json theme={null} { "os": { "name": "Ubuntu 22.04.5 LTS", "version": "22.04.5 LTS (Jammy Jellyfish)", "kernel": "5.10.186", "arch": "amd64", "hostname": "169.254.0.22", "timezone": "Etc/UTC" }, "hardware": { "cpu_cores": 2, "cpu_model": "AMD EPYC", "memory_mb": 1995, "disk_mb": 19987 }, "network": { "interfaces": [ { "name": "eth0", "ip": "192.168.1.100", "mac": "02:fc:00:00:00:1c" } ], "hostname": "169.254.0.22" }, "environment": { "shell": "", "path": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "user": "", "home": "", "working_dir": "/", "environment": { "LANG": "C.UTF-8", "TERM": "linux" } }, "capabilities": [ "Go", "Git", "Curl", "Nano", "Make", "Wget", "Vim", "Bash", "GCC", "Pip", "NPM", "Python", "Node.js" ] } ``` ### Response Fields | Field | Type | Description | | -------------------- | ------- | ---------------------------- | | `os` | object | Operating system information | | `os.name` | string | OS name and version | | `os.kernel` | string | Kernel version | | `os.arch` | string | System architecture | | `hardware` | object | Hardware specifications | | `hardware.cpu_cores` | integer | Number of CPU cores | | `hardware.cpu_model` | string | CPU model | | `hardware.memory_mb` | integer | Total memory in MB | | `hardware.disk_mb` | integer | Total disk space in MB | | `network` | object | Network configuration | | `network.interfaces` | array | Network interfaces | | `environment` | object | Environment configuration | | `environment.path` | string | System PATH | | `capabilities` | array | Installed software and tools | ## Status Codes | Code | Description | | ---- | ------------ | | 200 | Success | | 401 | Unauthorized | ## Use Cases ### Get System Information ```bash theme={null} curl -s https://sandbox_abc123xyz.hopx.dev/system \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | \ jq '{os: .os.name, cpu_cores: .hardware.cpu_cores, memory_mb: .hardware.memory_mb}' ``` ### Check Hardware Specs ```bash theme={null} curl https://sandbox_abc123xyz.hopx.dev/system \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | \ jq '.hardware' ``` ### List Installed Capabilities ```bash theme={null} curl https://sandbox_abc123xyz.hopx.dev/system \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | \ jq '.capabilities[]' ``` ### Check OS Version ```bash theme={null} OS=$(curl -s https://sandbox_abc123xyz.hopx.dev/system \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | jq -r '.os.name') echo "Operating System: $OS" ``` ### Get Network Configuration ```bash theme={null} curl https://sandbox_abc123xyz.hopx.dev/system \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | \ jq '.network.interfaces[]' ``` ## Related * **SDK**: [sandbox.get\_agent\_metrics()](/sdk/python/sandbox#get_agent_metrics) - Python SDK method * [CLI System Commands](/cli/commands/system) - System operations from CLI ## Next Steps * **[Get Cache Statistics](/api/vm-agent/get-cache-stats)** - View cache metrics * **[List Processes](/api/vm-agent/list-system-processes)** - View running processes # Kill Background Process Source: https://docs.hopx.ai/api/vm-agent/kill-process Terminate a running background code execution process in sandboxes using the HopX VM Agent API. Stop long-running or stuck processes to free resources and manage execution. Learn how to use DELETE /execute/kill endpoint to terminate processes by process ID. Includes request examples and process management. Terminate a running background process. The process is killed immediately and cannot be restarted. ## Endpoint ``` DELETE /execute/kill ``` ## Request ### Headers ``` Authorization: Bearer YOUR_JWT_TOKEN Content-Type: application/json ``` ### Body Parameters | Parameter | Type | Required | Description | | ------------ | ------ | -------- | ------------------ | | `process_id` | string | Yes | Process ID to kill | ### Example Request ```bash theme={null} curl -X DELETE https://sandbox_abc123xyz.hopx.dev/execute/kill \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "process_id": "proc_abc123" }' ``` ## Response ### Success (200 OK) ```json theme={null} { "process_id": "proc_abc123", "status": "killed", "message": "Process terminated successfully" } ``` ### Response Fields | Field | Type | Description | | ------------ | ------ | -------------------------- | | `process_id` | string | Process ID that was killed | | `status` | string | New status (`killed`) | | `message` | string | Confirmation message | ## Status Codes | Code | Description | | ---- | ------------------------------------- | | 200 | Process killed successfully | | 400 | Invalid request (missing process\_id) | | 401 | Unauthorized | | 404 | Process not found | ## Errors ### Process Not Found (404) ```json theme={null} { "error": "Process not found", "code": "RESOURCE_NOT_FOUND" } ``` **Cause:** The process ID doesn't exist or has already completed. **Fix:** Verify the process ID using the List Processes endpoint. ## Use Cases ### Kill Long-Running Task ```bash theme={null} # Start a long-running task RESPONSE=$(curl -s -X POST https://sandbox_abc123xyz.hopx.dev/execute/background \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "code": "import time\nfor i in range(3600):\n time.sleep(1)", "language": "python" }') PROCESS_ID=$(echo "$RESPONSE" | jq -r '.process_id') echo "Started process: $PROCESS_ID" # ... later, kill it ... curl -X DELETE https://sandbox_abc123xyz.hopx.dev/execute/kill \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"process_id\": \"$PROCESS_ID\"}" ``` ### Kill All Running Processes ```bash theme={null} #!/bin/bash # Get all running processes PROCESSES=$(curl -s https://sandbox_abc123xyz.hopx.dev/execute/processes \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | \ jq -r '.processes[] | select(.status == "running") | .process_id') # Kill each one for PROCESS_ID in $PROCESSES; do curl -X DELETE https://sandbox_abc123xyz.hopx.dev/execute/kill \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"process_id\": \"$PROCESS_ID\"}" echo "Killed $PROCESS_ID" done ``` ### Kill Process with Confirmation ```bash theme={null} #!/bin/bash PROCESS_ID="proc_abc123" # Check if process exists PROCESS=$(curl -s https://sandbox_abc123xyz.hopx.dev/execute/processes \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | \ jq ".processes[] | select(.process_id == \"$PROCESS_ID\")") if [ -n "$PROCESS" ]; then STATUS=$(echo "$PROCESS" | jq -r '.status') NAME=$(echo "$PROCESS" | jq -r '.name') echo "Found process: $NAME (status: $STATUS)" echo "Killing..." curl -X DELETE https://sandbox_abc123xyz.hopx.dev/execute/kill \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"process_id\": \"$PROCESS_ID\"}" echo "Process killed" else echo "Process not found" fi ``` ### Timeout and Kill ```bash theme={null} #!/bin/bash PROCESS_ID="proc_abc123" TIMEOUT=60 # seconds START_TIME=$(date +%s) while true; do CURRENT_TIME=$(date +%s) ELAPSED=$((CURRENT_TIME - START_TIME)) if [ $ELAPSED -gt $TIMEOUT ]; then echo "Timeout reached, killing process" curl -X DELETE https://sandbox_abc123xyz.hopx.dev/execute/kill \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"process_id\": \"$PROCESS_ID\"}" break fi STATUS=$(curl -s https://sandbox_abc123xyz.hopx.dev/execute/processes \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | \ jq -r ".processes[] | select(.process_id == \"$PROCESS_ID\") | .status") if [ "$STATUS" == "completed" ] || [ "$STATUS" == "failed" ]; then echo "Process finished naturally" break fi sleep 5 done ``` ## Important Notes Killing a process terminates it immediately without cleanup. Any unsaved data or partial results will be lost. * **Immediate termination** - Process is killed without graceful shutdown * **No recovery** - Killed processes cannot be restarted * **Check status** - Use List Processes to verify the process was killed ## Related * **SDK**: [sandbox.kill\_process()](/sdk/python/sandbox#kill_process) - Python SDK method * [CLI System Commands](/cli/commands/system) - System operations from CLI ## Next Steps * **[List Processes](/api/vm-agent/list-processes)** - View all background processes * **[Background Execution](/api/vm-agent/execute-background)** - Start new background processes * **[Execute Code](/api/vm-agent/execute)** - Synchronous code execution # List Files Source: https://docs.hopx.ai/api/vm-agent/list-files List directory contents in the sandbox using the HopX VM Agent API. Browse filesystem structure, view file metadata including size and modification times, and navigate directories. Learn how to use GET /files/list endpoint to list files and directories with filtering options. Includes request examples and response formats. List files and directories in a specified path. Returns metadata including size, permissions, and modification time. ## Endpoint ``` GET /files/list ``` ## Request ### Headers ``` Authorization: Bearer YOUR_JWT_TOKEN ``` ### Query Parameters | Parameter | Type | Required | Description | | --------- | ------ | -------- | -------------------------------------- | | `path` | string | No | Directory path (default: `/workspace`) | ### Example Request ```bash theme={null} curl "https://sandbox_abc123xyz.hopx.dev/files/list?path=/workspace" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" ``` ## Response ### Success (200 OK) ```json theme={null} { "files": [ { "name": "data.txt", "path": "/workspace/data.txt", "size": 1024, "is_directory": false, "permissions": "rw-r--r--", "modified_time": "2025-01-28T00:00:00Z" }, { "name": "scripts", "path": "/workspace/scripts", "size": 4096, "is_directory": true, "permissions": "rwxr-xr-x", "modified_time": "2025-01-28T00:00:00Z" } ] } ``` ## Status Codes | Code | Description | | ---- | ------------------- | | 200 | Success | | 401 | Unauthorized | | 404 | Directory not found | ## Use Cases ### Browse Workspace ```bash theme={null} curl "https://sandbox_abc123xyz.hopx.dev/files/list?path=/workspace" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | jq '.files[] | {name, size, is_directory}' ``` ### Find Large Files ```bash theme={null} curl "https://sandbox_abc123xyz.hopx.dev/files/list?path=/workspace" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | \ jq '.files[] | select(.size > 1000000) | {name, size}' ``` ### List Only Directories ```bash theme={null} curl "https://sandbox_abc123xyz.hopx.dev/files/list?path=/workspace" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | \ jq '.files[] | select(.is_directory == true) | .name' ``` ## Related * **SDK**: [sandbox.files.list()](/sdk/python/files#list) - Python SDK method * [CLI File Operations](/cli/commands/files) - File operations from CLI ## Next Steps * **[Read File](/api/vm-agent/read-file)** - Read file contents * **[File Exists](/api/vm-agent/file-exists)** - Check if file exists # List Background Processes Source: https://docs.hopx.ai/api/vm-agent/list-processes List all background code execution processes in sandboxes and check their status using the HopX VM Agent API. Monitor running background processes, check execution status, and track process lifecycle. Learn how to use GET /processes endpoint to list processes, view status, and manage background executions. Includes request examples and response formats. List all background execution processes started with the background execution endpoint. Check their status, output, and execution details. ## Endpoint ``` GET /execute/processes ``` ## Request ### Headers ``` Authorization: Bearer YOUR_JWT_TOKEN ``` ### Example Request ```bash theme={null} curl https://sandbox_abc123xyz.hopx.dev/execute/processes \ -H "Authorization: Bearer YOUR_JWT_TOKEN" ``` ## Response ### Success (200 OK) ```json theme={null} { "processes": [ { "process_id": "proc_abc123", "execution_id": "exec_xyz789", "name": "data-processing", "status": "running", "language": "python", "started_at": "2025-01-28T00:00:00Z", "completed_at": null, "stdout": "Processing step 1/10\nProcessing step 2/10\n", "stderr": "", "exit_code": null, "execution_time": 15.5 }, { "process_id": "proc_def456", "execution_id": "exec_uvw012", "name": "model-training", "status": "completed", "language": "python", "started_at": "2025-01-27T23:00:00Z", "completed_at": "2025-01-27T23:30:00Z", "stdout": "Training complete! Accuracy: 0.95\n", "stderr": "", "exit_code": 0, "execution_time": 1800.3 } ], "count": 2 } ``` ### Response Fields | Field | Type | Description | | ----------- | ------- | ------------------------- | | `processes` | array | Array of process objects | | `count` | integer | Total number of processes | ### Process Object | Field | Type | Description | | ---------------- | ------- | -------------------------------------------------- | | `process_id` | string | Process ID | | `execution_id` | string | Execution ID | | `name` | string | Process name (if provided) | | `status` | string | Status: `queued`, `running`, `completed`, `failed` | | `language` | string | Programming language | | `started_at` | string | ISO 8601 start timestamp | | `completed_at` | string | ISO 8601 completion timestamp (if complete) | | `stdout` | string | Standard output | | `stderr` | string | Standard error | | `exit_code` | integer | Exit code (null if still running) | | `execution_time` | number | Execution time in seconds | ## Status Codes | Code | Description | | ---- | ------------ | | 200 | Success | | 401 | Unauthorized | ## Process Statuses | Status | Description | | ----------- | ------------------------------- | | `queued` | Process is queued for execution | | `running` | Process is currently running | | `completed` | Process completed successfully | | `failed` | Process failed with error | ## Use Cases ### Monitor All Processes ```bash theme={null} curl https://sandbox_abc123xyz.hopx.dev/execute/processes \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | jq '.' ``` ### Check Specific Process ```bash theme={null} curl https://sandbox_abc123xyz.hopx.dev/execute/processes \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | \ jq '.processes[] | select(.process_id == "proc_abc123")' ``` ### Filter Running Processes ```bash theme={null} curl https://sandbox_abc123xyz.hopx.dev/execute/processes \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | \ jq '.processes[] | select(.status == "running")' ``` ### Get Process Output ```bash theme={null} curl https://sandbox_abc123xyz.hopx.dev/execute/processes \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | \ jq -r '.processes[] | select(.process_id == "proc_abc123") | .stdout' ``` ### Wait for Completion ```bash theme={null} #!/bin/bash PROCESS_ID="proc_abc123" while true; do RESPONSE=$(curl -s https://sandbox_abc123xyz.hopx.dev/execute/processes \ -H "Authorization: Bearer YOUR_JWT_TOKEN") PROCESS=$(echo "$RESPONSE" | jq ".processes[] | select(.process_id == \"$PROCESS_ID\")") STATUS=$(echo "$PROCESS" | jq -r '.status') echo "Status: $STATUS" if [ "$STATUS" == "completed" ]; then echo "Output:" echo "$PROCESS" | jq -r '.stdout' break elif [ "$STATUS" == "failed" ]; then echo "Error:" echo "$PROCESS" | jq -r '.stderr' break fi sleep 5 done ``` ### List Completed Processes ```bash theme={null} curl https://sandbox_abc123xyz.hopx.dev/execute/processes \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | \ jq '.processes[] | select(.status == "completed") | {name, execution_time, exit_code}' ``` ### Count Processes by Status ```bash theme={null} curl https://sandbox_abc123xyz.hopx.dev/execute/processes \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | \ jq '[.processes | group_by(.status) | .[] | {status: .[0].status, count: length}]' ``` ## Related * **SDK**: [sandbox.list\_processes()](/sdk/python/sandbox#list_processes) - Python SDK method * [CLI System Commands](/cli/commands/system) - System operations from CLI ## Next Steps * **[Background Execution](/api/vm-agent/execute-background)** - Start background processes * **[Kill Process](/api/vm-agent/kill-process)** - Terminate a running process * **[Async Execution](/api/vm-agent/execute-async)** - Execute with webhook callbacks # List System Processes Source: https://docs.hopx.ai/api/vm-agent/list-system-processes List all running system processes in the sandbox using the HopX VM Agent API. View all system processes including background executions, system services, and user processes. Learn how to use GET /processes/system endpoint to monitor system activity and debug process issues. Includes request examples and process information. List all running system processes in the sandbox with PID, command, and user information. ## Endpoint ``` GET /processes ``` ## Request ### Headers ``` Authorization: Bearer YOUR_JWT_TOKEN ``` ### Example Request ```bash theme={null} curl https://sandbox_abc123xyz.hopx.dev/processes \ -H "Authorization: Bearer YOUR_JWT_TOKEN" ``` ## Response ### Success (200 OK) ```json theme={null} { "processes": [ { "pid": 1, "command": "/usr/bin/python3 /app/agent.py", "user": "root" }, { "pid": 123, "command": "python -m http.server 8000", "user": "user" } ], "count": 2 } ``` ## Status Codes | Code | Description | | ---- | ------------ | | 200 | Success | | 401 | Unauthorized | ## Use Cases ### Find Specific Process ```bash theme={null} curl https://sandbox_abc123xyz.hopx.dev/processes \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | \ jq '.processes[] | select(.command | contains("python"))' ``` ### Count Processes ```bash theme={null} curl https://sandbox_abc123xyz.hopx.dev/processes \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | jq '.count' ``` ## Related * **[Process Monitoring](/core-concepts/observability/processes)** - Learn about process monitoring * **[List Background Processes](/api/vm-agent/list-processes)** - View background execution processes * **[Get System Metrics](/api/vm-agent/get-system-metrics)** - View resource usage * **SDK**: [sandbox.list\_system\_processes()](/sdk/python/sandbox#list_system_processes) - Python SDK method * [CLI System Commands](/cli/commands/system) - System operations from CLI ## Next Steps * **[Get System Metrics](/api/vm-agent/get-system-metrics)** - View resource usage * **[List Background Processes](/api/vm-agent/list-processes)** - View background execution processes # Create Directory in Sandbox Source: https://docs.hopx.ai/api/vm-agent/mkdir Create a directory in the sandbox using the HopX VM Agent API. Create new directories or directory structures for organizing files and managing filesystem hierarchy. Learn how to use POST /files/mkdir endpoint to create directories with parent directory creation. Includes request examples and directory management. Create a directory in the sandbox. Parent directories are created automatically if needed. ## Endpoint ``` POST /files/mkdir ``` ## Request ### Headers ``` Authorization: Bearer YOUR_JWT_TOKEN Content-Type: application/json ``` ### Body Parameters | Parameter | Type | Required | Description | | --------- | ------ | -------- | ------------------------ | | `path` | string | Yes | Directory path to create | ### Example Request ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/files/mkdir \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "path": "/workspace/project/src" }' ``` ## Response ### Success (200 OK) ```json theme={null} { "path": "/workspace/project/src", "message": "Directory created successfully" } ``` ## Status Codes | Code | Description | | ---- | ----------------- | | 200 | Directory created | | 401 | Unauthorized | | 403 | Path not allowed | ## Use Cases ### Setup Project Structure ```bash theme={null} for DIR in "src" "tests" "docs" "data"; do curl -X POST https://sandbox_abc123xyz.hopx.dev/files/mkdir \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"path\": \"/workspace/project/$DIR\"}" done ``` ## Related * **SDK**: [sandbox.files.mkdir()](/sdk/python/files#mkdir) - Python SDK method * [CLI Reference](/cli/introduction) - Command-line interface ## Next Steps * **[Write File](/api/vm-agent/write-file)** - Create files in directory * **[List Files](/api/vm-agent/list-files)** - Verify directory created # Overview Source: https://docs.hopx.ai/api/vm-agent/overview Execute code, manage files, and control sandbox resources with the HopX VM Agent API. Run code in multiple languages, perform file operations, execute shell commands, manage environment variables, and automate desktop interactions. Complete reference for all VM Agent API endpoints with authentication and examples. The VM Agent API runs inside each sandbox and provides endpoints for code execution, file operations, command execution, desktop automation, and observability. Each sandbox has its own VM Agent API instance. ## Base URL Each sandbox has a unique VM Agent API URL: ``` https://{sandbox_id}.hopx.dev ``` For example: ``` https://sandbox_abc123xyz.hopx.dev ``` The base URL is returned in the `public_host` or `direct_url` field when you create a sandbox. ## Authentication All VM Agent API requests require a JWT token. This token is automatically generated when you create a sandbox: ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "code": "print(\"Hello World\")", "language": "python" }' ``` The JWT token: * Is returned in the `auth_token` field when creating a sandbox * Expires after a set time (check `token_expires_at`) * Can be refreshed using the Control Plane API ## What You Can Do ### Code Execution * **Synchronous execution** - Execute code and wait for results * **Rich output capture** - Capture matplotlib plots, pandas DataFrames, and visualizations * **Background execution** - Run long-running tasks asynchronously * **Async execution** - Execute code with webhook callbacks * **Process management** - List and kill running processes ### Command Execution * **Run commands** - Execute shell commands synchronously * **Background commands** - Run long-running commands asynchronously ### File Operations * **Read/write files** - Manage files in the sandbox * **List directories** - Browse filesystem * **Upload/download** - Transfer files to/from sandbox * **File watching** - Monitor file changes ### Environment Variables * **Get/set variables** - Manage environment variables * **Update variables** - Merge or replace variables * **Clear variables** - Remove all variables ### Desktop Automation * **VNC access** - Remote desktop via VNC * **Mouse/keyboard control** - Automate user interactions * **Screenshots** - Capture screen images * **Screen recording** - Record desktop sessions * **Window management** - Control application windows ### Observability * **Metrics** - CPU, memory, disk usage * **Processes** - System and background processes * **Cache** - Execution result cache statistics * **Terminal** - Interactive terminal via WebSocket ## API Endpoints ### Code Execution | Endpoint | Method | Description | | --------------------- | ------ | -------------------------------- | | `/execute` | POST | Execute code synchronously | | `/execute/rich` | POST | Execute with rich output capture | | `/execute/background` | POST | Execute in background | | `/execute/async` | POST | Execute with webhook callback | | `/execute/processes` | GET | List background processes | | `/execute/kill` | DELETE | Kill a background process | ### Commands | Endpoint | Method | Description | | ---------------------- | ------ | ------------------------- | | `/commands/run` | POST | Run shell command | | `/commands/background` | POST | Run command in background | ### Files | Endpoint | Method | Description | | --------------- | ------ | ------------------------ | | `/files/read` | GET | Read file contents | | `/files/write` | POST | Write file contents | | `/files/list` | GET | List directory contents | | `/files/exists` | GET | Check if file exists | | `/files/remove` | DELETE | Delete file or directory | | `/files/mkdir` | POST | Create directory | ### Environment | Endpoint | Method | Description | | -------- | ------ | --------------------------------- | | `/env` | GET | Get all environment variables | | `/env` | PUT | Replace all environment variables | | `/env` | PATCH | Update environment variables | | `/env` | DELETE | Clear all environment variables | ### Desktop | Endpoint | Method | Description | | --------------------- | -------- | --------------------- | | `/desktop/vnc` | POST | Start/stop VNC server | | `/desktop/mouse` | POST | Control mouse | | `/desktop/keyboard` | POST | Control keyboard | | `/desktop/clipboard` | GET/POST | Manage clipboard | | `/desktop/screenshot` | POST | Take screenshot | | `/desktop/recording` | POST | Start/stop recording | | `/desktop/windows` | GET | List windows | | `/desktop/display` | GET/POST | Manage display | ### Observability | Endpoint | Method | Description | | -------------- | --------- | --------------------- | | `/system` | GET | Get system metrics | | `/processes` | GET | List system processes | | `/cache` | GET | Get cache statistics | | `/cache/clear` | POST | Clear cache | | `/terminal` | WebSocket | Interactive terminal | ## Response Format All responses use JSON: ### Success Response ```json theme={null} { "success": true, "stdout": "Hello World\n", "stderr": "", "exit_code": 0 } ``` ### Error Response ```json theme={null} { "error": "Error message", "code": "ERROR_CODE" } ``` ## Status Codes | Code | Description | | ---- | -------------------------- | | 200 | Success | | 400 | Bad Request | | 401 | Unauthorized (invalid JWT) | | 404 | Not Found | | 500 | Internal Server Error | ## Supported Languages The VM Agent supports multiple programming languages: * **Python** - Python 3.x with common packages * **JavaScript** - Node.js runtime * **Bash** - Shell scripting * **Go** - Go runtime (if available in template) ## Related * **[SDK: File Operations](/sdk/python/files)** - Python SDK file operations * **[SDK: Code Execution](/sdk/python/sandbox#run_code)** - Python SDK code execution * **[SDK: Commands](/sdk/python/commands)** - Python SDK command execution * **[Code Execution Concepts](/core-concepts/code-execution/synchronous)** - Learn about code execution * [CLI Reference](/cli/introduction) - Command-line interface ## Next Steps * **[Execute Code](/api/vm-agent/execute)** - Run code synchronously * **[Rich Output](/api/vm-agent/execute-rich)** - Capture plots and visualizations * **[Background Execution](/api/vm-agent/execute-background)** - Run long-running tasks * **[File Operations](/api/vm-agent/read-file)** - Manage files in sandbox # Read File from Sandbox Source: https://docs.hopx.ai/api/vm-agent/read-file Read file contents from the sandbox as text using the HopX VM Agent API. Learn how to use GET /files/read endpoint to retrieve file contents, handle text and binary files, manage encoding, and process file data. Includes request examples and response formats. Read file contents from the sandbox. Only allowed paths like `/workspace` and `/tmp` can be read. ## Endpoint ``` GET /files/read ``` ## Request ### Headers ``` Authorization: Bearer YOUR_JWT_TOKEN ``` ### Query Parameters | Parameter | Type | Required | Description | | --------- | ------ | -------- | --------------------------------------- | | `path` | string | Yes | File path (e.g., `/workspace/data.txt`) | ### Example Request ```bash theme={null} curl "https://sandbox_abc123xyz.hopx.dev/files/read?path=/workspace/data.txt" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" ``` ## Response ### Success (200 OK) ```json theme={null} { "content": "Hello World\nLine 2\nLine 3\n", "path": "/workspace/data.txt", "size": 30 } ``` ### Response Fields | Field | Type | Description | | --------- | ------- | --------------------- | | `content` | string | File contents as text | | `path` | string | File path | | `size` | integer | File size in bytes | ## Status Codes | Code | Description | | ---- | ---------------------------------------------- | | 200 | Success | | 401 | Unauthorized | | 403 | Path not allowed (outside allowed directories) | | 404 | File not found | ## Errors ### File Not Found (404) ```json theme={null} { "error": "File not found: /workspace/nonexistent.txt", "code": "FILE_NOT_FOUND" } ``` **Cause:** The file doesn't exist. **Fix:** Verify the file path and ensure the file exists. ### Path Not Allowed (403) ```json theme={null} { "error": "Path not allowed: /etc/passwd", "code": "FORBIDDEN" } ``` **Cause:** The path is outside allowed directories. **Fix:** Only read files from `/workspace`, `/tmp`, or other explicitly allowed paths. ## Allowed Paths You can read files from: * `/workspace/*` - Main working directory * `/tmp/*` - Temporary files * Other paths may be allowed depending on sandbox configuration ## Use Cases ### Read Configuration File ```bash theme={null} curl "https://sandbox_abc123xyz.hopx.dev/files/read?path=/workspace/config.json" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | jq '.content | fromjson' ``` ### Read Log File ```bash theme={null} curl "https://sandbox_abc123xyz.hopx.dev/files/read?path=/workspace/app.log" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | jq -r '.content' ``` ### Read CSV Data ```bash theme={null} curl "https://sandbox_abc123xyz.hopx.dev/files/read?path=/workspace/data.csv" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | jq -r '.content' | head -10 ``` ### Check File Size ```bash theme={null} curl "https://sandbox_abc123xyz.hopx.dev/files/read?path=/workspace/large_file.txt" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | jq '.size' ``` ### Read and Process ```python theme={null} import requests import json url = "https://sandbox_abc123xyz.hopx.dev/files/read" headers = {"Authorization": "Bearer YOUR_JWT_TOKEN"} params = {"path": "/workspace/results.json"} response = requests.get(url, headers=headers, params=params) data = response.json() # Parse JSON content file_content = json.loads(data["content"]) print(f"Read {data['size']} bytes from {data['path']}") print(f"Data: {file_content}") ``` ## Related * **SDK**: [sandbox.files.read()](/sdk/python/files#read) - Python SDK method * [CLI File Operations](/cli/commands/files) - File operations from CLI ## Next Steps * **[Write File](/api/vm-agent/write-file)** - Write file contents * **[List Files](/api/vm-agent/list-files)** - List directory contents * **[File Exists](/api/vm-agent/file-exists)** - Check if file exists # Remove File Source: https://docs.hopx.ai/api/vm-agent/remove-file Delete a file or directory from the sandbox using the HopX VM Agent API. Remove files or directories to clean up sandbox filesystem, free disk space, and manage storage. Learn how to use DELETE /files/remove endpoint to delete files or directories recursively. Includes request examples and cleanup best practices. Delete a file or directory. Directories are removed recursively. ## Endpoint ``` DELETE /files/remove ``` ## Request ### Headers ``` Authorization: Bearer YOUR_JWT_TOKEN ``` ### Query Parameters | Parameter | Type | Required | Description | | --------- | ------ | -------- | -------------- | | `path` | string | Yes | Path to delete | ### Example Request ```bash theme={null} curl -X DELETE "https://sandbox_abc123xyz.hopx.dev/files/remove?path=/workspace/old_data.txt" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" ``` ## Response ### Success (200 OK) ```json theme={null} { "message": "File deleted successfully", "path": "/workspace/old_data.txt" } ``` ## Status Codes | Code | Description | | ---- | -------------- | | 200 | Deleted | | 401 | Unauthorized | | 404 | File not found | ## Use Cases ### Cleanup Old Files ```bash theme={null} curl -X DELETE "https://sandbox_abc123xyz.hopx.dev/files/remove?path=/workspace/temp.txt" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" ``` ### Remove Directory ```bash theme={null} curl -X DELETE "https://sandbox_abc123xyz.hopx.dev/files/remove?path=/workspace/old_project" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" ``` ## Related * **SDK**: [sandbox.files.remove()](/sdk/python/files#remove) - Python SDK method * [CLI File Operations](/cli/commands/files) - File operations from CLI ## Next Steps * **[List Files](/api/vm-agent/list-files)** - Browse files * **[Write File](/api/vm-agent/write-file)** - Create new files # Run Command Source: https://docs.hopx.ai/api/vm-agent/run-command Execute shell commands synchronously in the sandbox using the HopX VM Agent API. Run shell commands for system administration, package installation, and automation tasks. Learn how to use POST /commands/run endpoint to execute commands, capture output, and handle errors. Includes request examples and command execution best practices. Execute shell commands in the sandbox and wait for completion. Commands run in `/bin/sh -c` and return stdout, stderr, and exit code. ## Endpoint ``` POST /commands/run ``` ## Request ### Headers ``` Authorization: Bearer YOUR_JWT_TOKEN Content-Type: application/json ``` ### Body Parameters | Parameter | Type | Required | Description | | ------------- | ------- | -------- | ------------------------------------------- | | `command` | string | Yes | Shell command to execute | | `timeout` | integer | No | Command timeout in seconds (default: 30) | | `working_dir` | string | No | Working directory (default: `/workspace`) | | `env` | object | No | Environment variables for this command only | ### Example Request Run a simple command: ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/commands/run \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "command": "ls -la /workspace" }' ``` Run with custom environment: ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/commands/run \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "command": "echo $MY_VAR", "env": { "MY_VAR": "hello" } }' ``` ## Response ### Success (200 OK) ```json theme={null} { "stdout": "total 8\ndrwxr-xr-x 2 user user 4096 Jan 28 00:00 .\ndrwxr-xr-x 3 user user 4096 Jan 28 00:00 ..\n", "stderr": "", "exit_code": 0 } ``` ### Response Fields | Field | Type | Description | | ----------- | ------- | ----------------------- | | `stdout` | string | Standard output | | `stderr` | string | Standard error | | `exit_code` | integer | Exit code (0 = success) | ## Status Codes | Code | Description | | ---- | --------------------------------- | | 200 | Command completed | | 400 | Invalid request (missing command) | | 401 | Unauthorized | | 408 | Command timeout | | 500 | Command failed | ## Errors ### Command Failed (500) ```json theme={null} { "stdout": "", "stderr": "ls: cannot access '/nonexistent': No such file or directory\n", "exit_code": 2 } ``` **Cause:** Command execution failed. **Fix:** Check the `stderr` field for error details and verify the command. ## Use Cases ### Install Packages ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/commands/run \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "command": "pip install requests numpy", "timeout": 120 }' ``` ### Check System Information ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/commands/run \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "command": "uname -a && df -h && free -h" }' ``` ### File Operations ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/commands/run \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "command": "cat /workspace/data.txt | wc -l", "working_dir": "/workspace" }' ``` ### Git Operations ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/commands/run \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "command": "git clone https://github.com/user/repo.git && cd repo && git log -1", "working_dir": "/workspace", "timeout": 60 }' ``` ### Build and Test ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/commands/run \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "command": "npm install && npm test", "working_dir": "/workspace/project", "timeout": 300 }' ``` ### Pipeline Multiple Commands ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/commands/run \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "command": "mkdir -p /workspace/output && python process.py && mv result.csv /workspace/output/", "working_dir": "/workspace" }' ``` ## Related * **SDK**: [sandbox.commands.run()](/sdk/python/commands#run) - Python SDK method * [CLI Commands](/cli/commands/cmd) - Shell commands from CLI ## Next Steps * **[Run Command in Background](/api/vm-agent/run-command-background)** - Run long-running commands * **[Execute Code](/api/vm-agent/execute)** - Execute code directly * **[File Operations](/api/vm-agent/read-file)** - Read and write files # Run Command in Background Source: https://docs.hopx.ai/api/vm-agent/run-command-background Execute shell commands in the background and return immediately using the HopX VM Agent API. Run long-running shell commands without blocking, monitor process status, and retrieve results when complete. Learn how to use POST /commands/background endpoint for asynchronous command execution. Includes request examples and process management. Execute shell commands in the background and return immediately with a process ID. Perfect for long-running commands like servers, monitoring, or batch jobs. ## Endpoint ``` POST /commands/background ``` ## Request ### Headers ``` Authorization: Bearer YOUR_JWT_TOKEN Content-Type: application/json ``` ### Body Parameters | Parameter | Type | Required | Description | | ------------- | ------- | -------- | -------------------------------------------- | | `command` | string | Yes | Shell command to execute | | `timeout` | integer | No | Max execution time in seconds (default: 300) | | `working_dir` | string | No | Working directory | | `env` | object | No | Environment variables | | `name` | string | No | Process name for identification | ### Example Request ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/commands/background \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "command": "python -m http.server 8000", "working_dir": "/workspace", "name": "web-server" }' ``` ## Response ### Success (200 OK) ```json theme={null} { "process_id": "proc_abc123", "execution_id": "exec_xyz789", "status": "running" } ``` ### Response Fields | Field | Type | Description | | -------------- | ------ | ---------------------------------------- | | `process_id` | string | Process ID (use to check status or kill) | | `execution_id` | string | Execution ID | | `status` | string | Initial status (`queued` or `running`) | ## Status Codes | Code | Description | | ---- | ----------------------- | | 200 | Command started | | 400 | Invalid request | | 401 | Unauthorized | | 500 | Failed to start command | ## Use Cases ### Start Web Server ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/commands/background \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "command": "python -m http.server 8080", "working_dir": "/workspace", "env": { "PORT": "8080" }, "name": "http-server" }' ``` ### Run Long Processing Job ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/commands/background \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "command": "for i in {1..3600}; do echo \"Processing batch $i\"; sleep 1; done > /workspace/log.txt", "timeout": 7200, "name": "batch-processing" }' ``` ### Monitor Files ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/commands/background \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "command": "tail -f /workspace/application.log", "name": "log-monitor" }' ``` ### Start Development Server ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/commands/background \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "command": "npm run dev", "working_dir": "/workspace/myapp", "env": { "NODE_ENV": "development", "PORT": "3000" }, "name": "dev-server" }' ``` ## Check Process Status Use the List Processes endpoint: ```bash theme={null} curl https://sandbox_abc123xyz.hopx.dev/execute/processes \ -H "Authorization: Bearer YOUR_JWT_TOKEN" | \ jq '.processes[] | select(.process_id == "proc_abc123")' ``` ## Kill Background Command Use the Kill Process endpoint: ```bash theme={null} curl -X DELETE https://sandbox_abc123xyz.hopx.dev/execute/kill \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "process_id": "proc_abc123" }' ``` ## Related * **SDK**: [sandbox.commands.run\_background()](/sdk/python/commands#run_background) - Python SDK method * [CLI Commands](/cli/commands/cmd) - Shell commands from CLI ## Next Steps * **[Run Command](/api/vm-agent/run-command)** - Execute commands synchronously * **[List Processes](/api/vm-agent/list-processes)** - Check background process status * **[Kill Process](/api/vm-agent/kill-process)** - Terminate a background process # Set Environment Variables Source: https://docs.hopx.ai/api/vm-agent/set-env Replace all global environment variables in the sandbox using the HopX VM Agent API. Set or replace environment variables for code execution configuration. Learn how to use PUT /env endpoint to set all variables at once, handle variable values, and manage environment configuration. Includes request examples and response formats. Replace all global environment variables in the sandbox. This operation clears existing variables and sets new ones. This replaces ALL environment variables. Use PATCH `/env` to merge variables instead. ## Endpoint ``` PUT /env ``` ## Request ### Headers ``` Authorization: Bearer YOUR_JWT_TOKEN Content-Type: application/json ``` ### Body Parameters | Parameter | Type | Required | Description | | ---------- | ------ | -------- | ----------------------------------- | | `env_vars` | object | Yes | Dictionary of environment variables | ### Example Request ```bash theme={null} curl -X PUT https://sandbox_abc123xyz.hopx.dev/env \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "env_vars": { "DATABASE_URL": "postgres://localhost/prod", "API_KEY": "sk-prod-123", "DEBUG": "false" } }' ``` ## Response ### Success (204 No Content) Empty response on success. ## Status Codes | Code | Description | | ---- | -------------------------- | | 204 | Variables set successfully | | 400 | Invalid request | | 401 | Unauthorized | ## Use Cases ### Reset Variables ```bash theme={null} curl -X PUT https://sandbox_abc123xyz.hopx.dev/env \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "env_vars": { "ENVIRONMENT": "production", "LOG_LEVEL": "info" } }' ``` ## Related * **SDK**: [sandbox.env.set()](/sdk/python/environment-variables#set) - Python SDK method * [CLI Environment Variables](/cli/commands/env) - Environment variables from CLI ## Next Steps * **[Get Environment Variables](/api/vm-agent/get-env)** - View all variables * **[Update Environment Variables](/api/vm-agent/update-env)** - Merge variables * **[Clear Environment Variables](/api/vm-agent/clear-env)** - Remove all variables # Update Environment Variables Source: https://docs.hopx.ai/api/vm-agent/update-env Update or add sandbox environment variables without removing existing ones using the HopX VM Agent API. Merge new variables with existing ones, update specific variables, and manage environment configuration incrementally. Learn how to use PATCH /env endpoint to update variables without clearing others. Includes request examples and merge behavior. Update or add environment variables. Merges with existing variables - only specified variables are updated, others are preserved. ## Endpoint ``` PATCH /env ``` ## Request ### Headers ``` Authorization: Bearer YOUR_JWT_TOKEN Content-Type: application/json ``` ### Body Parameters | Parameter | Type | Required | Description | | ---------- | ------- | -------- | ------------------------------------- | | `env_vars` | object | Yes | Dictionary of variables to update/add | | `merge` | boolean | Yes | Must be `true` for merge behavior | ### Example Request ```bash theme={null} curl -X PATCH https://sandbox_abc123xyz.hopx.dev/env \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "env_vars": { "DEBUG": "true", "NEW_VAR": "value" }, "merge": true }' ``` ## Response ### Success (204 No Content) Empty response on success. ## Status Codes | Code | Description | | ---- | ------------------------------ | | 204 | Variables updated successfully | | 400 | Invalid request | | 401 | Unauthorized | ## Use Cases ### Add New Variables ```bash theme={null} curl -X PATCH https://sandbox_abc123xyz.hopx.dev/env \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "env_vars": { "FEATURE_FLAG": "enabled" }, "merge": true }' ``` ## Related * **SDK**: [sandbox.env.update()](/sdk/python/environment-variables#update) - Python SDK method * [CLI Environment Variables](/cli/commands/env) - Environment variables from CLI ## Next Steps * **[Get Environment Variables](/api/vm-agent/get-env)** - View all variables * **[Set Environment Variables](/api/vm-agent/set-env)** - Replace all variables # Write File Source: https://docs.hopx.ai/api/vm-agent/write-file Write content to a file in the sandbox using the HopX VM Agent API. Create new files or overwrite existing files with text or binary content. Learn how to use POST /files/write endpoint with encoding options, file permissions, and error handling. Includes request examples and response formats. Write content to a file in the sandbox. Creates the file if it doesn't exist, or overwrites if it does. Only allowed paths can be written. ## Endpoint ``` POST /files/write ``` ## Request ### Headers ``` Authorization: Bearer YOUR_JWT_TOKEN Content-Type: application/json ``` ### Body Parameters | Parameter | Type | Required | Description | | --------- | ------ | -------- | --------------------- | | `path` | string | Yes | Destination file path | | `content` | string | Yes | File content to write | ### Example Request ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/files/write \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "path": "/workspace/data.txt", "content": "Hello World\nLine 2\nLine 3" }' ``` Write JSON file: ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/files/write \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "path": "/workspace/config.json", "content": "{\"api_key\": \"test\", \"timeout\": 30}" }' ``` ## Response ### Success (200 OK) ```json theme={null} { "path": "/workspace/data.txt", "size": 30, "message": "File written successfully" } ``` ### Response Fields | Field | Type | Description | | --------- | ------- | -------------------- | | `path` | string | File path | | `size` | integer | File size in bytes | | `message` | string | Confirmation message | ## Status Codes | Code | Description | | ---- | ----------------------------------------- | | 200 | File written successfully | | 400 | Invalid request (missing path or content) | | 401 | Unauthorized | | 403 | Path not allowed | | 500 | Write failed | ## Errors ### Path Not Allowed (403) ```json theme={null} { "error": "Path not allowed: /etc/config", "code": "FORBIDDEN" } ``` **Cause:** The path is outside allowed directories. **Fix:** Only write files to `/workspace`, `/tmp`, or other explicitly allowed paths. ## Use Cases ### Write Configuration ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/files/write \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "path": "/workspace/app_config.json", "content": "{\"database\": \"postgres://localhost/mydb\", \"port\": 5000}" }' ``` ### Write Python Script ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/files/write \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "path": "/workspace/script.py", "content": "import pandas as pd\n\ndf = pd.DataFrame({\"a\": [1,2,3]})\nprint(df)\n" }' ``` ### Write CSV Data ```bash theme={null} curl -X POST https://sandbox_abc123xyz.hopx.dev/files/write \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "path": "/workspace/data.csv", "content": "Name,Age,City\nAlice,25,NYC\nBob,30,LA\nCharlie,35,SF\n" }' ``` ### Write and Execute ```bash theme={null} #!/bin/bash # Write script curl -X POST https://sandbox_abc123xyz.hopx.dev/files/write \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "path": "/workspace/hello.py", "content": "print(\"Hello from HopX!\")" }' # Execute it curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "code": "exec(open(\"/workspace/hello.py\").read())", "language": "python" }' ``` ### Write from Python ```python theme={null} import requests import json url = "https://sandbox_abc123xyz.hopx.dev/files/write" headers = {"Authorization": "Bearer YOUR_JWT_TOKEN"} # Prepare data data = { "users": [ {"name": "Alice", "age": 25}, {"name": "Bob", "age": 30} ] } payload = { "path": "/workspace/users.json", "content": json.dumps(data, indent=2) } response = requests.post(url, headers=headers, json=payload) print(f"Wrote {response.json()['size']} bytes") ``` ## Related * **SDK**: [sandbox.files.write()](/sdk/python/files#write) - Python SDK method * [CLI File Operations](/cli/commands/files) - File operations from CLI ## Next Steps * **[Read File](/api/vm-agent/read-file)** - Read file contents * **[List Files](/api/vm-agent/list-files)** - List directory contents * **[Remove File](/api/vm-agent/remove-file)** - Delete files # Authentication Source: https://docs.hopx.ai/cli/commands/auth Complete reference for HopX CLI authentication commands - login, logout, status, validate, and API key management. Includes OAuth login, API key creation, and authentication verification. Manage authentication for the HopX CLI using the `auth` command. Authenticate via OAuth, manage API keys, and verify authentication status. ## Command Syntax ```bash theme={null} hopx auth [options] ``` ## Subcommands ### `login` Authenticate with HopX via browser OAuth. **Syntax:** ```bash theme={null} hopx auth login [OPTIONS] ``` **Options:** * `--provider TEXT` - OAuth provider: `GoogleOAuth`, `GitHubOAuth` (default: `GoogleOAuth`) * `--no-browser` - Headless mode: manually paste callback URL (for servers without browsers) **Examples:** ```bash theme={null} # OAuth login with Google (default) hopx auth login # OAuth login with GitHub hopx auth login --provider GitHubOAuth # Headless mode (for servers/containers without browsers) hopx auth login --no-browser ``` **Expected Output:** ``` ✓ Authentication successful ✓ You can now create API keys with 'hopx auth keys create' ``` **Exit Codes:** * `0` - Success * `1` - Authentication failed * `5` - Timeout ### `logout` Log out and clear stored credentials. **Syntax:** ```bash theme={null} hopx auth logout [OPTIONS] ``` **Examples:** ```bash theme={null} # Log out hopx auth logout ``` **Expected Output:** ``` ✓ Logged out successfully ``` **Exit Codes:** * `0` - Success ### `status` Check authentication status. **Syntax:** ```bash theme={null} hopx auth status [OPTIONS] ``` **Examples:** ```bash theme={null} # Check authentication status hopx auth status ``` **Expected Output:** ``` ✓ Authenticated ✓ API key: hopx_live_... (configured) ``` **Exit Codes:** * `0` - Authenticated * `3` - Not authenticated ### `validate` Validate current API key. **Syntax:** ```bash theme={null} hopx auth validate [OPTIONS] ``` **Examples:** ```bash theme={null} # Validate API key hopx auth validate ``` **Expected Output:** ``` ✓ API key is valid ``` **Exit Codes:** * `0` - Valid * `3` - Invalid or missing ### `refresh` Refresh OAuth token. **Syntax:** ```bash theme={null} hopx auth refresh [OPTIONS] ``` **Examples:** ```bash theme={null} # Refresh OAuth token hopx auth refresh ``` **Expected Output:** ``` ✓ Token refreshed successfully ``` **Exit Codes:** * `0` - Success * `3` - Authentication error ### `keys` Manage API keys. #### `keys list` List all API keys. **Syntax:** ```bash theme={null} hopx auth keys list [OPTIONS] ``` **Examples:** ```bash theme={null} # List API keys hopx auth keys list ``` **Expected Output:** ``` ┌──────────────┬─────────────────────┬──────────────┐ │ Name │ Created │ Last Used │ ├──────────────┼─────────────────────┼──────────────┤ │ my-key │ 2025-01-27 10:00:00 │ 2025-01-27 │ │ production │ 2025-01-26 09:00:00 │ 2025-01-27 │ └──────────────┴─────────────────────┴──────────────┘ ``` #### `keys create` Create a new API key. **Syntax:** ```bash theme={null} hopx auth keys create [OPTIONS] ``` **Options:** * `--name TEXT` - API key name (auto-generated if not provided) **Examples:** ```bash theme={null} # Create API key with name hopx auth keys create --name "my-key" # Create with auto-generated name hopx auth keys create ``` **Expected Output:** ``` ✓ API key created: hopx_live_... ✓ Key stored securely ``` **Exit Codes:** * `0` - Success * `3` - Authentication error #### `keys revoke` Revoke an API key. **Syntax:** ```bash theme={null} hopx auth keys revoke KEY_ID [OPTIONS] ``` **Arguments:** * `KEY_ID` - API key ID to revoke (required) **Examples:** ```bash theme={null} # Revoke API key hopx auth keys revoke key_abc123 ``` **Expected Output:** ``` ✓ API key revoked: key_abc123 ``` **Exit Codes:** * `0` - Success * `3` - Authentication error * `4` - Key not found #### `keys info` Get information about an API key. **Syntax:** ```bash theme={null} hopx auth keys info KEY_ID [OPTIONS] ``` **Arguments:** * `KEY_ID` - API key ID (required) **Examples:** ```bash theme={null} # Get API key info hopx auth keys info key_abc123 ``` **Expected Output:** ``` ┌─────────────┬─────────────────────────────────────┐ │ Property │ Value │ ├─────────────┼─────────────────────────────────────┤ │ Name │ my-key │ │ Created │ 2025-01-27 10:00:00 │ │ Last Used │ 2025-01-27 12:00:00 │ └─────────────┴─────────────────────────────────────┘ ``` ## Authentication Methods ### Method 1: OAuth Login (Recommended) ```bash theme={null} # Login with browser hopx auth login # Create API key hopx auth keys create --name "my-key" ``` ### Method 2: Environment Variable ```bash theme={null} # Set API key export HOPX_API_KEY="hopx_live_..." # Verify hopx auth status ``` ### Method 3: Config File API keys are automatically stored in `~/.hopx/credentials.yaml` after creation. ## Shell Scripting Examples ### Check Authentication Before Running Commands ```bash theme={null} #!/bin/bash # Check authentication if ! hopx auth status > /dev/null 2>&1; then echo "Not authenticated. Please run 'hopx auth login'" exit 1 fi # Proceed with commands hopx sandbox create --template python ``` ### Create and Use API Key ```bash theme={null} #!/bin/bash # Create API key KEY_NAME="ci-$(date +%s)" hopx auth keys create --name "$KEY_NAME" # Use in script export HOPX_API_KEY=$(hopx auth keys info "$KEY_NAME" --output json | jq -r '.key') ``` ## Related * **[CLI Quickstart](/cli/quickstart)** - Get started with CLI authentication * **[CLI Installation](/cli/installation)** - Installation guide * **[API Key Guide](/api-key)** - Complete API key documentation * **[Configuration](/cli/commands/config)** - Configure CLI settings ## Next Steps * Complete [CLI Quickstart](/cli/quickstart) to authenticate and create your first sandbox * Learn about [Configuration](/cli/commands/config) to manage multiple profiles * Review [API Key Guide](/api-key) for security best practices # Billing Source: https://docs.hopx.ai/cli/commands/billing Complete reference for HopX CLI billing commands - view balance, billing history, invoices, and auto-recharge settings. Manage billing and payments using the `billing` command. View account balance, billing history, invoices, and configure auto-recharge. ## Command Syntax ```bash theme={null} hopx billing [options] ``` ## Subcommands ### `balance` View account balance. **Syntax:** ```bash theme={null} hopx billing balance [OPTIONS] ``` **Examples:** ```bash theme={null} # View balance hopx billing balance ``` **Expected Output:** ``` ┌─────────────┬─────────────────────────────────────┐ │ Property │ Value │ ├─────────────┼─────────────────────────────────────┤ │ Balance │ $150.00 │ │ Credits │ 1500 │ │ Currency │ USD │ └─────────────┴─────────────────────────────────────┘ ``` **Exit Codes:** * `0` - Success * `3` - Authentication error ### `history` View billing history. **Syntax:** ```bash theme={null} hopx billing history [OPTIONS] ``` **Options:** * `--limit INTEGER` - Number of records to show * `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`) **Examples:** ```bash theme={null} # View billing history hopx billing history # View with limit hopx billing history --limit 10 ``` **Expected Output:** ``` ┌──────────────┬──────────────┬─────────────┐ │ Date │ Amount │ Description │ ├──────────────┼──────────────┼─────────────┤ │ 2025-01-27 │ $50.00 │ Payment │ │ 2025-01-20 │ -$10.00 │ Usage │ └──────────────┴──────────────┴─────────────┘ ``` **Exit Codes:** * `0` - Success * `3` - Authentication error ### `invoices` List invoices. **Syntax:** ```bash theme={null} hopx billing invoices [OPTIONS] ``` **Options:** * `--limit INTEGER` - Number of invoices to show * `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`) **Examples:** ```bash theme={null} # List invoices hopx billing invoices # List with limit hopx billing invoices --limit 5 ``` **Expected Output:** ``` ┌──────────────┬──────────────┬─────────────┐ │ Invoice ID │ Date │ Amount │ ├──────────────┼──────────────┼─────────────┤ │ inv_abc123 │ 2025-01-27 │ $50.00 │ │ inv_def456 │ 2025-01-20 │ $30.00 │ └──────────────┴──────────────┴─────────────┘ ``` **Exit Codes:** * `0` - Success * `3` - Authentication error ### `auto-recharge` Configure auto-recharge settings. **Syntax:** ```bash theme={null} hopx billing auto-recharge [OPTIONS] ``` **Examples:** ```bash theme={null} # Configure auto-recharge hopx billing auto-recharge ``` **Expected Output:** ``` Auto-recharge configuration ✓ Auto-recharge enabled ``` **Exit Codes:** * `0` - Success * `3` - Authentication error ## Related * **[CLI Quickstart](/cli/quickstart)** - Get started with CLI * **[Usage Statistics](/cli/commands/usage)** - Monitor usage * **[Organization Commands](/cli/commands/org)** - Manage organizations ## Next Steps * Learn about [Usage Statistics](/cli/commands/usage) to monitor resource usage * Explore [Organization Management](/cli/commands/org) to manage organization settings * Review [Dashboard](https://console.hopx.dev) for billing management # Shell Commands Source: https://docs.hopx.ai/cli/commands/cmd Execute shell commands in HopX sandboxes using the CLI cmd command. Run commands synchronously or in the background with options for timeouts, working directories, and environment variables. Execute shell commands in HopX sandboxes using the `cmd` command. Run commands synchronously or in the background with full control over execution environment. ## Command Syntax ```bash theme={null} hopx cmd [options] ``` ## Subcommands ### `run` Run a shell command synchronously. **Syntax:** ```bash theme={null} hopx cmd run SANDBOX_ID COMMAND [OPTIONS] ``` **Arguments:** * `SANDBOX_ID` - Sandbox ID (required) * `COMMAND` - Shell command to execute (required) **Options:** * `--timeout INTEGER` - Command timeout in seconds * `--workdir TEXT` - Working directory for command execution * `--env TEXT` - Environment variable in KEY=VALUE format (repeatable) * `--background` - Run command in background (returns immediately) * `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`) **Examples:** ```bash theme={null} # Run simple command hopx cmd run sb_abc123 "ls -la" # Run with timeout hopx cmd run sb_abc123 "npm install" --timeout 300 # Run in working directory hopx cmd run sb_abc123 "pwd" --workdir /app # Run with environment variables hopx cmd run sb_abc123 "echo $API_KEY" --env API_KEY=secret123 # Run in background hopx cmd run sb_abc123 "python server.py" --background # Get JSON output hopx cmd run sb_abc123 "ls -la" --output json ``` **Expected Output:** ``` total 16 drwxr-xr-x 2 user user 4096 Jan 27 10:00 . drwxr-xr-x 3 user user 4096 Jan 27 10:00 .. -rw-r--r-- 1 user user 13 Jan 27 10:00 data.txt ``` **Expected Output (JSON):** ```json theme={null} { "stdout": "total 16\ndrwxr-xr-x 2 user user 4096 Jan 27 10:00 .\n", "stderr": "", "exit_code": 0, "execution_time": 0.5 } ``` **Exit Codes:** * `0` - Success * `1` - Command execution error * `3` - Authentication error * `4` - Sandbox not found * `5` - Timeout ### `exec` Execute a shell command (alias for `run`). **Syntax:** ```bash theme={null} hopx cmd exec SANDBOX_ID COMMAND [OPTIONS] ``` Same as `run` command. See `run` for options and examples. ## Shell Scripting Examples ### Install Dependencies ```bash theme={null} #!/bin/bash set -e SANDBOX_ID="sb_abc123" # Install packages hopx cmd run "$SANDBOX_ID" "pip install requests pandas" --timeout 120 # Verify installation hopx cmd run "$SANDBOX_ID" "pip list | grep requests" ``` ### Run Tests ```bash theme={null} #!/bin/bash # Run tests with environment variables hopx cmd run sb_abc123 "npm test" \ --env NODE_ENV=test \ --env CI=true \ --workdir /app ``` ### Background Process ```bash theme={null} #!/bin/bash # Start server in background hopx cmd run sb_abc123 "python server.py" --background # Server is now running in background # Use other commands to interact with it ``` ### Chain Commands ```bash theme={null} #!/bin/bash # Chain multiple commands hopx cmd run sb_abc123 "cd /app && npm install && npm test" ``` ## Related * **[CLI Quickstart](/cli/quickstart)** - Get started with CLI * **[Sandbox Commands](/cli/commands/sandbox)** - Manage sandboxes * **[Code Execution](/cli/commands/run)** - Execute code in sandboxes * **[Environment Variables](/cli/commands/env)** - Manage environment variables * **[Python SDK: Commands](/sdk/python/commands)** - Python SDK command execution * **[JavaScript SDK: Commands](/sdk/javascript/commands)** - JavaScript SDK command execution * **[API: Run Command](/api/vm-agent/run-command)** - REST API endpoint ## Next Steps * Learn about [Code Execution](/cli/commands/run) to run code alongside commands * Explore [File Operations](/cli/commands/files) to work with files via commands * Review [Environment Variables](/cli/commands/env) to configure command execution # Configuration Source: https://docs.hopx.ai/cli/commands/config Complete reference for HopX CLI configuration commands - show, set, get, and manage configuration profiles. Configure CLI settings, default values, and multiple profiles for different environments. Manage CLI configuration using the `config` command. View and modify settings, manage configuration profiles, and configure default values for commands. ## Command Syntax ```bash theme={null} hopx config [options] ``` ## Subcommands ### `show` Show current configuration. **Syntax:** ```bash theme={null} hopx config show [OPTIONS] ``` **Examples:** ```bash theme={null} # Show current configuration hopx config show ``` **Expected Output:** ``` ┌─────────────────────┬─────────────────────────────────────┐ │ Setting │ Value │ ├─────────────────────┼─────────────────────────────────────┤ │ Profile │ default │ │ API Key │ hopx_live_... (configured) │ │ Base URL │ https://api.hopx.dev │ │ Default Template │ code-interpreter │ │ Default Timeout │ 3600 │ │ Output Format │ table │ └─────────────────────┴─────────────────────────────────────┘ ``` **Exit Codes:** * `0` - Success ### `set` Set a configuration value. **Syntax:** ```bash theme={null} hopx config set KEY VALUE [OPTIONS] ``` **Arguments:** * `KEY` - Configuration key (required) * `VALUE` - Configuration value (required) **Examples:** ```bash theme={null} # Set default template hopx config set default_template python # Set default timeout hopx config set default_timeout 7200 # Set output format hopx config set output_format json ``` **Expected Output:** ``` ✓ Configuration updated: default_template = python ``` **Exit Codes:** * `0` - Success * `2` - Invalid key or value ### `get` Get a configuration value. **Syntax:** ```bash theme={null} hopx config get KEY [OPTIONS] ``` **Arguments:** * `KEY` - Configuration key (required) **Examples:** ```bash theme={null} # Get default template hopx config get default_template # Get output format hopx config get output_format ``` **Expected Output:** ``` python ``` **Exit Codes:** * `0` - Success * `2` - Key not found ### `path` Show configuration file path. **Syntax:** ```bash theme={null} hopx config path [OPTIONS] ``` **Examples:** ```bash theme={null} # Show config file path hopx config path ``` **Expected Output:** ``` ~/.hopx/config.yaml ``` **Exit Codes:** * `0` - Success ### `init` Initialize configuration (interactive setup). **Syntax:** ```bash theme={null} hopx config init [OPTIONS] ``` **Examples:** ```bash theme={null} # Initialize configuration hopx config init ``` **Expected Output:** ``` Configuration setup wizard ✓ Configuration initialized ``` **Exit Codes:** * `0` - Success ### `profiles` Manage configuration profiles. #### `profiles list` List all configuration profiles. **Syntax:** ```bash theme={null} hopx config profiles list [OPTIONS] ``` **Examples:** ```bash theme={null} # List profiles hopx config profiles list ``` **Expected Output:** ``` ┌───────────┬──────────────┐ │ Profile │ Active │ ├───────────┼──────────────┤ │ default │ ✓ │ │ production│ │ │ staging │ │ └───────────┴──────────────┘ ``` #### `profiles create` Create a new configuration profile. **Syntax:** ```bash theme={null} hopx config profiles create PROFILE_NAME [OPTIONS] ``` **Arguments:** * `PROFILE_NAME` - Profile name (required) **Examples:** ```bash theme={null} # Create profile hopx config profiles create production ``` **Expected Output:** ``` ✓ Profile created: production ``` #### `profiles use` Switch to a configuration profile. **Syntax:** ```bash theme={null} hopx config profiles use PROFILE_NAME [OPTIONS] ``` **Arguments:** * `PROFILE_NAME` - Profile name (required) **Examples:** ```bash theme={null} # Switch to profile hopx config profiles use production ``` **Expected Output:** ``` ✓ Switched to profile: production ``` #### `profiles delete` Delete a configuration profile. **Syntax:** ```bash theme={null} hopx config profiles delete PROFILE_NAME [OPTIONS] ``` **Arguments:** * `PROFILE_NAME` - Profile name (required) **Examples:** ```bash theme={null} # Delete profile hopx config profiles delete staging ``` **Expected Output:** ``` ✓ Profile deleted: staging ``` ## Configuration Keys Common configuration keys: * `default_template` - Default template for sandbox creation * `default_timeout` - Default timeout in seconds * `output_format` - Default output format (`table`, `json`, `plain`) * `base_url` - API base URL (default: `https://api.hopx.dev`) ## Shell Scripting Examples ### Configure for Different Environments ```bash theme={null} #!/bin/bash # Create production profile hopx config profiles create production hopx config profiles use production hopx config set default_template python hopx config set default_timeout 7200 # Create staging profile hopx config profiles create staging hopx config profiles use staging hopx config set default_template code-interpreter hopx config set default_timeout 3600 ``` ### Use Profile for Single Command ```bash theme={null} #!/bin/bash # Use production profile for single command hopx --profile production sandbox create --template python ``` ## Related * **[CLI Quickstart](/cli/quickstart)** - Get started with CLI * **[CLI Installation](/cli/installation)** - Installation and initial setup * **[Authentication](/cli/commands/auth)** - Configure authentication ## Next Steps * Learn about [Authentication](/cli/commands/auth) to configure API keys * Explore [Sandbox Management](/cli/commands/sandbox) to use configured defaults * Review [Environment Variables](/cli/commands/env) for sandbox configuration # Environment Variables Source: https://docs.hopx.ai/cli/commands/env Complete reference for HopX CLI environment variable commands - list, get, set, and delete environment variables in sandboxes. Includes examples for configuring execution environments. Manage environment variables in HopX sandboxes using the `env` command. List, get, set, and delete environment variables to configure execution environments. ## Command Syntax ```bash theme={null} hopx env [options] ``` ## Subcommands ### `list` List all environment variables in a sandbox. **Syntax:** ```bash theme={null} hopx env list SANDBOX_ID [OPTIONS] ``` **Arguments:** * `SANDBOX_ID` - Sandbox ID (required) **Options:** * `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`) **Examples:** ```bash theme={null} # List all environment variables hopx env list sb_abc123 # List with JSON output hopx env list sb_abc123 --output json ``` **Expected Output (Table):** ``` ┌───────────┬─────────────┐ │ Variable │ Value │ ├───────────┼─────────────┤ │ API_KEY │ secret123 │ │ DEBUG │ true │ │ NODE_ENV │ production │ └───────────┴─────────────┘ ``` **Exit Codes:** * `0` - Success * `3` - Authentication error * `4` - Sandbox not found ### `get` Get the value of a specific environment variable. **Syntax:** ```bash theme={null} hopx env get SANDBOX_ID VARIABLE [OPTIONS] ``` **Arguments:** * `SANDBOX_ID` - Sandbox ID (required) * `VARIABLE` - Environment variable name (required) **Examples:** ```bash theme={null} # Get environment variable hopx env get sb_abc123 API_KEY # Get with JSON output hopx env get sb_abc123 DEBUG --output json ``` **Expected Output:** ``` secret123 ``` **Exit Codes:** * `0` - Success * `3` - Authentication error * `4` - Sandbox or variable not found ### `set` Set one or more environment variables. **Syntax:** ```bash theme={null} hopx env set SANDBOX_ID [KEY] [VALUE] [OPTIONS] ``` **Arguments:** * `SANDBOX_ID` - Sandbox ID (required) * `KEY` - Environment variable name (optional, use with `--env` for multiple) * `VALUE` - Environment variable value (optional, use with `--env` for multiple) **Options:** * `--env, -e TEXT` - Environment variable in KEY=VALUE format (repeatable) * `--env-file PATH` - Load environment variables from file **Examples:** ```bash theme={null} # Set single variable (positional arguments) hopx env set sb_abc123 API_KEY secret123 # Set multiple variables using --env flag hopx env set sb_abc123 --env API_KEY=secret123 --env DEBUG=true --env NODE_ENV=production # Set from file hopx env set sb_abc123 --env-file .env ``` **Expected Output:** ``` ✓ Environment variables set ``` **Exit Codes:** * `0` - Success * `3` - Authentication error * `4` - Sandbox not found ### `delete` Delete an environment variable. **Syntax:** ```bash theme={null} hopx env delete SANDBOX_ID VARIABLE [OPTIONS] ``` **Arguments:** * `SANDBOX_ID` - Sandbox ID (required) * `VARIABLE` - Environment variable name to delete (required) **Examples:** ```bash theme={null} # Delete environment variable hopx env delete sb_abc123 DEBUG ``` **Expected Output:** ``` ✓ Environment variable deleted: DEBUG ``` **Exit Codes:** * `0` - Success * `3` - Authentication error * `4` - Sandbox or variable not found ## Shell Scripting Examples ### Configure Environment for Code Execution ```bash theme={null} #!/bin/bash set -e SANDBOX_ID="sb_abc123" # Set environment variables hopx env set "$SANDBOX_ID" \ API_KEY=secret123 \ DEBUG=true \ NODE_ENV=production # Execute code that uses environment variables hopx run "import os; print(os.environ['API_KEY'])" --sandbox "$SANDBOX_ID" ``` ### Load Environment from File ```bash theme={null} #!/bin/bash # Create .env file cat > .env << EOF API_KEY=secret123 DEBUG=true NODE_ENV=production EOF # Load into sandbox hopx env set sb_abc123 --env-file .env ``` ### Conditional Environment Setup ```bash theme={null} #!/bin/bash # Check if variable exists if hopx env get sb_abc123 API_KEY > /dev/null 2>&1; then echo "API_KEY already set" else echo "Setting API_KEY..." hopx env set sb_abc123 API_KEY=secret123 fi ``` ### List and Export Variables ```bash theme={null} #!/bin/bash # List variables and export to local environment hopx env list sb_abc123 --output json | jq -r 'to_entries[] | "export \(.key)=\(.value)"' | source /dev/stdin ``` ## Related * **[CLI Quickstart](/cli/quickstart)** - Get started with CLI * **[Sandbox Commands](/cli/commands/sandbox)** - Manage sandboxes * **[Code Execution](/cli/commands/run)** - Execute code with environment variables * **[Shell Commands](/cli/commands/cmd)** - Run commands with environment variables * **[Python SDK: Environment Variables](/sdk/python/environment-variables)** - Python SDK environment management * **[JavaScript SDK: Environment Variables](/sdk/javascript/environment-variables)** - JavaScript SDK environment management * **[API: Environment Variables](/api/vm-agent/get-env)** - REST API endpoints ## Next Steps * Learn about [Code Execution](/cli/commands/run) to use environment variables in code * Explore [Shell Commands](/cli/commands/cmd) to run commands with environment variables * Review [Sandbox Management](/cli/commands/sandbox) to create sandboxes with initial environment variables # File Operations Source: https://docs.hopx.ai/cli/commands/files Complete reference for HopX CLI file commands - read, write, list, upload, download, delete, and manage files in sandboxes. Includes all flags, options, examples, and exit codes. Manage files in HopX sandboxes using the `files` command (alias: `f`). Read, write, list, upload, download, and delete files from the command line. ## Command Syntax ```bash theme={null} hopx files [options] ``` ## Subcommands ### `read` Read file contents from a sandbox. **Syntax:** ```bash theme={null} hopx files read SANDBOX_ID PATH [OPTIONS] ``` **Arguments:** * `SANDBOX_ID` - Sandbox ID (required) * `PATH` - File path to read (required) **Options:** * `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`) **Examples:** ```bash theme={null} # Read file hopx files read sb_abc123 /app/config.json # Read with JSON output hopx files read sb_abc123 /app/data.txt --output json ``` **Expected Output:** ``` {"key": "value"} ``` **Exit Codes:** * `0` - Success * `3` - Authentication error * `4` - Sandbox or file not found ### `write` Write data to a file in a sandbox. **Syntax:** ```bash theme={null} hopx files write SANDBOX_ID PATH [OPTIONS] ``` **Arguments:** * `SANDBOX_ID` - Sandbox ID (required) * `PATH` - File path to write (required) **Options:** * `--data, -d TEXT` - Data to write (use `-` to read from stdin) **Examples:** ```bash theme={null} # Write file with data hopx files write sb_abc123 /app/config.json --data '{"key": "value"}' # Write from stdin echo "Hello, World!" | hopx files write sb_abc123 /app/data.txt --data - # Write from file cat local.txt | hopx files write sb_abc123 /app/data.txt --data - ``` **Expected Output:** ``` ✓ File written: /app/config.json ``` **Exit Codes:** * `0` - Success * `3` - Authentication error * `4` - Sandbox not found ### `list` List files and directories in a sandbox. **Syntax:** ```bash theme={null} hopx files list SANDBOX_ID [PATH] [OPTIONS] ``` **Arguments:** * `SANDBOX_ID` - Sandbox ID (required) * `PATH` - Directory path (optional, default: `/workspace`) **Options:** * `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`) **Examples:** ```bash theme={null} # List files in workspace hopx files list sb_abc123 # List files in specific directory hopx files list sb_abc123 /app/ # List with JSON output hopx files list sb_abc123 --output json ``` **Expected Output (Table):** ``` ┌──────────────┬──────┬─────────────────────┐ │ Name │ Size │ Modified │ ├──────────────┼──────┼─────────────────────┤ │ config.json │ 234 │ 2025-01-27 10:00:00 │ │ data.txt │ 13 │ 2025-01-27 10:00:00 │ └──────────────┴──────┴─────────────────────┘ ``` **Exit Codes:** * `0` - Success * `3` - Authentication error * `4` - Sandbox not found ### `delete` Delete a file or directory from a sandbox. **Syntax:** ```bash theme={null} hopx files delete SANDBOX_ID PATH [OPTIONS] ``` **Arguments:** * `SANDBOX_ID` - Sandbox ID (required) * `PATH` - File or directory path to delete (required) **Options:** * `--force` - Skip confirmation prompt **Examples:** ```bash theme={null} # Delete file hopx files delete sb_abc123 /app/temp.txt # Delete without confirmation hopx files delete sb_abc123 /app/temp.txt --force ``` **Expected Output:** ``` ✓ File deleted: /app/temp.txt ``` **Exit Codes:** * `0` - Success * `3` - Authentication error * `4` - Sandbox or file not found ### `upload` Upload a local file to a sandbox. **Syntax:** ```bash theme={null} hopx files upload SANDBOX_ID LOCAL_PATH REMOTE_PATH [OPTIONS] ``` **Arguments:** * `SANDBOX_ID` - Sandbox ID (required) * `LOCAL_PATH` - Local file path (required) * `REMOTE_PATH` - Remote file path in sandbox (required) **Examples:** ```bash theme={null} # Upload local file hopx files upload sb_abc123 ./local.txt /app/remote.txt # Upload with progress hopx files upload sb_abc123 ./large.csv /app/data.csv ``` **Expected Output:** ``` ✓ File uploaded: /app/remote.txt ``` **Exit Codes:** * `0` - Success * `3` - Authentication error * `4` - Sandbox not found ### `download` Download a file from a sandbox to local filesystem. **Syntax:** ```bash theme={null} hopx files download SANDBOX_ID REMOTE_PATH LOCAL_PATH [OPTIONS] ``` **Arguments:** * `SANDBOX_ID` - Sandbox ID (required) * `REMOTE_PATH` - Remote file path in sandbox (required) * `LOCAL_PATH` - Local file path (required) **Examples:** ```bash theme={null} # Download file hopx files download sb_abc123 /app/data.txt ./local.txt # Download with progress hopx files download sb_abc123 /app/result.csv ./result.csv ``` **Expected Output:** ``` ✓ File downloaded: ./local.txt ``` **Exit Codes:** * `0` - Success * `3` - Authentication error * `4` - Sandbox or file not found ### `info` Get detailed information about a file or directory. **Syntax:** ```bash theme={null} hopx files info SANDBOX_ID PATH [OPTIONS] ``` **Arguments:** * `SANDBOX_ID` - Sandbox ID (required) * `PATH` - File or directory path (required) **Options:** * `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`) **Examples:** ```bash theme={null} # Get file info hopx files info sb_abc123 /app/config.json # Get info with JSON output hopx files info sb_abc123 /app/data.txt --output json ``` **Expected Output (Table):** ``` ┌─────────────┬─────────────────────────────────────┐ │ Property │ Value │ ├─────────────┼─────────────────────────────────────┤ │ Name │ config.json │ │ Path │ /app/config.json │ │ Size │ 234 B │ │ Type │ file │ │ Modified │ 2025-01-27 10:00:00 │ └─────────────┴─────────────────────────────────────┘ ``` **Exit Codes:** * `0` - Success * `3` - Authentication error * `4` - Sandbox or file not found ## Shell Scripting Examples ### Upload and Process File ```bash theme={null} #!/bin/bash set -e SANDBOX_ID="sb_abc123" # Upload file hopx files upload "$SANDBOX_ID" ./data.csv /app/data.csv # Process file hopx run "import pandas as pd; df = pd.read_csv('/app/data.csv'); print(df.head())" --sandbox "$SANDBOX_ID" ``` ### Download Results ```bash theme={null} #!/bin/bash # Download file hopx files download sb_abc123 /app/results.json ./results.json # Process locally jq '.summary' ./results.json ``` ### Batch File Operations ```bash theme={null} #!/bin/bash # List files and download each hopx files list sb_abc123 /app/ --output json | jq -r '.[].name' | while read file; do echo "Downloading $file..." hopx files download sb_abc123 "/app/$file" "./$file" done ``` ## Related * **[CLI Quickstart](/cli/quickstart)** - Get started with CLI * **[Sandbox Commands](/cli/commands/sandbox)** - Manage sandboxes * **[Code Execution](/cli/commands/run)** - Execute code in sandboxes * **[Python SDK: Files](/sdk/python/files)** - Python SDK file operations * **[JavaScript SDK: Files](/sdk/javascript/files)** - JavaScript SDK file operations * **[API: File Operations](/api/vm-agent/read-file)** - REST API endpoints ## Next Steps * Learn about [Code Execution](/cli/commands/run) to process files * Explore [Environment Variables](/cli/commands/env) to configure file operations * Review [Sandbox Management](/cli/commands/sandbox) to create and manage sandboxes # Setup Wizard Source: https://docs.hopx.ai/cli/commands/init Interactive setup wizard for first-time HopX CLI configuration. Guides you through authentication, API key creation, and initial configuration. Run the interactive setup wizard using the `init` command. This guides you through first-time CLI configuration including authentication, API key creation, and initial settings. ## Command Syntax ```bash theme={null} hopx init [OPTIONS] ``` ## Options * `--no-browser` - Headless mode: manually paste callback URL (for servers without browsers) * `--skip-test` - Skip the sandbox test step ## Description The `init` command is an interactive setup wizard that helps you configure the HopX CLI for first-time use. It guides you through: 1. **Authentication** - Browser-based OAuth login 2. **API Key Creation** - Create and store your first API key 3. **Configuration** - Set default settings 4. **Verification** - Test your connection (unless `--skip-test` is used) ## Examples ```bash theme={null} # Full interactive setup hopx init # Headless mode (for servers without browsers) hopx init --no-browser # Skip the sandbox test hopx init --skip-test ``` **Expected Output:** ``` Welcome to HopX CLI Setup ✓ Opening browser for authentication... ✓ Authentication successful ✓ Creating API key... ✓ API key created and stored ✓ Configuration complete ✓ Testing connection... ✓ Setup complete! ``` ## When to Use * **First-time setup** - Run `hopx init` after installing the CLI * **Reconfiguration** - Run `hopx init` to reconfigure your CLI settings * **New environment** - Run `hopx init` when setting up on a new machine ## Manual Setup Alternative If you prefer manual setup, you can configure the CLI step by step: ```bash theme={null} # Authenticate hopx auth login # Create API key hopx auth keys create --name "my-key" # Configure settings hopx config set default_template python ``` ## Related * **[CLI Installation](/cli/installation)** - Install the CLI * **[CLI Quickstart](/cli/quickstart)** - Get started guide * **[Authentication](/cli/commands/auth)** - Authentication commands * **[Configuration](/cli/commands/config)** - Configuration commands ## Next Steps * Complete [CLI Quickstart](/cli/quickstart) to run your first command * Learn about [Authentication](/cli/commands/auth) for API key management * Explore [Configuration](/cli/commands/config) to customize CLI settings # Members Source: https://docs.hopx.ai/cli/commands/members Complete reference for HopX CLI members commands - list organization members, invite new members, and remove members. Manage organization members using the `members` command. List members, invite new members, and remove members from your organization. ## Command Syntax ```bash theme={null} hopx members [options] ``` ## Subcommands ### `list` List all organization members. **Syntax:** ```bash theme={null} hopx members list [OPTIONS] ``` **Examples:** ```bash theme={null} # List members hopx members list ``` **Expected Output:** ``` ┌──────────────┬──────────────┬─────────────┐ │ Name │ Email │ Role │ ├──────────────┼──────────────┼─────────────┤ │ John Doe │ john@ex.com │ owner │ │ Jane Smith │ jane@ex.com │ member │ └──────────────┴──────────────┴─────────────┘ ``` **Exit Codes:** * `0` - Success * `3` - Authentication error ### `invite` Invite a new member to the organization. **Syntax:** ```bash theme={null} hopx members invite EMAIL [OPTIONS] ``` **Arguments:** * `EMAIL` - Email address to invite (required) **Options:** * `--role TEXT` - Member role: `member`, `admin` (default: `member`) **Examples:** ```bash theme={null} # Invite member hopx members invite user@example.com # Invite as admin hopx members invite admin@example.com --role admin ``` **Expected Output:** ``` ✓ Invitation sent to user@example.com ``` **Exit Codes:** * `0` - Success * `3` - Authentication error ### `remove` Remove a member from the organization. **Syntax:** ```bash theme={null} hopx members remove EMAIL [OPTIONS] ``` **Arguments:** * `EMAIL` - Email address to remove (required) **Examples:** ```bash theme={null} # Remove member hopx members remove user@example.com ``` **Expected Output:** ``` ✓ Member removed: user@example.com ``` **Exit Codes:** * `0` - Success * `3` - Authentication error * `4` - Member not found ## Related * **[CLI Quickstart](/cli/quickstart)** - Get started with CLI * **[Organization Commands](/cli/commands/org)** - Manage organizations * **[Authentication](/cli/commands/auth)** - Authenticate with CLI ## Next Steps * Learn about [Organization Management](/cli/commands/org) to manage organization settings * Explore [Billing](/cli/commands/billing) to view organization billing * Review [Usage Statistics](/cli/commands/usage) to monitor organization usage # Organization Source: https://docs.hopx.ai/cli/commands/org Complete reference for HopX CLI organization commands - view organization info, update settings, list organizations, and switch between organizations. Manage organization settings using the `org` command. View organization information, update settings, list organizations, and switch between organizations. ## Command Syntax ```bash theme={null} hopx org [options] ``` ## Subcommands ### `info` Get organization information. **Syntax:** ```bash theme={null} hopx org info [OPTIONS] ``` **Examples:** ```bash theme={null} # Get organization info hopx org info ``` **Expected Output:** ``` ┌─────────────┬─────────────────────────────────────┐ │ Property │ Value │ ├─────────────┼─────────────────────────────────────┤ │ Name │ My Organization │ │ ID │ org_abc123 │ │ Plan │ Pro │ │ Members │ 5 │ └─────────────┴─────────────────────────────────────┘ ``` **Exit Codes:** * `0` - Success * `3` - Authentication error ### `update` Update organization settings. **Syntax:** ```bash theme={null} hopx org update [OPTIONS] ``` **Options:** * `--name TEXT` - Organization name **Examples:** ```bash theme={null} # Update organization name hopx org update --name "New Organization Name" ``` **Expected Output:** ``` ✓ Organization updated ``` **Exit Codes:** * `0` - Success * `3` - Authentication error ### `list` List all organizations you belong to. **Syntax:** ```bash theme={null} hopx org list [OPTIONS] ``` **Examples:** ```bash theme={null} # List organizations hopx org list ``` **Expected Output:** ``` ┌──────────────┬──────────────────────┐ │ Name │ Role │ ├──────────────┼──────────────────────┤ │ My Org │ owner │ │ Team Org │ member │ └──────────────┴──────────────────────┘ ``` **Exit Codes:** * `0` - Success * `3` - Authentication error ### `switch` Switch to a different organization. **Syntax:** ```bash theme={null} hopx org switch ORGANIZATION_ID [OPTIONS] ``` **Arguments:** * `ORGANIZATION_ID` - Organization ID (required) **Examples:** ```bash theme={null} # Switch organization hopx org switch org_abc123 ``` **Expected Output:** ``` ✓ Switched to organization: My Organization ``` **Exit Codes:** * `0` - Success * `3` - Authentication error * `4` - Organization not found ## Related * **[CLI Quickstart](/cli/quickstart)** - Get started with CLI * **[Authentication](/cli/commands/auth)** - Authenticate with CLI * **[Members](/cli/commands/members)** - Manage organization members ## Next Steps * Learn about [Members Management](/cli/commands/members) to manage team members * Explore [Billing](/cli/commands/billing) to view organization billing * Review [Usage Statistics](/cli/commands/usage) to monitor organization usage # Profile Source: https://docs.hopx.ai/cli/commands/profile Complete reference for HopX CLI profile commands - view and update user profile information. Manage your user profile using the `profile` command. View and update your profile information. ## Command Syntax ```bash theme={null} hopx profile [options] ``` ## Subcommands ### `info` Get user profile information. **Syntax:** ```bash theme={null} hopx profile info [OPTIONS] ``` **Examples:** ```bash theme={null} # Get profile info hopx profile info ``` **Expected Output:** ``` ┌─────────────┬─────────────────────────────────────┐ │ Property │ Value │ ├─────────────┼─────────────────────────────────────┤ │ Name │ John Doe │ │ Email │ john@example.com │ │ User ID │ user_abc123 │ │ Created │ 2025-01-01 │ └─────────────┴─────────────────────────────────────┘ ``` **Exit Codes:** * `0` - Success * `3` - Authentication error ### `update` Update user profile information. **Syntax:** ```bash theme={null} hopx profile update [OPTIONS] ``` **Options:** * `--name TEXT` - Full name * `--email TEXT` - Email address **Examples:** ```bash theme={null} # Update profile name hopx profile update --name "Jane Doe" # Update email hopx profile update --email "jane@example.com" ``` **Expected Output:** ``` ✓ Profile updated ``` **Exit Codes:** * `0` - Success * `3` - Authentication error ## Related * **[CLI Quickstart](/cli/quickstart)** - Get started with CLI * **[Authentication](/cli/commands/auth)** - Authenticate with CLI * **[Configuration](/cli/commands/config)** - Configure CLI settings ## Next Steps * Learn about [Authentication](/cli/commands/auth) to manage API keys * Explore [Configuration](/cli/commands/config) to configure CLI settings * Review [Organization Settings](/cli/commands/org) for organization management # Code Execution Source: https://docs.hopx.ai/cli/commands/run Execute code in HopX sandboxes using the CLI run command. Run Python, JavaScript, Bash, and Go code with options for files, environment variables, timeouts, and sandbox selection. Execute code in HopX sandboxes using the `run` command. Supports Python, JavaScript, Bash, and Go with options for files, environment variables, and timeouts. ## Command Syntax ```bash theme={null} hopx run [CODE|FILE] [OPTIONS] ``` ## Options * `CODE` - Code to execute as argument (use `-` to read from stdin) * `--file, -f PATH` - File containing code to execute * `--sandbox, -s TEXT` - Sandbox ID (creates temporary sandbox if omitted) * `--template, -t TEXT` - Template for temporary sandbox (default: `code-interpreter`) * `--language, -l TEXT` - Programming language: `python`, `javascript`, `bash`, `go` * `--timeout INTEGER` - Execution timeout in seconds * `--env TEXT` - Environment variable in KEY=VALUE format (repeatable) * `--workdir TEXT` - Working directory for execution * `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`) ## Examples ### Execute Python Code ```bash theme={null} # Simple Python code hopx run "print('Hello, World!')" # Python with imports hopx run "import sys; print(sys.version)" # Python with calculations hopx run "result = 2 + 2; print(f'Result: {result}')" ``` **Expected Output:** ``` Hello, World! ``` ### Execute JavaScript ```bash theme={null} # Simple JavaScript hopx run "console.log('Hello, World!')" -l javascript # JavaScript with Node.js APIs hopx run "console.log(process.version)" -l javascript ``` **Expected Output:** ``` Hello, World! ``` ### Execute Bash ```bash theme={null} # Simple Bash command hopx run "echo 'Hello, World!'" -l bash # Bash with system commands hopx run "ls -la && pwd" -l bash ``` **Expected Output:** ``` Hello, World! ``` ### Execute from File ```bash theme={null} # Create local file echo "print('Hello from file!')" > script.py # Execute from file hopx run -f script.py # Execute JavaScript from file hopx run -f script.js -l javascript ``` **Expected Output:** ``` Hello from file! ``` ### Execute with Environment Variables ```bash theme={null} # Single environment variable hopx run "import os; print(os.environ['API_KEY'])" -e API_KEY=secret123 # Multiple environment variables hopx run "import os; print(os.environ['API_KEY'], os.environ['DEBUG'])" \ -e API_KEY=secret123 \ -e DEBUG=true ``` **Expected Output:** ``` secret123 ``` ### Execute in Existing Sandbox ```bash theme={null} # Create sandbox first SANDBOX_ID=$(hopx sandbox create --template python --output json | jq -r '.id') # Execute in existing sandbox hopx run "print('Hello')" --sandbox "$SANDBOX_ID" ``` **Expected Output:** ``` Hello ``` ### Execute with Timeout ```bash theme={null} # Long-running code with timeout hopx run "import time; time.sleep(60)" --timeout 120 ``` ### Execute from stdin ```bash theme={null} # Pipe code from stdin echo "print('Hello from stdin!')" | hopx run - # Pipe file content cat script.py | hopx run - ``` **Expected Output:** ``` Hello from stdin! ``` ## JSON Output Get JSON output for scripting: ```bash theme={null} hopx run "print('Hello')" --output json ``` **Expected Output:** ```json theme={null} { "stdout": "Hello\n", "stderr": "", "exit_code": 0, "execution_time": 0.5 } ``` ## Exit Codes * `0` - Success * `1` - General error * `3` - Authentication error * `4` - Sandbox not found * `5` - Timeout ## Shell Scripting Examples ### Execute and Capture Output ```bash theme={null} #!/bin/bash # Execute and capture output OUTPUT=$(hopx run "print('Hello')" --output plain) echo "Output: $OUTPUT" ``` ### Execute with Error Handling ```bash theme={null} #!/bin/bash # Execute with error handling if hopx run "print('Hello')" > /dev/null 2>&1; then echo "Execution successful" else case $? in 3) echo "Authentication failed" ;; 4) echo "Sandbox not found" ;; 5) echo "Execution timed out" ;; *) echo "Execution failed" ;; esac exit 1 fi ``` ### Execute Multiple Scripts ```bash theme={null} #!/bin/bash # Execute multiple scripts for script in *.py; do echo "Running $script..." hopx run -f "$script" done ``` ## Related * **[CLI Quickstart](/cli/quickstart)** - Get started with CLI * **[Sandbox Commands](/cli/commands/sandbox)** - Manage sandboxes * **[Python SDK: Code Execution](/sdk/python/code-execution)** - Python SDK code execution * **[JavaScript SDK: Code Execution](/sdk/javascript/code-execution)** - JavaScript SDK code execution * **[API: Execute Code](/api/vm-agent/execute)** - REST API endpoint ## Next Steps * Learn about [Sandbox Management](/cli/commands/sandbox) to create and manage sandboxes * Explore [File Operations](/cli/commands/files) to work with files * Review [Environment Variables](/cli/commands/env) to configure execution environment # Sandbox Source: https://docs.hopx.ai/cli/commands/sandbox Complete reference for HopX CLI sandbox commands - create, list, pause, resume, kill, and manage sandboxes. Includes all flags, options, examples, and exit codes for sandbox lifecycle management. Manage sandbox lifecycle with the `sandbox` command (alias: `sb`). Create, list, pause, resume, and kill sandboxes from the command line. ## Command Syntax ```bash theme={null} hopx sandbox [options] ``` ## Subcommands ### `create` Create a new sandbox from a template. **Syntax:** ```bash theme={null} hopx sandbox create [OPTIONS] ``` **Options:** * `--template, -t TEXT` - Template name or ID (default: `code-interpreter`) * `--template-id TEXT` - Template ID (alternative to `--template`) * `--timeout INTEGER` - Auto-kill timeout in seconds (0 = no timeout) * `--region TEXT` - Preferred deployment region (e.g., `us-east`, `eu-west`) * `--env TEXT` - Environment variable in KEY=VALUE format (repeatable) * `--env-file PATH` - Load environment variables from file * `--no-internet` - Disable internet access for sandbox * `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`) **Examples:** ```bash theme={null} # Create sandbox with Python template hopx sandbox create --template python # Create with timeout hopx sandbox create --template python --timeout 7200 # Create in specific region hopx sandbox create --template python --region us-east # Get JSON output for scripting hopx sandbox create --template python --output json ``` **Expected Output (Table):** ``` ┌──────────────────┬─────────┬────────────┐ │ ID │ Status │ Template │ ├──────────────────┼─────────┼────────────┤ │ sb_abc123 │ running │ python │ └──────────────────┴─────────┴────────────┘ ``` **Expected Output (JSON):** ```json theme={null} { "id": "sb_abc123", "status": "running", "template": "python", "created_at": "2025-01-27T10:00:00Z" } ``` **Exit Codes:** * `0` - Success * `3` - Authentication error * `4` - Template not found * `7` - Rate limit exceeded ### `list` List all sandboxes. **Syntax:** ```bash theme={null} hopx sandbox list [OPTIONS] ``` **Options:** * `--status TEXT` - Filter by status: `running`, `paused`, `stopped` * `--template TEXT` - Filter by template * `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`) **Examples:** ```bash theme={null} # List all sandboxes hopx sandbox list # List running sandboxes only hopx sandbox list --status running # List with JSON output hopx sandbox list --output json # Filter by template hopx sandbox list --template python ``` **Expected Output (Table):** ``` ┌──────────────────┬─────────┬────────────┬─────────────────────┐ │ ID │ Status │ Template │ Created │ ├──────────────────┼─────────┼────────────┼─────────────────────┤ │ sb_abc123 │ running │ python │ 2025-01-27 10:00:00 │ │ sb_def456 │ paused │ nodejs │ 2025-01-27 09:00:00 │ └──────────────────┴─────────┴────────────┴─────────────────────┘ ``` **Exit Codes:** * `0` - Success * `3` - Authentication error ### `info` Get detailed information about a sandbox. **Syntax:** ```bash theme={null} hopx sandbox info SANDBOX_ID [OPTIONS] ``` **Options:** * `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`) **Examples:** ```bash theme={null} # Get sandbox info hopx sandbox info sb_abc123 # Get JSON output hopx sandbox info sb_abc123 --output json ``` **Expected Output (Table):** ``` ┌─────────────────┬─────────────────────────────────────┐ │ Field │ Value │ ├─────────────────┼─────────────────────────────────────┤ │ ID │ sb_abc123 │ │ Status │ running │ │ Template │ python │ │ Region │ us-east │ │ Created │ 2025-01-27 10:00:00 │ │ Timeout │ 3600 seconds │ └─────────────────┴─────────────────────────────────────┘ ``` **Exit Codes:** * `0` - Success * `3` - Authentication error * `4` - Sandbox not found ### `pause` Pause a running sandbox (preserves state, saves resources). **Syntax:** ```bash theme={null} hopx sandbox pause SANDBOX_ID [OPTIONS] ``` **Options:** * `--force` - Skip confirmation prompt **Examples:** ```bash theme={null} # Pause sandbox hopx sandbox pause sb_abc123 # Pause without confirmation hopx sandbox pause sb_abc123 --force ``` **Expected Output:** ``` ✓ Sandbox paused: sb_abc123 ``` **Exit Codes:** * `0` - Success * `3` - Authentication error * `4` - Sandbox not found ### `resume` Resume a paused sandbox. **Syntax:** ```bash theme={null} hopx sandbox resume SANDBOX_ID [OPTIONS] ``` **Examples:** ```bash theme={null} # Resume sandbox hopx sandbox resume sb_abc123 ``` **Expected Output:** ``` ✓ Sandbox resumed: sb_abc123 ``` **Exit Codes:** * `0` - Success * `3` - Authentication error * `4` - Sandbox not found ### `kill` Kill a sandbox (permanently delete). **Syntax:** ```bash theme={null} hopx sandbox kill SANDBOX_ID [OPTIONS] ``` **Options:** * `--force` - Skip confirmation prompt **Examples:** ```bash theme={null} # Kill sandbox (with confirmation) hopx sandbox kill sb_abc123 # Kill without confirmation hopx sandbox kill sb_abc123 --force ``` **Expected Output:** ``` ✓ Sandbox killed: sb_abc123 ``` **Exit Codes:** * `0` - Success * `3` - Authentication error * `4` - Sandbox not found ### `url` Get preview URL for a service running on a port. **Syntax:** ```bash theme={null} hopx sandbox url SANDBOX_ID --port PORT [OPTIONS] ``` **Options:** * `--port INTEGER` - Port number (required) **Examples:** ```bash theme={null} # Get preview URL for port 8080 hopx sandbox url sb_abc123 --port 8080 ``` **Expected Output:** ``` https://8080-sb_abc123.us-east.vms.hopx.dev/ ``` **Exit Codes:** * `0` - Success * `3` - Authentication error * `4` - Sandbox not found ## Shell Scripting Examples ### Create and Use Sandbox ```bash theme={null} #!/bin/bash set -e # Create sandbox SANDBOX_ID=$(hopx sandbox create --template python --output json | jq -r '.id') echo "Created sandbox: $SANDBOX_ID" # Use sandbox hopx run "print('Hello')" --sandbox "$SANDBOX_ID" # Cleanup trap "hopx sandbox kill $SANDBOX_ID --force" EXIT ``` ### List and Process Sandboxes ```bash theme={null} #!/bin/bash # List running sandboxes hopx sandbox list --status running --output json | jq -r '.[].id' | while read id; do echo "Processing sandbox: $id" hopx sandbox info "$id" done ``` ### Conditional Sandbox Management ```bash theme={null} #!/bin/bash # Create sandbox with error handling if SANDBOX_ID=$(hopx sandbox create --template python --output json 2>/dev/null | jq -r '.id'); then echo "Sandbox created: $SANDBOX_ID" else case $? in 3) echo "Authentication failed" ;; 4) echo "Template not found" ;; 7) echo "Rate limit exceeded" ;; *) echo "Error creating sandbox" ;; esac exit 1 fi ``` ## Related * **[CLI Quickstart](/cli/quickstart)** - Get started with CLI * **[Code Execution](/cli/commands/run)** - Execute code in sandboxes * **[File Operations](/cli/commands/files)** - Manage files in sandboxes * **[Python SDK: Sandbox](/sdk/python/sandbox)** - Python SDK sandbox methods * **[JavaScript SDK: Sandbox](/sdk/javascript/sandbox)** - JavaScript SDK sandbox methods * **[API: Create Sandbox](/api/control-plane/create-sandbox)** - REST API endpoint ## Next Steps * Learn about [Code Execution](/cli/commands/run) to execute code in sandboxes * Explore [File Operations](/cli/commands/files) to manage files * Review [Templates](/cli/commands/template) to list and build custom templates # System Source: https://docs.hopx.ai/cli/commands/system Complete reference for HopX CLI system commands - health checks, metrics, agent info, processes, Jupyter access, and system snapshots. Monitor and inspect sandbox system resources. Monitor and inspect HopX sandbox system resources using the `system` command. Check health, view metrics, get agent information, list processes, access Jupyter, and capture system snapshots. ## Command Syntax ```bash theme={null} hopx system [options] ``` ## Subcommands ### `health` Check API health status. **Syntax:** ```bash theme={null} hopx system health [OPTIONS] ``` **Examples:** ```bash theme={null} # Check API health hopx system health ``` **Expected Output:** ``` ✓ API is healthy ✓ All services operational ``` **Exit Codes:** * `0` - Healthy * `1` - Unhealthy * `6` - Network error ### `metrics` Get sandbox system metrics. **Syntax:** ```bash theme={null} hopx system metrics SANDBOX_ID [OPTIONS] ``` **Arguments:** * `SANDBOX_ID` - Sandbox ID (required) **Options:** * `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`) **Examples:** ```bash theme={null} # Get sandbox metrics hopx system metrics sb_abc123 # Get metrics with JSON output hopx system metrics sb_abc123 --output json ``` **Expected Output (Table):** ``` ┌─────────────┬─────────────────────────────────────┐ │ Metric │ Value │ ├─────────────┼─────────────────────────────────────┤ │ CPU Usage │ 15.2% │ │ Memory │ 512 MB / 2 GB (25.6%) │ │ Disk Usage │ 1.2 GB / 10 GB (12.0%) │ │ Uptime │ 2h 15m │ └─────────────┴─────────────────────────────────────┘ ``` **Exit Codes:** * `0` - Success * `3` - Authentication error * `4` - Sandbox not found ### `agent-info` Get VM agent information. **Syntax:** ```bash theme={null} hopx system agent-info SANDBOX_ID [OPTIONS] ``` **Arguments:** * `SANDBOX_ID` - Sandbox ID (required) **Options:** * `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`) **Examples:** ```bash theme={null} # Get agent info hopx system agent-info sb_abc123 # Get info with JSON output hopx system agent-info sb_abc123 --output json ``` **Expected Output (Table):** ``` ┌─────────────┬─────────────────────────────────────┐ │ Property │ Value │ ├─────────────┼─────────────────────────────────────┤ │ Version │ 1.2.3 │ │ Status │ running │ │ Features │ code-execution, files, terminal │ └─────────────┴─────────────────────────────────────┘ ``` **Exit Codes:** * `0` - Success * `3` - Authentication error * `4` - Sandbox not found ### `processes` List running processes in a sandbox. **Syntax:** ```bash theme={null} hopx system processes SANDBOX_ID [OPTIONS] ``` **Arguments:** * `SANDBOX_ID` - Sandbox ID (required) **Options:** * `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`) **Examples:** ```bash theme={null} # List processes hopx system processes sb_abc123 # List with JSON output hopx system processes sb_abc123 --output json ``` **Expected Output (Table):** ``` ┌──────┬──────────────┬─────────┬─────────────┐ │ PID │ Command │ User │ CPU % │ ├──────┼──────────────┼─────────┼─────────────┤ │ 1234 │ python │ user │ 5.2 │ │ 1235 │ node │ user │ 2.1 │ └──────┴──────────────┴─────────┴─────────────┘ ``` **Exit Codes:** * `0` - Success * `3` - Authentication error * `4` - Sandbox not found ### `jupyter` Get Jupyter access information. **Syntax:** ```bash theme={null} hopx system jupyter SANDBOX_ID [OPTIONS] ``` **Arguments:** * `SANDBOX_ID` - Sandbox ID (required) **Options:** * `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`) **Examples:** ```bash theme={null} # Get Jupyter info hopx system jupyter sb_abc123 ``` **Expected Output:** ``` Jupyter URL: https://jupyter-sb_abc123.us-east.vms.hopx.dev/ Token: jupyter-token-abc123 ``` **Exit Codes:** * `0` - Success * `3` - Authentication error * `4` - Sandbox not found ### `snapshot` Capture system snapshot. **Syntax:** ```bash theme={null} hopx system snapshot SANDBOX_ID [OPTIONS] ``` **Arguments:** * `SANDBOX_ID` - Sandbox ID (required) **Options:** * `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`) **Examples:** ```bash theme={null} # Capture system snapshot hopx system snapshot sb_abc123 ``` **Expected Output:** ``` ✓ System snapshot captured ✓ Snapshot ID: snap_abc123 ``` **Exit Codes:** * `0` - Success * `3` - Authentication error * `4` - Sandbox not found ## Shell Scripting Examples ### Monitor Sandbox Health ```bash theme={null} #!/bin/bash # Check API health if ! hopx system health > /dev/null 2>&1; then echo "API is unhealthy" exit 1 fi # Monitor sandbox metrics hopx system metrics sb_abc123 --output json | jq '.cpu_percent' ``` ### Check Resource Usage ```bash theme={null} #!/bin/bash # Get metrics and check memory usage MEMORY=$(hopx system metrics sb_abc123 --output json | jq -r '.memory_percent') if (( $(echo "$MEMORY > 80" | bc -l) )); then echo "Warning: High memory usage: ${MEMORY}%" fi ``` ## Related * **[CLI Quickstart](/cli/quickstart)** - Get started with CLI * **[Sandbox Commands](/cli/commands/sandbox)** - Create and manage sandboxes * **[Python SDK: Observability](/sdk/python/observability)** - Python SDK system monitoring * **[JavaScript SDK: Observability](/sdk/javascript/observability)** - JavaScript SDK system monitoring * **[API: System Metrics](/api/vm-agent/get-system-metrics)** - REST API endpoints ## Next Steps * Learn about [Sandbox Management](/cli/commands/sandbox) to create sandboxes * Explore [Observability](/core-concepts/observability/metrics) for monitoring concepts * Review [Process Management](/core-concepts/observability/processes) for process monitoring # Template Source: https://docs.hopx.ai/cli/commands/template Complete reference for HopX CLI template commands - list, info, build, and delete templates. Manage pre-built and custom templates for sandbox creation. Manage templates for HopX sandboxes using the `template` command (alias: `tpl`). List available templates, view template details, build custom templates, and delete templates. ## Command Syntax ```bash theme={null} hopx template [options] ``` ## Subcommands ### `list` List all available templates. **Syntax:** ```bash theme={null} hopx template list [OPTIONS] ``` **Options:** * `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`) **Examples:** ```bash theme={null} # List all templates hopx template list # List with JSON output hopx template list --output json ``` **Expected Output (Table):** ``` ┌──────────────┬──────────────────────┬─────────────┐ │ Name │ Description │ Category │ ├──────────────┼──────────────────────┼─────────────┤ │ python │ Python 3.11 │ language │ │ nodejs │ Node.js 20 │ language │ │ code-interpreter │ Data science stack │ development │ └──────────────┴──────────────────────┴─────────────┘ ``` **Exit Codes:** * `0` - Success * `3` - Authentication error ### `info` Get detailed information about a template. **Syntax:** ```bash theme={null} hopx template info TEMPLATE_NAME [OPTIONS] ``` **Arguments:** * `TEMPLATE_NAME` - Template name or ID (required) **Options:** * `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`) **Examples:** ```bash theme={null} # Get template info hopx template info python # Get info with JSON output hopx template info code-interpreter --output json ``` **Expected Output (Table):** ``` ┌─────────────┬─────────────────────────────────────┐ │ Property │ Value │ ├─────────────┼─────────────────────────────────────┤ │ Name │ python │ │ ID │ 123 │ │ Description │ Python 3.11 with pip │ │ Category │ language │ │ Language │ python │ └─────────────┴─────────────────────────────────────┘ ``` **Exit Codes:** * `0` - Success * `3` - Authentication error * `4` - Template not found ### `build` Build a custom template from a Dockerfile. **Syntax:** ```bash theme={null} hopx template build [OPTIONS] ``` **Options:** * `--name TEXT` - Template name (required) * `--dockerfile PATH` - Path to Dockerfile * `--image TEXT` - Base image (e.g., `python:3.11`, `node:20`) * `--context PATH` - Build context directory * `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`) **Examples:** ```bash theme={null} # Build template from Dockerfile hopx template build --name my-app --dockerfile ./Dockerfile # Build with context directory hopx template build --name my-app --dockerfile ./Dockerfile --context ./build-context ``` **Expected Output:** ``` Building template: my-app ✓ Template built successfully ✓ Template ID: tpl_abc123 ``` **Exit Codes:** * `0` - Success * `1` - Build failed * `3` - Authentication error ### `delete` Delete a custom template. **Syntax:** ```bash theme={null} hopx template delete TEMPLATE_ID [OPTIONS] ``` **Arguments:** * `TEMPLATE_ID` - Template ID to delete (required) **Options:** * `--force` - Skip confirmation prompt **Examples:** ```bash theme={null} # Delete template hopx template delete tpl_abc123 # Delete without confirmation hopx template delete tpl_abc123 --force ``` **Expected Output:** ``` ✓ Template deleted: tpl_abc123 ``` **Exit Codes:** * `0` - Success * `3` - Authentication error * `4` - Template not found ## Shell Scripting Examples ### List and Filter Templates ```bash theme={null} #!/bin/bash # List templates and filter by category hopx template list --output json | jq '.[] | select(.category == "language")' ``` ### Build and Use Custom Template ```bash theme={null} #!/bin/bash set -e # Build custom template TEMPLATE_ID=$(hopx template build --name my-app --dockerfile ./Dockerfile --output json | jq -r '.id') # Create sandbox from custom template SANDBOX_ID=$(hopx sandbox create --template-id "$TEMPLATE_ID" --output json | jq -r '.id') echo "Created sandbox $SANDBOX_ID from template $TEMPLATE_ID" ``` ## Related * **[CLI Quickstart](/cli/quickstart)** - Get started with CLI * **[Sandbox Commands](/cli/commands/sandbox)** - Create sandboxes from templates * **[Python SDK: Template Builder](/sdk/python/template-builder)** - Python SDK template building * **[JavaScript SDK: Template Builder](/sdk/javascript/template-builder)** - JavaScript SDK template building * **[API: Templates](/api/control-plane/list-templates)** - REST API endpoints ## Next Steps * Learn about [Sandbox Management](/cli/commands/sandbox) to create sandboxes from templates * Explore [Template Building](/sdk/python/template-builder) for advanced template creation * Review [Pre-built Templates](/supported-languages) for available templates # Terminal Source: https://docs.hopx.ai/cli/commands/terminal Complete reference for HopX CLI terminal commands - connect to interactive terminal sessions, get terminal info, and get WebSocket URLs for terminal access. Connect to interactive terminal sessions in HopX sandboxes using the `terminal` command (alias: `term`). Access WebSocket-based terminal sessions for interactive shell access. ## Command Syntax ```bash theme={null} hopx terminal [options] ``` ## Subcommands ### `connect` Connect to an interactive terminal session. **Syntax:** ```bash theme={null} hopx terminal connect SANDBOX_ID [OPTIONS] ``` **Arguments:** * `SANDBOX_ID` - Sandbox ID (required) **Options:** * `--command TEXT` - Command to execute (default: interactive shell) * `--timeout INTEGER` - Connection timeout in seconds **Examples:** ```bash theme={null} # Connect to interactive terminal hopx terminal connect sb_abc123 # Execute command and exit hopx terminal connect sb_abc123 --command "ls -la" # Connect with timeout hopx terminal connect sb_abc123 --timeout 60 ``` **Expected Output:** ``` Connected to terminal session $ ``` **Exit Codes:** * `0` - Success * `3` - Authentication error * `4` - Sandbox not found * `5` - Connection timeout ### `info` Get terminal information for a sandbox. **Syntax:** ```bash theme={null} hopx terminal info SANDBOX_ID [OPTIONS] ``` **Arguments:** * `SANDBOX_ID` - Sandbox ID (required) **Options:** * `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`) **Examples:** ```bash theme={null} # Get terminal info hopx terminal info sb_abc123 # Get info with JSON output hopx terminal info sb_abc123 --output json ``` **Expected Output (Table):** ``` ┌─────────────┬─────────────────────────────────────┐ │ Property │ Value │ ├─────────────┼─────────────────────────────────────┤ │ Status │ active │ │ WebSocket │ wss://... │ │ Terminal │ /bin/bash │ └─────────────┴─────────────────────────────────────┘ ``` **Exit Codes:** * `0` - Success * `3` - Authentication error * `4` - Sandbox not found ### `url` Get WebSocket URL for terminal access. **Syntax:** ```bash theme={null} hopx terminal url SANDBOX_ID [OPTIONS] ``` **Arguments:** * `SANDBOX_ID` - Sandbox ID (required) **Examples:** ```bash theme={null} # Get terminal WebSocket URL hopx terminal url sb_abc123 ``` **Expected Output:** ``` wss://terminal-sb_abc123.us-east.vms.hopx.dev/ ``` **Exit Codes:** * `0` - Success * `3` - Authentication error * `4` - Sandbox not found ## Interactive Terminal Usage When connected to an interactive terminal: * Type commands as you would in a normal terminal * Press `Ctrl+C` to interrupt running commands * Press `Ctrl+D` or type `exit` to disconnect * Use arrow keys for command history * Tab completion is available ## Shell Scripting Examples ### Connect and Execute Commands ```bash theme={null} #!/bin/bash # Connect and run commands echo "ls -la" | hopx terminal connect sb_abc123 --command "bash" ``` ### Get Terminal URL for External Tools ```bash theme={null} #!/bin/bash # Get terminal URL for use with external WebSocket clients TERMINAL_URL=$(hopx terminal url sb_abc123) echo "Terminal URL: $TERMINAL_URL" ``` ## Related * **[CLI Quickstart](/cli/quickstart)** - Get started with CLI * **[Sandbox Commands](/cli/commands/sandbox)** - Create and manage sandboxes * **[Shell Commands](/cli/commands/cmd)** - Run non-interactive shell commands * **[Python SDK: Terminal](/sdk/python/terminal)** - Python SDK terminal access * **[JavaScript SDK: Terminal](/sdk/javascript/terminal)** - JavaScript SDK terminal access * **[API: Terminal](/api/vm-agent/terminal)** - REST API endpoints ## Next Steps * Learn about [Sandbox Management](/cli/commands/sandbox) to create sandboxes * Explore [Shell Commands](/cli/commands/cmd) for non-interactive command execution * Review [Code Execution](/cli/commands/run) to run code in sandboxes # Usage Source: https://docs.hopx.ai/cli/commands/usage Complete reference for HopX CLI usage commands - view usage summary, plans, history, and sandbox usage statistics. Monitor usage statistics using the `usage` command. View usage summary, available plans, usage history, and sandbox usage. ## Command Syntax ```bash theme={null} hopx usage [options] ``` ## Subcommands ### `summary` View usage summary. **Syntax:** ```bash theme={null} hopx usage summary [OPTIONS] ``` **Examples:** ```bash theme={null} # View usage summary hopx usage summary ``` **Expected Output:** ``` ┌─────────────┬─────────────────────────────────────┐ │ Metric │ Value │ ├─────────────┼─────────────────────────────────────┤ │ Sandboxes │ 15 / 100 (15%) │ │ Compute │ 50h / 200h (25%) │ │ Storage │ 5 GB / 50 GB (10%) │ │ Period │ January 2025 │ └─────────────┴─────────────────────────────────────┘ ``` **Exit Codes:** * `0` - Success * `3` - Authentication error ### `plans` View available plans. **Syntax:** ```bash theme={null} hopx usage plans [OPTIONS] ``` **Examples:** ```bash theme={null} # View plans hopx usage plans ``` **Expected Output:** ``` ┌──────────────┬──────────────┬─────────────┐ │ Plan │ Price │ Features │ ├──────────────┼──────────────┼─────────────┤ │ Free │ $0 │ 10 sandboxes│ │ Pro │ $29/mo │ 100 sandboxes│ │ Enterprise │ Custom │ Unlimited │ └──────────────┴──────────────┴─────────────┘ ``` **Exit Codes:** * `0` - Success * `3` - Authentication error ### `history` View usage history. **Syntax:** ```bash theme={null} hopx usage history [OPTIONS] ``` **Options:** * `--limit INTEGER` - Number of records to show * `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`) **Examples:** ```bash theme={null} # View usage history hopx usage history # View with limit hopx usage history --limit 20 ``` **Expected Output:** ``` ┌──────────────┬──────────────┬─────────────┐ │ Date │ Sandboxes │ Compute │ ├──────────────┼──────────────┼─────────────┤ │ 2025-01-27 │ 15 │ 2.5h │ │ 2025-01-26 │ 12 │ 2.0h │ └──────────────┴──────────────┴─────────────┘ ``` **Exit Codes:** * `0` - Success * `3` - Authentication error ### `sandboxes` View sandbox usage statistics. **Syntax:** ```bash theme={null} hopx usage sandboxes [OPTIONS] ``` **Options:** * `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`) **Examples:** ```bash theme={null} # View sandbox usage hopx usage sandboxes ``` **Expected Output:** ``` ┌──────────────┬──────────────┬─────────────┐ │ Sandbox ID │ Runtime │ Resources │ ├──────────────┼──────────────┼─────────────┤ │ sb_abc123 │ 2h 15m │ 2 CPU, 4GB │ │ sb_def456 │ 1h 30m │ 1 CPU, 2GB │ └──────────────┴──────────────┴─────────────┘ ``` **Exit Codes:** * `0` - Success * `3` - Authentication error ## Related * **[CLI Quickstart](/cli/quickstart)** - Get started with CLI * **[Billing](/cli/commands/billing)** - Manage billing * **[Organization Commands](/cli/commands/org)** - Manage organizations ## Next Steps * Learn about [Billing](/cli/commands/billing) to manage payments * Explore [Organization Management](/cli/commands/org) to manage organization settings * Review [Dashboard](https://console.hopx.dev) for detailed usage analytics # Installation Source: https://docs.hopx.ai/cli/installation Install the HopX CLI on Linux, macOS, or Windows. Multiple installation methods including quick install script, uv, pipx, and pip. Includes verification steps and troubleshooting. Install the HopX CLI to manage cloud sandboxes from your terminal. The CLI supports multiple installation methods and works on Linux, macOS, and Windows (including WSL). ## Prerequisites * **Python 3.12+** - Required for CLI operation * **Terminal access** - Command-line interface * **Internet connection** - For installation and API access ## Quick Install (Recommended) The quick install script handles everything automatically, including PEP 668 environments on macOS/modern Linux: ```bash theme={null} curl -fsSL https://raw.githubusercontent.com/hopx-ai/hopx/main/cli/scripts/install.sh | bash ``` This script: * Detects your platform (Linux, macOS, Windows/WSL) * Installs the CLI using the best method for your system * Adds the CLI to your PATH * Verifies the installation **Expected Output:** ``` ✓ HopX CLI installed successfully ✓ Version: 0.1.2 ✓ Run 'hopx init' to get started ``` ## Alternative Installation Methods ### uv (Fastest) [uv](https://github.com/astral-sh/uv) is a fast Python package installer: ```bash theme={null} # Install uv curl -LsSf https://astral.sh/uv/install.sh | sh # Install HopX CLI uv tool install hopx-cli # Verify installation hopx --version ``` ### pipx (Isolated) [pipx](https://github.com/pypa/pipx) installs Python applications in isolated environments: ```bash theme={null} # Install pipx (if not installed) python3 -m pip install --user pipx python3 -m pipx ensurepath # Install HopX CLI pipx install hopx-cli # Verify installation hopx --version ``` ### pip (User Install) Install directly with pip: ```bash theme={null} # Install for current user pip install --user hopx-cli # Add to PATH (if needed) export PATH="$PATH:$(python3 -m site --user-base)/bin" # Verify installation hopx --version ``` On macOS and modern Linux systems with PEP 668, you may need to use `--user` flag or a virtual environment. The quick install script handles this automatically. ## Verify Installation After installation, verify the CLI is working: ```bash theme={null} # Check version hopx --version # Expected output: # hopx-cli 0.1.2 # Check help hopx --help # Check system health hopx system health ``` ## Update CLI Update to the latest version: ```bash theme={null} hopx self-update ``` Or reinstall using your original installation method: ```bash theme={null} # With uv uv tool install hopx-cli --force # With pipx pipx upgrade hopx-cli # With pip pip install --user --upgrade hopx-cli ``` ## Post-Installation Setup After installation, complete first-time setup: ```bash theme={null} # Interactive setup wizard hopx init ``` The setup wizard will: 1. Guide you through authentication 2. Help you create an API key 3. Configure default settings 4. Test your connection Or set up manually: ```bash theme={null} # Authenticate hopx auth login # Create API key hopx auth keys create --name "my-key" # Verify authentication hopx auth status ``` ## Troubleshooting ### Command Not Found If `hopx` command is not found: **Linux/macOS:** ```bash theme={null} # Check if installed pip show hopx-cli # Add to PATH export PATH="$PATH:$(python3 -m site --user-base)/bin" # Add to shell profile (permanent) echo 'export PATH="$PATH:$(python3 -m site --user-base)/bin"' >> ~/.bashrc source ~/.bashrc ``` **Windows:** ```powershell theme={null} # Check if installed pip show hopx-cli # Add to PATH (replace USERNAME) $env:Path += ";C:\Users\USERNAME\AppData\Roaming\Python\Python312\Scripts" ``` ### Python Version Issues The CLI requires Python 3.12+: ```bash theme={null} # Check Python version python3 --version # Should show: Python 3.12.x or higher # If using older Python, upgrade or use pyenv pyenv install 3.12.0 pyenv global 3.12.0 ``` ### Permission Errors If you encounter permission errors: ```bash theme={null} # Use --user flag pip install --user hopx-cli # Or use virtual environment python3 -m venv venv source venv/bin/activate pip install hopx-cli ``` ### PEP 668 Errors (macOS/Linux) On systems with PEP 668 (external package managers), use `--user` or `pipx`: ```bash theme={null} # Use pipx (recommended) pipx install hopx-cli # Or use --user pip install --user hopx-cli ``` ### Installation Verification Test the installation: ```bash theme={null} # Check version hopx --version # Check help hopx --help # Test system health (requires authentication) hopx system health ``` ## Platform-Specific Notes ### Linux Works on all major Linux distributions. The quick install script detects your distribution and uses the appropriate method. ### macOS Works on macOS 10.15+. The quick install script handles Homebrew and system Python correctly. ### Windows Works on Windows 10+ and Windows Subsystem for Linux (WSL). For native Windows, use WSL or ensure Python 3.12+ is installed. ## Related * **[CLI Overview](/cli/introduction)** - Learn about the CLI * **[CLI Quickstart](/cli/quickstart)** - Get started with your first command * **[API Key Setup](/api-key)** - Get your API key for authentication ## Next Steps * Complete [CLI Quickstart](/cli/quickstart) to run your first command * Learn about [Authentication](/cli/commands/auth) for CLI access * Explore [Command Reference](/cli/commands/sandbox) for all available commands # Overview Source: https://docs.hopx.ai/cli/introduction Official HopX CLI for managing cloud sandboxes from the command line. Install the CLI, authenticate with your API key, and start creating sandboxes, executing code, managing files, and automating workflows. Complete command-line interface reference with examples for all 15 command groups. The HopX CLI provides terminal access to HopX cloud sandboxes - secure, isolated VMs that start in seconds. Execute code, manage files, run commands, and build custom templates from your terminal. ## What is the HopX CLI? The HopX CLI is the official command-line interface for HopX.ai cloud sandboxes. It provides terminal-based access to all HopX features including sandbox management, code execution, file operations, and template building. **Version**: 0.1.2\ **Python Support**: 3.12+\ **Framework**: Typer (built on Click) ## Use Cases * **AI agent code execution** - Execute AI-generated code safely in isolated environments * **Running untrusted code** - Test code without risking your local machine * **Integration testing** - Run tests in clean, reproducible environments * **Data processing pipelines** - Process data in isolated sandboxes * **Browser automation** - Automate browser interactions with desktop features * **Educational environments** - Create learning environments for students ## When to Use CLI vs SDK vs API ### Use CLI When: * You prefer command-line workflows * You're writing shell scripts or automation * You need quick one-off operations * You're integrating with CI/CD pipelines * You want interactive terminal sessions ### Use SDK When: * You're building applications in Python or JavaScript * You need programmatic control in your code * You want type safety and IDE support * You're building libraries or frameworks ### Use API When: * You're building in languages without SDK support * You need direct HTTP control * You're building custom integrations * You need fine-grained request/response handling ## Command Groups The CLI provides 15 command groups for complete sandbox management: | Command | Alias | Description | | ---------- | ------ | ------------------------------ | | `init` | - | First-run setup wizard | | `auth` | - | Authentication management | | `sandbox` | `sb` | Sandbox lifecycle management | | `run` | - | Code execution | | `files` | `f` | File operations | | `cmd` | - | Shell commands | | `env` | - | Environment variables | | `terminal` | `term` | Interactive terminal sessions | | `template` | `tpl` | Template management | | `config` | - | Configuration management | | `system` | - | Health checks and metrics | | `org` | - | Organization settings | | `profile` | - | User profile management | | `members` | - | Organization member management | | `billing` | - | Billing information | | `usage` | - | Usage statistics | ## Quick Example ```bash theme={null} # Install CLI curl -fsSL https://raw.githubusercontent.com/hopx-ai/hopx/main/cli/scripts/install.sh | bash # Authenticate hopx auth login # Create sandbox hopx sandbox create --template python # Execute code hopx run "print('Hello, World!')" ``` ## Features ### Authentication * Browser-based OAuth login (Google, GitHub) * API key management (create, list, revoke) * Secure credential storage via system keyring * Multi-profile support for different environments ### Output Formats * **Table** (default) - Human-readable tables with borders * **JSON** - Machine-readable JSON for scripting * **Plain** - Minimal text output for piping ### Configuration * YAML configuration file (`~/.hopx/config.yaml`) * Environment variable support (`HOPX_*` prefix) * Multiple profiles for dev/prod environments * Config precedence: CLI flags > environment > config file > defaults ### Exit Codes The CLI uses standardized exit codes for scripting automation: | Code | Meaning | | ---- | -------------------- | | 0 | Success | | 1 | General error | | 2 | Validation error | | 3 | Authentication error | | 4 | Not found | | 5 | Timeout | | 6 | Network error | | 7 | Rate limit | | 130 | Interrupted (Ctrl+C) | ## Global Options All commands support these global options: ``` --api-key TEXT API key (overrides HOPX_API_KEY) --profile TEXT Configuration profile (default: "default") --output, -o FORMAT Output format: table, json, plain -q, --quiet Suppress non-essential output -v, --verbose Increase output verbosity --no-color Disable colored output --version Show version and exit --help Show help message ``` ## Related * **[CLI Installation](/cli/installation)** - Install the CLI * **[CLI Quickstart](/cli/quickstart)** - Get started in 5 minutes * **[Python SDK Overview](/sdk/python/introduction)** - Python SDK reference * **[JavaScript SDK Overview](/sdk/javascript/introduction)** - JavaScript SDK reference * **[API Overview](/api/introduction)** - REST API reference ## Next Steps * Follow the [Installation Guide](/cli/installation) to install the CLI * Complete the [Quickstart Guide](/cli/quickstart) to run your first command * Explore [Command Reference](/cli/commands/sandbox) for detailed command documentation # Quickstart Source: https://docs.hopx.ai/cli/quickstart Get started with the HopX CLI in 5 minutes. Learn how to install, authenticate, create your first sandbox, execute code, and manage files from the command line. Get up and running with the HopX CLI in 5 minutes. This guide walks you through installation, authentication, creating your first sandbox, executing code, and managing files. ## What You'll Learn In this quickstart, you'll learn how to: * Install the HopX CLI * Authenticate with your API key * Create your first sandbox * Execute code in multiple languages * Manage files in sandboxes * Clean up sandboxes ## Prerequisites * [HopX API key](https://console.hopx.dev) (get one [here](/api-key) if you don't have it) * Python 3.12+ installed * Terminal access ## Step 1: Install the CLI Install the CLI using the quick install script: ```bash theme={null} curl -fsSL https://raw.githubusercontent.com/hopx-ai/hopx/main/cli/scripts/install.sh | bash ``` **Expected Output:** ``` ✓ HopX CLI installed successfully ✓ Version: 0.1.2 ✓ Run 'hopx init' to get started ``` Verify installation: ```bash theme={null} hopx --version ``` **Expected Output:** ``` hopx-cli 0.1.2 ``` ## Step 2: Authenticate ### Option 1: Interactive Setup (Recommended) Run the interactive setup wizard: ```bash theme={null} hopx init ``` The wizard will: 1. Guide you through browser-based OAuth login 2. Help you create an API key 3. Configure default settings 4. Test your connection ### Option 2: Manual Authentication Authenticate manually: ```bash theme={null} # Browser login hopx auth login # Create API key hopx auth keys create --name "my-key" # Verify authentication hopx auth status ``` **Expected Output:** ``` ✓ Authenticated ✓ API key: hopx_live_... (configured) ``` ### Option 3: Environment Variable Set your API key as an environment variable: ```bash theme={null} export HOPX_API_KEY="hopx_live_..." ``` Get your API key at [console.hopx.dev](https://console.hopx.dev). ## Step 3: Create Your First Sandbox Create a sandbox from a pre-built template: ```bash theme={null} hopx sandbox create --template python ``` **Expected Output:** ``` ✓ Sandbox created: sb_abc123 ✓ Status: running ✓ Template: python ``` List your sandboxes: ```bash theme={null} hopx sandbox list ``` **Expected Output:** ``` ┌──────────────────┬─────────┬────────────┐ │ ID │ Status │ Template │ ├──────────────────┼─────────┼────────────┤ │ sb_abc123 │ running │ python │ └──────────────────┴─────────┴────────────┘ ``` ## Step 4: Execute Code Execute Python code in your sandbox: ```bash theme={null} hopx run "print('Hello, World!')" ``` **Expected Output:** ``` Hello, World! ``` Execute code from a file: ```bash theme={null} # Create a local file echo "print('Hello from file!')" > script.py # Execute from file hopx run -f script.py ``` **Expected Output:** ``` Hello from file! ``` Execute JavaScript: ```bash theme={null} hopx run "console.log('Hello from JavaScript!')" -l javascript ``` **Expected Output:** ``` Hello from JavaScript! ``` Execute Bash: ```bash theme={null} hopx run "echo 'Hello from Bash!'" -l bash ``` **Expected Output:** ``` Hello from Bash! ``` ## Step 5: Manage Files Write a file to your sandbox: ```bash theme={null} hopx files write sb_abc123 /app/data.txt "Hello, World!" ``` **Expected Output:** ``` ✓ File written: /app/data.txt ``` Read the file: ```bash theme={null} hopx files read sb_abc123 /app/data.txt ``` **Expected Output:** ``` Hello, World! ``` List files in a directory: ```bash theme={null} hopx files list sb_abc123 /app/ ``` **Expected Output:** ``` ┌──────────────┬──────┬─────────────────────┐ │ Name │ Size │ Modified │ ├──────────────┼──────┼─────────────────────┤ │ data.txt │ 13 │ 2025-01-27 10:00:00 │ └──────────────┴──────┴─────────────────────┘ ``` Upload a local file: ```bash theme={null} # Create local file echo "Local content" > local.txt # Upload to sandbox hopx files upload sb_abc123 ./local.txt /app/uploaded.txt ``` **Expected Output:** ``` ✓ File uploaded: /app/uploaded.txt ``` Download a file: ```bash theme={null} hopx files download sb_abc123 /app/data.txt ./downloaded.txt ``` **Expected Output:** ``` ✓ File downloaded: ./downloaded.txt ``` ## Step 6: Run Shell Commands Run shell commands in your sandbox: ```bash theme={null} hopx cmd run sb_abc123 "ls -la /app" ``` **Expected Output:** ``` total 16 drwxr-xr-x 2 user user 4096 Jan 27 10:00 . drwxr-xr-x 3 user user 4096 Jan 27 10:00 .. -rw-r--r-- 1 user user 13 Jan 27 10:00 data.txt -rw-r--r-- 1 user user 14 Jan 27 10:00 uploaded.txt ``` Install packages: ```bash theme={null} hopx cmd run sb_abc123 "pip install requests" ``` **Expected Output:** ``` Collecting requests Downloading requests-2.31.0-py3-none-any.whl (62 kB) ... Successfully installed requests-2.31.0 ``` ## Step 7: Manage Environment Variables Set environment variables: ```bash theme={null} hopx env set sb_abc123 API_KEY=secret123 DEBUG=true ``` **Expected Output:** ``` ✓ Environment variables set ``` List environment variables: ```bash theme={null} hopx env list sb_abc123 ``` **Expected Output:** ``` ┌───────────┬─────────────┐ │ Variable │ Value │ ├───────────┼─────────────┤ │ API_KEY │ secret123 │ │ DEBUG │ true │ └───────────┴─────────────┘ ``` Get a specific variable: ```bash theme={null} hopx env get sb_abc123 API_KEY ``` **Expected Output:** ``` secret123 ``` ## Step 8: Clean Up Kill your sandbox when done: ```bash theme={null} hopx sandbox kill sb_abc123 ``` **Expected Output:** ``` ✓ Sandbox killed: sb_abc123 ``` Or pause it to preserve state: ```bash theme={null} hopx sandbox pause sb_abc123 ``` **Expected Output:** ``` ✓ Sandbox paused: sb_abc123 ``` Resume later: ```bash theme={null} hopx sandbox resume sb_abc123 ``` **Expected Output:** ``` ✓ Sandbox resumed: sb_abc123 ``` ## Next Steps Now that you've completed the quickstart, explore more CLI features: * **[Sandbox Management](/cli/commands/sandbox)** - Complete sandbox lifecycle management * **[Code Execution](/cli/commands/run)** - Execute code in multiple languages * **[File Operations](/cli/commands/files)** - Advanced file management * **[Shell Commands](/cli/commands/cmd)** - Run system commands * **[Environment Variables](/cli/commands/env)** - Manage environment configuration * **[Templates](/cli/commands/template)** - List and build custom templates * **[Configuration](/cli/commands/config)** - Configure CLI settings and profiles ## Related * **[CLI Overview](/cli/introduction)** - Learn about CLI features * **[CLI Installation](/cli/installation)** - Detailed installation guide * **[Python SDK Quickstart](/sdk/python/quickstart)** - Get started with Python SDK * **[JavaScript SDK Quickstart](/sdk/javascript/quickstart)** - Get started with JavaScript SDK # Building an AI Code Interpreter Agent Source: https://docs.hopx.ai/cookbooks/ai-integration/code-interpreter-agent Create a secure AI code interpreter that safely executes AI-generated code with error handling, rich outputs, and security best practices Build a production-ready AI code interpreter that safely executes AI-generated code in isolated sandboxes. This cookbook shows you how to create an agent that can execute code, capture rich outputs like plots and dataframes, handle errors gracefully, and maintain security. ## Overview An AI code interpreter agent allows AI models to generate and execute code safely. This pattern is used by platforms like OpenAI's Code Interpreter and other AI agent systems. HopX provides the secure execution environment needed for this use case. ## Prerequisites * HopX API key ([Get one here](https://console.hopx.dev/api-keys)) * Python 3.8+ or Node.js 16+ * Basic understanding of async programming * Familiarity with AI/LLM integration patterns ## Architecture The AI code interpreter follows this architecture: ``` ┌─────────────┐ │ AI Model │ Generates code └──────┬──────┘ │ ▼ ┌─────────────────┐ │ Interpreter │ Validates & executes │ Agent │ └──────┬──────────┘ │ ▼ ┌─────────────────┐ │ HopX Sandbox │ Secure execution └──────┬──────────┘ │ ▼ ┌─────────────────┐ │ Rich Outputs │ Plots, DataFrames, etc. └─────────────────┘ ``` ## Implementation ### Step 1: Basic Code Execution Start with a simple code execution function that safely runs AI-generated code: ```python Python theme={null} from hopx_ai import Sandbox from hopx_ai.errors import HopxError, CodeExecutionError import os class AICodeInterpreter: def __init__(self, api_key: str): self.api_key = api_key self.sandbox = None def execute_code(self, code: str, language: str = "python", timeout: int = 30): """Execute AI-generated code safely""" try: # Create sandbox if needed if not self.sandbox: self.sandbox = Sandbox.create( template="code-interpreter", api_key=self.api_key, timeout_seconds=600 ) # Execute code with timeout result = self.sandbox.run_code( code, language=language, timeout=timeout ) return { "success": result.success, "stdout": result.stdout, "stderr": result.stderr, "exit_code": result.exit_code, "execution_time": result.execution_time } except CodeExecutionError as e: return { "success": False, "error": f"Execution failed: {e.message}", "stderr": str(e) } except Exception as e: return { "success": False, "error": f"Unexpected error: {str(e)}" } def cleanup(self): """Clean up sandbox resources""" if self.sandbox: self.sandbox.kill() self.sandbox = None # Usage interpreter = AICodeInterpreter(api_key=os.getenv("HOPX_API_KEY")) result = interpreter.execute_code("print('Hello from AI!')") print(result) interpreter.cleanup() ``` ```javascript JavaScript theme={null} import { Sandbox } from '@hopx-ai/sdk'; class AICodeInterpreter { constructor(apiKey) { this.apiKey = apiKey; this.sandbox = null; } async executeCode(code, language = 'python', timeout = 30) { try { // Create sandbox if needed if (!this.sandbox) { this.sandbox = await Sandbox.create({ template: 'code-interpreter', apiKey: this.apiKey, timeoutSeconds: 600 }); } // Execute code with timeout const result = await this.sandbox.runCode(code, { language, timeout }); return { success: result.success, stdout: result.stdout, stderr: result.stderr, exitCode: result.exit_code, executionTime: result.execution_time }; } catch (error) { return { success: false, error: `Execution failed: ${error.message}`, stderr: error.toString() }; } } async cleanup() { if (this.sandbox) { await this.sandbox.kill(); this.sandbox = null; } } } // Usage const interpreter = new AICodeInterpreter(process.env.HOPX_API_KEY); const result = await interpreter.executeCode("print('Hello from AI!')"); console.log(result); await interpreter.cleanup(); ``` ### Step 2: Rich Output Capture Capture plots, dataframes, and other rich outputs that AI models generate: ```python Python theme={null} def execute_with_rich_outputs(self, code: str, language: str = "python"): """Execute code and capture rich outputs (plots, dataframes)""" try: if not self.sandbox: self.sandbox = Sandbox.create( template="code-interpreter", api_key=self.api_key ) # Execute with rich output capture result = self.sandbox.run_code(code, language=language) rich_outputs = [] if result.rich_outputs: for output in result.rich_outputs: rich_outputs.append({ "type": output.type, "data": output.data }) return { "success": result.success, "stdout": result.stdout, "stderr": result.stderr, "rich_outputs": rich_outputs, "rich_count": len(rich_outputs) if result.rich_outputs else 0 } except Exception as e: return { "success": False, "error": str(e) } # Example: Generate plot code = """ import matplotlib.pyplot as plt import numpy as np x = np.linspace(0, 10, 100) y = np.sin(x) plt.plot(x, y) plt.title('Sine Wave') plt.savefig('/tmp/plot.png') plt.show() """ result = interpreter.execute_with_rich_outputs(code) print(f"Captured {result['rich_count']} rich outputs") ``` ```javascript JavaScript theme={null} async executeWithRichOutputs(code, language = 'python') { try { if (!this.sandbox) { this.sandbox = await Sandbox.create({ template: 'code-interpreter', apiKey: this.apiKey }); } // Execute with rich output capture const result = await this.sandbox.runCode(code, { language, rich: true // Enable rich output capture }); const richOutputs = []; if (result.richOutputs) { for (const output of result.richOutputs) { richOutputs.push({ type: output.type, data: output.data }); } } return { success: result.success, stdout: result.stdout, stderr: result.stderr, richOutputs, richCount: richOutputs.length }; } catch (error) { return { success: false, error: error.message }; } } // Example: Generate plot const code = ` import matplotlib.pyplot as plt import numpy as np x = np.linspace(0, 10, 100); y = np.sin(x); plt.plot(x, y); plt.title('Sine Wave'); plt.savefig('/tmp/plot.png'); plt.show(); `; const result = await interpreter.executeWithRichOutputs(code); console.log(`Captured ${result.richCount} rich outputs`); ``` ### Step 3: Multi-Turn Conversation Handle multi-turn conversations where the AI builds on previous execution results: ```python Python theme={null} class MultiTurnInterpreter: def __init__(self, api_key: str): self.api_key = api_key self.sandbox = None self.conversation_history = [] def execute_turn(self, code: str, context: dict = None): """Execute code in conversation context""" try: if not self.sandbox: self.sandbox = Sandbox.create( template="code-interpreter", api_key=self.api_key ) # Add context from previous turns if context: # Set environment variables from context env_vars = context.get('env_vars', {}) if env_vars: self.sandbox.env.set_all(env_vars) # Upload files from context files = context.get('files', {}) for path, content in files.items(): self.sandbox.files.write(path, content) # Execute code result = self.sandbox.run_code(code) # Capture outputs for next turn outputs = { "stdout": result.stdout, "stderr": result.stderr, "files": {} } # List generated files if result.success: files_list = self.sandbox.files.list("/workspace") for file in files_list: if not file.is_dir: outputs["files"][file.path] = self.sandbox.files.read(file.path) # Store in history self.conversation_history.append({ "code": code, "result": outputs, "success": result.success }) return { "success": result.success, "outputs": outputs, "history_length": len(self.conversation_history) } except Exception as e: return { "success": False, "error": str(e) } def get_context_for_next_turn(self): """Get context to pass to next turn""" if not self.conversation_history: return {} last_result = self.conversation_history[-1]["result"] return { "stdout": last_result["stdout"], "files": last_result["files"], "env_vars": self.sandbox.env.get_all() if self.sandbox else {} } # Usage: Multi-turn conversation interpreter = MultiTurnInterpreter(api_key=os.getenv("HOPX_API_KEY")) # Turn 1: Create data result1 = interpreter.execute_turn(""" import pandas as pd df = pd.DataFrame({'x': [1, 2, 3], 'y': [4, 5, 6]}) df.to_csv('/workspace/data.csv', index=False) print("Data created") """) # Turn 2: Use previous data context = interpreter.get_context_for_next_turn() result2 = interpreter.execute_turn(""" import pandas as pd df = pd.read_csv('/workspace/data.csv') print(f"Data shape: {df.shape}") print(df.describe()) """, context) interpreter.sandbox.kill() ``` ```javascript JavaScript theme={null} class MultiTurnInterpreter { constructor(apiKey) { this.apiKey = apiKey; this.sandbox = null; this.conversationHistory = []; } async executeTurn(code, context = null) { try { if (!this.sandbox) { this.sandbox = await Sandbox.create({ template: 'code-interpreter', apiKey: this.apiKey }); } // Add context from previous turns if (context) { // Set environment variables from context const envVars = context.envVars || {}; if (Object.keys(envVars).length > 0) { await this.sandbox.env.setAll(envVars); } // Upload files from context const files = context.files || {}; for (const [path, content] of Object.entries(files)) { await this.sandbox.files.write(path, content); } } // Execute code const result = await this.sandbox.runCode(code); // Capture outputs for next turn const outputs = { stdout: result.stdout, stderr: result.stderr, files: {} }; // List generated files if (result.success) { const filesList = await this.sandbox.files.list('/workspace'); for (const file of filesList) { if (!file.isDir) { outputs.files[file.path] = await this.sandbox.files.read(file.path); } } } // Store in history this.conversationHistory.push({ code, result: outputs, success: result.success }); return { success: result.success, outputs, historyLength: this.conversationHistory.length }; } catch (error) { return { success: false, error: error.message }; } } getContextForNextTurn() { if (this.conversationHistory.length === 0) { return {}; } const lastResult = this.conversationHistory[this.conversationHistory.length - 1].result; return { stdout: lastResult.stdout, files: lastResult.files, envVars: {} // Would get from sandbox.env.getAll() if available }; } async cleanup() { if (this.sandbox) { await this.sandbox.kill(); this.sandbox = null; } } } // Usage: Multi-turn conversation const interpreter = new MultiTurnInterpreter(process.env.HOPX_API_KEY); // Turn 1: Create data const result1 = await interpreter.executeTurn(` import pandas as pd df = pd.DataFrame({'x': [1, 2, 3], 'y': [4, 5, 6]}) df.to_csv('/workspace/data.csv', index=False) print("Data created") `); // Turn 2: Use previous data const context = interpreter.getContextForNextTurn(); const result2 = await interpreter.executeTurn(` import pandas as pd df = pd.read_csv('/workspace/data.csv') print(f"Data shape: {df.shape}") print(df.describe()) `, context); await interpreter.cleanup(); ``` ### Step 4: Error Handling and Validation Implement robust error handling and code validation: ```python Python theme={null} import re from typing import Dict, Any class SecureAICodeInterpreter: def __init__(self, api_key: str): self.api_key = api_key self.sandbox = None self.max_code_length = 100000 # 100KB limit self.blocked_patterns = [ r'import\s+os\.system', r'import\s+subprocess', r'eval\s*\(', r'exec\s*\(', r'__import__', r'open\s*\([^)]*[\'"]/etc', ] def validate_code(self, code: str) -> Dict[str, Any]: """Validate code before execution""" # Check length if len(code) > self.max_code_length: return { "valid": False, "error": f"Code exceeds maximum length of {self.max_code_length} characters" } # Check for blocked patterns for pattern in self.blocked_patterns: if re.search(pattern, code, re.IGNORECASE): return { "valid": False, "error": f"Code contains blocked pattern: {pattern}" } return {"valid": True} def execute_safely(self, code: str, timeout: int = 30): """Execute code with validation and error handling""" # Validate code validation = self.validate_code(code) if not validation["valid"]: return { "success": False, "error": validation["error"], "validation_failed": True } try: if not self.sandbox: self.sandbox = Sandbox.create( template="code-interpreter", api_key=self.api_key, timeout_seconds=600 ) # Execute with timeout result = self.sandbox.run_code(code, timeout=timeout) # Check for suspicious output if result.stderr and any(keyword in result.stderr.lower() for keyword in ['permission denied', 'access denied', 'unauthorized']): return { "success": False, "error": "Security violation detected in execution", "stderr": result.stderr } return { "success": result.success, "stdout": result.stdout, "stderr": result.stderr, "exit_code": result.exit_code } except Exception as e: return { "success": False, "error": f"Execution error: {str(e)}" } def cleanup(self): if self.sandbox: self.sandbox.kill() self.sandbox = None # Usage interpreter = SecureAICodeInterpreter(api_key=os.getenv("HOPX_API_KEY")) # This will be blocked result = interpreter.execute_safely("import subprocess; subprocess.call(['rm', '-rf', '/'])") print(result) # {"success": False, "error": "Code contains blocked pattern...", "validation_failed": True} # This will execute result = interpreter.execute_safely("print('Hello, safe code!')") print(result) interpreter.cleanup() ``` ```javascript JavaScript theme={null} class SecureAICodeInterpreter { constructor(apiKey) { this.apiKey = apiKey; this.sandbox = null; this.maxCodeLength = 100000; // 100KB limit this.blockedPatterns = [ /import\s+os\.system/i, /import\s+subprocess/i, /eval\s*\(/i, /exec\s*\(/i, /__import__/i, /open\s*\([^)]*['"]\/etc/i ]; } validateCode(code) { // Check length if (code.length > this.maxCodeLength) { return { valid: false, error: `Code exceeds maximum length of ${this.maxCodeLength} characters` }; } // Check for blocked patterns for (const pattern of this.blockedPatterns) { if (pattern.test(code)) { return { valid: false, error: `Code contains blocked pattern: ${pattern}` }; } } return { valid: true }; } async executeSafely(code, timeout = 30) { // Validate code const validation = this.validateCode(code); if (!validation.valid) { return { success: false, error: validation.error, validationFailed: true }; } try { if (!this.sandbox) { this.sandbox = await Sandbox.create({ template: 'code-interpreter', apiKey: this.apiKey, timeoutSeconds: 600 }); } // Execute with timeout const result = await this.sandbox.runCode(code, { timeout }); // Check for suspicious output if (result.stderr && /permission denied|access denied|unauthorized/i.test(result.stderr)) { return { success: false, error: 'Security violation detected in execution', stderr: result.stderr }; } return { success: result.success, stdout: result.stdout, stderr: result.stderr, exitCode: result.exit_code }; } catch (error) { return { success: false, error: `Execution error: ${error.message}` }; } } async cleanup() { if (this.sandbox) { await this.sandbox.kill(); this.sandbox = null; } } } // Usage const interpreter = new SecureAICodeInterpreter(process.env.HOPX_API_KEY); // This will be blocked const result1 = await interpreter.executeSafely("import subprocess; subprocess.call(['rm', '-rf', '/'])"); console.log(result1); // {success: false, error: "Code contains blocked pattern...", validationFailed: true} // This will execute const result2 = await interpreter.executeSafely("print('Hello, safe code!')"); console.log(result2); await interpreter.cleanup(); ``` ## Best Practices ### Security Always validate AI-generated code before execution. Never trust user input or AI output without validation. 1. **Code Validation**: Check for dangerous patterns before execution 2. **Resource Limits**: Set appropriate timeouts and memory limits 3. **Sandbox Isolation**: Each execution should be in a fresh or properly isolated sandbox 4. **Output Sanitization**: Validate outputs before returning to users ### Performance Reuse sandboxes for multi-turn conversations to maintain state, but create fresh sandboxes for unrelated executions to ensure isolation. 1. **Sandbox Reuse**: Reuse sandboxes within a conversation session 2. **Timeout Management**: Set appropriate timeouts based on expected execution time 3. **Parallel Execution**: Use background execution for long-running tasks 4. **Caching**: Cache environment variables and common setup code ### Error Handling 1. **Graceful Degradation**: Always return structured error responses 2. **Error Logging**: Log errors with context for debugging 3. **User-Friendly Messages**: Transform technical errors into user-friendly messages 4. **Retry Logic**: Implement retry for transient failures ## Real-World Examples This pattern is used by: * **OpenAI Code Interpreter**: Executes Python code in isolated environments * **AI Agent Platforms**: Various platforms that execute code generated by AI models * **LangChain Code Execution**: Agent frameworks that execute code ## Related Cookbooks * [Multi-Agent Execution](/cookbooks/ai-integration/multi-agent-execution) - Multi-agent workflows * [Rich Output Capture](/core-concepts/code-execution/rich-output) - Handling plots and dataframes ## Next Steps 1. Implement code validation based on your security requirements 2. Add rich output handling for your specific use case 3. Integrate with your AI model API 4. Set up monitoring and logging 5. Test with various code scenarios # Multi-Agent Code Execution Workflow Source: https://docs.hopx.ai/cookbooks/ai-integration/multi-agent-execution Coordinate multiple AI agents with code execution, parallel execution, result aggregation, and error recovery patterns Build a production-ready multi-agent system where multiple AI agents coordinate to execute code, share results, and recover from errors. This cookbook demonstrates how to orchestrate multiple agents using HopX for secure code execution. ## Overview Multi-agent systems coordinate multiple AI agents to solve complex problems. Each agent can execute code, share results with other agents, and the system aggregates outcomes. This pattern is used in advanced AI systems where agents collaborate on tasks. ## Prerequisites * HopX API key ([Get one here](https://console.hopx.dev/api-keys)) * Python 3.8+ or Node.js 16+ * Understanding of async programming * Basic knowledge of agent orchestration patterns ## Architecture ``` ┌──────────────┐ │ Orchestrator │ Coordinates agents └──────┬───────┘ │ ├──► Agent 1 ──► Sandbox 1 ├──► Agent 2 ──► Sandbox 2 └──► Agent 3 ──► Sandbox 3 │ ▼ ┌──────────────┐ │ Aggregator │ Combine results └──────────────┘ ``` ## Implementation ### Step 1: Basic Multi-Agent System Create a system that coordinates multiple agents: ```python Python theme={null} from hopx_ai import Sandbox import os import asyncio from typing import Dict, List, Any from concurrent.futures import ThreadPoolExecutor class Agent: def __init__(self, agent_id: str, api_key: str): self.agent_id = agent_id self.api_key = api_key self.sandbox = None def initialize(self): """Initialize agent sandbox""" self.sandbox = Sandbox.create( template="code-interpreter", api_key=self.api_key, timeout_seconds=600 ) def execute_task(self, task_code: str, context: Dict = None) -> Dict[str, Any]: """Execute task assigned to this agent""" try: # Set context if provided if context: for key, value in context.items(): self.sandbox.env.set(key, str(value)) # Execute task result = self.sandbox.run_code(task_code, timeout=30) return { "agent_id": self.agent_id, "success": result.success, "stdout": result.stdout, "stderr": result.stderr, "execution_time": result.execution_time } except Exception as e: return { "agent_id": self.agent_id, "success": False, "error": str(e) } def cleanup(self): """Clean up agent resources""" if self.sandbox: self.sandbox.kill() self.sandbox = None class MultiAgentOrchestrator: def __init__(self, api_key: str, num_agents: int = 3): self.api_key = api_key self.agents = [ Agent(f"agent_{i}", api_key) for i in range(num_agents) ] def initialize_agents(self): """Initialize all agents""" for agent in self.agents: agent.initialize() def execute_parallel_tasks(self, tasks: List[Dict]) -> List[Dict[str, Any]]: """Execute tasks in parallel across agents""" results = [] with ThreadPoolExecutor(max_workers=len(self.agents)) as executor: # Assign tasks to agents future_to_agent = {} for i, task in enumerate(tasks): agent = self.agents[i % len(self.agents)] future = executor.submit(agent.execute_task, task["code"], task.get("context")) future_to_agent[future] = (agent, task) # Collect results for future in future_to_agent: agent, task = future_to_agent[future] try: result = future.result() results.append(result) except Exception as e: results.append({ "agent_id": agent.agent_id, "success": False, "error": str(e) }) return results def cleanup_all(self): """Clean up all agents""" for agent in self.agents: agent.cleanup() # Usage orchestrator = MultiAgentOrchestrator(api_key=os.getenv("HOPX_API_KEY"), num_agents=3) orchestrator.initialize_agents() tasks = [ {"code": "result = 2 + 2\nprint(f'Result: {result}')", "context": None}, {"code": "result = 3 * 4\nprint(f'Result: {result}')", "context": None}, {"code": "result = 10 / 2\nprint(f'Result: {result}')", "context": None} ] results = orchestrator.execute_parallel_tasks(tasks) for result in results: print(f"Agent {result['agent_id']}: {result.get('stdout', result.get('error'))}") orchestrator.cleanup_all() ``` ```javascript JavaScript theme={null} import { Sandbox } from '@hopx-ai/sdk'; class Agent { constructor(agentId, apiKey) { this.agentId = agentId; this.apiKey = apiKey; this.sandbox = null; } async initialize() { this.sandbox = await Sandbox.create({ template: 'code-interpreter', apiKey: this.apiKey, timeoutSeconds: 600 }); } async executeTask(taskCode, context = null) { try { // Set context if provided if (context) { for (const [key, value] of Object.entries(context)) { await this.sandbox.env.set(key, String(value)); } } // Execute task const result = await this.sandbox.runCode(taskCode, { timeout: 30 }); return { agentId: this.agentId, success: result.success, stdout: result.stdout, stderr: result.stderr, executionTime: result.execution_time }; } catch (error) { return { agentId: this.agentId, success: false, error: error.message }; } } async cleanup() { if (this.sandbox) { await this.sandbox.kill(); this.sandbox = null; } } } class MultiAgentOrchestrator { constructor(apiKey, numAgents = 3) { this.apiKey = apiKey; this.agents = Array.from({ length: numAgents }, (_, i) => new Agent(`agent_${i}`, apiKey) ); } async initializeAgents() { await Promise.all(this.agents.map(agent => agent.initialize())); } async executeParallelTasks(tasks) { const results = []; // Execute tasks in parallel const promises = tasks.map(async (task, index) => { const agent = this.agents[index % this.agents.length]; return await agent.executeTask(task.code, task.context); }); const taskResults = await Promise.all(promises); results.push(...taskResults); return results; } async cleanupAll() { await Promise.all(this.agents.map(agent => agent.cleanup())); } } // Usage const orchestrator = new MultiAgentOrchestrator(process.env.HOPX_API_KEY, 3); await orchestrator.initializeAgents(); const tasks = [ { code: "result = 2 + 2\nprint(f'Result: {result}')", context: null }, { code: "result = 3 * 4\nprint(f'Result: {result}')", context: null }, { code: "result = 10 / 2\nprint(f'Result: {result}')", context: null } ]; const results = await orchestrator.executeParallelTasks(tasks); for (const result of results) { console.log(`Agent ${result.agentId}: ${result.stdout || result.error}`); } await orchestrator.cleanupAll(); ``` ### Step 2: Result Aggregation Aggregate results from multiple agents: ```python Python theme={null} class ResultAggregator: def __init__(self): self.results = [] def add_result(self, result: Dict[str, Any]): """Add agent result""" self.results.append(result) def aggregate(self) -> Dict[str, Any]: """Aggregate all results""" total = len(self.results) successful = sum(1 for r in self.results if r.get("success", False)) failed = total - successful # Extract outputs outputs = [r.get("stdout", "") for r in self.results if r.get("success")] # Calculate average execution time execution_times = [ r.get("execution_time", 0) for r in self.results if "execution_time" in r ] avg_time = sum(execution_times) / len(execution_times) if execution_times else 0 return { "total_agents": total, "successful": successful, "failed": failed, "success_rate": (successful / total * 100) if total > 0 else 0, "average_execution_time": avg_time, "outputs": outputs, "all_results": self.results } # Usage with orchestrator orchestrator = MultiAgentOrchestrator(api_key=os.getenv("HOPX_API_KEY"), num_agents=3) orchestrator.initialize_agents() tasks = [ {"code": "print('Agent 1 result: 10')"}, {"code": "print('Agent 2 result: 20')"}, {"code": "print('Agent 3 result: 30')"} ] results = orchestrator.execute_parallel_tasks(tasks) aggregator = ResultAggregator() for result in results: aggregator.add_result(result) summary = aggregator.aggregate() print(f"Success rate: {summary['success_rate']:.1f}%") print(f"Average execution time: {summary['average_execution_time']:.2f}s") orchestrator.cleanup_all() ``` ```javascript JavaScript theme={null} class ResultAggregator { constructor() { this.results = []; } addResult(result) { this.results.push(result); } aggregate() { const total = this.results.length; const successful = this.results.filter(r => r.success).length; const failed = total - successful; // Extract outputs const outputs = this.results .filter(r => r.success) .map(r => r.stdout || ''); // Calculate average execution time const executionTimes = this.results .map(r => r.executionTime || 0) .filter(t => t > 0); const avgTime = executionTimes.length > 0 ? executionTimes.reduce((a, b) => a + b, 0) / executionTimes.length : 0; return { totalAgents: total, successful, failed, successRate: total > 0 ? (successful / total * 100) : 0, averageExecutionTime: avgTime, outputs, allResults: this.results }; } } // Usage with orchestrator const orchestrator = new MultiAgentOrchestrator(process.env.HOPX_API_KEY, 3); await orchestrator.initializeAgents(); const tasks = [ { code: "print('Agent 1 result: 10')" }, { code: "print('Agent 2 result: 20')" }, { code: "print('Agent 3 result: 30')" } ]; const results = await orchestrator.executeParallelTasks(tasks); const aggregator = new ResultAggregator(); for (const result of results) { aggregator.addResult(result); } const summary = aggregator.aggregate(); console.log(`Success rate: ${summary.successRate.toFixed(1)}%`); console.log(`Average execution time: ${summary.averageExecutionTime.toFixed(2)}s`); await orchestrator.cleanupAll(); ``` ### Step 3: Error Recovery Patterns Implement error recovery for failed agents: ```python Python theme={null} class ResilientMultiAgentOrchestrator(MultiAgentOrchestrator): def execute_with_retry(self, task: Dict, max_retries: int = 3) -> Dict[str, Any]: """Execute task with retry logic""" agent = self.agents[0] # Use first available agent for attempt in range(max_retries): result = agent.execute_task(task["code"], task.get("context")) if result.get("success"): return result # Wait before retry import time time.sleep(1) return { "agent_id": agent.agent_id, "success": False, "error": f"Failed after {max_retries} attempts" } def execute_with_fallback(self, tasks: List[Dict]) -> List[Dict[str, Any]]: """Execute tasks with fallback agents""" results = [] for task in tasks: # Try primary agent primary_result = self.agents[0].execute_task(task["code"], task.get("context")) if primary_result.get("success"): results.append(primary_result) else: # Fallback to secondary agent fallback_result = self.agents[1].execute_task(task["code"], task.get("context")) results.append({ **fallback_result, "used_fallback": True, "primary_failed": True }) return results # Usage orchestrator = ResilientMultiAgentOrchestrator(api_key=os.getenv("HOPX_API_KEY"), num_agents=3) orchestrator.initialize_agents() # Task that might fail task = {"code": "result = 1 / 0\nprint(result)"} # Will fail # Execute with retry result = orchestrator.execute_with_retry(task, max_retries=3) print(f"Result after retry: {result}") orchestrator.cleanup_all() ``` ```javascript JavaScript theme={null} class ResilientMultiAgentOrchestrator extends MultiAgentOrchestrator { async executeWithRetry(task, maxRetries = 3) { const agent = this.agents[0]; // Use first available agent for (let attempt = 0; attempt < maxRetries; attempt++) { const result = await agent.executeTask(task.code, task.context); if (result.success) { return result; } // Wait before retry await new Promise(resolve => setTimeout(resolve, 1000)); } return { agentId: agent.agentId, success: false, error: `Failed after ${maxRetries} attempts` }; } async executeWithFallback(tasks) { const results = []; for (const task of tasks) { // Try primary agent const primaryResult = await this.agents[0].executeTask(task.code, task.context); if (primaryResult.success) { results.push(primaryResult); } else { // Fallback to secondary agent const fallbackResult = await this.agents[1].executeTask(task.code, task.context); results.push({ ...fallbackResult, usedFallback: true, primaryFailed: true }); } } return results; } } // Usage const orchestrator = new ResilientMultiAgentOrchestrator(process.env.HOPX_API_KEY, 3); await orchestrator.initializeAgents(); // Task that might fail const task = { code: "result = 1 / 0\nprint(result)" }; // Will fail // Execute with retry const result = await orchestrator.executeWithRetry(task, 3); console.log(`Result after retry: ${JSON.stringify(result)}`); await orchestrator.cleanupAll(); ``` ## Best Practices ### Coordination Use a message queue or shared state system for agents to communicate results and coordinate tasks. 1. **Task Distribution**: Distribute tasks evenly across agents 2. **State Sharing**: Share necessary state between agents 3. **Result Aggregation**: Aggregate results efficiently 4. **Error Handling**: Handle agent failures gracefully ### Performance 1. **Parallel Execution**: Execute independent tasks in parallel 2. **Resource Management**: Monitor and limit resource usage 3. **Caching**: Cache common results between agents 4. **Load Balancing**: Balance load across agents ### Reliability 1. **Retry Logic**: Implement retry for transient failures 2. **Fallback Agents**: Use fallback agents when primary fails 3. **Health Checks**: Monitor agent health 4. **Graceful Degradation**: Continue with available agents ## Real-World Examples This pattern is used by: * **AutoGPT**: Multi-agent AI system * **LangChain Multi-Agent**: Agent orchestration framework * **CrewAI**: Multi-agent orchestration platform ## Related Cookbooks * [AI Code Interpreter Agent](/cookbooks/ai-integration/code-interpreter-agent) - Single agent execution ## Next Steps 1. Implement agent communication protocol 2. Add task queue for agent coordination 3. Create agent health monitoring 4. Implement dynamic agent scaling 5. Add result persistence # API Testing Automation Platform Source: https://docs.hopx.ai/cookbooks/automation/api-testing-platform Build a Postman-style API testing platform with test script execution, environment management, assertion frameworks, and test reporting Build a production-ready API testing automation platform that executes test scripts, manages environments, validates responses, and generates reports. This cookbook demonstrates how to create a platform similar to Postman or Insomnia using HopX. ## Overview API testing platforms allow developers to write, execute, and manage API tests. The platform executes test scripts, manages test environments, validates responses with assertions, and generates comprehensive test reports. HopX provides the secure execution environment needed for this use case. ## Prerequisites * HopX API key ([Get one here](https://console.hopx.dev/api-keys)) * Python 3.8+ or Node.js 16+ * Understanding of REST APIs * Basic knowledge of test frameworks ## Architecture ``` ┌──────────────┐ │ Test Script │ API test definition └──────┬───────┘ │ ▼ ┌─────────────────┐ │ Test Runner │ Execute, validate └──────┬──────────┘ │ ▼ ┌─────────────────┐ │ HopX Sandbox │ Secure execution └──────┬──────────┘ │ ▼ ┌─────────────────┐ │ Test Report │ Results & metrics └─────────────────┘ ``` ## Implementation ### Step 1: Basic API Test Execution Execute API test scripts: ```python Python theme={null} from hopx_ai import Sandbox import os import json from typing import Dict, Any class APITestRunner: def __init__(self, api_key: str): self.api_key = api_key self.sandbox = None def initialize(self): """Initialize test sandbox""" self.sandbox = Sandbox.create( template="code-interpreter", api_key=self.api_key, timeout_seconds=600 ) # Install requests library self.sandbox.commands.run("pip install requests", timeout=30) def run_test(self, test_code: str, env_vars: Dict[str, str] = None) -> Dict[str, Any]: """Execute API test""" try: # Set environment variables if env_vars: self.sandbox.env.set_all(env_vars) # Execute test result = self.sandbox.run_code(test_code, timeout=30) # Parse test results test_results = self._parse_test_results(result.stdout) return { "success": result.success and test_results.get("all_passed", False), "stdout": result.stdout, "stderr": result.stderr, "test_results": test_results, "execution_time": result.execution_time } except Exception as e: return { "success": False, "error": str(e) } def _parse_test_results(self, output: str) -> Dict[str, Any]: """Parse test output""" # Simple parsing - in production, use proper test framework passed = output.count("PASS") or output.count("✓") failed = output.count("FAIL") or output.count("✗") return { "all_passed": failed == 0 and passed > 0, "passed": passed, "failed": failed } def cleanup(self): """Clean up test resources""" if self.sandbox: self.sandbox.kill() self.sandbox = None # Usage runner = APITestRunner(api_key=os.getenv("HOPX_API_KEY")) runner.initialize() test_code = """ import requests import json # Test GET endpoint response = requests.get('https://jsonplaceholder.typicode.com/posts/1') assert response.status_code == 200, f"Expected 200, got {response.status_code}" data = response.json() assert 'userId' in data, "Missing userId field" print("PASS: GET test") """ result = runner.run_test(test_code) print(json.dumps(result, indent=2)) runner.cleanup() ``` ```javascript JavaScript theme={null} import { Sandbox } from '@hopx-ai/sdk'; class APITestRunner { constructor(apiKey) { this.apiKey = apiKey; this.sandbox = null; } async initialize() { this.sandbox = await Sandbox.create({ template: 'code-interpreter', apiKey: this.apiKey, timeoutSeconds: 600 }); // Install axios await this.sandbox.commands.run('npm install axios', { timeout: 30 }); } async runTest(testCode, envVars = null) { try { // Set environment variables if (envVars) { await this.sandbox.env.setAll(envVars); } // Execute test const result = await this.sandbox.runCode(testCode, { timeout: 30 }); // Parse test results const testResults = this.parseTestResults(result.stdout); return { success: result.success && testResults.allPassed, stdout: result.stdout, stderr: result.stderr, testResults, executionTime: result.execution_time }; } catch (error) { return { success: false, error: error.message }; } } parseTestResults(output) { const passed = (output.match(/PASS/g) || []).length || (output.match(/✓/g) || []).length; const failed = (output.match(/FAIL/g) || []).length || (output.match(/✗/g) || []).length; return { allPassed: failed === 0 && passed > 0, passed, failed }; } async cleanup() { if (this.sandbox) { await this.sandbox.kill(); this.sandbox = null; } } } // Usage const runner = new APITestRunner(process.env.HOPX_API_KEY); await runner.initialize(); const testCode = ` const axios = require('axios'); // Test GET endpoint const response = await axios.get('https://jsonplaceholder.typicode.com/posts/1'); if (response.status !== 200) { throw new Error(\`Expected 200, got \${response.status}\`); } if (!response.data.userId) { throw new Error('Missing userId field'); } console.log('PASS: GET test'); `; const result = await runner.runTest(testCode); console.log(JSON.stringify(result, null, 2)); await runner.cleanup(); ``` ### Step 2: Environment Management Manage test environments: ```python Python theme={null} class EnvironmentManager: def __init__(self, sandbox: Sandbox): self.sandbox = sandbox self.environments = {} def create_environment(self, env_name: str, variables: Dict[str, str]): """Create test environment""" self.environments[env_name] = variables def use_environment(self, env_name: str): """Use environment for tests""" if env_name in self.environments: self.sandbox.env.set_all(self.environments[env_name]) return True return False # Usage sandbox = Sandbox.create(template="code-interpreter", api_key=os.getenv("HOPX_API_KEY")) env_manager = EnvironmentManager(sandbox) env_manager.create_environment("production", { "API_URL": "https://api.example.com", "API_KEY": "prod-key-123" }) env_manager.create_environment("staging", { "API_URL": "https://staging-api.example.com", "API_KEY": "staging-key-456" }) env_manager.use_environment("production") sandbox.kill() ``` ```javascript JavaScript theme={null} class EnvironmentManager { constructor(sandbox) { this.sandbox = sandbox; this.environments = {}; } createEnvironment(envName, variables) { this.environments[envName] = variables; } async useEnvironment(envName) { if (this.environments[envName]) { await this.sandbox.env.setAll(this.environments[envName]); return true; } return false; } } // Usage const sandbox = await Sandbox.create({ template: 'code-interpreter', apiKey: process.env.HOPX_API_KEY }); const envManager = new EnvironmentManager(sandbox); envManager.createEnvironment('production', { API_URL: 'https://api.example.com', API_KEY: 'prod-key-123' }); envManager.createEnvironment('staging', { API_URL: 'https://staging-api.example.com', API_KEY: 'staging-key-456' }); await envManager.useEnvironment('production'); await sandbox.kill(); ``` ## Best Practices 1. **Test Isolation**: Each test should be independent 2. **Environment Management**: Use separate environments for different stages 3. **Assertion Framework**: Use proper assertion libraries 4. **Test Reporting**: Generate comprehensive test reports ## Related Cookbooks * [Isolated Test Execution](/cookbooks/testing/isolated-test-execution) - Test isolation * [Web Scraping Service](/cookbooks/automation/web-scraping-service) - Automation workflows ## Next Steps 1. Implement test collection management 2. Add support for multiple HTTP methods 3. Create test result visualization 4. Implement test scheduling 5. Add API mocking support # Web Scraping Service Source: https://docs.hopx.ai/cookbooks/automation/web-scraping-service Build a browser automation and scraping service with desktop features, screenshot capture, data extraction workflows, and rate limiting Build a production-ready web scraping service that automates browsers, captures screenshots, extracts data, and handles rate limiting. This cookbook demonstrates how to create a scraping service using HopX's desktop automation features. ## Overview Web scraping services automate browser interactions to extract data from websites. The service uses browser automation, captures screenshots, records interactions, and implements ethical scraping practices with rate limiting. ## Prerequisites * HopX API key ([Get one here](https://console.hopx.dev/api-keys)) * Python 3.8+ or Node.js 16+ * Understanding of web scraping * Basic knowledge of browser automation ## Architecture ``` ┌──────────────┐ │ Scraping │ Define targets │ Request │ └──────┬───────┘ │ ▼ ┌─────────────────┐ │ Scraping │ Navigate, extract │ Service │ └──────┬──────────┘ │ ▼ ┌─────────────────┐ │ Desktop │ Browser automation │ Sandbox │ └─────────────────┘ ``` ## Implementation ### Step 1: Basic Web Scraping Scrape websites using code execution: ```python Python theme={null} from hopx_ai import Sandbox import os from typing import Dict, Any class WebScrapingService: def __init__(self, api_key: str): self.api_key = api_key self.sandbox = None def initialize(self): """Initialize scraping sandbox""" self.sandbox = Sandbox.create( template="desktop", # Desktop template for browser automation api_key=self.api_key, timeout_seconds=600 ) # Install scraping libraries self.sandbox.commands.run("pip install requests beautifulsoup4", timeout=60) def scrape_url(self, url: str, selector: str = None) -> Dict[str, Any]: """Scrape data from URL""" try: scraping_code = f""" import requests from bs4 import BeautifulSoup response = requests.get('{url}') soup = BeautifulSoup(response.content, 'html.parser') if '{selector}': elements = soup.select('{selector}') data = [elem.get_text() for elem in elements] else: data = soup.get_text() print(data) """ result = self.sandbox.run_code(scraping_code, timeout=30) return { "success": result.success, "data": result.stdout, "url": url } except Exception as e: return { "success": False, "error": str(e) } def take_screenshot(self, url: str) -> Dict[str, Any]: """Take screenshot of webpage""" try: # Navigate to URL (would use desktop automation) # For now, use code execution code = f""" import requests response = requests.get('{url}') print(f"Page loaded: {{len(response.content)}} bytes") """ result = self.sandbox.run_code(code, timeout=30) # Take screenshot using desktop features screenshot = self.sandbox.desktop.screenshot() return { "success": True, "screenshot_size": len(screenshot), "url": url } except Exception as e: return { "success": False, "error": str(e) } def cleanup(self): """Clean up scraping resources""" if self.sandbox: self.sandbox.kill() self.sandbox = None # Usage service = WebScrapingService(api_key=os.getenv("HOPX_API_KEY")) service.initialize() result = service.scrape_url("https://example.com", selector="h1") print(result) service.cleanup() ``` ```javascript JavaScript theme={null} import { Sandbox } from '@hopx-ai/sdk'; class WebScrapingService { constructor(apiKey) { this.apiKey = apiKey; this.sandbox = null; } async initialize() { this.sandbox = await Sandbox.create({ template: 'desktop', // Desktop template for browser automation apiKey: this.apiKey, timeoutSeconds: 600 }); // Install scraping libraries await this.sandbox.commands.run('pip install requests beautifulsoup4', { timeout: 60 }); } async scrapeUrl(url, selector = null) { try { const scrapingCode = ` import requests from bs4 import BeautifulSoup response = requests.get('${url}') soup = BeautifulSoup(response.content, 'html.parser') if '${selector}': elements = soup.select('${selector}') data = [elem.get_text() for elem in elements] else: data = soup.get_text() print(data) `; const result = await this.sandbox.runCode(scrapingCode, { timeout: 30 }); return { success: result.success, data: result.stdout, url }; } catch (error) { return { success: false, error: error.message }; } } async takeScreenshot(url) { try { // Navigate to URL const code = ` import requests response = requests.get('${url}') print(f"Page loaded: {len(response.content)} bytes") `; const result = await this.sandbox.runCode(code, { timeout: 30 }); // Take screenshot using desktop features const screenshot = await this.sandbox.desktop.screenshot(); return { success: true, screenshotSize: screenshot.length, url }; } catch (error) { return { success: false, error: error.message }; } } async cleanup() { if (this.sandbox) { await this.sandbox.kill(); this.sandbox = null; } } } // Usage const service = new WebScrapingService(process.env.HOPX_API_KEY); await service.initialize(); const result = await service.scrapeUrl('https://example.com', 'h1'); console.log(result); await service.cleanup(); ``` ## Best Practices Always respect robots.txt, implement rate limiting, and follow website terms of service when scraping. 1. **Rate Limiting**: Implement delays between requests 2. **Respect robots.txt**: Check and follow robots.txt rules 3. **Error Handling**: Handle network errors gracefully 4. **Data Extraction**: Use proper selectors and parsing ## Related Cookbooks * [API Testing Platform](/cookbooks/automation/api-testing-platform) - Testing automation ## Next Steps 1. Implement browser automation with desktop features 2. Add screenshot and recording capabilities 3. Create data extraction workflows 4. Implement rate limiting and ethics 5. Add proxy support # Data Analysis Pipeline Service Source: https://docs.hopx.ai/cookbooks/data-science/analysis-pipeline Build automated data analysis services with multi-step workflows, data transformation chains, result export, and scheduled jobs Build a production-ready data analysis pipeline service that processes data through multiple steps, transforms it, and exports results. This cookbook demonstrates how to create automated analysis workflows using HopX. ## Overview Data analysis pipelines automate the process of ingesting, transforming, analyzing, and exporting data. The service executes multi-step workflows, handles data transformations, and generates reports. This pattern is used in data processing platforms and analytics services. ## Prerequisites * HopX API key ([Get one here](https://console.hopx.dev/api-keys)) * Python 3.8+ or Node.js 16+ * Understanding of data pipelines * Basic knowledge of data transformation ## Architecture ``` ┌──────────────┐ │ Data Input │ Raw data └──────┬───────┘ │ ▼ ┌─────────────────┐ │ Pipeline │ Step 1 → Step 2 → Step 3 │ Engine │ └──────┬──────────┘ │ ▼ ┌─────────────────┐ │ HopX Sandbox │ Execute each step └──────┬──────────┘ │ ▼ ┌─────────────────┐ │ Results Export │ Reports, visualizations └─────────────────┘ ``` ## Implementation ### Step 1: Pipeline Definition Define and execute multi-step pipelines: ```python Python theme={null} from hopx_ai import Sandbox import os from typing import Dict, List, Any class PipelineStep: def __init__(self, step_id: str, code: str, dependencies: List[str] = None): self.step_id = step_id self.code = code self.dependencies = dependencies or [] class DataAnalysisPipeline: def __init__(self, api_key: str): self.api_key = api_key self.sandbox = None self.steps = [] def initialize(self): """Initialize pipeline sandbox""" self.sandbox = Sandbox.create( template="code-interpreter", api_key=self.api_key, timeout_seconds=3600 ) def add_step(self, step: PipelineStep): """Add pipeline step""" self.steps.append(step) def execute_pipeline(self, input_data: str = None) -> Dict[str, Any]: """Execute entire pipeline""" results = [] # Upload input data if provided if input_data: self.sandbox.files.write("/workspace/input.csv", input_data) # Execute steps in order for step in self.steps: result = self.sandbox.run_code(step.code, timeout=60) results.append({ "step_id": step.step_id, "success": result.success, "stdout": result.stdout, "stderr": result.stderr }) if not result.success: break # Stop on failure # Export results export_result = self._export_results() return { "success": all(r["success"] for r in results), "steps_executed": len(results), "step_results": results, "export": export_result } def _export_results(self) -> Dict[str, Any]: """Export pipeline results""" try: # Check for output files files = self.sandbox.files.list("/workspace") output_files = [f for f in files if f.name.endswith(('.csv', '.json', '.png'))] exports = {} for file in output_files: content = self.sandbox.files.read(file.path) exports[file.name] = { "size": len(content), "type": file.name.split('.')[-1] } return { "success": True, "files": exports } except Exception as e: return { "success": False, "error": str(e) } def cleanup(self): """Clean up pipeline resources""" if self.sandbox: self.sandbox.kill() self.sandbox = None # Usage pipeline = DataAnalysisPipeline(api_key=os.getenv("HOPX_API_KEY")) pipeline.initialize() # Define pipeline steps pipeline.add_step(PipelineStep( step_id="load_data", code=""" import pandas as pd df = pd.read_csv('/workspace/input.csv') print(f"Loaded {len(df)} rows") """ )) pipeline.add_step(PipelineStep( step_id="analyze", code=""" import pandas as pd df = pd.read_csv('/workspace/input.csv') summary = df.describe() summary.to_csv('/workspace/summary.csv') print("Analysis complete") """ )) # Execute result = pipeline.execute_pipeline(input_data="name,age\nAlice,25\nBob,30") print(result) pipeline.cleanup() ``` ```javascript JavaScript theme={null} import { Sandbox } from '@hopx-ai/sdk'; class PipelineStep { constructor(stepId, code, dependencies = []) { this.stepId = stepId; this.code = code; this.dependencies = dependencies; } } class DataAnalysisPipeline { constructor(apiKey) { this.apiKey = apiKey; this.sandbox = null; this.steps = []; } async initialize() { this.sandbox = await Sandbox.create({ template: 'code-interpreter', apiKey: this.apiKey, timeoutSeconds: 3600 }); } addStep(step) { this.steps.push(step); } async executePipeline(inputData = null) { const results = []; // Upload input data if provided if (inputData) { await this.sandbox.files.write('/workspace/input.csv', inputData); } // Execute steps in order for (const step of this.steps) { const result = await this.sandbox.runCode(step.code, { timeout: 60 }); results.push({ stepId: step.stepId, success: result.success, stdout: result.stdout, stderr: result.stderr }); if (!result.success) { break; // Stop on failure } } // Export results const exportResult = await this.exportResults(); return { success: results.every(r => r.success), stepsExecuted: results.length, stepResults: results, export: exportResult }; } async exportResults() { try { // Check for output files const files = await this.sandbox.files.list('/workspace'); const outputFiles = files.filter(f => f.name.endsWith('.csv') || f.name.endsWith('.json') || f.name.endsWith('.png') ); const exports = {}; for (const file of outputFiles) { const content = await this.sandbox.files.read(file.path); exports[file.name] = { size: content.length, type: file.name.split('.').pop() }; } return { success: true, files: exports }; } catch (error) { return { success: false, error: error.message }; } } async cleanup() { if (this.sandbox) { await this.sandbox.kill(); this.sandbox = null; } } } // Usage const pipeline = new DataAnalysisPipeline(process.env.HOPX_API_KEY); await pipeline.initialize(); // Define pipeline steps pipeline.addStep(new PipelineStep( 'load_data', ` import pandas as pd df = pd.read_csv('/workspace/input.csv') print(f"Loaded {len(df)} rows") ` )); pipeline.addStep(new PipelineStep( 'analyze', ` import pandas as pd df = pd.read_csv('/workspace/input.csv') summary = df.describe() summary.to_csv('/workspace/summary.csv') print("Analysis complete") ` )); // Execute const result = await pipeline.executePipeline('name,age\nAlice,25\nBob,30'); console.log(result); await pipeline.cleanup(); ``` ## Best Practices 1. **Step Isolation**: Each step should be independent and testable 2. **Error Handling**: Handle errors gracefully and provide recovery options 3. **Data Validation**: Validate data between steps 4. **Result Caching**: Cache intermediate results for efficiency ## Related Cookbooks * [Cloud Jupyter Notebook](/cookbooks/data-science/cloud-jupyter) - Notebook execution * [ML Model Training Service](/cookbooks/data-science/ml-training-service) - Machine learning workflows ## Next Steps 1. Implement pipeline scheduling 2. Add data validation between steps 3. Create pipeline visualization 4. Implement result caching 5. Add monitoring and alerting # Cloud Jupyter Notebook Service Source: https://docs.hopx.ai/cookbooks/data-science/cloud-jupyter Build a Kaggle/Colab-style notebook hosting service with rich output rendering, large dataset handling, and model training workflows Build a production-ready cloud Jupyter notebook service that provides notebook execution, rich output rendering, and data science workflows. This cookbook demonstrates how to create a service similar to Kaggle or Google Colab using HopX. ## Overview Cloud Jupyter notebook services allow data scientists to run notebooks in the cloud without local setup. The service executes notebook cells, captures rich outputs (plots, dataframes), handles large datasets, and supports model training workflows. HopX provides the secure execution environment needed for this use case. ## Prerequisites * HopX API key ([Get one here](https://console.hopx.dev/api-keys)) * Python 3.8+ or Node.js 16+ * Understanding of Jupyter notebook format * Basic knowledge of data science workflows ## Architecture ``` ┌──────────────┐ │ Notebook │ Cell execution requests │ UI │ └──────┬───────┘ │ ▼ ┌─────────────────┐ │ Notebook │ Parse, execute, capture │ Service │ └──────┬──────────┘ │ ▼ ┌─────────────────┐ │ HopX Sandbox │ Secure execution └──────┬──────────┘ │ ▼ ┌─────────────────┐ │ Rich Outputs │ Plots, DataFrames, HTML └─────────────────┘ ``` ## Implementation ### Step 1: Notebook Cell Execution Execute individual notebook cells and capture outputs: ```python Python theme={null} from hopx_ai import Sandbox import json import os from typing import Dict, List, Any class JupyterNotebookService: def __init__(self, api_key: str): self.api_key = api_key self.sandbox = None self.cell_state = {} # Store variables between cells def initialize_notebook(self, notebook_id: str) -> Dict[str, Any]: """Initialize a new notebook session""" try: self.sandbox = Sandbox.create( template="code-interpreter", api_key=self.api_key, timeout_seconds=3600 # 1 hour session ) # Set up data science environment self.sandbox.env.set_all({ "JUPYTER_MODE": "true", "PYTHONPATH": "/workspace" }) return { "success": True, "notebook_id": notebook_id, "sandbox_id": self.sandbox.sandbox_id } except Exception as e: return { "success": False, "error": str(e) } def execute_cell(self, cell_code: str, cell_id: str = None) -> Dict[str, Any]: """Execute a notebook cell""" try: # Use IPython execution for notebook-like behavior result = self.sandbox.run_ipython(cell_code) # Capture outputs outputs = [] if result.rich_outputs: for output in result.rich_outputs: outputs.append({ "type": output.type, "data": output.data }) # Store cell state if cell_id: self.cell_state[cell_id] = { "code": cell_code, "outputs": outputs, "stdout": result.stdout, "stderr": result.stderr } return { "success": result.success, "stdout": result.stdout, "stderr": result.stderr, "outputs": outputs, "output_count": len(outputs), "execution_time": result.execution_time } except Exception as e: return { "success": False, "error": str(e), "stderr": str(e) } def execute_notebook(self, notebook_json: Dict) -> Dict[str, Any]: """Execute entire notebook""" cells = notebook_json.get("cells", []) results = [] for i, cell in enumerate(cells): if cell.get("cell_type") != "code": continue source = "".join(cell.get("source", [])) cell_result = self.execute_cell(source, cell_id=f"cell_{i}") results.append({ "cell_index": i, "result": cell_result }) return { "success": True, "cells_executed": len(results), "results": results } def cleanup(self): """Clean up notebook session""" if self.sandbox: self.sandbox.kill() self.sandbox = None # Usage service = JupyterNotebookService(api_key=os.getenv("HOPX_API_KEY")) service.initialize_notebook("my-notebook") # Execute a cell result = service.execute_cell(""" import pandas as pd import numpy as np df = pd.DataFrame({ 'x': np.random.rand(10), 'y': np.random.rand(10) }) df # Display dataframe """) print(f"Captured {result['output_count']} outputs") print(result) service.cleanup() ``` ```javascript JavaScript theme={null} import { Sandbox } from '@hopx-ai/sdk'; class JupyterNotebookService { constructor(apiKey) { this.apiKey = apiKey; this.sandbox = null; this.cellState = {}; // Store variables between cells } async initializeNotebook(notebookId) { try { this.sandbox = await Sandbox.create({ template: 'code-interpreter', apiKey: this.apiKey, timeoutSeconds: 3600 // 1 hour session }); // Set up data science environment await this.sandbox.env.setAll({ JUPYTER_MODE: 'true', PYTHONPATH: '/workspace' }); return { success: true, notebookId, sandboxId: this.sandbox.sandboxId }; } catch (error) { return { success: false, error: error.message }; } } async executeCell(cellCode, cellId = null) { try { // Use IPython execution for notebook-like behavior const result = await this.sandbox.runIpython(cellCode); // Capture outputs const outputs = []; if (result.richOutputs) { for (const output of result.richOutputs) { outputs.push({ type: output.type, data: output.data }); } } // Store cell state if (cellId) { this.cellState[cellId] = { code: cellCode, outputs, stdout: result.stdout, stderr: result.stderr }; } return { success: result.success, stdout: result.stdout, stderr: result.stderr, outputs, outputCount: outputs.length, executionTime: result.execution_time }; } catch (error) { return { success: false, error: error.message, stderr: error.toString() }; } } async executeNotebook(notebookJson) { const cells = notebookJson.cells || []; const results = []; for (let i = 0; i < cells.length; i++) { const cell = cells[i]; if (cell.cell_type !== 'code') { continue; } const source = cell.source.join(''); const cellResult = await this.executeCell(source, `cell_${i}`); results.push({ cellIndex: i, result: cellResult }); } return { success: true, cellsExecuted: results.length, results }; } async cleanup() { if (this.sandbox) { await this.sandbox.kill(); this.sandbox = null; } } } // Usage const service = new JupyterNotebookService(process.env.HOPX_API_KEY); await service.initializeNotebook('my-notebook'); // Execute a cell const result = await service.executeCell(` import pandas as pd import numpy as np df = pd.DataFrame({ 'x': np.random.rand(10), 'y': np.random.rand(10) }) df # Display dataframe `); console.log(`Captured ${result.outputCount} outputs`); console.log(result); await service.cleanup(); ``` ### Step 2: Rich Output Rendering Handle plots, dataframes, and other rich outputs: ```python Python theme={null} class RichOutputRenderer: def __init__(self, sandbox: Sandbox): self.sandbox = sandbox def render_outputs(self, outputs: List[Dict]) -> List[Dict[str, Any]]: """Render rich outputs for display""" rendered = [] for output in outputs: output_type = output.get("type", "") data = output.get("data", {}) if "image/png" in output_type or "image/jpeg" in output_type: # Image output rendered.append({ "type": "image", "format": "png" if "png" in output_type else "jpeg", "data": data.get("image/png") or data.get("image/jpeg"), "encoding": "base64" }) elif "text/html" in output_type: # HTML output (DataFrames, etc.) rendered.append({ "type": "html", "data": data.get("text/html", ""), "mime_type": "text/html" }) elif "application/json" in output_type: # JSON output rendered.append({ "type": "json", "data": data.get("application/json", {}), "mime_type": "application/json" }) else: # Plain text rendered.append({ "type": "text", "data": str(data), "mime_type": "text/plain" }) return rendered # Usage service = JupyterNotebookService(api_key=os.getenv("HOPX_API_KEY")) service.initialize_notebook("notebook-1") # Execute cell with plot result = service.execute_cell(""" import matplotlib.pyplot as plt import numpy as np x = np.linspace(0, 10, 100) y = np.sin(x) plt.plot(x, y) plt.title('Sine Wave') plt.show() """) # Render outputs renderer = RichOutputRenderer(service.sandbox) rendered = renderer.render_outputs(result["outputs"]) for output in rendered: print(f"Output type: {output['type']}") if output['type'] == 'image': print(f" Image data length: {len(output['data'])} bytes") service.cleanup() ``` ```javascript JavaScript theme={null} class RichOutputRenderer { constructor(sandbox) { this.sandbox = sandbox; } renderOutputs(outputs) { const rendered = []; for (const output of outputs) { const outputType = output.type || ''; const data = output.data || {}; if (outputType.includes('image/png') || outputType.includes('image/jpeg')) { // Image output rendered.push({ type: 'image', format: outputType.includes('png') ? 'png' : 'jpeg', data: data['image/png'] || data['image/jpeg'], encoding: 'base64' }); } else if (outputType.includes('text/html')) { // HTML output (DataFrames, etc.) rendered.push({ type: 'html', data: data['text/html'] || '', mimeType: 'text/html' }); } else if (outputType.includes('application/json')) { // JSON output rendered.push({ type: 'json', data: data['application/json'] || {}, mimeType: 'application/json' }); } else { // Plain text rendered.push({ type: 'text', data: String(data), mimeType: 'text/plain' }); } } return rendered; } } // Usage const service = new JupyterNotebookService(process.env.HOPX_API_KEY); await service.initializeNotebook('notebook-1'); // Execute cell with plot const result = await service.executeCell(` import matplotlib.pyplot as plt import numpy as np x = np.linspace(0, 10, 100) y = np.sin(x) plt.plot(x, y) plt.title('Sine Wave') plt.show() `); // Render outputs const renderer = new RichOutputRenderer(service.sandbox); const rendered = renderer.renderOutputs(result.outputs); for (const output of rendered) { console.log(`Output type: ${output.type}`); if (output.type === 'image') { console.log(` Image data length: ${output.data.length} bytes`); } } await service.cleanup(); ``` ### Step 3: Large Dataset Handling Handle large datasets efficiently: ```python Python theme={null} class LargeDatasetHandler: def __init__(self, sandbox: Sandbox): self.sandbox = sandbox def upload_dataset(self, file_path: str, data: bytes) -> Dict[str, Any]: """Upload large dataset to sandbox""" try: # For large files, use upload method self.sandbox.files.write(f"/workspace/data/{file_path}", data) return { "success": True, "path": f"/workspace/data/{file_path}", "size": len(data) } except Exception as e: return { "success": False, "error": str(e) } def process_large_dataset(self, dataset_path: str, chunk_size: int = 10000) -> Dict[str, Any]: """Process large dataset in chunks""" try: # Process in chunks to avoid memory issues code = f""" import pandas as pd import os # Read dataset in chunks chunk_size = {chunk_size} dataset_path = '{dataset_path}' chunks = [] for chunk in pd.read_csv(dataset_path, chunksize=chunk_size): # Process chunk processed = chunk.describe() chunks.append(processed) # Combine results result = pd.concat(chunks) print(f"Processed {{len(chunks)}} chunks") print(result) """ result = self.sandbox.run_code(code, timeout=300) # 5 minute timeout return { "success": result.success, "stdout": result.stdout, "chunks_processed": result.stdout.count("chunks") if result.success else 0 } except Exception as e: return { "success": False, "error": str(e) } # Usage sandbox = Sandbox.create(template="code-interpreter", api_key=os.getenv("HOPX_API_KEY")) handler = LargeDatasetHandler(sandbox) # Upload dataset with open("large_dataset.csv", "rb") as f: data = f.read() result = handler.upload_dataset("large_dataset.csv", data) print(result) # Process result = handler.process_large_dataset("/workspace/data/large_dataset.csv") print(result) sandbox.kill() ``` ```javascript JavaScript theme={null} class LargeDatasetHandler { constructor(sandbox) { this.sandbox = sandbox; } async uploadDataset(filePath, data) { try { // For large files, use write method await this.sandbox.files.write(`/workspace/data/${filePath}`, data); return { success: true, path: `/workspace/data/${filePath}`, size: data.length }; } catch (error) { return { success: false, error: error.message }; } } async processLargeDataset(datasetPath, chunkSize = 10000) { try { // Process in chunks to avoid memory issues const code = ` import pandas as pd import os # Read dataset in chunks chunk_size = ${chunkSize} dataset_path = '${datasetPath}' chunks = [] for chunk in pd.read_csv(dataset_path, chunksize=chunk_size): # Process chunk processed = chunk.describe() chunks.append(processed) # Combine results result = pd.concat(chunks) print(f"Processed {len(chunks)} chunks") print(result) `; const result = await this.sandbox.runCode(code, { timeout: 300 }); // 5 minute timeout return { success: result.success, stdout: result.stdout, chunksProcessed: result.success ? (result.stdout.match(/chunks/g) || []).length : 0 }; } catch (error) { return { success: false, error: error.message }; } } } // Usage const sandbox = await Sandbox.create({ template: 'code-interpreter', apiKey: process.env.HOPX_API_KEY }); const handler = new LargeDatasetHandler(sandbox); // Upload dataset (assuming you have the file data) const fs = require('fs'); const data = fs.readFileSync('large_dataset.csv'); const uploadResult = await handler.uploadDataset('large_dataset.csv', data); console.log(uploadResult); // Process const processResult = await handler.processLargeDataset('/workspace/data/large_dataset.csv'); console.log(processResult); await sandbox.kill(); ``` ### Step 4: Model Training Workflows Support ML model training: ```python Python theme={null} class ModelTrainingService: def __init__(self, sandbox: Sandbox): self.sandbox = sandbox def train_model(self, training_code: str, timeout: int = 1800) -> Dict[str, Any]: """Train ML model with progress monitoring""" try: # Use background execution for long training execution_id = self.sandbox.run_code_background(training_code) # Monitor progress import time max_wait = timeout waited = 0 while waited < max_wait: time.sleep(5) # Check every 5 seconds waited += 5 # Check if process is still running processes = self.sandbox.list_processes() training_process = any( 'python' in p.get('name', '').lower() or 'train' in p.get('name', '').lower() for p in processes ) if not training_process: # Training completed break # Check for model file if self.sandbox.files.exists("/workspace/model.pkl"): model_data = self.sandbox.files.read("/workspace/model.pkl") return { "success": True, "model_saved": True, "model_size": len(model_data), "execution_id": execution_id } else: return { "success": True, "model_saved": False, "execution_id": execution_id } except Exception as e: return { "success": False, "error": str(e) } # Usage sandbox = Sandbox.create(template="code-interpreter", api_key=os.getenv("HOPX_API_KEY")) trainer = ModelTrainingService(sandbox) training_code = """ from sklearn.datasets import load_iris from sklearn.ensemble import RandomForestClassifier import pickle # Load data iris = load_iris() X, y = iris.data, iris.target # Train model model = RandomForestClassifier(n_estimators=100) model.fit(X, y) # Save model with open('/workspace/model.pkl', 'wb') as f: pickle.dump(model, f) print("Model trained and saved!") """ result = trainer.train_model(training_code) print(result) sandbox.kill() ``` ```javascript JavaScript theme={null} class ModelTrainingService { constructor(sandbox) { this.sandbox = sandbox; } async trainModel(trainingCode, timeout = 1800) { try { // Use background execution for long training const executionId = await this.sandbox.runCodeBackground(trainingCode); // Monitor progress const maxWait = timeout; let waited = 0; while (waited < maxWait) { await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5 seconds waited += 5; // Check if process is still running const processes = await this.sandbox.listProcesses(); const trainingProcess = processes.some(p => { const name = (p.name || '').toLowerCase(); return name.includes('python') || name.includes('train'); }); if (!trainingProcess) { // Training completed break; } } // Check for model file const modelExists = await this.sandbox.files.exists('/workspace/model.pkl'); if (modelExists) { const modelData = await this.sandbox.files.read('/workspace/model.pkl'); return { success: true, modelSaved: true, modelSize: modelData.length, executionId }; } else { return { success: true, modelSaved: false, executionId }; } } catch (error) { return { success: false, error: error.message }; } } } // Usage const sandbox = await Sandbox.create({ template: 'code-interpreter', apiKey: process.env.HOPX_API_KEY }); const trainer = new ModelTrainingService(sandbox); const trainingCode = ` from sklearn.datasets import load_iris from sklearn.ensemble import RandomForestClassifier import pickle # Load data iris = load_iris() X, y = iris.data, iris.target # Train model model = RandomForestClassifier(n_estimators=100) model.fit(X, y) # Save model with open('/workspace/model.pkl', 'wb') as f: pickle.dump(model, f) print("Model trained and saved!") `; const result = await trainer.trainModel(trainingCode); console.log(result); await sandbox.kill(); ``` ## Best Practices ### Performance Use IPython execution mode for notebook cells to automatically capture rich outputs like DataFrames and plots. 1. **Cell State Management**: Maintain state between cells for interactive workflows 2. **Output Caching**: Cache rendered outputs to avoid re-rendering 3. **Chunked Processing**: Process large datasets in chunks 4. **Background Execution**: Use background execution for long-running training ### Resource Management 1. **Session Timeouts**: Set appropriate session timeouts 2. **Memory Monitoring**: Monitor memory usage for large datasets 3. **Cleanup**: Clean up temporary files and models 4. **Resource Limits**: Set limits based on user tier ### User Experience 1. **Progress Indicators**: Show execution progress for long operations 2. **Error Messages**: Provide clear, actionable error messages 3. **Output Formatting**: Format outputs for easy reading 4. **Auto-Save**: Auto-save notebook state ## Real-World Examples This pattern is used by: * **Kaggle Notebooks**: Data science competition platform * **Google Colab**: Free Jupyter notebook environment * **Azure Notebooks**: Cloud-based Jupyter service * **Binder**: Turn GitHub repos into interactive notebooks ## Related Cookbooks * [Data Analysis Pipeline](/cookbooks/data-science/analysis-pipeline) - Analysis workflows * [ML Model Training Service](/cookbooks/data-science/ml-training-service) - Machine learning workflows ## Next Steps 1. Implement notebook format parsing (Jupyter .ipynb format) 2. Add support for markdown and code cells 3. Create a web UI for notebook editing 4. Implement cell execution queue 5. Add collaboration features # ML Model Training Service Source: https://docs.hopx.ai/cookbooks/data-science/ml-training-service Build a cloud-based ML training platform with resource allocation, long-running execution, progress monitoring, and model checkpointing Build a production-ready ML model training service that handles resource allocation, monitors training progress, and manages model checkpoints. This cookbook demonstrates how to create a training platform using HopX. ## Overview ML training services provide cloud-based environments for training machine learning models. The service allocates resources, executes long-running training jobs, monitors progress, and saves model checkpoints. ## Prerequisites * HopX API key ([Get one here](https://console.hopx.dev/api-keys)) * Python 3.8+ or Node.js 16+ * Understanding of ML training workflows * Basic knowledge of model checkpointing ## Architecture ``` ┌──────────────┐ │ Training │ Submit training job │ Request │ └──────┬───────┘ │ ▼ ┌─────────────────┐ │ Training │ Allocate resources │ Service │ └──────┬──────────┘ │ ▼ ┌─────────────────┐ │ HopX Sandbox │ Execute training │ (High resources)│ └──────┬──────────┘ │ ▼ ┌─────────────────┐ │ Model Storage │ Save checkpoints └─────────────────┘ ``` ## Implementation ### Step 1: Training Job Execution Execute ML training jobs: ```python Python theme={null} from hopx_ai import Sandbox import os import time from typing import Dict, Any class MLTrainingService: def __init__(self, api_key: str): self.api_key = api_key self.sandbox = None def start_training(self, training_code: str, resources: Dict[str, int] = None) -> Dict[str, Any]: """Start ML training job""" try: # Create sandbox with appropriate resources # Note: Resources come from template, but we can request high-resource template self.sandbox = Sandbox.create( template="code-interpreter", # Use ML-optimized template if available api_key=self.api_key, timeout_seconds=7200 # 2 hour timeout for training ) # Start training in background execution_id = self.sandbox.run_code_background(training_code) return { "success": True, "execution_id": execution_id, "sandbox_id": self.sandbox.sandbox_id } except Exception as e: return { "success": False, "error": str(e) } def monitor_training(self, execution_id: str) -> Dict[str, Any]: """Monitor training progress""" try: # Check processes processes = self.sandbox.list_processes() training_processes = [ p for p in processes if 'python' in p.get('name', '').lower() or 'train' in p.get('name', '').lower() ] # Check for checkpoint files files = self.sandbox.files.list("/workspace") checkpoints = [f for f in files if 'checkpoint' in f.name.lower() or f.name.endswith('.pkl')] return { "training_active": len(training_processes) > 0, "checkpoints": len(checkpoints), "processes": len(training_processes) } except Exception as e: return { "error": str(e) } def get_checkpoint(self, checkpoint_path: str) -> Dict[str, Any]: """Retrieve model checkpoint""" try: checkpoint_data = self.sandbox.files.read(checkpoint_path) return { "success": True, "data": checkpoint_data, "size": len(checkpoint_data) } except Exception as e: return { "success": False, "error": str(e) } def cleanup(self): """Clean up training resources""" if self.sandbox: self.sandbox.kill() self.sandbox = None # Usage service = MLTrainingService(api_key=os.getenv("HOPX_API_KEY")) training_code = """ from sklearn.datasets import load_iris from sklearn.ensemble import RandomForestClassifier import pickle iris = load_iris() X, y = iris.data, iris.target model = RandomForestClassifier(n_estimators=100) model.fit(X, y) with open('/workspace/model.pkl', 'wb') as f: pickle.dump(model, f) """ result = service.start_training(training_code) print(result) # Monitor time.sleep(5) status = service.monitor_training(result["execution_id"]) print(status) service.cleanup() ``` ```javascript JavaScript theme={null} import { Sandbox } from '@hopx-ai/sdk'; class MLTrainingService { constructor(apiKey) { this.apiKey = apiKey; this.sandbox = null; } async startTraining(trainingCode, resources = null) { try { // Create sandbox with appropriate resources this.sandbox = await Sandbox.create({ template: 'code-interpreter', // Use ML-optimized template if available apiKey: this.apiKey, timeoutSeconds: 7200 // 2 hour timeout for training }); // Start training in background const executionId = await this.sandbox.runCodeBackground(trainingCode); return { success: true, executionId, sandboxId: this.sandbox.sandboxId }; } catch (error) { return { success: false, error: error.message }; } } async monitorTraining(executionId) { try { // Check processes const processes = await this.sandbox.listProcesses(); const trainingProcesses = processes.filter(p => { const name = (p.name || '').toLowerCase(); return name.includes('python') || name.includes('train'); }); // Check for checkpoint files const files = await this.sandbox.files.list('/workspace'); const checkpoints = files.filter(f => f.name.toLowerCase().includes('checkpoint') || f.name.endsWith('.pkl') ); return { trainingActive: trainingProcesses.length > 0, checkpoints: checkpoints.length, processes: trainingProcesses.length }; } catch (error) { return { error: error.message }; } } async getCheckpoint(checkpointPath) { try { const checkpointData = await this.sandbox.files.read(checkpointPath); return { success: true, data: checkpointData, size: checkpointData.length }; } catch (error) { return { success: false, error: error.message }; } } async cleanup() { if (this.sandbox) { await this.sandbox.kill(); this.sandbox = null; } } } // Usage const service = new MLTrainingService(process.env.HOPX_API_KEY); const trainingCode = ` from sklearn.datasets import load_iris from sklearn.ensemble import RandomForestClassifier import pickle iris = load_iris() X, y = iris.data, iris.target model = RandomForestClassifier(n_estimators=100) model.fit(X, y) with open('/workspace/model.pkl', 'wb') as f: pickle.dump(model, f) `; const result = await service.startTraining(trainingCode); console.log(result); // Monitor await new Promise(resolve => setTimeout(resolve, 5000)); const status = await service.monitorTraining(result.executionId); console.log(status); await service.cleanup(); ``` ## Best Practices 1. **Resource Allocation**: Request appropriate resources for training 2. **Progress Monitoring**: Monitor training progress regularly 3. **Checkpointing**: Save model checkpoints frequently 4. **Error Recovery**: Handle training failures gracefully ## Related Cookbooks * [Cloud Jupyter Notebook](/cookbooks/data-science/cloud-jupyter) - Notebook execution * [Data Analysis Pipeline](/cookbooks/data-science/analysis-pipeline) - Analysis workflows ## Next Steps 1. Implement distributed training support 2. Add hyperparameter tuning 3. Create training dashboard 4. Implement model versioning 5. Add training job scheduling # Browser-Based Code Editor Source: https://docs.hopx.ai/cookbooks/development/browser-editor Build a StackBlitz-style browser IDE with client-server architecture, file operations via API, hot reload patterns, and package management Build a production-ready browser-based code editor that runs entirely in the browser with a backend API. This cookbook demonstrates how to create a platform similar to StackBlitz or CodeSandbox using HopX. ## Overview Browser-based code editors provide a full IDE experience in the browser. The frontend handles editing, and the backend manages file operations, code execution, and package management through APIs. ## Prerequisites * HopX API key ([Get one here](https://console.hopx.dev/api-keys)) * Python 3.8+ or Node.js 16+ * Understanding of client-server architecture * Basic knowledge of web APIs ## Architecture ``` ┌──────────────┐ │ Browser │ Editor UI └──────┬───────┘ │ HTTP/WebSocket ▼ ┌─────────────────┐ │ Editor Backend │ File ops, execution └──────┬──────────┘ │ ▼ ┌─────────────────┐ │ HopX Sandbox │ Secure execution └─────────────────┘ ``` ## Implementation ### Step 1: File Operations API Provide file operations via API: ```python Python theme={null} from hopx_ai import Sandbox import os from typing import Dict, Any class EditorBackend: def __init__(self, api_key: str): self.api_key = api_key self.sandbox = None def initialize_project(self, project_id: str) -> Dict[str, Any]: """Initialize editor project""" self.sandbox = Sandbox.create( template="code-interpreter", api_key=self.api_key, timeout_seconds=3600 ) self.sandbox.files.mkdir("/workspace/project") return { "success": True, "project_id": project_id, "sandbox_id": self.sandbox.sandbox_id } def handle_file_request(self, method: str, path: str, content: str = None) -> Dict[str, Any]: """Handle file operation requests""" full_path = f"/workspace/project{path}" if method == "GET": # Read file try: content = self.sandbox.files.read(full_path) return {"success": True, "content": content} except Exception as e: return {"success": False, "error": str(e)} elif method == "PUT": # Write file try: self.sandbox.files.write(full_path, content) return {"success": True, "path": path} except Exception as e: return {"success": False, "error": str(e)} elif method == "DELETE": # Delete file try: self.sandbox.files.remove(full_path) return {"success": True, "path": path} except Exception as e: return {"success": False, "error": str(e)} elif method == "LIST": # List directory try: files = self.sandbox.files.list(full_path) return { "success": True, "files": [ { "name": f.name, "path": f.path, "is_dir": f.is_dir, "size": f.size } for f in files ] } except Exception as e: return {"success": False, "error": str(e)} return {"success": False, "error": f"Unknown method: {method}"} def cleanup(self): """Clean up editor resources""" if self.sandbox: self.sandbox.kill() self.sandbox = None # Usage backend = EditorBackend(api_key=os.getenv("HOPX_API_KEY")) backend.initialize_project("my-project") # File operations result = backend.handle_file_request("PUT", "/app.js", "console.log('Hello');") print(result) result = backend.handle_file_request("GET", "/app.js") print(result) backend.cleanup() ``` ```javascript JavaScript theme={null} import { Sandbox } from '@hopx-ai/sdk'; class EditorBackend { constructor(apiKey) { this.apiKey = apiKey; this.sandbox = null; } async initializeProject(projectId) { this.sandbox = await Sandbox.create({ template: 'code-interpreter', apiKey: this.apiKey, timeoutSeconds: 3600 }); await this.sandbox.files.mkdir('/workspace/project'); return { success: true, projectId, sandboxId: this.sandbox.sandboxId }; } async handleFileRequest(method, path, content = null) { const fullPath = `/workspace/project${path}`; if (method === 'GET') { try { const fileContent = await this.sandbox.files.read(fullPath); return { success: true, content: fileContent }; } catch (error) { return { success: false, error: error.message }; } } else if (method === 'PUT') { try { await this.sandbox.files.write(fullPath, content); return { success: true, path }; } catch (error) { return { success: false, error: error.message }; } } else if (method === 'DELETE') { try { await this.sandbox.files.remove(fullPath); return { success: true, path }; } catch (error) { return { success: false, error: error.message }; } } else if (method === 'LIST') { try { const files = await this.sandbox.files.list(fullPath); return { success: true, files: files.map(f => ({ name: f.name, path: f.path, isDir: f.isDir, size: f.size })) }; } catch (error) { return { success: false, error: error.message }; } } return { success: false, error: `Unknown method: ${method}` }; } async cleanup() { if (this.sandbox) { await this.sandbox.kill(); this.sandbox = null; } } } // Usage const backend = new EditorBackend(process.env.HOPX_API_KEY); await backend.initializeProject('my-project'); // File operations const result1 = await backend.handleFileRequest('PUT', '/app.js', "console.log('Hello');"); console.log(result1); const result2 = await backend.handleFileRequest('GET', '/app.js'); console.log(result2); await backend.cleanup(); ``` ## Best Practices 1. **API Design**: Design RESTful APIs for file operations 2. **Hot Reload**: Implement file watching for live updates 3. **Package Management**: Support npm, pip, etc. 4. **Error Handling**: Provide clear error messages ## Related Cookbooks * [Cloud-Based IDE Backend](/cookbooks/development/cloud-ide-backend) - Full IDE backend ## Next Steps 1. Implement WebSocket for real-time updates 2. Add package installation support 3. Create frontend editor interface 4. Implement hot reload functionality 5. Add collaboration features # Cloud-Based IDE Backend Source: https://docs.hopx.ai/cookbooks/development/cloud-ide-backend Build a Replit/CodeSandbox-style online IDE with file system management, terminal emulation, and multi-file project execution Build a production-ready cloud-based IDE backend that provides file system management, terminal access, and code execution. This cookbook demonstrates how to create a backend similar to Replit or CodeSandbox using HopX for secure execution. ## Overview Cloud-based IDEs allow developers to code, run, and debug applications entirely in the browser. The backend manages file systems, provides terminal access, executes code, and handles real-time updates. HopX provides the secure execution environment needed for this use case. ## Prerequisites * HopX API key ([Get one here](https://console.hopx.dev/api-keys)) * Python 3.8+ or Node.js 16+ * Understanding of WebSocket connections * Basic knowledge of IDE architecture ## Architecture ``` ┌──────────────┐ │ Browser │ Editor, Terminal UI └──────┬───────┘ │ WebSocket/HTTP ▼ ┌─────────────────┐ │ IDE Backend │ File ops, Terminal, Execution └──────┬──────────┘ │ ▼ ┌─────────────────┐ │ HopX Sandbox │ Secure execution environment └─────────────────┘ ``` ## Implementation ### Step 1: File System Management Create a file system manager for the IDE: ```python Python theme={null} from hopx_ai import Sandbox import os from typing import Dict, List, Any class IDEFileSystem: def __init__(self, api_key: str): self.api_key = api_key self.sandbox = None def initialize_project(self, project_id: str) -> Dict[str, Any]: """Initialize a new project sandbox""" try: self.sandbox = Sandbox.create( template="code-interpreter", api_key=self.api_key, timeout_seconds=3600 # 1 hour for IDE session ) # Create project structure self.sandbox.files.mkdir("/workspace/project") self.sandbox.files.write("/workspace/project/.gitignore", "__pycache__/\n*.pyc\n") return { "success": True, "sandbox_id": self.sandbox.sandbox_id, "project_path": "/workspace/project" } except Exception as e: return { "success": False, "error": str(e) } def list_files(self, path: str = "/workspace/project") -> List[Dict[str, Any]]: """List files and directories""" try: files = self.sandbox.files.list(path) return [ { "name": f.name, "path": f.path, "is_dir": f.is_dir, "size": f.size, "modified": f.modified_time.isoformat() if hasattr(f.modified_time, 'isoformat') else str(f.modified_time) } for f in files ] except Exception as e: return [] def read_file(self, file_path: str) -> Dict[str, Any]: """Read file contents""" try: content = self.sandbox.files.read(file_path) return { "success": True, "content": content, "path": file_path } except Exception as e: return { "success": False, "error": str(e), "path": file_path } def write_file(self, file_path: str, content: str) -> Dict[str, Any]: """Write file contents""" try: self.sandbox.files.write(file_path, content) return { "success": True, "path": file_path, "size": len(content) } except Exception as e: return { "success": False, "error": str(e), "path": file_path } def create_directory(self, dir_path: str) -> Dict[str, Any]: """Create a directory""" try: self.sandbox.files.mkdir(dir_path) return { "success": True, "path": dir_path } except Exception as e: return { "success": False, "error": str(e), "path": dir_path } def delete_file(self, file_path: str) -> Dict[str, Any]: """Delete a file or directory""" try: self.sandbox.files.remove(file_path) return { "success": True, "path": file_path } except Exception as e: return { "success": False, "error": str(e), "path": file_path } def cleanup(self): """Clean up sandbox""" if self.sandbox: self.sandbox.kill() self.sandbox = None # Usage fs = IDEFileSystem(api_key=os.getenv("HOPX_API_KEY")) result = fs.initialize_project("my-project") print(result) # List files files = fs.list_files() print(files) # Create a file fs.write_file("/workspace/project/main.py", "print('Hello, World!')") # Read the file content = fs.read_file("/workspace/project/main.py") print(content) fs.cleanup() ``` ```javascript JavaScript theme={null} import { Sandbox } from '@hopx-ai/sdk'; class IDEFileSystem { constructor(apiKey) { this.apiKey = apiKey; this.sandbox = null; } async initializeProject(projectId) { try { this.sandbox = await Sandbox.create({ template: 'code-interpreter', apiKey: this.apiKey, timeoutSeconds: 3600 // 1 hour for IDE session }); // Create project structure await this.sandbox.files.mkdir('/workspace/project'); await this.sandbox.files.write('/workspace/project/.gitignore', '__pycache__/\n*.pyc\n'); return { success: true, sandboxId: this.sandbox.sandboxId, projectPath: '/workspace/project' }; } catch (error) { return { success: false, error: error.message }; } } async listFiles(path = '/workspace/project') { try { const files = await this.sandbox.files.list(path); return files.map(f => ({ name: f.name, path: f.path, isDir: f.isDir, size: f.size, modified: f.modifiedTime })); } catch (error) { return []; } } async readFile(filePath) { try { const content = await this.sandbox.files.read(filePath); return { success: true, content, path: filePath }; } catch (error) { return { success: false, error: error.message, path: filePath }; } } async writeFile(filePath, content) { try { await this.sandbox.files.write(filePath, content); return { success: true, path: filePath, size: content.length }; } catch (error) { return { success: false, error: error.message, path: filePath }; } } async createDirectory(dirPath) { try { await this.sandbox.files.mkdir(dirPath); return { success: true, path: dirPath }; } catch (error) { return { success: false, error: error.message, path: dirPath }; } } async deleteFile(filePath) { try { await this.sandbox.files.remove(filePath); return { success: true, path: filePath }; } catch (error) { return { success: false, error: error.message, path: filePath }; } } async cleanup() { if (this.sandbox) { await this.sandbox.kill(); this.sandbox = null; } } } // Usage const fs = new IDEFileSystem(process.env.HOPX_API_KEY); const result = await fs.initializeProject('my-project'); console.log(result); // List files const files = await fs.listFiles(); console.log(files); // Create a file await fs.writeFile('/workspace/project/main.py', "print('Hello, World!')"); // Read the file const content = await fs.readFile('/workspace/project/main.py'); console.log(content); await fs.cleanup(); ``` ### Step 2: Terminal Emulation Implement terminal access using WebSocket: ```python Python theme={null} import asyncio from typing import AsyncIterator, Dict, Any class IDETerminal: def __init__(self, sandbox: Sandbox): self.sandbox = sandbox self.terminal_session = None async def connect(self) -> Dict[str, Any]: """Connect to terminal""" try: self.terminal_session = await self.sandbox.terminal.connect() return { "success": True, "session_id": str(self.terminal_session) } except Exception as e: return { "success": False, "error": str(e) } async def send_command(self, command: str) -> None: """Send command to terminal""" if self.terminal_session: await self.sandbox.terminal.send_input( self.terminal_session, command + "\n" ) async def receive_output(self) -> AsyncIterator[Dict[str, Any]]: """Receive terminal output""" if not self.terminal_session: return async for message in self.sandbox.terminal.iter_output(self.terminal_session): yield { "type": message.get("type", "output"), "data": message.get("data", ""), "timestamp": message.get("timestamp") } async def resize(self, rows: int, cols: int) -> None: """Resize terminal""" if self.terminal_session: await self.sandbox.terminal.resize( self.terminal_session, rows=rows, cols=cols ) async def disconnect(self): """Disconnect from terminal""" self.terminal_session = None # Usage sandbox = Sandbox.create(template="code-interpreter", api_key=os.getenv("HOPX_API_KEY")) terminal = IDETerminal(sandbox) await terminal.connect() await terminal.send_command("pwd") await terminal.send_command("ls -la") async for output in terminal.receive_output(): print(output) # Break after some outputs break await terminal.disconnect() sandbox.kill() ``` ```javascript JavaScript theme={null} class IDETerminal { constructor(sandbox) { this.sandbox = sandbox; this.terminalSession = null; } async connect() { try { this.terminalSession = await this.sandbox.terminal.connect(); return { success: true, sessionId: String(this.terminalSession) }; } catch (error) { return { success: false, error: error.message }; } } async sendCommand(command) { if (this.terminalSession) { await this.sandbox.terminal.sendInput( this.terminalSession, command + '\n' ); } } async *receiveOutput() { if (!this.terminalSession) { return; } for await (const message of this.sandbox.terminal.iterOutput(this.terminalSession)) { yield { type: message.type || 'output', data: message.data || '', timestamp: message.timestamp }; } } async resize(rows, cols) { if (this.terminalSession) { await this.sandbox.terminal.resize( this.terminalSession, rows, cols ); } } async disconnect() { this.terminalSession = null; } } // Usage const sandbox = await Sandbox.create({ template: 'code-interpreter', apiKey: process.env.HOPX_API_KEY }); const terminal = new IDETerminal(sandbox); await terminal.connect(); await terminal.sendCommand('pwd'); await terminal.sendCommand('ls -la'); for await (const output of terminal.receiveOutput()) { console.log(output); // Break after some outputs break; } await terminal.disconnect(); await sandbox.kill(); ``` ### Step 3: Multi-File Project Execution Execute projects with multiple files: ```python Python theme={null} class IDEProjectExecutor: def __init__(self, sandbox: Sandbox): self.sandbox = sandbox def execute_project(self, entry_point: str, working_dir: str = "/workspace/project") -> Dict[str, Any]: """Execute a multi-file project""" try: # Determine language from file extension language = self._detect_language(entry_point) # Execute in project directory result = self.sandbox.run_code( self._get_execution_code(entry_point, language), language=language, working_dir=working_dir, timeout=30 ) return { "success": result.success, "stdout": result.stdout, "stderr": result.stderr, "exit_code": result.exit_code, "execution_time": result.execution_time } except Exception as e: return { "success": False, "error": str(e) } def _detect_language(self, file_path: str) -> str: """Detect language from file extension""" ext = file_path.split('.')[-1].lower() language_map = { 'py': 'python', 'js': 'javascript', 'ts': 'typescript', 'java': 'java', 'go': 'go' } return language_map.get(ext, 'python') def _get_execution_code(self, entry_point: str, language: str) -> str: """Get code to execute based on language""" if language == 'python': return f"exec(open('{entry_point}').read())" elif language == 'javascript': return f"require('{entry_point.replace('.js', '')}')" else: # For other languages, use appropriate execution method return f"# Execute {entry_point}" # Usage sandbox = Sandbox.create(template="code-interpreter", api_key=os.getenv("HOPX_API_KEY")) executor = IDEProjectExecutor(sandbox) # Create a multi-file project sandbox.files.write("/workspace/project/utils.py", """ def greet(name): return f"Hello, {name}!" """) sandbox.files.write("/workspace/project/main.py", """ from utils import greet print(greet("World")) """) # Execute result = executor.execute_project("main.py") print(result) sandbox.kill() ``` ```javascript JavaScript theme={null} class IDEProjectExecutor { constructor(sandbox) { this.sandbox = sandbox; } async executeProject(entryPoint, workingDir = '/workspace/project') { try { // Determine language from file extension const language = this.detectLanguage(entryPoint); // Execute in project directory const executionCode = this.getExecutionCode(entryPoint, language); const result = await this.sandbox.runCode(executionCode, { language, workingDir, timeout: 30 }); return { success: result.success, stdout: result.stdout, stderr: result.stderr, exitCode: result.exit_code, executionTime: result.execution_time }; } catch (error) { return { success: false, error: error.message }; } } detectLanguage(filePath) { const ext = filePath.split('.').pop().toLowerCase(); const languageMap = { 'py': 'python', 'js': 'javascript', 'ts': 'typescript', 'java': 'java', 'go': 'go' }; return languageMap[ext] || 'python'; } getExecutionCode(entryPoint, language) { if (language === 'python') { return `exec(open('${entryPoint}').read())`; } else if (language === 'javascript') { return `require('${entryPoint.replace('.js', '')}')`; } else { return `# Execute ${entryPoint}`; } } } // Usage const sandbox = await Sandbox.create({ template: 'code-interpreter', apiKey: process.env.HOPX_API_KEY }); const executor = new IDEProjectExecutor(sandbox); // Create a multi-file project await sandbox.files.write('/workspace/project/utils.py', ` def greet(name): return f"Hello, {name}!" `); await sandbox.files.write('/workspace/project/main.py', ` from utils import greet print(greet("World")) `); // Execute const result = await executor.executeProject('main.py'); console.log(result); await sandbox.kill(); ``` ### Step 4: Complete IDE Backend Combine all components into a complete IDE backend: ```python Python theme={null} class CloudIDEBackend: def __init__(self, api_key: str): self.api_key = api_key self.fs = IDEFileSystem(api_key) self.sandbox = None self.terminal = None self.executor = None def initialize(self, project_id: str) -> Dict[str, Any]: """Initialize IDE session""" result = self.fs.initialize_project(project_id) if result["success"]: self.sandbox = self.fs.sandbox self.terminal = IDETerminal(self.sandbox) self.executor = IDEProjectExecutor(self.sandbox) return result async def handle_file_operation(self, operation: str, **kwargs) -> Dict[str, Any]: """Handle file operations""" if operation == "list": return {"files": self.fs.list_files(kwargs.get("path", "/workspace/project"))} elif operation == "read": return self.fs.read_file(kwargs["path"]) elif operation == "write": return self.fs.write_file(kwargs["path"], kwargs["content"]) elif operation == "create_dir": return self.fs.create_directory(kwargs["path"]) elif operation == "delete": return self.fs.delete_file(kwargs["path"]) else: return {"success": False, "error": f"Unknown operation: {operation}"} async def handle_terminal_command(self, command: str) -> Dict[str, Any]: """Handle terminal command""" if not self.terminal.terminal_session: await self.terminal.connect() await self.terminal.send_command(command) # Collect output outputs = [] async for output in self.terminal.receive_output(): outputs.append(output) if len(outputs) >= 10: # Limit output break return {"outputs": outputs} def handle_execution(self, entry_point: str) -> Dict[str, Any]: """Handle code execution""" return self.executor.execute_project(entry_point) def cleanup(self): """Clean up all resources""" if self.terminal: asyncio.run(self.terminal.disconnect()) self.fs.cleanup() # Usage ide = CloudIDEBackend(api_key=os.getenv("HOPX_API_KEY")) ide.initialize("my-project") # File operations result = asyncio.run(ide.handle_file_operation("write", path="/workspace/project/app.py", content="print('Hello')")) print(result) # Terminal result = asyncio.run(ide.handle_terminal_command("ls -la")) print(result) # Execution result = ide.handle_execution("app.py") print(result) ide.cleanup() ``` ```javascript JavaScript theme={null} class CloudIDEBackend { constructor(apiKey) { this.apiKey = apiKey; this.fs = new IDEFileSystem(apiKey); this.sandbox = null; this.terminal = null; this.executor = null; } async initialize(projectId) { const result = await this.fs.initializeProject(projectId); if (result.success) { this.sandbox = this.fs.sandbox; this.terminal = new IDETerminal(this.sandbox); this.executor = new IDEProjectExecutor(this.sandbox); } return result; } async handleFileOperation(operation, ...args) { const kwargs = args[0] || {}; if (operation === 'list') { return { files: await this.fs.listFiles(kwargs.path || '/workspace/project') }; } else if (operation === 'read') { return await this.fs.readFile(kwargs.path); } else if (operation === 'write') { return await this.fs.writeFile(kwargs.path, kwargs.content); } else if (operation === 'createDir') { return await this.fs.createDirectory(kwargs.path); } else if (operation === 'delete') { return await this.fs.deleteFile(kwargs.path); } else { return { success: false, error: `Unknown operation: ${operation}` }; } } async handleTerminalCommand(command) { if (!this.terminal.terminalSession) { await this.terminal.connect(); } await this.terminal.sendCommand(command); // Collect output const outputs = []; for await (const output of this.terminal.receiveOutput()) { outputs.push(output); if (outputs.length >= 10) { // Limit output break; } } return { outputs }; } async handleExecution(entryPoint) { return await this.executor.executeProject(entryPoint); } async cleanup() { if (this.terminal) { await this.terminal.disconnect(); } await this.fs.cleanup(); } } // Usage const ide = new CloudIDEBackend(process.env.HOPX_API_KEY); await ide.initialize('my-project'); // File operations const result1 = await ide.handleFileOperation('write', { path: '/workspace/project/app.py', content: "print('Hello')" }); console.log(result1); // Terminal const result2 = await ide.handleTerminalCommand('ls -la'); console.log(result2); // Execution const result3 = await ide.handleExecution('app.py'); console.log(result3); await ide.cleanup(); ``` ## Best Practices ### Security Always validate file paths to prevent directory traversal attacks. Never allow access to files outside the project directory. 1. **Path Validation**: Sanitize all file paths 2. **Resource Limits**: Set appropriate timeouts and memory limits 3. **Sandbox Isolation**: One sandbox per user/project 4. **Input Validation**: Validate all user inputs ### Performance Use file watching to detect changes and update the UI in real-time, reducing the need for polling. 1. **Sandbox Reuse**: Reuse sandboxes for the duration of an IDE session 2. **Caching**: Cache file listings and metadata 3. **Async Operations**: Use async/await for all I/O operations 4. **Connection Pooling**: Manage WebSocket connections efficiently ### User Experience 1. **Real-Time Updates**: Use file watching for live file updates 2. **Auto-Save**: Implement auto-save functionality 3. **Error Handling**: Provide clear error messages 4. **Progress Indicators**: Show execution progress ## Real-World Examples This pattern is used by: * **Replit**: Online IDE and coding platform * **CodeSandbox**: Online code editor and prototyping tool * **Gitpod**: Cloud development environments * **GitHub Codespaces**: Cloud-based VS Code ## Related Cookbooks * [Browser-Based Code Editor](/cookbooks/development/browser-editor) - Client-side implementation * [Terminal WebSocket](/core-concepts/terminal/websocket) - Terminal integration * [Code Execution](/core-concepts/code-execution/synchronous) - Execution concepts ## Next Steps 1. Implement WebSocket server for real-time communication 2. Add file watching for live updates 3. Create a frontend editor interface 4. Implement package management (pip, npm, etc.) 5. Add debugging support # Coding Interview Platform Source: https://docs.hopx.ai/cookbooks/educational/coding-interviews Build a technical interview platform with problem execution environments, time limit enforcement, test case management, and performance monitoring Build a production-ready coding interview platform where candidates solve problems under time constraints. This cookbook demonstrates how to create a platform similar to LeetCode or HackerRank for technical interviews. ## Overview Coding interview platforms provide a controlled environment for technical assessments. Candidates solve problems within time limits, and the system validates solutions, monitors performance, and generates assessment reports. ## Prerequisites * HopX API key ([Get one here](https://console.hopx.dev/api-keys)) * Python 3.8+ or Node.js 16+ * Understanding of interview assessment workflows * Basic knowledge of performance monitoring ## Architecture ``` ┌──────────────┐ │ Candidate │ Submits solution └──────┬───────┘ │ ▼ ┌─────────────────┐ │ Interview │ Validate, monitor │ Platform │ └──────┬──────────┘ │ ▼ ┌─────────────────┐ │ HopX Sandbox │ Execute & time └─────────────────┘ ``` ## Implementation ### Step 1: Time-Limited Execution Execute code with strict time limits: ```python Python theme={null} from hopx_ai import Sandbox import os import time from typing import Dict, Any class InterviewPlatform: def __init__(self, api_key: str): self.api_key = api_key def execute_with_time_limit(self, code: str, time_limit: int, language: str = "python") -> Dict[str, Any]: """Execute code with strict time limit""" sandbox = None start_time = time.time() try: sandbox = Sandbox.create( template="code-interpreter", api_key=self.api_key, timeout_seconds=time_limit + 5 ) # Execute with timeout result = sandbox.run_code(code, language=language, timeout=time_limit) elapsed = time.time() - start_time # Check if timeout was exceeded if elapsed >= time_limit: return { "success": False, "timeout": True, "elapsed_time": elapsed, "time_limit": time_limit, "error": "Time limit exceeded" } return { "success": result.success, "stdout": result.stdout, "stderr": result.stderr, "elapsed_time": elapsed, "time_limit": time_limit, "within_limit": elapsed < time_limit } except Exception as e: return { "success": False, "error": str(e), "elapsed_time": time.time() - start_time } finally: if sandbox: sandbox.kill() # Usage platform = InterviewPlatform(api_key=os.getenv("HOPX_API_KEY")) result = platform.execute_with_time_limit( code="print('Hello')", time_limit=5 # 5 second limit ) print(result) ``` ```javascript JavaScript theme={null} import { Sandbox } from '@hopx-ai/sdk'; class InterviewPlatform { constructor(apiKey) { this.apiKey = apiKey; } async executeWithTimeLimit(code, timeLimit, language = 'python') { let sandbox = null; const startTime = Date.now(); try { sandbox = await Sandbox.create({ template: 'code-interpreter', apiKey: this.apiKey, timeoutSeconds: timeLimit + 5 }); // Execute with timeout const result = await sandbox.runCode(code, { language, timeout: timeLimit }); const elapsed = (Date.now() - startTime) / 1000; // Check if timeout was exceeded if (elapsed >= timeLimit) { return { success: false, timeout: true, elapsedTime: elapsed, timeLimit, error: 'Time limit exceeded' }; } return { success: result.success, stdout: result.stdout, stderr: result.stderr, elapsedTime: elapsed, timeLimit, withinLimit: elapsed < timeLimit }; } catch (error) { return { success: false, error: error.message, elapsedTime: (Date.now() - startTime) / 1000 }; } finally { if (sandbox) { await sandbox.kill(); } } } } // Usage const platform = new InterviewPlatform(process.env.HOPX_API_KEY); const result = await platform.executeWithTimeLimit( "print('Hello')", 5 // 5 second limit ); console.log(result); ``` ### Step 2: Performance Monitoring Monitor code performance: ```python Python theme={null} class PerformanceMonitor: def __init__(self, sandbox: Sandbox): self.sandbox = sandbox def monitor_execution(self, code: str) -> Dict[str, Any]: """Monitor code execution performance""" import time start_time = time.time() result = self.sandbox.run_code(code, timeout=30) elapsed = time.time() - start_time # Get system metrics metrics = self.sandbox.get_metrics_snapshot() return { "execution_time": elapsed, "code_execution_time": result.execution_time, "memory_usage": getattr(metrics, 'memory_usage_mb', 0) if hasattr(metrics, 'memory_usage_mb') else 0, "cpu_usage": getattr(metrics, 'cpu_percent', 0) if hasattr(metrics, 'cpu_percent') else 0, "success": result.success } # Usage sandbox = Sandbox.create(template="code-interpreter", api_key=os.getenv("HOPX_API_KEY")) monitor = PerformanceMonitor(sandbox) metrics = monitor.monitor_execution("print('Hello')") print(f"Execution time: {metrics['execution_time']:.2f}s") print(f"Memory usage: {metrics['memory_usage']}MB") sandbox.kill() ``` ```javascript JavaScript theme={null} class PerformanceMonitor { constructor(sandbox) { this.sandbox = sandbox; } async monitorExecution(code) { const startTime = Date.now(); const result = await this.sandbox.runCode(code, { timeout: 30 }); const elapsed = (Date.now() - startTime) / 1000; // Get system metrics const metrics = await this.sandbox.getSystemMetrics(); return { executionTime: elapsed, codeExecutionTime: result.execution_time, memoryUsage: metrics.memory_usage_mb || 0, cpuUsage: metrics.cpu_percent || 0, success: result.success }; } } // Usage const sandbox = await Sandbox.create({ template: 'code-interpreter', apiKey: process.env.HOPX_API_KEY }); const monitor = new PerformanceMonitor(sandbox); const metrics = await monitor.monitorExecution("print('Hello')"); console.log(`Execution time: ${metrics.executionTime.toFixed(2)}s`); console.log(`Memory usage: ${metrics.memoryUsage}MB`); await sandbox.kill(); ``` ## Best Practices 1. **Time Enforcement**: Strictly enforce time limits 2. **Performance Tracking**: Monitor execution time and resource usage 3. **Test Case Management**: Organize test cases efficiently 4. **Result Reporting**: Generate comprehensive assessment reports ## Related Cookbooks * [Online Coding Platform](/cookbooks/educational/online-coding-platform) - Full coding platform * [Interactive Tutorials](/cookbooks/educational/interactive-tutorials) - Learning platform * [Isolated Test Execution](/cookbooks/testing/isolated-test-execution) - Test isolation ## Next Steps 1. Implement problem database 2. Add candidate authentication 3. Create assessment dashboard 4. Implement result analytics 5. Add video/audio interview features # Interactive Programming Tutorials Source: https://docs.hopx.ai/cookbooks/educational/interactive-tutorials Build Codecademy-style interactive learning with step-by-step code execution, progress tracking, hint systems, and solution validation Build an interactive programming tutorial platform where students learn by writing and executing code step-by-step. This cookbook demonstrates how to create a Codecademy-style learning experience using HopX. ## Overview Interactive programming tutorials guide students through learning by executing code at each step. The system validates solutions, provides hints, tracks progress, and ensures students understand concepts before moving forward. ## Prerequisites * HopX API key ([Get one here](https://console.hopx.dev/api-keys)) * Python 3.8+ or Node.js 16+ * Understanding of educational content structure * Basic knowledge of progress tracking ## Architecture ``` ┌──────────────┐ │ Student │ Submits code └──────┬───────┘ │ ▼ ┌─────────────────┐ │ Tutorial │ Validate, provide hints │ Engine │ └──────┬──────────┘ │ ▼ ┌─────────────────┐ │ HopX Sandbox │ Execute & validate └─────────────────┘ ``` ## Implementation ### Step 1: Tutorial Step Execution Execute and validate tutorial steps: ```python Python theme={null} from hopx_ai import Sandbox import os from typing import Dict, List, Any class TutorialStep: def __init__(self, step_id: str, instructions: str, solution: str, hints: List[str]): self.step_id = step_id self.instructions = instructions self.solution = solution self.hints = hints class InteractiveTutorial: def __init__(self, api_key: str): self.api_key = api_key self.sandbox = None self.current_step = 0 self.steps = [] def initialize(self): """Initialize tutorial session""" self.sandbox = Sandbox.create( template="code-interpreter", api_key=self.api_key, timeout_seconds=3600 ) def add_step(self, step: TutorialStep): """Add tutorial step""" self.steps.append(step) def validate_step(self, step_index: int, student_code: str) -> Dict[str, Any]: """Validate student code for a step""" step = self.steps[step_index] # Execute student code result = self.sandbox.run_code(student_code, timeout=10) # Check if solution matches solution_result = self.sandbox.run_code(step.solution, timeout=10) # Compare outputs student_output = result.stdout.strip() if result.success else "" solution_output = solution_result.stdout.strip() if solution_result.success else "" passed = student_output == solution_output and result.success return { "passed": passed, "student_output": student_output, "expected_output": solution_output, "hint": step.hints[0] if not passed and step.hints else None, "success": result.success } def get_next_hint(self, step_index: int, hint_index: int) -> str: """Get hint for current step""" step = self.steps[step_index] if hint_index < len(step.hints): return step.hints[hint_index] return "No more hints available" def cleanup(self): """Clean up tutorial session""" if self.sandbox: self.sandbox.kill() self.sandbox = None # Usage tutorial = InteractiveTutorial(api_key=os.getenv("HOPX_API_KEY")) tutorial.initialize() # Add steps tutorial.add_step(TutorialStep( step_id="step_1", instructions="Print 'Hello, World!'", solution="print('Hello, World!')", hints=["Use the print() function", "Remember to use quotes around the text"] )) # Validate student code result = tutorial.validate_step(0, "print('Hello, World!')") print(f"Passed: {result['passed']}") tutorial.cleanup() ``` ```javascript JavaScript theme={null} import { Sandbox } from '@hopx-ai/sdk'; class TutorialStep { constructor(stepId, instructions, solution, hints) { this.stepId = stepId; this.instructions = instructions; this.solution = solution; this.hints = hints; } } class InteractiveTutorial { constructor(apiKey) { this.apiKey = apiKey; this.sandbox = null; this.currentStep = 0; this.steps = []; } async initialize() { this.sandbox = await Sandbox.create({ template: 'code-interpreter', apiKey: this.apiKey, timeoutSeconds: 3600 }); } addStep(step) { this.steps.push(step); } async validateStep(stepIndex, studentCode) { const step = this.steps[stepIndex]; // Execute student code const result = await this.sandbox.runCode(studentCode, { timeout: 10 }); // Check if solution matches const solutionResult = await this.sandbox.runCode(step.solution, { timeout: 10 }); // Compare outputs const studentOutput = result.success ? result.stdout.trim() : ''; const solutionOutput = solutionResult.success ? solutionResult.stdout.trim() : ''; const passed = studentOutput === solutionOutput && result.success; return { passed, studentOutput, expectedOutput: solutionOutput, hint: !passed && step.hints.length > 0 ? step.hints[0] : null, success: result.success }; } getNextHint(stepIndex, hintIndex) { const step = this.steps[stepIndex]; if (hintIndex < step.hints.length) { return step.hints[hintIndex]; } return 'No more hints available'; } async cleanup() { if (this.sandbox) { await this.sandbox.kill(); this.sandbox = null; } } } // Usage const tutorial = new InteractiveTutorial(process.env.HOPX_API_KEY); await tutorial.initialize(); // Add steps tutorial.addStep(new TutorialStep( 'step_1', "Print 'Hello, World!'", "print('Hello, World!')", ['Use the print() function', 'Remember to use quotes around the text'] )); // Validate student code const result = await tutorial.validateStep(0, "print('Hello, World!')"); console.log(`Passed: ${result.passed}`); await tutorial.cleanup(); ``` ### Step 2: Progress Tracking Track student progress through tutorials: ```python Python theme={null} class ProgressTracker: def __init__(self): self.progress = {} def update_progress(self, student_id: str, step_id: str, passed: bool): """Update student progress""" if student_id not in self.progress: self.progress[student_id] = { "completed_steps": [], "current_step": 0, "total_steps": 0 } if passed and step_id not in self.progress[student_id]["completed_steps"]: self.progress[student_id]["completed_steps"].append(step_id) def get_progress(self, student_id: str) -> Dict[str, Any]: """Get student progress""" if student_id not in self.progress: return { "completed_steps": [], "current_step": 0, "completion_percentage": 0 } student_progress = self.progress[student_id] total = student_progress.get("total_steps", 1) completed = len(student_progress["completed_steps"]) return { "completed_steps": student_progress["completed_steps"], "current_step": student_progress["current_step"], "completion_percentage": (completed / total * 100) if total > 0 else 0 } # Usage tracker = ProgressTracker() tracker.update_progress("student_1", "step_1", True) tracker.update_progress("student_1", "step_2", True) progress = tracker.get_progress("student_1") print(f"Completion: {progress['completion_percentage']:.1f}%") ``` ```javascript JavaScript theme={null} class ProgressTracker { constructor() { this.progress = {}; } updateProgress(studentId, stepId, passed) { if (!this.progress[studentId]) { this.progress[studentId] = { completedSteps: [], currentStep: 0, totalSteps: 0 }; } if (passed && !this.progress[studentId].completedSteps.includes(stepId)) { this.progress[studentId].completedSteps.push(stepId); } } getProgress(studentId) { if (!this.progress[studentId]) { return { completedSteps: [], currentStep: 0, completionPercentage: 0 }; } const studentProgress = this.progress[studentId]; const total = studentProgress.totalSteps || 1; const completed = studentProgress.completedSteps.length; return { completedSteps: studentProgress.completedSteps, currentStep: studentProgress.currentStep, completionPercentage: total > 0 ? (completed / total * 100) : 0 }; } } // Usage const tracker = new ProgressTracker(); tracker.updateProgress('student_1', 'step_1', true); tracker.updateProgress('student_1', 'step_2', true); const progress = tracker.getProgress('student_1'); console.log(`Completion: ${progress.completionPercentage.toFixed(1)}%`); ``` ## Best Practices 1. **Step-by-Step Learning**: Break concepts into small, digestible steps 2. **Immediate Feedback**: Provide instant validation feedback 3. **Progressive Hints**: Offer hints that guide without giving away solutions 4. **Progress Persistence**: Save progress so students can resume ## Related Cookbooks * [Online Coding Platform](/cookbooks/educational/online-coding-platform) - Full coding platform * [Coding Interview Platform](/cookbooks/educational/coding-interviews) - Interview preparation ## Next Steps 1. Create tutorial content management system 2. Implement hint system with multiple levels 3. Add progress persistence 4. Create tutorial authoring tools 5. Add analytics and reporting # Building an Online Coding Platform Source: https://docs.hopx.ai/cookbooks/educational/online-coding-platform Create a LeetCode/HackerRank-style platform with secure code execution, test case validation, and multi-language support Build a production-ready online coding platform where students can submit code, run test cases, and receive instant feedback. This cookbook demonstrates how to create a platform similar to LeetCode or HackerRank using HopX for secure code execution. ## Overview Online coding platforms enable students to practice programming by solving problems and submitting solutions. The platform executes code securely, validates against test cases, and provides feedback. ## Prerequisites * HopX API key ([Get one here](https://console.hopx.dev/api-keys)) * Python 3.8+ or Node.js 16+ * Understanding of test case validation * Basic knowledge of educational platform architecture ## Architecture ``` ┌──────────────┐ │ Student │ Submits code └──────┬───────┘ │ ▼ ┌─────────────────┐ │ Platform API │ Validates & queues └──────┬──────────┘ │ ▼ ┌─────────────────┐ │ HopX Sandbox │ Execute code └──────┬──────────┘ │ ▼ ┌─────────────────┐ │ Test Runner │ Validate results └──────┬──────────┘ │ ▼ ┌─────────────────┐ │ Feedback │ Return results └─────────────────┘ ``` ## Implementation ### Step 1: Basic Code Submission and Execution Create a system that accepts code submissions and executes them: ```python Python theme={null} from hopx_ai import Sandbox import os import json from typing import Dict, List, Any class CodingPlatform: def __init__(self, api_key: str): self.api_key = api_key def execute_submission(self, code: str, language: str, timeout: int = 10) -> Dict[str, Any]: """Execute student code submission""" sandbox = None try: # Create isolated sandbox for this submission sandbox = Sandbox.create( template="code-interpreter", api_key=self.api_key, timeout_seconds=timeout + 5 # Extra buffer ) # Execute code result = sandbox.run_code(code, language=language, timeout=timeout) return { "success": result.success, "stdout": result.stdout, "stderr": result.stderr, "exit_code": result.exit_code, "execution_time": result.execution_time, "timeout": result.execution_time >= timeout } except Exception as e: return { "success": False, "error": str(e), "stderr": str(e) } finally: if sandbox: sandbox.kill() def validate_solution(self, code: str, test_cases: List[Dict], language: str = "python") -> Dict[str, Any]: """Validate solution against test cases""" results = [] all_passed = True for i, test_case in enumerate(test_cases): # Prepare test code test_code = self._prepare_test_code(code, test_case, language) # Execute execution_result = self.execute_submission(test_code, language, timeout=5) # Check result passed = self._check_test_result(execution_result, test_case) results.append({ "test_case": i + 1, "passed": passed, "input": test_case.get("input"), "expected": test_case.get("expected"), "actual": execution_result.get("stdout", "").strip(), "error": execution_result.get("stderr") if not passed else None }) if not passed: all_passed = False return { "all_passed": all_passed, "total_tests": len(test_cases), "passed_tests": sum(1 for r in results if r["passed"]), "results": results } def _prepare_test_code(self, code: str, test_case: Dict, language: str) -> str: """Prepare code with test case""" if language == "python": input_data = test_case.get("input", "") expected = test_case.get("expected", "") # Wrap student code with test test_code = f""" {code} # Test case test_input = {input_data} result = solution(test_input) # Assuming function named 'solution' expected = {expected} if result == expected: print("PASS") else: print(f"FAIL: Expected {{expected}}, got {{result}}") """ return test_code else: # Similar for other languages return code def _check_test_result(self, execution_result: Dict, test_case: Dict) -> bool: """Check if test case passed""" if not execution_result.get("success"): return False stdout = execution_result.get("stdout", "").strip() return "PASS" in stdout or stdout == str(test_case.get("expected", "")).strip() # Usage platform = CodingPlatform(api_key=os.getenv("HOPX_API_KEY")) # Student submission student_code = """ def solution(nums): return sum(nums) """ # Test cases test_cases = [ {"input": "[1, 2, 3]", "expected": 6}, {"input": "[10, 20, 30]", "expected": 60}, {"input": "[]", "expected": 0} ] # Validate result = platform.validate_solution(student_code, test_cases) print(json.dumps(result, indent=2)) ``` ```javascript JavaScript theme={null} import { Sandbox } from '@hopx-ai/sdk'; class CodingPlatform { constructor(apiKey) { this.apiKey = apiKey; } async executeSubmission(code, language, timeout = 10) { let sandbox = null; try { // Create isolated sandbox for this submission sandbox = await Sandbox.create({ template: 'code-interpreter', apiKey: this.apiKey, timeoutSeconds: timeout + 5 // Extra buffer }); // Execute code const result = await sandbox.runCode(code, { language, timeout }); return { success: result.success, stdout: result.stdout, stderr: result.stderr, exitCode: result.exit_code, executionTime: result.execution_time, timeout: result.execution_time >= timeout }; } catch (error) { return { success: false, error: error.message, stderr: error.toString() }; } finally { if (sandbox) { await sandbox.kill(); } } } async validateSolution(code, testCases, language = 'python') { const results = []; let allPassed = true; for (let i = 0; i < testCases.length; i++) { const testCase = testCases[i]; // Prepare test code const testCode = this.prepareTestCode(code, testCase, language); // Execute const executionResult = await this.executeSubmission(testCode, language, 5); // Check result const passed = this.checkTestResult(executionResult, testCase); results.push({ testCase: i + 1, passed, input: testCase.input, expected: testCase.expected, actual: executionResult.stdout ? executionResult.stdout.trim() : '', error: !passed ? executionResult.stderr : null }); if (!passed) { allPassed = false; } } return { allPassed, totalTests: testCases.length, passedTests: results.filter(r => r.passed).length, results }; } prepareTestCode(code, testCase, language) { if (language === 'python') { const inputData = testCase.input || ''; const expected = testCase.expected || ''; // Wrap student code with test return ` ${code} # Test case test_input = ${inputData} result = solution(test_input) # Assuming function named 'solution' expected = ${expected} if result == expected: print("PASS") else: print(f"FAIL: Expected {expected}, got {result}") `; } else { // Similar for other languages return code; } } checkTestResult(executionResult, testCase) { if (!executionResult.success) { return false; } const stdout = executionResult.stdout ? executionResult.stdout.trim() : ''; return stdout.includes('PASS') || stdout === String(testCase.expected).trim(); } } // Usage const platform = new CodingPlatform(process.env.HOPX_API_KEY); // Student submission const studentCode = ` def solution(nums): return sum(nums) `; // Test cases const testCases = [ { input: '[1, 2, 3]', expected: 6 }, { input: '[10, 20, 30]', expected: 60 }, { input: '[]', expected: 0 } ]; // Validate const result = await platform.validateSolution(studentCode, testCases); console.log(JSON.stringify(result, null, 2)); ``` ### Step 2: Multi-Language Support Support multiple programming languages: ```python Python theme={null} class MultiLanguagePlatform(CodingPlatform): SUPPORTED_LANGUAGES = { "python": { "template": "code-interpreter", "extension": ".py", "runner": "python" }, "javascript": { "template": "code-interpreter", "extension": ".js", "runner": "node" }, "java": { "template": "code-interpreter", "extension": ".java", "runner": "javac && java" } } def execute_submission(self, code: str, language: str, timeout: int = 10) -> Dict[str, Any]: """Execute code in specified language""" if language not in self.SUPPORTED_LANGUAGES: return { "success": False, "error": f"Unsupported language: {language}" } lang_config = self.SUPPORTED_LANGUAGES[language] sandbox = None try: sandbox = Sandbox.create( template=lang_config["template"], api_key=self.api_key, timeout_seconds=timeout + 5 ) # Write code to file filename = f"/workspace/solution{lang_config['extension']}" sandbox.files.write(filename, code) # Execute based on language if language == "python": result = sandbox.run_code(code, language="python", timeout=timeout) elif language == "javascript": result = sandbox.run_code(code, language="javascript", timeout=timeout) elif language == "java": # Compile and run Java compile_result = sandbox.commands.run( f"javac {filename}", timeout=5 ) if not compile_result.exit_code == 0: return { "success": False, "stderr": compile_result.stderr, "error": "Compilation failed" } # Run compiled class result = sandbox.commands.run( "java -cp /workspace Solution", timeout=timeout ) return { "success": result.success if hasattr(result, 'success') else result.exit_code == 0, "stdout": result.stdout if hasattr(result, 'stdout') else result.stdout, "stderr": result.stderr if hasattr(result, 'stderr') else result.stderr, "exit_code": result.exit_code if hasattr(result, 'exit_code') else result.exit_code, "language": language } except Exception as e: return { "success": False, "error": str(e), "language": language } finally: if sandbox: sandbox.kill() # Usage platform = MultiLanguagePlatform(api_key=os.getenv("HOPX_API_KEY")) # Python submission python_code = "print('Hello from Python!')" result = platform.execute_submission(python_code, "python") print(result) # JavaScript submission js_code = "console.log('Hello from JavaScript!');" result = platform.execute_submission(js_code, "javascript") print(result) ``` ```javascript JavaScript theme={null} class MultiLanguagePlatform extends CodingPlatform { constructor(apiKey) { super(apiKey); this.supportedLanguages = { python: { template: 'code-interpreter', extension: '.py', runner: 'python' }, javascript: { template: 'code-interpreter', extension: '.js', runner: 'node' }, java: { template: 'code-interpreter', extension: '.java', runner: 'javac && java' } }; } async executeSubmission(code, language, timeout = 10) { if (!this.supportedLanguages[language]) { return { success: false, error: `Unsupported language: ${language}` }; } const langConfig = this.supportedLanguages[language]; let sandbox = null; try { sandbox = await Sandbox.create({ template: langConfig.template, apiKey: this.apiKey, timeoutSeconds: timeout + 5 }); // Write code to file const filename = `/workspace/solution${langConfig.extension}`; await sandbox.files.write(filename, code); // Execute based on language let result; if (language === 'python') { result = await sandbox.runCode(code, { language: 'python', timeout }); } else if (language === 'javascript') { result = await sandbox.runCode(code, { language: 'javascript', timeout }); } else if (language === 'java') { // Compile and run Java const compileResult = await sandbox.commands.run( `javac ${filename}`, { timeout: 5 } ); if (compileResult.exit_code !== 0) { return { success: false, stderr: compileResult.stderr, error: 'Compilation failed' }; } // Run compiled class result = await sandbox.commands.run( 'java -cp /workspace Solution', { timeout } ); } return { success: result.success !== undefined ? result.success : result.exit_code === 0, stdout: result.stdout || '', stderr: result.stderr || '', exitCode: result.exit_code || result.exit_code, language }; } catch (error) { return { success: false, error: error.message, language }; } finally { if (sandbox) { await sandbox.kill(); } } } } // Usage const platform = new MultiLanguagePlatform(process.env.HOPX_API_KEY); // Python submission const pythonCode = "print('Hello from Python!')"; const result1 = await platform.executeSubmission(pythonCode, 'python'); console.log(result1); // JavaScript submission const jsCode = "console.log('Hello from JavaScript!');"; const result2 = await platform.executeSubmission(jsCode, 'javascript'); console.log(result2); ``` ### Step 3: Resource Limits and Timeout Management Implement resource limits to prevent abuse: ```python Python theme={null} class ResourceLimitedPlatform(CodingPlatform): def __init__(self, api_key: str, max_execution_time: int = 10, max_memory_mb: int = 512): super().__init__(api_key) self.max_execution_time = max_execution_time self.max_memory_mb = max_memory_mb def execute_submission(self, code: str, language: str, timeout: int = None) -> Dict[str, Any]: """Execute with resource limits""" # Enforce maximum timeout actual_timeout = min(timeout or self.max_execution_time, self.max_execution_time) sandbox = None try: # Create sandbox with resource limits sandbox = Sandbox.create( template="code-interpreter", # Template defines resources api_key=self.api_key, timeout_seconds=actual_timeout + 2 # Small buffer ) # Set environment variables for resource monitoring sandbox.env.set_all({ "MAX_EXECUTION_TIME": str(actual_timeout), "MAX_MEMORY_MB": str(self.max_memory_mb) }) # Execute with strict timeout result = sandbox.run_code(code, language=language, timeout=actual_timeout) # Check if timeout was exceeded if result.execution_time >= actual_timeout: return { "success": False, "error": "Execution timeout exceeded", "timeout": True, "execution_time": result.execution_time } # Check memory usage (if available) metrics = sandbox.get_metrics_snapshot() memory_used = metrics.get('memory_usage_mb', 0) if hasattr(metrics, 'get') else 0 if memory_used > self.max_memory_mb: return { "success": False, "error": f"Memory limit exceeded: {memory_used}MB > {self.max_memory_mb}MB", "memory_exceeded": True } return { "success": result.success, "stdout": result.stdout, "stderr": result.stderr, "execution_time": result.execution_time, "memory_used_mb": memory_used } except Exception as e: return { "success": False, "error": str(e) } finally: if sandbox: sandbox.kill() # Usage platform = ResourceLimitedPlatform( api_key=os.getenv("HOPX_API_KEY"), max_execution_time=5, # 5 second limit max_memory_mb=256 # 256MB limit ) result = platform.execute_submission("print('Hello')", "python") print(result) ``` ```javascript JavaScript theme={null} class ResourceLimitedPlatform extends CodingPlatform { constructor(apiKey, maxExecutionTime = 10, maxMemoryMB = 512) { super(apiKey); this.maxExecutionTime = maxExecutionTime; this.maxMemoryMB = maxMemoryMB; } async executeSubmission(code, language, timeout = null) { // Enforce maximum timeout const actualTimeout = Math.min(timeout || this.maxExecutionTime, this.maxExecutionTime); let sandbox = null; try { // Create sandbox with resource limits sandbox = await Sandbox.create({ template: 'code-interpreter', // Template defines resources apiKey: this.apiKey, timeoutSeconds: actualTimeout + 2 // Small buffer }); // Set environment variables for resource monitoring await sandbox.env.setAll({ MAX_EXECUTION_TIME: String(actualTimeout), MAX_MEMORY_MB: String(this.maxMemoryMB) }); // Execute with strict timeout const result = await sandbox.runCode(code, { language, timeout: actualTimeout }); // Check if timeout was exceeded if (result.execution_time >= actualTimeout) { return { success: false, error: 'Execution timeout exceeded', timeout: true, executionTime: result.execution_time }; } // Check memory usage (if available) const metrics = await sandbox.getSystemMetrics(); const memoryUsed = metrics.memory_usage_mb || 0; if (memoryUsed > this.maxMemoryMB) { return { success: false, error: `Memory limit exceeded: ${memoryUsed}MB > ${this.maxMemoryMB}MB`, memoryExceeded: true }; } return { success: result.success, stdout: result.stdout, stderr: result.stderr, executionTime: result.execution_time, memoryUsedMB: memoryUsed }; } catch (error) { return { success: false, error: error.message }; } finally { if (sandbox) { await sandbox.kill(); } } } } // Usage const platform = new ResourceLimitedPlatform( process.env.HOPX_API_KEY, 5, // 5 second limit 256 // 256MB limit ); const result = await platform.executeSubmission("print('Hello')", 'python'); console.log(result); ``` ### Step 4: Grading and Feedback System Create a comprehensive grading system: ```python Python theme={null} class GradingSystem: def __init__(self, platform: CodingPlatform): self.platform = platform def grade_submission(self, code: str, problem: Dict, language: str = "python") -> Dict[str, Any]: """Grade a student submission""" # Validate solution validation_result = self.platform.validate_solution( code, problem.get("test_cases", []), language ) # Calculate score score = self._calculate_score(validation_result, problem) # Generate feedback feedback = self._generate_feedback(validation_result, problem) return { "score": score, "max_score": problem.get("max_score", 100), "percentage": (score / problem.get("max_score", 100)) * 100, "all_tests_passed": validation_result["all_passed"], "test_results": validation_result["results"], "feedback": feedback, "submission_time": self._get_timestamp() } def _calculate_score(self, validation_result: Dict, problem: Dict) -> float: """Calculate score based on test results""" if validation_result["all_passed"]: return problem.get("max_score", 100) # Partial credit based on passed tests passed = validation_result["passed_tests"] total = validation_result["total_tests"] max_score = problem.get("max_score", 100) return (passed / total) * max_score def _generate_feedback(self, validation_result: Dict, problem: Dict) -> str: """Generate feedback for student""" if validation_result["all_passed"]: return "Excellent! All test cases passed." failed_tests = [r for r in validation_result["results"] if not r["passed"]] feedback = f"Some test cases failed ({len(failed_tests)}/{validation_result['total_tests']}).\n\n" for test in failed_tests[:3]: # Show first 3 failures feedback += f"Test {test['test_case']}: Expected {test['expected']}, got {test['actual']}\n" if test.get("error"): feedback += f" Error: {test['error']}\n" return feedback def _get_timestamp(self) -> str: from datetime import datetime return datetime.now().isoformat() # Usage platform = CodingPlatform(api_key=os.getenv("HOPX_API_KEY")) grader = GradingSystem(platform) problem = { "title": "Sum of Array", "description": "Write a function that returns the sum of all elements in an array", "max_score": 100, "test_cases": [ {"input": "[1, 2, 3]", "expected": 6}, {"input": "[10, 20, 30]", "expected": 60}, {"input": "[]", "expected": 0} ] } student_code = """ def solution(nums): return sum(nums) """ grade = grader.grade_submission(student_code, problem) print(json.dumps(grade, indent=2)) ``` ```javascript JavaScript theme={null} class GradingSystem { constructor(platform) { this.platform = platform; } async gradeSubmission(code, problem, language = 'python') { // Validate solution const validationResult = await this.platform.validateSolution( code, problem.testCases || [], language ); // Calculate score const score = this.calculateScore(validationResult, problem); // Generate feedback const feedback = this.generateFeedback(validationResult, problem); return { score, maxScore: problem.maxScore || 100, percentage: (score / (problem.maxScore || 100)) * 100, allTestsPassed: validationResult.allPassed, testResults: validationResult.results, feedback, submissionTime: new Date().toISOString() }; } calculateScore(validationResult, problem) { if (validationResult.allPassed) { return problem.maxScore || 100; } // Partial credit based on passed tests const passed = validationResult.passedTests; const total = validationResult.totalTests; const maxScore = problem.maxScore || 100; return (passed / total) * maxScore; } generateFeedback(validationResult, problem) { if (validationResult.allPassed) { return 'Excellent! All test cases passed.'; } const failedTests = validationResult.results.filter(r => !r.passed); let feedback = `Some test cases failed (${failedTests.length}/${validationResult.totalTests}).\n\n`; for (const test of failedTests.slice(0, 3)) { // Show first 3 failures feedback += `Test ${test.testCase}: Expected ${test.expected}, got ${test.actual}\n`; if (test.error) { feedback += ` Error: ${test.error}\n`; } } return feedback; } } // Usage const platform = new CodingPlatform(process.env.HOPX_API_KEY); const grader = new GradingSystem(platform); const problem = { title: 'Sum of Array', description: 'Write a function that returns the sum of all elements in an array', maxScore: 100, testCases: [ { input: '[1, 2, 3]', expected: 6 }, { input: '[10, 20, 30]', expected: 60 }, { input: '[]', expected: 0 } ] }; const studentCode = ` def solution(nums): return sum(nums) `; const grade = await grader.gradeSubmission(studentCode, problem); console.log(JSON.stringify(grade, null, 2)); ``` ## Best Practices ### Security Always create a fresh sandbox for each student submission to ensure complete isolation between submissions. 1. **Sandbox Isolation**: Never reuse sandboxes between different students 2. **Code Validation**: Check for dangerous patterns before execution 3. **Resource Limits**: Enforce strict timeouts and memory limits 4. **Input Sanitization**: Validate all inputs before processing ### Performance Use parallel execution for multiple test cases when possible, but ensure each test case runs in isolation. 1. **Sandbox Pooling**: Consider sandbox pooling for high-volume platforms 2. **Caching**: Cache problem definitions and test cases 3. **Async Processing**: Process submissions asynchronously for better scalability 4. **Resource Monitoring**: Monitor sandbox usage and optimize accordingly ### Educational Value 1. **Clear Feedback**: Provide detailed, actionable feedback 2. **Progressive Difficulty**: Structure problems from easy to hard 3. **Hints System**: Offer hints without revealing solutions 4. **Performance Metrics**: Track execution time and memory usage ## Real-World Examples This pattern is used by: * **LeetCode**: Online coding interview platform * **HackerRank**: Competitive programming platform * **Codecademy**: Interactive coding lessons * **Educational Platforms**: Various platforms that provide secure code execution for students ## Related Cookbooks * [Interactive Programming Tutorials](/cookbooks/educational/interactive-tutorials) - Step-by-step learning * [Coding Interview Platform](/cookbooks/educational/coding-interviews) - Interview preparation * [Isolated Test Execution](/cookbooks/testing/isolated-test-execution) - Test isolation strategies ## Next Steps 1. Implement your problem database 2. Add user authentication and submission tracking 3. Create a web interface for code submission 4. Implement leaderboards and progress tracking 5. Add support for more programming languages # Low-Code Platform Backend Source: https://docs.hopx.ai/cookbooks/enterprise/low-code-backend Build a low-code/no-code platform backend with visual to code translation, script execution, integration patterns, and custom logic execution Build a production-ready low-code platform backend that translates visual workflows to code and executes them. This cookbook demonstrates how to create a platform similar to Zapier or Microsoft Power Automate using HopX. ## Overview Low-code platforms allow users to build applications visually without writing code. The backend translates visual workflows to executable code, executes scripts, handles integrations, and runs custom logic. ## Prerequisites * HopX API key ([Get one here](https://console.hopx.dev/api-keys)) * Python 3.8+ or Node.js 16+ * Understanding of workflow engines * Basic knowledge of code generation ## Architecture ``` ┌──────────────┐ │ Visual │ Workflow definition │ Workflow │ └──────┬───────┘ │ ▼ ┌─────────────────┐ │ Code │ Translate to code │ Generator │ └──────┬──────────┘ │ ▼ ┌─────────────────┐ │ HopX Sandbox │ Execute generated code └─────────────────┘ ``` ## Implementation ### Step 1: Visual to Code Translation Translate visual workflows to executable code: ```python Python theme={null} from hopx_ai import Sandbox import os from typing import Dict, Any, List class WorkflowNode: def __init__(self, node_id: str, node_type: str, config: Dict[str, Any]): self.node_id = node_id self.node_type = node_type self.config = config class LowCodeBackend: def __init__(self, api_key: str): self.api_key = api_key self.sandbox = None def initialize(self): """Initialize backend""" self.sandbox = Sandbox.create( template="code-interpreter", api_key=self.api_key, timeout_seconds=3600 ) def translate_workflow(self, nodes: List[WorkflowNode]) -> str: """Translate visual workflow to code""" code_parts = [] for node in nodes: if node.node_type == "trigger": code_parts.append(f"# Trigger: {node.config.get('name', '')}") elif node.node_type == "action": action_code = self._generate_action_code(node) code_parts.append(action_code) elif node.node_type == "condition": condition_code = self._generate_condition_code(node) code_parts.append(condition_code) return "\n".join(code_parts) def _generate_action_code(self, node: WorkflowNode) -> str: """Generate code for action node""" action_type = node.config.get("action_type", "") if action_type == "http_request": return f""" import requests response = requests.{node.config.get('method', 'get').lower()}('{node.config.get('url', '')}') print(response.text) """ elif action_type == "data_transform": return f""" data = {node.config.get('data', '{}')} # Transform data result = data print(result) """ else: return f"# Action: {action_type}" def _generate_condition_code(self, node: WorkflowNode) -> str: """Generate code for condition node""" condition = node.config.get("condition", "") return f""" if {condition}: # Condition met pass else: # Condition not met pass """ def execute_workflow(self, nodes: List[WorkflowNode]) -> Dict[str, Any]: """Execute visual workflow""" try: # Translate to code code = self.translate_workflow(nodes) # Execute result = self.sandbox.run_code(code, timeout=60) return { "success": result.success, "stdout": result.stdout, "stderr": result.stderr, "generated_code": code } except Exception as e: return { "success": False, "error": str(e) } def cleanup(self): """Clean up backend resources""" if self.sandbox: self.sandbox.kill() self.sandbox = None # Usage backend = LowCodeBackend(api_key=os.getenv("HOPX_API_KEY")) backend.initialize() # Define workflow nodes = [ WorkflowNode("node_1", "trigger", {"name": "webhook"}), WorkflowNode("node_2", "action", { "action_type": "http_request", "method": "GET", "url": "https://api.example.com/data" }) ] result = backend.execute_workflow(nodes) print(result) backend.cleanup() ``` ```javascript JavaScript theme={null} import { Sandbox } from '@hopx-ai/sdk'; class WorkflowNode { constructor(nodeId, nodeType, config) { this.nodeId = nodeId; this.nodeType = nodeType; this.config = config; } } class LowCodeBackend { constructor(apiKey) { this.apiKey = apiKey; this.sandbox = null; } async initialize() { this.sandbox = await Sandbox.create({ template: 'code-interpreter', apiKey: this.apiKey, timeoutSeconds: 3600 }); } translateWorkflow(nodes) { const codeParts = []; for (const node of nodes) { if (node.nodeType === 'trigger') { codeParts.push(`# Trigger: ${node.config.name || ''}`); } else if (node.nodeType === 'action') { codeParts.push(this.generateActionCode(node)); } else if (node.nodeType === 'condition') { codeParts.push(this.generateConditionCode(node)); } } return codeParts.join('\n'); } generateActionCode(node) { const actionType = node.config.actionType || ''; if (actionType === 'http_request') { return ` import requests response = requests.${(node.config.method || 'get').toLowerCase()}('${node.config.url || ''}') print(response.text) `; } else if (actionType === 'data_transform') { return ` data = ${JSON.stringify(node.config.data || {})} # Transform data result = data print(result) `; } else { return `# Action: ${actionType}`; } } generateConditionCode(node) { const condition = node.config.condition || ''; return ` if ${condition}: # Condition met pass else: # Condition not met pass `; } async executeWorkflow(nodes) { try { // Translate to code const code = this.translateWorkflow(nodes); // Execute const result = await this.sandbox.runCode(code, { timeout: 60 }); return { success: result.success, stdout: result.stdout, stderr: result.stderr, generatedCode: code }; } catch (error) { return { success: false, error: error.message }; } } async cleanup() { if (this.sandbox) { await this.sandbox.kill(); this.sandbox = null; } } } // Usage const backend = new LowCodeBackend(process.env.HOPX_API_KEY); await backend.initialize(); // Define workflow const nodes = [ new WorkflowNode('node_1', 'trigger', { name: 'webhook' }), new WorkflowNode('node_2', 'action', { actionType: 'http_request', method: 'GET', url: 'https://api.example.com/data' }) ]; const result = await backend.executeWorkflow(nodes); console.log(result); await backend.cleanup(); ``` ## Best Practices 1. **Code Generation**: Generate clean, maintainable code 2. **Error Handling**: Handle translation errors gracefully 3. **Integration Patterns**: Support common integration patterns 4. **Custom Logic**: Allow custom code injection ## Related Cookbooks * [User-Defined Functions](/cookbooks/marketplace/user-functions) - Custom functions * [Multi-Tenant Execution](/cookbooks/enterprise/multi-tenant-execution) - Multi-tenant patterns ## Next Steps 1. Implement visual workflow builder 2. Add more node types 3. Create integration library 4. Implement workflow versioning 5. Add workflow monitoring # Multi-Tenant Code Execution Platform Source: https://docs.hopx.ai/cookbooks/enterprise/multi-tenant-execution Build a SaaS platform with custom code execution featuring tenant isolation, resource quotas, security boundaries, and billing integration Build a production-ready multi-tenant code execution platform for SaaS applications. This cookbook demonstrates how to create a platform with tenant isolation, resource quotas, and security boundaries using HopX. ## Overview Multi-tenant platforms serve multiple customers (tenants) on shared infrastructure. Each tenant's code must be completely isolated, resources must be quota-limited, and security boundaries must be enforced. ## Prerequisites * HopX API key ([Get one here](https://console.hopx.dev/api-keys)) * Python 3.8+ or Node.js 16+ * Understanding of multi-tenant architecture * Basic knowledge of resource quotas ## Architecture ``` ┌──────────────┐ │ Tenant A │ Code execution └──────┬───────┘ │ ▼ ┌─────────────────┐ │ Tenant │ Isolate, quota │ Manager │ └──────┬──────────┘ │ ▼ ┌─────────────────┐ │ Tenant │ Isolated sandbox │ Sandbox A │ └─────────────────┘ ``` ## Implementation ### Step 1: Tenant Isolation Ensure complete tenant isolation: ```python Python theme={null} from hopx_ai import Sandbox import os from typing import Dict, Any class Tenant: def __init__(self, tenant_id: str, quota: Dict[str, int]): self.tenant_id = tenant_id self.quota = quota # {"executions_per_hour": 100, "max_execution_time": 60} class MultiTenantPlatform: def __init__(self, api_key: str): self.api_key = api_key self.tenants = {} self.tenant_sandboxes = {} self.usage_tracking = {} def register_tenant(self, tenant: Tenant): """Register a tenant""" self.tenants[tenant.tenant_id] = tenant self.usage_tracking[tenant.tenant_id] = { "executions": 0, "execution_time": 0 } def execute_for_tenant(self, tenant_id: str, code: str) -> Dict[str, Any]: """Execute code for specific tenant""" if tenant_id not in self.tenants: return { "success": False, "error": f"Tenant {tenant_id} not found" } tenant = self.tenants[tenant_id] usage = self.usage_tracking[tenant_id] # Check quota if usage["executions"] >= tenant.quota.get("executions_per_hour", 100): return { "success": False, "error": "Execution quota exceeded" } sandbox = None try: # Create or get tenant sandbox (isolated per tenant) if tenant_id not in self.tenant_sandboxes: self.tenant_sandboxes[tenant_id] = Sandbox.create( template="code-interpreter", api_key=self.api_key, timeout_seconds=tenant.quota.get("max_execution_time", 60) ) sandbox = self.tenant_sandboxes[tenant_id] # Set tenant context sandbox.env.set("TENANT_ID", tenant_id) # Execute code result = sandbox.run_code(code, timeout=tenant.quota.get("max_execution_time", 60)) # Update usage usage["executions"] += 1 usage["execution_time"] += result.execution_time return { "success": result.success, "stdout": result.stdout, "stderr": result.stderr, "tenant_id": tenant_id, "usage": usage } except Exception as e: return { "success": False, "error": str(e), "tenant_id": tenant_id } def get_tenant_usage(self, tenant_id: str) -> Dict[str, Any]: """Get tenant usage statistics""" if tenant_id not in self.usage_tracking: return {"error": "Tenant not found"} return self.usage_tracking[tenant_id] def cleanup_tenant(self, tenant_id: str): """Clean up tenant resources""" if tenant_id in self.tenant_sandboxes: self.tenant_sandboxes[tenant_id].kill() del self.tenant_sandboxes[tenant_id] # Usage platform = MultiTenantPlatform(api_key=os.getenv("HOPX_API_KEY")) # Register tenants platform.register_tenant(Tenant("tenant_1", {"executions_per_hour": 100, "max_execution_time": 60})) platform.register_tenant(Tenant("tenant_2", {"executions_per_hour": 200, "max_execution_time": 120})) # Execute for tenant result = platform.execute_for_tenant("tenant_1", "print('Hello from tenant 1')") print(result) usage = platform.get_tenant_usage("tenant_1") print(usage) ``` ```javascript JavaScript theme={null} import { Sandbox } from '@hopx-ai/sdk'; class Tenant { constructor(tenantId, quota) { this.tenantId = tenantId; this.quota = quota; // {executionsPerHour: 100, maxExecutionTime: 60} } } class MultiTenantPlatform { constructor(apiKey) { this.apiKey = apiKey; this.tenants = {}; this.tenantSandboxes = {}; this.usageTracking = {}; } registerTenant(tenant) { this.tenants[tenant.tenantId] = tenant; this.usageTracking[tenant.tenantId] = { executions: 0, executionTime: 0 }; } async executeForTenant(tenantId, code) { if (!this.tenants[tenantId]) { return { success: false, error: `Tenant ${tenantId} not found` }; } const tenant = this.tenants[tenantId]; const usage = this.usageTracking[tenantId]; // Check quota if (usage.executions >= (tenant.quota.executionsPerHour || 100)) { return { success: false, error: 'Execution quota exceeded' }; } try { // Create or get tenant sandbox (isolated per tenant) if (!this.tenantSandboxes[tenantId]) { this.tenantSandboxes[tenantId] = await Sandbox.create({ template: 'code-interpreter', apiKey: this.apiKey, timeoutSeconds: tenant.quota.maxExecutionTime || 60 }); } const sandbox = this.tenantSandboxes[tenantId]; // Set tenant context await sandbox.env.set('TENANT_ID', tenantId); // Execute code const result = await sandbox.runCode(code, { timeout: tenant.quota.maxExecutionTime || 60 }); // Update usage usage.executions += 1; usage.executionTime += result.execution_time || 0; return { success: result.success, stdout: result.stdout, stderr: result.stderr, tenantId, usage }; } catch (error) { return { success: false, error: error.message, tenantId }; } } getTenantUsage(tenantId) { if (!this.usageTracking[tenantId]) { return { error: 'Tenant not found' }; } return this.usageTracking[tenantId]; } async cleanupTenant(tenantId) { if (this.tenantSandboxes[tenantId]) { await this.tenantSandboxes[tenantId].kill(); delete this.tenantSandboxes[tenantId]; } } } // Usage const platform = new MultiTenantPlatform(process.env.HOPX_API_KEY); // Register tenants platform.registerTenant(new Tenant('tenant_1', { executionsPerHour: 100, maxExecutionTime: 60 })); platform.registerTenant(new Tenant('tenant_2', { executionsPerHour: 200, maxExecutionTime: 120 })); // Execute for tenant const result = await platform.executeForTenant('tenant_1', "print('Hello from tenant 1')"); console.log(result); const usage = platform.getTenantUsage('tenant_1'); console.log(usage); ``` ## Best Practices 1. **Complete Isolation**: One sandbox per tenant 2. **Resource Quotas**: Enforce strict quotas 3. **Security Boundaries**: Maintain security between tenants 4. **Usage Tracking**: Track usage for billing ## Related Cookbooks * [Plugin System](/cookbooks/marketplace/plugin-system) - Plugin isolation * [Low-Code Platform Backend](/cookbooks/enterprise/low-code-backend) - Enterprise platforms ## Next Steps 1. Implement billing integration 2. Add tenant management UI 3. Create usage analytics 4. Implement quota enforcement 5. Add tenant onboarding # Plugin System with Code Execution Source: https://docs.hopx.ai/cookbooks/marketplace/plugin-system Build a WordPress/Shopify-style plugin marketplace with untrusted code execution, permission systems, API access control, and sandbox isolation Build a production-ready plugin system that safely executes untrusted code from third-party developers. This cookbook demonstrates how to create a plugin marketplace with security isolation using HopX. ## Overview Plugin systems allow third-party developers to extend platform functionality. The system must execute untrusted code safely, enforce permissions, control API access, and maintain complete isolation between plugins. ## Prerequisites * HopX API key ([Get one here](https://console.hopx.dev/api-keys)) * Python 3.8+ or Node.js 16+ * Understanding of security isolation * Basic knowledge of permission systems ## Architecture ``` ┌──────────────┐ │ Plugin │ Untrusted code └──────┬───────┘ │ ▼ ┌─────────────────┐ │ Plugin │ Validate, isolate │ Manager │ └──────┬──────────┘ │ ▼ ┌─────────────────┐ │ Isolated │ One per plugin │ Sandbox │ └─────────────────┘ ``` ## Implementation ### Step 1: Plugin Execution with Isolation Execute plugins in isolated sandboxes: ```python Python theme={null} from hopx_ai import Sandbox import os from typing import Dict, Any, List class Plugin: def __init__(self, plugin_id: str, code: str, permissions: List[str]): self.plugin_id = plugin_id self.code = code self.permissions = permissions class PluginSystem: def __init__(self, api_key: str): self.api_key = api_key self.plugins = {} self.plugin_sandboxes = {} def register_plugin(self, plugin: Plugin): """Register a plugin""" self.plugins[plugin.plugin_id] = plugin def execute_plugin(self, plugin_id: str, context: Dict[str, Any] = None) -> Dict[str, Any]: """Execute plugin in isolated sandbox""" if plugin_id not in self.plugins: return { "success": False, "error": f"Plugin {plugin_id} not found" } plugin = self.plugins[plugin_id] sandbox = None try: # Create fresh sandbox for each execution sandbox = Sandbox.create( template="code-interpreter", api_key=self.api_key, timeout_seconds=60 ) # Set up plugin environment with limited permissions env_vars = { "PLUGIN_ID": plugin_id, "PERMISSIONS": ",".join(plugin.permissions) } sandbox.env.set_all(env_vars) # Add context if provided if context: for key, value in context.items(): sandbox.env.set(f"CONTEXT_{key}", str(value)) # Execute plugin code result = sandbox.run_code(plugin.code, timeout=30) return { "success": result.success, "stdout": result.stdout, "stderr": result.stderr, "plugin_id": plugin_id } except Exception as e: return { "success": False, "error": str(e), "plugin_id": plugin_id } finally: if sandbox: sandbox.kill() # Always cleanup def cleanup_all(self): """Clean up all plugin resources""" for sandbox in self.plugin_sandboxes.values(): sandbox.kill() self.plugin_sandboxes.clear() # Usage system = PluginSystem(api_key=os.getenv("HOPX_API_KEY")) # Register plugin system.register_plugin(Plugin( plugin_id="calculator", code="result = 2 + 2\nprint(f'Result: {result}')", permissions=["compute"] )) # Execute result = system.execute_plugin("calculator") print(result) system.cleanup_all() ``` ```javascript JavaScript theme={null} import { Sandbox } from '@hopx-ai/sdk'; class Plugin { constructor(pluginId, code, permissions) { this.pluginId = pluginId; this.code = code; this.permissions = permissions; } } class PluginSystem { constructor(apiKey) { this.apiKey = apiKey; this.plugins = {}; this.pluginSandboxes = {}; } registerPlugin(plugin) { this.plugins[plugin.pluginId] = plugin; } async executePlugin(pluginId, context = null) { if (!this.plugins[pluginId]) { return { success: false, error: `Plugin ${pluginId} not found` }; } const plugin = this.plugins[pluginId]; let sandbox = null; try { // Create fresh sandbox for each execution sandbox = await Sandbox.create({ template: 'code-interpreter', apiKey: this.apiKey, timeoutSeconds: 60 }); // Set up plugin environment with limited permissions const envVars = { PLUGIN_ID: pluginId, PERMISSIONS: plugin.permissions.join(',') }; await sandbox.env.setAll(envVars); // Add context if provided if (context) { for (const [key, value] of Object.entries(context)) { await sandbox.env.set(`CONTEXT_${key}`, String(value)); } } // Execute plugin code const result = await sandbox.runCode(plugin.code, { timeout: 30 }); return { success: result.success, stdout: result.stdout, stderr: result.stderr, pluginId }; } catch (error) { return { success: false, error: error.message, pluginId }; } finally { if (sandbox) { await sandbox.kill(); // Always cleanup } } } async cleanupAll() { await Promise.all( Object.values(this.pluginSandboxes).map(sandbox => sandbox.kill()) ); this.pluginSandboxes = {}; } } // Usage const system = new PluginSystem(process.env.HOPX_API_KEY); // Register plugin system.registerPlugin(new Plugin( 'calculator', "result = 2 + 2\nprint(f'Result: {result}')", ['compute'] )); // Execute const result = await system.executePlugin('calculator'); console.log(result); await system.cleanupAll(); ``` ## Best Practices Always execute plugins in fresh, isolated sandboxes. Never trust plugin code or allow plugins to access system resources. 1. **Complete Isolation**: One sandbox per plugin execution 2. **Permission System**: Enforce permissions strictly 3. **Code Validation**: Validate plugin code before execution 4. **Resource Limits**: Set strict resource limits ## Related Cookbooks * [Multi-Tenant Execution](/cookbooks/enterprise/multi-tenant-execution) - Multi-tenant patterns * [User-Defined Functions](/cookbooks/marketplace/user-functions) - Custom functions ## Next Steps 1. Implement permission system 2. Add plugin marketplace features 3. Create plugin validation 4. Implement plugin versioning 5. Add plugin monitoring # User-Defined Functions Platform Source: https://docs.hopx.ai/cookbooks/marketplace/user-functions Build a Zapier/Make.com-style workflow automation platform with custom function execution, workflow orchestration, data transformation, and error handling Build a production-ready user-defined functions platform where users can create custom functions for workflow automation. This cookbook demonstrates how to create a platform similar to Zapier or Make.com using HopX. ## Overview User-defined functions platforms allow users to create custom functions for workflow automation. Users write functions, the platform executes them in workflows, transforms data, and handles errors gracefully. ## Prerequisites * HopX API key ([Get one here](https://console.hopx.dev/api-keys)) * Python 3.8+ or Node.js 16+ * Understanding of workflow automation * Basic knowledge of data transformation ## Architecture ``` ┌──────────────┐ │ User │ Define function └──────┬───────┘ │ ▼ ┌─────────────────┐ │ Workflow │ Orchestrate steps │ Engine │ └──────┬──────────┘ │ ▼ ┌─────────────────┐ │ HopX Sandbox │ Execute function └─────────────────┘ ``` ## Implementation ### Step 1: User Function Execution Execute user-defined functions: ```python Python theme={null} from hopx_ai import Sandbox import os from typing import Dict, Any, List class UserFunction: def __init__(self, function_id: str, code: str, inputs: List[str], outputs: List[str]): self.function_id = function_id self.code = code self.inputs = inputs self.outputs = outputs class UserFunctionPlatform: def __init__(self, api_key: str): self.api_key = api_key self.functions = {} self.sandbox = None def initialize(self): """Initialize platform""" self.sandbox = Sandbox.create( template="code-interpreter", api_key=self.api_key, timeout_seconds=3600 ) def register_function(self, function: UserFunction): """Register user function""" self.functions[function.function_id] = function def execute_function(self, function_id: str, inputs: Dict[str, Any]) -> Dict[str, Any]: """Execute user function with inputs""" if function_id not in self.functions: return { "success": False, "error": f"Function {function_id} not found" } function = self.functions[function_id] try: # Prepare function code with inputs import json function_code = f""" import json # Inputs inputs = {json.dumps(inputs)} # User function {function.code} """ result = self.sandbox.run_code(function_code, timeout=30) return { "success": result.success, "output": result.stdout, "error": result.stderr if not result.success else None } except Exception as e: return { "success": False, "error": str(e) } def cleanup(self): """Clean up platform resources""" if self.sandbox: self.sandbox.kill() self.sandbox = None # Usage platform = UserFunctionPlatform(api_key=os.getenv("HOPX_API_KEY")) platform.initialize() # Register function platform.register_function(UserFunction( function_id="add_numbers", code="result = inputs['a'] + inputs['b']\nprint(result)", inputs=["a", "b"], outputs=["result"] )) # Execute result = platform.execute_function("add_numbers", {"a": 5, "b": 3}) print(result) platform.cleanup() ``` ```javascript JavaScript theme={null} import { Sandbox } from '@hopx-ai/sdk'; class UserFunction { constructor(functionId, code, inputs, outputs) { this.functionId = functionId; this.code = code; this.inputs = inputs; this.outputs = outputs; } } class UserFunctionPlatform { constructor(apiKey) { this.apiKey = apiKey; this.functions = {}; this.sandbox = null; } async initialize() { this.sandbox = await Sandbox.create({ template: 'code-interpreter', apiKey: this.apiKey, timeoutSeconds: 3600 }); } registerFunction(func) { this.functions[func.functionId] = func; } async executeFunction(functionId, inputs) { if (!this.functions[functionId]) { return { success: false, error: `Function ${functionId} not found` }; } const func = this.functions[functionId]; try { // Prepare function code with inputs const functionCode = ` // Inputs const inputs = ${JSON.stringify(inputs)}; // User function ${func.code} `; const result = await this.sandbox.runCode(functionCode, { timeout: 30 }); return { success: result.success, output: result.stdout, error: !result.success ? result.stderr : null }; } catch (error) { return { success: false, error: error.message }; } } async cleanup() { if (this.sandbox) { await this.sandbox.kill(); this.sandbox = null; } } } // Usage const platform = new UserFunctionPlatform(process.env.HOPX_API_KEY); await platform.initialize(); // Register function platform.registerFunction(new UserFunction( 'add_numbers', "const result = inputs.a + inputs.b;\nconsole.log(result);", ['a', 'b'], ['result'] )); // Execute const result = await platform.executeFunction('add_numbers', { a: 5, b: 3 }); console.log(result); await platform.cleanup(); ``` ## Best Practices 1. **Function Validation**: Validate function code before execution 2. **Input Validation**: Validate inputs before passing to functions 3. **Error Handling**: Handle errors gracefully 4. **Workflow Orchestration**: Chain functions efficiently ## Related Cookbooks * [Plugin System](/cookbooks/marketplace/plugin-system) - Plugin architecture * [Low-Code Platform Backend](/cookbooks/enterprise/low-code-backend) - Enterprise platforms ## Next Steps 1. Implement workflow builder 2. Add function marketplace 3. Create workflow execution engine 4. Implement data transformation 5. Add workflow monitoring # Custom Serverless Platform Source: https://docs.hopx.ai/cookbooks/serverless/custom-functions Build an AWS Lambda-style serverless platform with function execution, cold start optimization, event-driven execution, and resource allocation Build a production-ready serverless platform that executes functions on-demand, optimizes cold starts, handles events, and manages resources. This cookbook demonstrates how to create a serverless platform similar to AWS Lambda using HopX. ## Overview Serverless platforms execute functions in response to events without managing servers. The platform handles function execution, optimizes cold starts, routes events, and allocates resources dynamically. This pattern is used by platforms like AWS Lambda, Vercel Functions, and Netlify Functions. ## Prerequisites * HopX API key ([Get one here](https://console.hopx.dev/api-keys)) * Python 3.8+ or Node.js 16+ * Understanding of serverless architecture * Basic knowledge of event-driven systems ## Architecture ``` ┌──────────────┐ │ Event │ Trigger function └──────┬───────┘ │ ▼ ┌─────────────────┐ │ Function │ Route & execute │ Router │ └──────┬──────────┘ │ ▼ ┌─────────────────┐ │ HopX Sandbox │ Function execution └──────┬──────────┘ │ ▼ ┌─────────────────┐ │ Response │ Return result └─────────────────┘ ``` ## Implementation ### Step 1: Function Execution Execute serverless functions: ```python Python theme={null} from hopx_ai import Sandbox import os import json from typing import Dict, Any, Callable class ServerlessFunction: def __init__(self, function_id: str, code: str, runtime: str = "python"): self.function_id = function_id self.code = code self.runtime = runtime self.sandbox = None def initialize(self, api_key: str): """Initialize function sandbox""" self.sandbox = Sandbox.create( template="code-interpreter", api_key=api_key, timeout_seconds=300 # 5 minute timeout ) def invoke(self, event: Dict[str, Any], context: Dict[str, Any] = None) -> Dict[str, Any]: """Invoke function with event""" try: # Prepare function code with event function_code = f""" import json # Event data event = {json.dumps(event)} # Context data context = {json.dumps(context or {})} # User function {self.code} """ # Execute function result = self.sandbox.run_code(function_code, timeout=30) return { "success": result.success, "result": result.stdout, "error": result.stderr if not result.success else None, "execution_time": result.execution_time } except Exception as e: return { "success": False, "error": str(e) } def cleanup(self): """Clean up function resources""" if self.sandbox: self.sandbox.kill() self.sandbox = None class ServerlessPlatform: def __init__(self, api_key: str): self.api_key = api_key self.functions = {} def register_function(self, function_id: str, code: str, runtime: str = "python"): """Register a serverless function""" func = ServerlessFunction(function_id, code, runtime) func.initialize(self.api_key) self.functions[function_id] = func def invoke_function(self, function_id: str, event: Dict[str, Any]) -> Dict[str, Any]: """Invoke registered function""" if function_id not in self.functions: return { "success": False, "error": f"Function {function_id} not found" } return self.functions[function_id].invoke(event) def cleanup_all(self): """Clean up all functions""" for func in self.functions.values(): func.cleanup() # Usage platform = ServerlessPlatform(api_key=os.getenv("HOPX_API_KEY")) # Register function platform.register_function( "hello_world", """ def handler(event, context): name = event.get('name', 'World') return f"Hello, {name}!" """, "python" ) # Invoke function result = platform.invoke_function("hello_world", {"name": "HopX"}) print(result) platform.cleanup_all() ``` ```javascript JavaScript theme={null} import { Sandbox } from '@hopx-ai/sdk'; class ServerlessFunction { constructor(functionId, code, runtime = 'javascript') { this.functionId = functionId; this.code = code; this.runtime = runtime; this.sandbox = null; } async initialize(apiKey) { this.sandbox = await Sandbox.create({ template: 'code-interpreter', apiKey, timeoutSeconds: 300 // 5 minute timeout }); } async invoke(event, context = null) { try { // Prepare function code with event const functionCode = ` // Event data const event = ${JSON.stringify(event)}; // Context data const context = ${JSON.stringify(context || {})}; // User function ${this.code} `; // Execute function const result = await this.sandbox.runCode(functionCode, { language: this.runtime, timeout: 30 }); return { success: result.success, result: result.stdout, error: !result.success ? result.stderr : null, executionTime: result.execution_time }; } catch (error) { return { success: false, error: error.message }; } } async cleanup() { if (this.sandbox) { await this.sandbox.kill(); this.sandbox = null; } } } class ServerlessPlatform { constructor(apiKey) { this.apiKey = apiKey; this.functions = {}; } async registerFunction(functionId, code, runtime = 'javascript') { const func = new ServerlessFunction(functionId, code, runtime); await func.initialize(this.apiKey); this.functions[functionId] = func; } async invokeFunction(functionId, event) { if (!this.functions[functionId]) { return { success: false, error: `Function ${functionId} not found` }; } return await this.functions[functionId].invoke(event); } async cleanupAll() { await Promise.all( Object.values(this.functions).map(func => func.cleanup()) ); } } // Usage const platform = new ServerlessPlatform(process.env.HOPX_API_KEY); // Register function await platform.registerFunction( 'hello_world', ` function handler(event, context) { const name = event.name || 'World'; return \`Hello, \${name}!\`; } `, 'javascript' ); // Invoke function const result = await platform.invokeFunction('hello_world', { name: 'HopX' }); console.log(result); await platform.cleanupAll(); ``` ### Step 2: Cold Start Optimization Optimize function cold starts: ```python Python theme={null} class OptimizedServerlessPlatform(ServerlessPlatform): def __init__(self, api_key: str): super().__init__(api_key) self.warm_pool = {} # Keep sandboxes warm def _warm_function(self, function_id: str): """Warm up function sandbox""" if function_id not in self.warm_pool: func = self.functions[function_id] # Keep sandbox alive self.warm_pool[function_id] = func.sandbox def invoke_function_optimized(self, function_id: str, event: Dict[str, Any]) -> Dict[str, Any]: """Invoke with cold start optimization""" # Warm function if not already warm if function_id not in self.warm_pool: self._warm_function(function_id) return self.invoke_function(function_id, event) # Usage platform = OptimizedServerlessPlatform(api_key=os.getenv("HOPX_API_KEY")) platform.register_function("my_function", "def handler(e, c): return 'OK'") platform._warm_function("my_function") # Pre-warm result = platform.invoke_function_optimized("my_function", {}) print(result) ``` ```javascript JavaScript theme={null} class OptimizedServerlessPlatform extends ServerlessPlatform { constructor(apiKey) { super(apiKey); this.warmPool = {}; // Keep sandboxes warm } async warmFunction(functionId) { if (!this.warmPool[functionId]) { const func = this.functions[functionId]; // Keep sandbox alive this.warmPool[functionId] = func.sandbox; } } async invokeFunctionOptimized(functionId, event) { // Warm function if not already warm if (!this.warmPool[functionId]) { await this.warmFunction(functionId); } return await this.invokeFunction(functionId, event); } } // Usage const platform = new OptimizedServerlessPlatform(process.env.HOPX_API_KEY); await platform.registerFunction('my_function', "function handler(e, c) { return 'OK'; }"); await platform.warmFunction('my_function'); // Pre-warm const result = await platform.invokeFunctionOptimized('my_function', {}); console.log(result); ``` ## Best Practices 1. **Cold Start Optimization**: Pre-warm frequently used functions 2. **Resource Limits**: Set appropriate timeouts and memory limits 3. **Error Handling**: Handle errors gracefully 4. **Event Routing**: Route events efficiently ## Real-World Examples This pattern is used by: * **AWS Lambda**: Serverless compute service * **Vercel Functions**: Serverless functions for web apps * **Netlify Functions**: Serverless functions platform ## Related Cookbooks * [Edge Function Execution](/cookbooks/serverless/edge-functions) - Edge computing ## Next Steps 1. Implement function versioning 2. Add event source integrations 3. Create function monitoring dashboard 4. Implement auto-scaling 5. Add function deployment pipeline # Edge Function Execution Source: https://docs.hopx.ai/cookbooks/serverless/edge-functions Build edge computing functions with geographic distribution, low-latency execution, resource constraints, and request routing Build a production-ready edge function execution platform that runs code close to users for low latency. This cookbook demonstrates how to create an edge computing platform using HopX. ## Overview Edge functions execute code at geographic locations close to users, reducing latency. The platform routes requests to appropriate edge locations, executes functions with resource constraints, and returns results quickly. ## Prerequisites * HopX API key ([Get one here](https://console.hopx.dev/api-keys)) * Python 3.8+ or Node.js 16+ * Understanding of edge computing * Basic knowledge of request routing ## Architecture ``` ┌──────────────┐ │ User │ Request └──────┬───────┘ │ ▼ ┌─────────────────┐ │ Edge Router │ Route to nearest └──────┬──────────┘ │ ▼ ┌─────────────────┐ │ Edge Sandbox │ Execute function │ (Region-based) │ └─────────────────┘ ``` ## Implementation ### Step 1: Edge Function Execution Execute functions at edge locations: ```python Python theme={null} from hopx_ai import Sandbox import os from typing import Dict, Any class EdgeFunctionPlatform: def __init__(self, api_key: str): self.api_key = api_key self.edge_sandboxes = {} # Region -> sandbox mapping def get_edge_sandbox(self, region: str) -> Sandbox: """Get or create edge sandbox for region""" if region not in self.edge_sandboxes: self.edge_sandboxes[region] = Sandbox.create( template="code-interpreter", api_key=self.api_key, timeout_seconds=300, region=region # Specify region if supported ) return self.edge_sandboxes[region] def execute_at_edge(self, function_code: str, region: str, event: Dict[str, Any]) -> Dict[str, Any]: """Execute function at edge location""" try: sandbox = self.get_edge_sandbox(region) # Prepare function with event import json full_code = f""" import json event = {json.dumps(event)} {function_code} """ result = sandbox.run_code(full_code, timeout=10) # Fast execution for edge return { "success": result.success, "result": result.stdout, "region": region, "execution_time": result.execution_time } except Exception as e: return { "success": False, "error": str(e), "region": region } def route_to_nearest(self, user_location: str, function_code: str, event: Dict[str, Any]) -> Dict[str, Any]: """Route request to nearest edge location""" # Simple routing logic (in production, use geolocation) region_map = { "us": "us-east-1", "eu": "eu-west-1", "asia": "ap-southeast-1" } region = region_map.get(user_location, "us-east-1") return self.execute_at_edge(function_code, region, event) def cleanup_all(self): """Clean up all edge sandboxes""" for sandbox in self.edge_sandboxes.values(): sandbox.kill() self.edge_sandboxes.clear() # Usage platform = EdgeFunctionPlatform(api_key=os.getenv("HOPX_API_KEY")) result = platform.route_to_nearest( user_location="us", function_code="print('Hello from edge!')", event={} ) print(result) platform.cleanup_all() ``` ```javascript JavaScript theme={null} import { Sandbox } from '@hopx-ai/sdk'; class EdgeFunctionPlatform { constructor(apiKey) { this.apiKey = apiKey; this.edgeSandboxes = {}; // Region -> sandbox mapping } async getEdgeSandbox(region) { if (!this.edgeSandboxes[region]) { this.edgeSandboxes[region] = await Sandbox.create({ template: 'code-interpreter', apiKey: this.apiKey, timeoutSeconds: 300, region // Specify region if supported }); } return this.edgeSandboxes[region]; } async executeAtEdge(functionCode, region, event) { try { const sandbox = await this.getEdgeSandbox(region); // Prepare function with event const fullCode = ` const event = ${JSON.stringify(event)}; ${functionCode} `; const result = await sandbox.runCode(fullCode, { timeout: 10 }); // Fast execution for edge return { success: result.success, result: result.stdout, region, executionTime: result.execution_time }; } catch (error) { return { success: false, error: error.message, region }; } } async routeToNearest(userLocation, functionCode, event) { // Simple routing logic (in production, use geolocation) const regionMap = { us: 'us-east-1', eu: 'eu-west-1', asia: 'ap-southeast-1' }; const region = regionMap[userLocation] || 'us-east-1'; return await this.executeAtEdge(functionCode, region, event); } async cleanupAll() { await Promise.all( Object.values(this.edgeSandboxes).map(sandbox => sandbox.kill()) ); this.edgeSandboxes = {}; } } // Usage const platform = new EdgeFunctionPlatform(process.env.HOPX_API_KEY); const result = await platform.routeToNearest( 'us', "print('Hello from edge!')", {} ); console.log(result); await platform.cleanupAll(); ``` ## Best Practices 1. **Low Latency**: Optimize for fast execution 2. **Resource Constraints**: Use minimal resources at edge 3. **Geographic Distribution**: Deploy to multiple regions 4. **Request Routing**: Route to nearest edge location ## Related Cookbooks * [Custom Serverless Platform](/cookbooks/serverless/custom-functions) - Serverless functions ## Next Steps 1. Implement geolocation-based routing 2. Add edge location management 3. Create request routing logic 4. Implement resource optimization 5. Add edge monitoring # Isolated Test Execution Service Source: https://docs.hopx.ai/cookbooks/testing/isolated-test-execution Build a CI/CD test execution platform with parallel test execution, test isolation strategies, and result aggregation Build a production-ready isolated test execution service for CI/CD pipelines. This cookbook demonstrates how to create a test execution platform that runs tests in isolated sandboxes, supports parallel execution, and aggregates results. ## Overview Isolated test execution services run tests in completely isolated environments, ensuring test reliability and preventing interference between test runs. This pattern is essential for CI/CD pipelines, test automation platforms, and quality assurance systems. HopX provides the secure isolation needed for this use case. ## Prerequisites * HopX API key ([Get one here](https://console.hopx.dev/api-keys)) * Python 3.8+ or Node.js 16+ * Understanding of test frameworks (pytest, jest, etc.) * Basic knowledge of CI/CD concepts ## Architecture ``` ┌──────────────┐ │ CI/CD │ Test execution requests │ Pipeline │ └──────┬───────┘ │ ▼ ┌─────────────────┐ │ Test Runner │ Parallel execution └──────┬──────────┘ │ ▼ ┌─────────────────┐ │ HopX Sandboxes │ Isolated execution │ (One per test) │ └──────┬──────────┘ │ ▼ ┌─────────────────┐ │ Result │ Aggregate & report │ Aggregator │ └─────────────────┘ ``` ## Implementation ### Step 1: Basic Isolated Test Execution Execute tests in isolated sandboxes: ```python Python theme={null} from hopx_ai import Sandbox import os import json from typing import Dict, List, Any from concurrent.futures import ThreadPoolExecutor, as_completed class IsolatedTestExecutor: def __init__(self, api_key: str): self.api_key = api_key def execute_test(self, test_code: str, test_framework: str = "pytest", timeout: int = 60) -> Dict[str, Any]: """Execute a single test in isolated sandbox""" sandbox = None try: # Create fresh sandbox for each test sandbox = Sandbox.create( template="code-interpreter", api_key=self.api_key, timeout_seconds=timeout + 10 ) # Write test file test_file = "/workspace/test_file.py" sandbox.files.write(test_file, test_code) # Install test framework if needed if test_framework == "pytest": sandbox.commands.run("pip install pytest", timeout=30) # Execute test result = sandbox.commands.run(f"pytest {test_file} -v", timeout=timeout) elif test_framework == "unittest": result = sandbox.commands.run(f"python -m unittest {test_file}", timeout=timeout) else: result = sandbox.run_code(test_code, timeout=timeout) # Parse test results test_results = self._parse_test_results(result.stdout, test_framework) return { "success": result.exit_code == 0, "exit_code": result.exit_code, "stdout": result.stdout, "stderr": result.stderr, "test_results": test_results, "execution_time": getattr(result, 'execution_time', 0) } except Exception as e: return { "success": False, "error": str(e), "stderr": str(e) } finally: if sandbox: sandbox.kill() def _parse_test_results(self, output: str, framework: str) -> Dict[str, Any]: """Parse test framework output""" if framework == "pytest": # Parse pytest output passed = output.count("PASSED") failed = output.count("FAILED") return { "passed": passed, "failed": failed, "total": passed + failed } else: return { "passed": 0, "failed": 0, "total": 0 } # Usage executor = IsolatedTestExecutor(api_key=os.getenv("HOPX_API_KEY")) test_code = """ def test_addition(): assert 1 + 1 == 2 def test_subtraction(): assert 5 - 3 == 2 """ result = executor.execute_test(test_code, test_framework="pytest") print(json.dumps(result, indent=2)) ``` ```javascript JavaScript theme={null} import { Sandbox } from '@hopx-ai/sdk'; class IsolatedTestExecutor { constructor(apiKey) { this.apiKey = apiKey; } async executeTest(testCode, testFramework = 'jest', timeout = 60) { let sandbox = null; try { // Create fresh sandbox for each test sandbox = await Sandbox.create({ template: 'code-interpreter', apiKey: this.apiKey, timeoutSeconds: timeout + 10 }); // Write test file const testFile = '/workspace/test_file.js'; await sandbox.files.write(testFile, testCode); // Install test framework if needed if (testFramework === 'jest') { await sandbox.commands.run('npm install jest', { timeout: 30 }); // Execute test const result = await sandbox.commands.run(`npx jest ${testFile}`, { timeout }); // Parse test results const testResults = this.parseTestResults(result.stdout, testFramework); return { success: result.exit_code === 0, exitCode: result.exit_code, stdout: result.stdout, stderr: result.stderr, testResults, executionTime: result.execution_time || 0 }; } else { const result = await sandbox.runCode(testCode, { timeout }); return { success: result.success, stdout: result.stdout, stderr: result.stderr }; } } catch (error) { return { success: false, error: error.message, stderr: error.toString() }; } finally { if (sandbox) { await sandbox.kill(); } } } parseTestResults(output, framework) { if (framework === 'jest') { // Parse jest output const passed = (output.match(/PASS/g) || []).length; const failed = (output.match(/FAIL/g) || []).length; return { passed, failed, total: passed + failed }; } else { return { passed: 0, failed: 0, total: 0 }; } } } // Usage const executor = new IsolatedTestExecutor(process.env.HOPX_API_KEY); const testCode = ` test('addition', () => { expect(1 + 1).toBe(2); }); test('subtraction', () => { expect(5 - 3).toBe(2); }); `; const result = await executor.executeTest(testCode, 'jest'); console.log(JSON.stringify(result, null, 2)); ``` ### Step 2: Parallel Test Execution Execute multiple tests in parallel: ```python Python theme={null} class ParallelTestExecutor(IsolatedTestExecutor): def execute_test_suite(self, test_suite: List[Dict], max_workers: int = 5) -> Dict[str, Any]: """Execute multiple tests in parallel""" results = [] with ThreadPoolExecutor(max_workers=max_workers) as executor: # Submit all tests future_to_test = { executor.submit( self.execute_test, test["code"], test.get("framework", "pytest"), test.get("timeout", 60) ): test for test in test_suite } # Collect results as they complete for future in as_completed(future_to_test): test = future_to_test[future] try: result = future.result() results.append({ "test_name": test.get("name", "unknown"), "result": result }) except Exception as e: results.append({ "test_name": test.get("name", "unknown"), "result": { "success": False, "error": str(e) } }) # Aggregate results total_tests = len(results) passed_tests = sum(1 for r in results if r["result"].get("success", False)) failed_tests = total_tests - passed_tests return { "total_tests": total_tests, "passed": passed_tests, "failed": failed_tests, "success_rate": (passed_tests / total_tests * 100) if total_tests > 0 else 0, "results": results } # Usage executor = ParallelTestExecutor(api_key=os.getenv("HOPX_API_KEY")) test_suite = [ { "name": "test_math", "code": """ def test_addition(): assert 1 + 1 == 2 """, "framework": "pytest", "timeout": 30 }, { "name": "test_strings", "code": """ def test_concatenation(): assert "hello" + " " + "world" == "hello world" """, "framework": "pytest", "timeout": 30 } ] results = executor.execute_test_suite(test_suite, max_workers=2) print(json.dumps(results, indent=2)) ``` ```javascript JavaScript theme={null} class ParallelTestExecutor extends IsolatedTestExecutor { async executeTestSuite(testSuite, maxWorkers = 5) { const results = []; // Execute tests in parallel (limited by maxWorkers) const chunks = []; for (let i = 0; i < testSuite.length; i += maxWorkers) { chunks.push(testSuite.slice(i, i + maxWorkers)); } for (const chunk of chunks) { const chunkResults = await Promise.all( chunk.map(async (test) => { try { const result = await this.executeTest( test.code, test.framework || 'jest', test.timeout || 60 ); return { testName: test.name || 'unknown', result }; } catch (error) { return { testName: test.name || 'unknown', result: { success: false, error: error.message } }; } }) ); results.push(...chunkResults); } // Aggregate results const totalTests = results.length; const passedTests = results.filter(r => r.result.success).length; const failedTests = totalTests - passedTests; return { totalTests, passed: passedTests, failed: failedTests, successRate: totalTests > 0 ? (passedTests / totalTests * 100) : 0, results }; } } // Usage const executor = new ParallelTestExecutor(process.env.HOPX_API_KEY); const testSuite = [ { name: 'test_math', code: ` test('addition', () => { expect(1 + 1).toBe(2); }); `, framework: 'jest', timeout: 30 }, { name: 'test_strings', code: ` test('concatenation', () => { expect('hello' + ' ' + 'world').toBe('hello world'); }); `, framework: 'jest', timeout: 30 } ]; const results = await executor.executeTestSuite(testSuite, 2); console.log(JSON.stringify(results, null, 2)); ``` ### Step 3: Test Isolation Strategies Ensure complete test isolation: ```python Python theme={null} class IsolatedTestRunner: def __init__(self, api_key: str): self.api_key = api_key def run_isolated_test(self, test_config: Dict) -> Dict[str, Any]: """Run test with complete isolation""" sandbox = None try: # Create sandbox with clean environment sandbox = Sandbox.create( template="code-interpreter", api_key=self.api_key, timeout_seconds=test_config.get("timeout", 60) + 10, env_vars=test_config.get("env_vars", {}) ) # Set up test environment setup_code = test_config.get("setup", "") if setup_code: setup_result = sandbox.run_code(setup_code, timeout=30) if not setup_result.success: return { "success": False, "error": f"Setup failed: {setup_result.stderr}", "stage": "setup" } # Write test files for file_config in test_config.get("files", []): sandbox.files.write( file_config["path"], file_config["content"] ) # Execute test test_result = sandbox.run_code( test_config["test_code"], language=test_config.get("language", "python"), timeout=test_config.get("timeout", 60) ) # Cleanup (teardown) teardown_code = test_config.get("teardown", "") if teardown_code: sandbox.run_code(teardown_code, timeout=30) return { "success": test_result.success, "stdout": test_result.stdout, "stderr": test_result.stderr, "exit_code": test_result.exit_code, "execution_time": test_result.execution_time } except Exception as e: return { "success": False, "error": str(e) } finally: # Always cleanup - fresh sandbox for next test if sandbox: sandbox.kill() # Usage runner = IsolatedTestRunner(api_key=os.getenv("HOPX_API_KEY")) test_config = { "test_code": """ import unittest class TestMath(unittest.TestCase): def test_addition(self): self.assertEqual(1 + 1, 2) def test_multiplication(self): self.assertEqual(2 * 3, 6) if __name__ == '__main__': unittest.main() """, "setup": "import unittest", "timeout": 30, "env_vars": { "TEST_MODE": "true" }, "files": [ { "path": "/workspace/test_utils.py", "content": "def helper(): return 'helper'" } ] } result = runner.run_isolated_test(test_config) print(json.dumps(result, indent=2)) ``` ```javascript JavaScript theme={null} class IsolatedTestRunner { constructor(apiKey) { this.apiKey = apiKey; } async runIsolatedTest(testConfig) { let sandbox = null; try { // Create sandbox with clean environment sandbox = await Sandbox.create({ template: 'code-interpreter', apiKey: this.apiKey, timeoutSeconds: (testConfig.timeout || 60) + 10, envVars: testConfig.envVars || {} }); // Set up test environment const setupCode = testConfig.setup || ''; if (setupCode) { const setupResult = await sandbox.runCode(setupCode, { timeout: 30 }); if (!setupResult.success) { return { success: false, error: `Setup failed: ${setupResult.stderr}`, stage: 'setup' }; } } // Write test files for (const fileConfig of testConfig.files || []) { await sandbox.files.write( fileConfig.path, fileConfig.content ); } // Execute test const testResult = await sandbox.runCode( testConfig.testCode, { language: testConfig.language || 'python', timeout: testConfig.timeout || 60 } ); // Cleanup (teardown) const teardownCode = testConfig.teardown || ''; if (teardownCode) { await sandbox.runCode(teardownCode, { timeout: 30 }); } return { success: testResult.success, stdout: testResult.stdout, stderr: testResult.stderr, exitCode: testResult.exit_code, executionTime: testResult.execution_time }; } catch (error) { return { success: false, error: error.message }; } finally { // Always cleanup - fresh sandbox for next test if (sandbox) { await sandbox.kill(); } } } } // Usage const runner = new IsolatedTestRunner(process.env.HOPX_API_KEY); const testConfig = { testCode: ` const assert = require('assert'); describe('Math Tests', () => { it('should add numbers', () => { assert.strictEqual(1 + 1, 2); }); it('should multiply numbers', () => { assert.strictEqual(2 * 3, 6); }); }); `, setup: 'const assert = require("assert");', timeout: 30, envVars: { TEST_MODE: 'true' }, files: [ { path: '/workspace/test_utils.js', content: "function helper() { return 'helper'; }" } ] }; const result = await runner.runIsolatedTest(testConfig); console.log(JSON.stringify(result, null, 2)); ``` ### Step 4: Result Aggregation and Reporting Aggregate test results and generate reports: ```python Python theme={null} class TestResultAggregator: def __init__(self): self.results = [] def add_result(self, test_name: str, result: Dict[str, Any]): """Add test result to aggregation""" self.results.append({ "test_name": test_name, "result": result, "timestamp": self._get_timestamp() }) def generate_report(self) -> Dict[str, Any]: """Generate aggregated test report""" total = len(self.results) passed = sum(1 for r in self.results if r["result"].get("success", False)) failed = total - passed # Calculate execution times execution_times = [ r["result"].get("execution_time", 0) for r in self.results if "execution_time" in r["result"] ] avg_time = sum(execution_times) / len(execution_times) if execution_times else 0 total_time = sum(execution_times) # Group by status passed_tests = [r for r in self.results if r["result"].get("success", False)] failed_tests = [r for r in self.results if not r["result"].get("success", False)] return { "summary": { "total": total, "passed": passed, "failed": failed, "success_rate": (passed / total * 100) if total > 0 else 0, "average_execution_time": avg_time, "total_execution_time": total_time }, "passed_tests": [ { "name": r["test_name"], "execution_time": r["result"].get("execution_time", 0) } for r in passed_tests ], "failed_tests": [ { "name": r["test_name"], "error": r["result"].get("error") or r["result"].get("stderr", ""), "execution_time": r["result"].get("execution_time", 0) } for r in failed_tests ], "all_results": self.results } def _get_timestamp(self) -> str: from datetime import datetime return datetime.now().isoformat() # Usage aggregator = TestResultAggregator() # Add results aggregator.add_result("test_1", {"success": True, "execution_time": 1.5}) aggregator.add_result("test_2", {"success": False, "error": "Assertion failed"}) aggregator.add_result("test_3", {"success": True, "execution_time": 2.1}) # Generate report report = aggregator.generate_report() print(json.dumps(report, indent=2)) ``` ```javascript JavaScript theme={null} class TestResultAggregator { constructor() { this.results = []; } addResult(testName, result) { this.results.push({ testName, result, timestamp: new Date().toISOString() }); } generateReport() { const total = this.results.length; const passed = this.results.filter(r => r.result.success).length; const failed = total - passed; // Calculate execution times const executionTimes = this.results .map(r => r.result.executionTime || 0) .filter(t => t > 0); const avgTime = executionTimes.length > 0 ? executionTimes.reduce((a, b) => a + b, 0) / executionTimes.length : 0; const totalTime = executionTimes.reduce((a, b) => a + b, 0); // Group by status const passedTests = this.results.filter(r => r.result.success); const failedTests = this.results.filter(r => !r.result.success); return { summary: { total, passed, failed, successRate: total > 0 ? (passed / total * 100) : 0, averageExecutionTime: avgTime, totalExecutionTime: totalTime }, passedTests: passedTests.map(r => ({ name: r.testName, executionTime: r.result.executionTime || 0 })), failedTests: failedTests.map(r => ({ name: r.testName, error: r.result.error || r.result.stderr || '', executionTime: r.result.executionTime || 0 })), allResults: this.results }; } } // Usage const aggregator = new TestResultAggregator(); // Add results aggregator.addResult('test_1', { success: true, executionTime: 1.5 }); aggregator.addResult('test_2', { success: false, error: 'Assertion failed' }); aggregator.addResult('test_3', { success: true, executionTime: 2.1 }); // Generate report const report = aggregator.generateReport(); console.log(JSON.stringify(report, null, 2)); ``` ## Best Practices ### Isolation Always create a fresh sandbox for each test to ensure complete isolation. Never reuse sandboxes between tests. 1. **Fresh Sandboxes**: One sandbox per test execution 2. **Clean Environment**: Start with clean environment variables 3. **No Shared State**: Tests should not depend on each other 4. **Resource Cleanup**: Always cleanup sandboxes after tests ### Performance Use parallel execution for independent tests, but ensure each test runs in its own isolated sandbox. 1. **Parallel Execution**: Run independent tests in parallel 2. **Resource Limits**: Set appropriate timeouts per test 3. **Result Caching**: Cache test results when possible 4. **Efficient Cleanup**: Clean up sandboxes efficiently ### Reliability 1. **Error Handling**: Handle all error cases gracefully 2. **Timeout Management**: Set appropriate timeouts 3. **Retry Logic**: Implement retry for transient failures 4. **Logging**: Log all test executions for debugging ## Real-World Examples This pattern is used by: * **GitHub Actions**: CI/CD test execution * **Jenkins**: Continuous integration platform * **CircleCI**: Cloud-based CI/CD * **Travis CI**: Continuous integration service ## Related Cookbooks * [API Testing Platform](/cookbooks/automation/api-testing-platform) - API testing automation ## Next Steps 1. Integrate with CI/CD platforms (GitHub Actions, GitLab CI, etc.) 2. Add test result persistence and history 3. Implement test result notifications 4. Create test execution dashboard 5. Add support for more test frameworks # Clearing Source: https://docs.hopx.ai/core-concepts/cache/clearing Clear sandbox execution result cache to free memory and reset cache statistics in HopX sandboxes. Remove cached execution results to free resources, force re-execution of code, or reset cache performance metrics. Essential for memory management and debugging. Includes Python and JavaScript SDK examples and REST API endpoints. Clear the execution result cache to free memory, reset cache statistics, and ensure fresh executions for testing or debugging. ## Overview Clearing the cache is useful when: * Cache has grown too large and you need to free memory * You want to reset cache statistics * Testing code changes that should bypass cache * Debugging cache-related issues * Starting fresh after code modifications Clearing the cache will remove all cached execution results. Subsequent executions will be cache misses until new entries are created. ## Clearing Cache Clear all cached execution results: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Get cache stats before clearing before = sandbox.cache.stats() before_cache = before['cache'] print(f"Before clearing: Size={before_cache['size']}, Hits={before_cache['total_hits']}") # Clear the cache result = sandbox.cache.clear() print(f"Result: {result['message']}") # Get cache stats after clearing after = sandbox.cache.stats() after_cache = after['cache'] print(f"After clearing: Size={after_cache['size']}, Hits={after_cache['total_hits']}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Get cache stats before clearing const before = await sandbox.cache.stats(); const beforeCache = before.cache; console.log(`Before clearing: Size=${beforeCache.size}, Hits=${beforeCache.total_hits}`); // Clear the cache const result = await sandbox.cache.clear(); console.log(`Result: ${result.message}`); // Get cache stats after clearing const after = await sandbox.cache.stats(); const afterCache = after.cache; console.log(`After clearing: Size=${afterCache.size}, Hits=${afterCache.total_hits}`); await sandbox.kill(); ``` ## Cache Clear Response The cache clear operation returns a confirmation: ```json theme={null} { "message": "Cache cleared successfully", "timestamp": "2025-01-27T19:49:28Z" } ``` ### Field Descriptions * **`message`**: Confirmation message * **`timestamp`**: Timestamp when the cache was cleared ## Use Cases ### Freeing Memory Clear cache when it consumes too much memory: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Check cache size stats = sandbox.cache.stats() cache_data = stats['cache'] cache_size = cache_data['size'] max_size = cache_data['max_size'] # Clear if cache is too large (80% of max) CACHE_SIZE_THRESHOLD = max_size * 0.8 if cache_size > CACHE_SIZE_THRESHOLD: print(f"Cache size ({cache_size}) exceeds threshold ({CACHE_SIZE_THRESHOLD})") result = sandbox.cache.clear() print(f"Cache cleared: {result['message']}") else: print(f"Cache size ({cache_size}) is within acceptable range") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Check cache size const stats = await sandbox.cache.stats(); const cacheData = stats.cache; const cacheSize = cacheData.size; const maxSize = cacheData.max_size; // Clear if cache is too large (80% of max) const CACHE_SIZE_THRESHOLD = maxSize * 0.8; if (cacheSize > CACHE_SIZE_THRESHOLD) { console.log(`Cache size (${cacheSize}) exceeds threshold (${CACHE_SIZE_THRESHOLD})`); const result = await sandbox.cache.clear(); console.log(`Cache cleared: ${result.message}`); } else { console.log(`Cache size (${cacheSize}) is within acceptable range`); } await sandbox.kill(); ``` ### Resetting for Testing Clear cache before running tests to ensure fresh executions: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Clear cache before testing print("Clearing cache for fresh test execution...") sandbox.cache.clear() # Run test code (will be cache miss) result = sandbox.run_code(""" import time start = time.time() # Simulate some computation sum(range(100000)) end = time.time() print(f"Execution time: {end - start:.3f}s") """) print("Test completed with fresh execution") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Clear cache before testing console.log('Clearing cache for fresh test execution...'); await sandbox.cache.clear(); // Run test code (will be cache miss) const result = await sandbox.runCode(` import time start = time.time() # Simulate some computation sum(range(100000)) end = time.time() print(f"Execution time: {end - start:.3f}s") `); console.log('Test completed with fresh execution'); await sandbox.kill(); ``` ### Periodic Cache Maintenance Clear cache periodically to prevent unbounded growth: ```python theme={null} from hopx_ai import Sandbox import time sandbox = Sandbox.create(template="code-interpreter") # Run some code to generate cache entries for i in range(20): sandbox.run_code(f"print('Execution {i}')") time.sleep(0.1) # Check cache stats stats = sandbox.cache.stats() cache_data = stats['cache'] print(f"Cache size: {cache_data['size']}") print(f"Cache hits: {cache_data['total_hits']}") # Clear cache periodically (e.g., if size > 80% of max) if cache_data['size'] > cache_data['max_size'] * 0.8: print("Clearing cache due to high size...") result = sandbox.cache.clear() print(f"Cleared: {result['message']}") # Verify cache is cleared after_stats = sandbox.cache.stats() after_cache = after_stats['cache'] print(f"Cache size after clear: {after_cache['size']}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Run some code to generate cache entries for (let i = 0; i < 20; i++) { await sandbox.runCode(`print('Execution ${i}')`); await new Promise(resolve => setTimeout(resolve, 100)); } // Check cache stats const stats = await sandbox.cache.stats(); const cacheData = stats.cache; console.log(`Cache size: ${cacheData.size}`); console.log(`Cache hits: ${cacheData.total_hits}`); // Clear cache periodically (e.g., if size > 80% of max) if (cacheData.size > cacheData.max_size * 0.8) { console.log('Clearing cache due to high size...'); const result = await sandbox.cache.clear(); console.log(`Cleared: ${result.message}`); // Verify cache is cleared const afterStats = await sandbox.cache.stats(); const afterCache = afterStats.cache; console.log(`Cache size after clear: ${afterCache.size}`); } await sandbox.kill(); ``` ## Best Practices **Monitor cache size** before clearing. Only clear when necessary to avoid losing beneficial cached results. **Clear cache before testing** to ensure code changes are properly tested without cache interference. **Clearing cache affects performance**. After clearing, all executions will be cache misses until new entries are created. **Set up periodic cache maintenance** if you have long-running sandboxes with many executions. ## API Reference ### Python SDK * `sandbox.cache.clear(*, timeout=None)` - Clear execution cache ### JavaScript SDK * `sandbox.cache.clear()` - Clear execution cache ### API Endpoint * **POST** `/cache/clear` - Clear execution result cache ## Related * **[Cache Statistics](/core-concepts/cache/statistics)** - Monitor cache performance * **SDK**: [sandbox.cache.clear()](/sdk/python/cache#clear) - Python SDK method * **API**: [POST /cache/clear](/api/vm-agent/clear-cache) - VM Agent API endpoint ## Next Steps * Learn about [Cache Statistics](/core-concepts/cache/statistics) to monitor cache * Review [Code Execution](/core-concepts/code-execution/synchronous) for execution results * [Cache Statistics](/core-concepts/cache/statistics) - Monitor cache performance * **[CLI System Commands](/cli/commands/system)** - View cache statistics from CLI # Cache Source: https://docs.hopx.ai/core-concepts/cache/index Complete guide to cache management in HopX sandboxes - statistics, clearing, and optimization. Learn how to view cache statistics, clear execution cache, optimize cache usage, and monitor cache performance. Manage cache for improved execution speed and resource efficiency. Includes Python and JavaScript SDK examples and REST API endpoints. Manage execution cache in HopX sandboxes for performance optimization. This hub covers cache statistics, clearing, and best practices. ## Related * [CLI System Commands](/cli/commands/system) - System operations from CLI ## What You'll Learn * How to view cache statistics * How to clear execution cache * How to optimize cache usage * How to monitor cache performance * Best practices for cache management ## Cache Management Overview | Operation | SDK Method | API Endpoint | | ------------------------------------------------- | ----------------------- | ------------------- | | **[Statistics](/core-concepts/cache/statistics)** | `sandbox.cache.stats()` | `GET /cache/stats` | | **[Clearing](/core-concepts/cache/clearing)** | `sandbox.cache.clear()` | `POST /cache/clear` | ## Core Concepts ### Cache Statistics View cache statistics including hit rate and cached items. * **[Cache Statistics](/core-concepts/cache/statistics)** - View cache statistics * **SDK**: [Python: sandbox.cache.stats()](/sdk/python/cache#stats) | [JavaScript: sandbox.cache.stats()](/sdk/javascript/cache#stats) * **API**: [GET /cache/stats](/api/vm-agent/get-cache-stats) ### Clearing Cache Clear execution cache to free memory or force re-execution. * **[Clearing Cache](/core-concepts/cache/clearing)** - Clear execution cache * **SDK**: [Python: sandbox.cache.clear()](/sdk/python/cache#clear) | [JavaScript: sandbox.cache.clear()](/sdk/javascript/cache#clear) * **API**: [POST /cache/clear](/api/vm-agent/clear-cache) ## SDK Reference ### Python SDK Complete reference for Python cache operations. * **[Cache Module](/sdk/python/cache)** - Complete cache API * `cache.stats()` - Get cache statistics * `cache.clear()` - Clear cache ### JavaScript SDK Complete reference for JavaScript/TypeScript cache operations. * **[Cache Module](/sdk/javascript/cache)** - Complete cache API * `cache.stats()` - Get cache statistics * `cache.clear()` - Clear cache ## API Reference ### VM Agent API REST API endpoints for cache management. * **[VM Agent API Overview](/api/vm-agent/overview)** - API overview * **[Get Cache Statistics](/api/vm-agent/get-cache-stats)** - `GET /cache/stats` - Get cache stats * **[Clear Cache](/api/vm-agent/clear-cache)** - `POST /cache/clear` - Clear cache ## Quick Start If you're new to cache management, start here: 1. **[Cache Statistics](/core-concepts/cache/statistics)** - View cache performance 2. **[Clearing Cache](/core-concepts/cache/clearing)** - Clear cache when needed ## Related Topics * **[Code Execution](/core-concepts/code-execution/synchronous)** - Cache affects code execution * **[Observability](/core-concepts/observability/metrics)** - Monitor cache metrics * **[Sandboxes](/core-concepts/sandboxes/managing-state)** - Cache persists across state changes ## Next Steps * Learn about [Cache Statistics](/core-concepts/cache/statistics) for monitoring * Explore [Clearing Cache](/core-concepts/cache/clearing) for optimization * Review [Code Execution](/core-concepts/code-execution/synchronous) to understand cache impact * Check out [Observability](/core-concepts/observability/metrics) for performance monitoring # Statistics Source: https://docs.hopx.ai/core-concepts/cache/statistics Get cache hit rate and usage statistics for sandbox code execution results in HopX sandboxes. Monitor cache performance, view hit rates, track cached items, and optimize execution speed. Essential for understanding cache effectiveness and performance tuning. Includes Python and JavaScript SDK examples and REST API endpoints. Monitor the execution result cache to understand cache performance, optimize your code patterns, and track cache usage over time. ## Overview HopX caches execution results to improve performance for repeated code executions. Cache statistics help you: * Monitor cache hit rates * Track cache size and entry counts * Optimize code patterns for better caching * Understand cache effectiveness The cache stores execution results based on code content and environment. Identical code executions with the same environment variables will hit the cache. ## Getting Cache Statistics Retrieve current cache statistics: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Get cache statistics stats = sandbox.cache.stats() # Cache data is nested under 'cache' key cache_data = stats['cache'] print(f"Total Hits: {cache_data['total_hits']}") print(f"Cache Size: {cache_data['size']}") print(f"Max Size: {cache_data['max_size']}") print(f"TTL: {cache_data['ttl']}") print(f"Timestamp: {stats['timestamp']}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Get cache statistics const stats = await sandbox.cache.stats(); // Cache data is nested under 'cache' key const cacheData = stats.cache; console.log(`Total Hits: ${cacheData.total_hits}`); console.log(`Cache Size: ${cacheData.size}`); console.log(`Max Size: ${cacheData.max_size}`); console.log(`TTL: ${cacheData.ttl}`); console.log(`Timestamp: ${stats.timestamp}`); await sandbox.kill(); ``` ## Understanding Cache Metrics ### Cache Size and Hits Monitor cache usage and performance: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") stats = sandbox.cache.stats() cache_data = stats['cache'] print(f"Total Cache Hits: {cache_data['total_hits']}") print(f"Current Cache Size: {cache_data['size']}") print(f"Max Cache Size: {cache_data['max_size']}") print(f"Cache TTL: {cache_data['ttl']}") if cache_data['total_hits'] > 100: print("✅ Cache is being utilized effectively") else: print("💡 Consider optimizing code patterns for better caching") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); const stats = await sandbox.cache.stats(); const cacheData = stats.cache; console.log(`Total Cache Hits: ${cacheData.total_hits}`); console.log(`Current Cache Size: ${cacheData.size}`); console.log(`Max Cache Size: ${cacheData.max_size}`); console.log(`Cache TTL: ${cacheData.ttl}`); if (cacheData.total_hits > 100) { console.log('✅ Cache is being utilized effectively'); } else { console.log('💡 Consider optimizing code patterns for better caching'); } await sandbox.kill(); ``` ### Cache Size Monitor cache size to ensure it's not consuming excessive resources: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") stats = sandbox.cache.stats() cache_data = stats['cache'] cache_size = cache_data['size'] max_size = cache_data['max_size'] print(f"Cache Size: {cache_size}") print(f"Max Cache Size: {max_size}") print(f"Cache TTL: {cache_data['ttl']}") if cache_size > max_size * 0.8: print("⚠️ Cache size is approaching maximum. Consider clearing if needed.") elif cache_size > max_size * 0.5: print("Cache size is moderate.") else: print("Cache size is small.") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); const stats = await sandbox.cache.stats(); const cacheData = stats.cache; const cacheSize = cacheData.size; const maxSize = cacheData.max_size; console.log(`Cache Size: ${cacheSize}`); console.log(`Max Cache Size: ${maxSize}`); console.log(`Cache TTL: ${cacheData.ttl}`); if (cacheSize > maxSize * 0.8) { console.log('⚠️ Cache size is approaching maximum. Consider clearing if needed.'); } else if (cacheSize > maxSize * 0.5) { console.log('Cache size is moderate.'); } else { console.log('Cache size is small.'); } await sandbox.kill(); ``` ## Monitoring Cache Performance Track cache performance over time: ```python theme={null} from hopx_ai import Sandbox import time sandbox = Sandbox.create(template="code-interpreter") # Run some code to generate cache entries for i in range(5): sandbox.run_code(f"print('Execution {i}')") time.sleep(1) # Check cache statistics stats = sandbox.cache.stats() cache_data = stats['cache'] print("Cache Performance:") print(f" Total Cache Hits: {cache_data['total_hits']}") print(f" Current Cache Size: {cache_data['size']}") print(f" Max Cache Size: {cache_data['max_size']}") print(f" Cache TTL: {cache_data['ttl']}") print(f" Timestamp: {stats['timestamp']}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Run some code to generate cache entries for (let i = 0; i < 5; i++) { await sandbox.runCode(`print('Execution ${i}')`); await new Promise(resolve => setTimeout(resolve, 1000)); } // Check cache statistics const stats = await sandbox.cache.stats(); const cacheData = stats.cache; console.log('Cache Performance:'); console.log(` Total Cache Hits: ${cacheData.total_hits}`); console.log(` Current Cache Size: ${cacheData.size}`); console.log(` Max Cache Size: ${cacheData.max_size}`); console.log(` Cache TTL: ${cacheData.ttl}`); console.log(` Timestamp: ${stats.timestamp}`); await sandbox.kill(); ``` ## Cache Statistics Response The cache statistics response includes: ```json theme={null} { "cache": { "max_size": 1000, "size": 0, "total_hits": 0, "ttl": "5m0s" }, "timestamp": "2025-01-27T19:43:55Z" } ``` ### Field Descriptions * **`cache.max_size`**: Maximum cache size limit * **`cache.size`**: Current cache size * **`cache.total_hits`**: Total number of cache hits (cached results reused) * **`cache.ttl`**: Time-to-live for cache entries * **`timestamp`**: Timestamp when the statistics were retrieved ## Use Cases ### Optimizing for Cache Test cache effectiveness with repeated executions: ```python theme={null} from hopx_ai import Sandbox import time sandbox = Sandbox.create(template="code-interpreter") # Initial execution (cache miss) code = "result = sum(range(1000000)); print(f'Sum: {result}')" sandbox.run_code(code) # Get initial stats initial_stats = sandbox.cache.stats() initial_hits = initial_stats['cache']['total_hits'] print(f"After first execution - Total Hits: {initial_hits}") # Repeat same code (should hit cache) sandbox.run_code(code) # Check stats after repeat final_stats = sandbox.cache.stats() final_hits = final_stats['cache']['total_hits'] print(f"After repeat execution - Total Hits: {final_hits}") if final_hits > initial_hits: print("✅ Cache hit confirmed - repeated execution used cached result") else: print("⚠️ No cache hit - execution may have been different") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Initial execution (cache miss) const code = "result = sum(range(1000000)); print(f'Sum: {result}')"; await sandbox.runCode(code); // Get initial stats const initialStats = await sandbox.cache.stats(); const initialHits = initialStats.cache.total_hits; console.log(`After first execution - Total Hits: ${initialHits}`); // Repeat same code (should hit cache) await sandbox.runCode(code); // Check stats after repeat const finalStats = await sandbox.cache.stats(); const finalHits = finalStats.cache.total_hits; console.log(`After repeat execution - Total Hits: ${finalHits}`); if (finalHits > initialHits) { console.log('✅ Cache hit confirmed - repeated execution used cached result'); } else { console.log('⚠️ No cache hit - execution may have been different'); } await sandbox.kill(); ``` ### Monitoring Cache Growth Track how cache grows over time: ```python theme={null} from hopx_ai import Sandbox import time sandbox = Sandbox.create(template="code-interpreter") # Monitor cache growth for i in range(10): # Execute different code each time sandbox.run_code(f"print('Execution {i}: {i * 10}')") stats = sandbox.cache.stats() cache_data = stats['cache'] print(f"After execution {i+1}: Size={cache_data['size']}, Hits={cache_data['total_hits']}") time.sleep(0.5) sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Monitor cache growth for (let i = 0; i < 10; i++) { // Execute different code each time await sandbox.runCode(`print('Execution ${i}: ${i * 10}')`); const stats = await sandbox.cache.stats(); const cacheData = stats.cache; console.log(`After execution ${i+1}: Size=${cacheData.size}, Hits=${cacheData.total_hits}`); await new Promise(resolve => setTimeout(resolve, 500)); } await sandbox.kill(); ``` ## Best Practices **Monitor total hits** to understand cache effectiveness. A high number of total hits indicates good cache utilization. **Cache works best with deterministic code**. Code that produces the same output for the same input will benefit most from caching. **Cache size can grow over time**. Monitor cache size and clear it periodically if it becomes too large. **Environment variables affect caching**. Code with different environment variables will have separate cache entries. ## API Reference ### Python SDK * `sandbox.cache.stats(*, timeout=None)` - Get cache statistics ### JavaScript SDK * `sandbox.cache.stats()` - Get cache statistics ### API Endpoint * **GET** `/cache/stats` - Get execution cache statistics ## Related * **[Clearing Cache](/core-concepts/cache/clearing)** - Clear cache to free memory * **SDK**: [sandbox.cache.stats()](/sdk/python/cache#stats) - Python SDK method * **API**: [GET /cache/stats](/api/vm-agent/get-cache-stats) - VM Agent API endpoint ## Next Steps * Learn about [Clearing Cache](/core-concepts/cache/clearing) to free memory * Review [Code Execution](/core-concepts/code-execution/synchronous) to see cached results * [Clearing Cache](/core-concepts/cache/clearing) - Clear the execution cache * **[CLI System Commands](/cli/commands/system)** - View cache statistics from CLI # Async Webhooks Source: https://docs.hopx.ai/core-concepts/code-execution/async-webhooks Execute very long-running code with webhook callbacks in HopX sandboxes. Run code asynchronously and receive results via webhook callbacks when execution completes. Perfect for long-running tasks, batch processing, and async workflows. Learn how to configure webhooks and handle callback responses. Includes examples and webhook setup. Async execution with webhooks is designed for very long-running tasks (>30 minutes) that would otherwise timeout. The execution happens asynchronously, and results are delivered to your webhook endpoint when complete. ## Overview Async webhook execution is perfect for: * ML model training (30+ minutes) * Large dataset processing * Video encoding/processing * Long-running simulations * Any task that exceeds normal timeout limits Async webhook execution returns immediately with an `execution_id`. The agent executes code in the background and POSTs results to your callback URL when complete. ## Basic Usage Start async execution with a webhook callback: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Start async execution response = sandbox.run_code_async( code=''' import time print("Starting long task...") time.sleep(600) # 10 minutes print("Task completed!") ''', callback_url='https://your-app.com/webhooks/HopX-complete', language='python', timeout=1800 # 30 minutes max ) print(f"Execution ID: {response['execution_id']}") print(f"Status: {response['status']}") print(f"Callback URL: {response['callback_url']}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Start async execution const response = await sandbox.runCodeAsync( ` import time print("Starting long task...") time.sleep(600) # 10 minutes print("Task completed!") `, { callbackUrl: 'https://your-app.com/webhooks/HopX-complete', language: 'python', timeout: 1800 // 30 minutes max } ); console.log(`Execution ID: ${response.executionId}`); console.log(`Status: ${response.status}`); console.log(`Callback URL: ${response.callbackUrl}`); await sandbox.kill(); ``` ## Webhook Callback Your webhook endpoint will receive a POST request when execution completes: ```python theme={null} from flask import Flask, request import hmac import hashlib app = Flask(__name__) @app.route('/webhooks/HopX-complete', methods=['POST']) def hopx_webhook(): # Verify signature (if secret provided) signature = request.headers.get('X-HopX-Signature') timestamp = request.headers.get('X-HopX-Timestamp') # Verify signature if secret was provided # secret = 'your-webhook-secret' # expected_sig = hmac.new( # secret.encode(), # f"{timestamp}{request.data}".encode(), # hashlib.sha256 # ).hexdigest() # if signature != f"sha256={expected_sig}": # return "Invalid signature", 401 # Process webhook payload data = request.json execution_id = data['execution_id'] status = data['status'] stdout = data.get('stdout', '') stderr = data.get('stderr', '') exit_code = data.get('exit_code', 0) execution_time = data.get('execution_time', 0) print(f"Execution {execution_id} completed with status: {status}") print(f"Output: {stdout}") if status == 'completed': # Handle successful completion process_results(execution_id, stdout) else: # Handle failure handle_error(execution_id, stderr) return "OK", 200 ``` ```javascript theme={null} const express = require('express'); const crypto = require('crypto'); const app = express(); app.use(express.json()); app.post('/webhooks/HopX-complete', (req, res) => { // Verify signature (if secret provided) const signature = req.headers['x-HopX-signature']; const timestamp = req.headers['x-HopX-timestamp']; // Verify signature if secret was provided // const secret = 'your-webhook-secret'; // const expectedSig = crypto // .createHmac('sha256', secret) // .update(`${timestamp}${JSON.stringify(req.body)}`) // .digest('hex'); // if (signature !== `sha256=${expectedSig}`) { // return res.status(401).send('Invalid signature'); // } // Process webhook payload const { executionId, status, stdout, stderr, exitCode, executionTime } = req.body; console.log(`Execution ${executionId} completed with status: ${status}`); console.log(`Output: ${stdout}`); if (status === 'completed') { // Handle successful completion processResults(executionId, stdout); } else { // Handle failure handleError(executionId, stderr); } res.status(200).send('OK'); }); ``` ## Signature Verification Verify webhook signatures for security: ```python theme={null} from hopx_ai import Sandbox import hmac import hashlib sandbox = Sandbox.create(template="code-interpreter") # Start async execution with signature secret response = sandbox.run_code_async( code='import time; time.sleep(600); print("Done")', callback_url='https://your-app.com/webhooks/HopX-complete', callback_signature_secret='your-webhook-secret-123', language='python' ) print(f"Execution ID: {response['execution_id']}") # In your webhook handler: # signature = request.headers.get('X-HopX-Signature') # timestamp = request.headers.get('X-HopX-Timestamp') # body = request.data # # expected = hmac.new( # 'your-webhook-secret-123'.encode(), # f"{timestamp}{body}".encode(), # hashlib.sha256 # ).hexdigest() # # if signature == f"sha256={expected}": # # Valid signature # pass ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import crypto from 'crypto'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Start async execution with signature secret const response = await sandbox.runCodeAsync( 'import time; time.sleep(600); print("Done")', { callbackUrl: 'https://your-app.com/webhooks/HopX-complete', callbackSignatureSecret: 'your-webhook-secret-123', language: 'python' } ); console.log(`Execution ID: ${response.executionId}`); // In your webhook handler: // const signature = req.headers['x-HopX-signature']; // const timestamp = req.headers['x-HopX-timestamp']; // const body = JSON.stringify(req.body); // // const expected = crypto // .createHmac('sha256', 'your-webhook-secret-123') // .update(`${timestamp}${body}`) // .digest('hex'); // // if (signature === `sha256=${expected}`) { // // Valid signature // } ``` ## Custom Headers Include custom headers in webhook callbacks: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Start async execution with custom headers response = sandbox.run_code_async( code='import time; time.sleep(600); print("Done")', callback_url='https://your-app.com/webhooks/HopX-complete', callback_headers={ 'Authorization': 'Bearer your-api-token', 'X-Custom-Header': 'custom-value' }, language='python' ) print(f"Execution ID: {response['execution_id']}") # Your webhook will receive: # POST https://your-app.com/webhooks/HopX-complete # Authorization: Bearer your-api-token # X-Custom-Header: custom-value # X-HopX-Signature: sha256=... # X-HopX-Timestamp: 1698765432 ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Start async execution with custom headers const response = await sandbox.runCodeAsync( 'import time; time.sleep(600); print("Done")', { callbackUrl: 'https://your-app.com/webhooks/HopX-complete', callbackHeaders: { 'Authorization': 'Bearer your-api-token', 'X-Custom-Header': 'custom-value' }, language: 'python' } ); console.log(`Execution ID: ${response.executionId}`); // Your webhook will receive: // POST https://your-app.com/webhooks/HopX-complete // Authorization: Bearer your-api-token // X-Custom-Header: custom-value // X-HopX-Signature: sha256=... // X-HopX-Timestamp: 1698765432 ``` ## Complete Example Here's a complete example with ML model training: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Start ML training with async webhook response = sandbox.run_code_async( code=''' import time import random print("Starting ML model training...") print("Epoch 1/10...") time.sleep(60) for epoch in range(2, 11): loss = random.uniform(0.1, 0.5) accuracy = random.uniform(0.8, 0.95) print(f"Epoch {epoch}/10 - Loss: {loss:.4f}, Accuracy: {accuracy:.4f}") time.sleep(60) print("Training completed!") print("Model saved to /workspace/model.pkl") ''', callback_url='https://your-app.com/webhooks/ml-training-complete', callback_headers={ 'Authorization': 'Bearer ml-api-token', 'X-Training-ID': 'training-123' }, callback_signature_secret='ml-webhook-secret', language='python', timeout=3600, # 1 hour env={ 'WANDB_API_KEY': 'your-wandb-key', 'HF_TOKEN': 'your-huggingface-token' } ) print(f"✅ Training started") print(f"Execution ID: {response['execution_id']}") print(f"Status: {response['status']}") print(f"Results will be posted to: {response['callback_url']}") # Your webhook will receive results when training completes sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Start ML training with async webhook const response = await sandbox.runCodeAsync( ` import time import random print("Starting ML model training...") print("Epoch 1/10...") time.sleep(60) for epoch in range(2, 11): loss = random.uniform(0.1, 0.5) accuracy = random.uniform(0.8, 0.95) print(f"Epoch {epoch}/10 - Loss: {loss:.4f}, Accuracy: {accuracy:.4f}") time.sleep(60) print("Training completed!") print("Model saved to /workspace/model.pkl") `, { callbackUrl: 'https://your-app.com/webhooks/ml-training-complete', callbackHeaders: { 'Authorization': 'Bearer ml-api-token', 'X-Training-ID': 'training-123' }, callbackSignatureSecret: 'ml-webhook-secret', language: 'python', timeout: 3600, // 1 hour env: { WANDB_API_KEY: 'your-wandb-key', HF_TOKEN: 'your-huggingface-token' } } ); console.log('✅ Training started'); console.log(`Execution ID: ${response.executionId}`); console.log(`Status: ${response.status}`); console.log(`Results will be posted to: ${response.callbackUrl}`); // Your webhook will receive results when training completes await sandbox.kill(); ``` ## Webhook Payload The webhook payload structure: ```json theme={null} { "execution_id": "abc123", "status": "completed", "stdout": "Task output...", "stderr": "", "exit_code": 0, "execution_time": 600.123 } ``` **Headers:** * `X-HopX-Signature`: HMAC-SHA256 signature (if secret provided) * `X-HopX-Timestamp`: Unix timestamp * Custom headers from `callback_headers` ## Best Practices Use `callback_signature_secret` and verify signatures in your webhook handler to ensure requests are authentic. Set appropriate timeouts based on expected execution time. Default is 30 minutes, max is typically 1 hour. Include authentication tokens or identifiers in `callback_headers` for secure webhook processing. Check the `status` field in webhook payloads to handle both successful completions and failures. Store `execution_id` when starting async execution to correlate webhook callbacks with your records. ## Related * **[Synchronous Execution](/core-concepts/code-execution/synchronous)** - Basic code execution * **[Background Execution](/core-concepts/code-execution/background)** - Long-running tasks * **[Streaming Execution](/core-concepts/code-execution/streaming)** - Real-time output streaming * **SDK**: [sandbox.run\_code\_async()](/sdk/python/sandbox#run_code_async) - Python SDK method * **API**: [POST /execute/async](/api/vm-agent/execute-async) - VM Agent API endpoint * [CLI Code Execution](/cli/commands/run) - Execute code from CLI ## Next Steps * Learn about [Background Execution](/core-concepts/code-execution/background) for shorter tasks * Explore [Process Management](/core-concepts/code-execution/process-management) for monitoring * Review [Synchronous Execution](/core-concepts/code-execution/synchronous) for immediate results # Background Source: https://docs.hopx.ai/core-concepts/code-execution/background Execute code in the background without blocking. Learn how to run long-running code in HopX sandboxes asynchronously, monitor background processes, retrieve results when complete, and manage process lifecycle. Perfect for training models, processing large datasets, or running time-consuming operations. Includes Python and JavaScript SDK examples. Background execution allows you to start code execution and return immediately, without waiting for completion. This is ideal for long-running tasks that you want to monitor and manage separately. ## Prerequisites Before you begin, make sure you have: * **Active sandbox** - A running sandbox (see [Creating Sandboxes](/core-concepts/sandboxes/creating)) * **Understanding of synchronous execution** - Familiarity with [Synchronous Execution](/core-concepts/code-execution/synchronous) is helpful * **Long-running task** - Code that takes more than a few minutes to complete ## Overview Background execution is perfect for: * Long-running computations (>5 minutes) * Tasks that don't need immediate results * Parallel processing of multiple tasks * Workflows where you want to check status periodically Background execution returns immediately with a `process_id`. Use [Process Management](/core-concepts/code-execution/process-management) to check status and manage background processes. ## Starting Background Execution Start code execution in the background: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Start background execution result = sandbox.run_code_background( code=''' import time for i in range(10): print(f"Step {i+1}/10") time.sleep(2) print("Done!") ''', language='python', name='long-task' ) process_id = result['process_id'] print(f"Process started: {process_id}") print(f"Status: {result['status']}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Start background execution const result = await sandbox.runCodeBackground( ` import time for i in range(10): print(f"Step {i+1}/10") time.sleep(2) print("Done!") `, { language: 'python', name: 'long-task' } ); const processId = result.processId; console.log(`Process started: ${processId}`); console.log(`Status: ${result.status}`); await sandbox.kill(); ``` ## Checking Process Status Check the status of background processes: ```python theme={null} from hopx_ai import Sandbox import time sandbox = Sandbox.create(template="code-interpreter") # Start background task result = sandbox.run_code_background( code='import time; time.sleep(30); print("Done")', language='python', name='check-status-demo' ) process_id = result['process_id'] # Check status periodically for i in range(5): processes = sandbox.list_processes() for proc in processes: if proc['process_id'] == process_id: print(f"Status: {proc['status']}") if proc['status'] == 'completed': print(f"Output: {proc.get('stdout', '')}") break time.sleep(2) sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Start background task const result = await sandbox.runCodeBackground( 'import time; time.sleep(30); print("Done")', { language: 'python', name: 'check-status-demo' } ); const processId = result.processId; // Check status periodically for (let i = 0; i < 5; i++) { const processes = await sandbox.listProcesses(); const proc = processes.find(p => p.processId === processId); if (proc) { console.log(`Status: ${proc.status}`); if (proc.status === 'completed') { console.log(`Output: ${proc.stdout || ''}`); break; } } await new Promise(resolve => setTimeout(resolve, 2000)); } await sandbox.kill(); ``` ## Process Naming Name your processes for easier identification: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Start multiple named processes proc1 = sandbox.run_code_background( code='import time; time.sleep(60)', language='python', name='data-processing' ) proc2 = sandbox.run_code_background( code='import time; time.sleep(60)', language='python', name='ml-training' ) # List processes by name processes = sandbox.list_processes() for proc in processes: print(f"{proc.get('name', 'unnamed')}: {proc['status']}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Start multiple named processes const proc1 = await sandbox.runCodeBackground( 'import time; time.sleep(60)', { language: 'python', name: 'data-processing' } ); const proc2 = await sandbox.runCodeBackground( 'import time; time.sleep(60)', { language: 'python', name: 'ml-training' } ); // List processes by name const processes = await sandbox.listProcesses(); for (const proc of processes) { console.log(`${proc.name || 'unnamed'}: ${proc.status}`); } await sandbox.kill(); ``` ## Environment Variables Pass environment variables to background execution: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Start background task with environment variables result = sandbox.run_code_background( code=''' import os import time api_key = os.getenv("API_KEY") print(f"Using API key: {api_key[:10]}...") time.sleep(30) print("Task completed") ''', language='python', env={ "API_KEY": "sk-123456", "DEBUG": "true" }, name='env-demo' ) print(f"Process ID: {result['process_id']}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Start background task with environment variables const result = await sandbox.runCodeBackground( ` import os import time api_key = os.getenv("API_KEY") print(f"Using API key: {api_key[:10]}...") time.sleep(30) print("Task completed") `, { language: 'python', env: { API_KEY: 'sk-123456', DEBUG: 'true' }, name: 'env-demo' } ); console.log(`Process ID: ${result.processId}`); await sandbox.kill(); ``` ## Timeout Configuration Set timeout for background execution: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Start background task with 10 minute timeout result = sandbox.run_code_background( code='import time; time.sleep(300)', language='python', timeout=600, # 10 minutes name='long-task' ) print(f"Process started with {result.get('timeout', 'default')}s timeout") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Start background task with 10 minute timeout const result = await sandbox.runCodeBackground( 'import time; time.sleep(300)', { language: 'python', timeout: 600, // 10 minutes name: 'long-task' } ); console.log(`Process started with ${result.timeout || 'default'}s timeout`); await sandbox.kill(); ``` ## Complete Example Here's a complete example showing background execution workflow: ```python theme={null} from hopx_ai import Sandbox import time sandbox = Sandbox.create(template="code-interpreter") # Start background task result = sandbox.run_code_background( code=''' import time import random for i in range(20): value = random.randint(1, 100) print(f"Step {i+1}: Generated {value}") time.sleep(1) print("All done!") ''', language='python', timeout=300, name='random-generator', env={"SEED": "42"} ) process_id = result['process_id'] print(f"✅ Background task started: {process_id}") # Monitor progress while True: processes = sandbox.list_processes() proc = next((p for p in processes if p['process_id'] == process_id), None) if not proc: print("Process not found") break status = proc['status'] print(f"Status: {status}") if status == 'completed': print(f"✅ Task completed!") print(f"Output:\n{proc.get('stdout', '')}") break elif status == 'failed': print(f"❌ Task failed!") print(f"Error: {proc.get('stderr', '')}") break time.sleep(2) sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Start background task const result = await sandbox.runCodeBackground( ` import time import random for i in range(20): value = random.randint(1, 100) print(f"Step {i+1}: Generated {value}") time.sleep(1) print("All done!") `, { language: 'python', timeout: 300, name: 'random-generator', env: { SEED: '42' } } ); const processId = result.processId; console.log(`✅ Background task started: ${processId}`); // Monitor progress while (true) { const processes = await sandbox.listProcesses(); const proc = processes.find(p => p.processId === processId); if (!proc) { console.log('Process not found'); break; } const status = proc.status; console.log(`Status: ${status}`); if (status === 'completed') { console.log('✅ Task completed!'); console.log(`Output:\n${proc.stdout || ''}`); break; } else if (status === 'failed') { console.log('❌ Task failed!'); console.log(`Error: ${proc.stderr || ''}`); break; } await new Promise(resolve => setTimeout(resolve, 2000)); } await sandbox.kill(); ``` ## Best Practices Always name your background processes for easier identification when listing and managing them. Set timeouts based on expected execution time. Default is 5 minutes, but you can extend for longer tasks. Check process status periodically to track progress and handle completion or failures. Remove completed processes to keep your process list manageable. Use [Process Management](/core-concepts/code-execution/process-management) for cleanup. Always check for failed status and handle errors appropriately. Access `stderr` for error details. ## Implementation * **SDK**: [sandbox.run\_code\_background()](/sdk/python/sandbox#run_code_background) - Python SDK method * **[CLI](/cli/introduction)** - Command-line interface * **API**: [POST /execute/background](/api/vm-agent/execute-background) - VM Agent API endpoint ## Related * **[Process Management](/core-concepts/code-execution/process-management)** - Monitor and manage background processes * **[Synchronous Execution](/core-concepts/code-execution/synchronous)** - Execute code synchronously * **[Streaming Execution](/core-concepts/code-execution/streaming)** - Real-time output streaming * **[Async Execution with Webhooks](/core-concepts/code-execution/async-webhooks)** - Very long-running tasks ## Next Steps * Learn about [Process Management](/core-concepts/code-execution/process-management) to monitor and control background processes * Explore [Async Webhooks](/core-concepts/code-execution/async-webhooks) for very long-running tasks (>30 minutes) * Review [Synchronous Execution](/core-concepts/code-execution/synchronous) for immediate results # Code Execution Source: https://docs.hopx.ai/core-concepts/code-execution/index Complete guide to executing code in HopX sandboxes - synchronous, asynchronous, background, and streaming execution modes. Learn how to run Python, JavaScript, Bash, and Go code, capture rich outputs like plots and DataFrames, manage background processes, and stream execution results in real-time using SDK methods or REST API endpoints. Execute code in HopX sandboxes using multiple execution modes. This hub covers all code execution methods, from simple synchronous runs to advanced background and streaming execution. ## Related * [CLI Code Execution](/cli/commands/run) - Execute code from CLI ## What You'll Learn * How to execute code synchronously and asynchronously * How to capture rich outputs (plots, DataFrames, visualizations) * How to run code in the background for long-running tasks * How to stream execution results in real-time * How to manage processes and handle async webhooks ## Code Execution Overview | Execution Mode | SDK Method | API Endpoint | | -------------------------------------------------------------------------- | --------------------------------------- | -------------------------- | | **[Synchronous](/core-concepts/code-execution/synchronous)** | `sandbox.run_code()` | `POST /execute` | | **[Rich Output](/core-concepts/code-execution/rich-output)** | `sandbox.run_code()` with `rich_output` | `POST /execute` | | **[Background](/core-concepts/code-execution/background)** | `sandbox.run_code_background()` | `POST /execute/background` | | **[Streaming](/core-concepts/code-execution/streaming)** | `sandbox.run_code_stream()` | `POST /execute/stream` | | **[Process Management](/core-concepts/code-execution/process-management)** | `sandbox.list_processes()` | `GET /processes` | | **[Async Webhooks](/core-concepts/code-execution/async-webhooks)** | Webhook configuration | Webhook endpoints | ## Core Concepts ### Synchronous Execution Execute code and wait for results. Perfect for quick scripts and data analysis. * **[Synchronous Execution](/core-concepts/code-execution/synchronous)** - Execute code and get results immediately * **SDK**: [Python: sandbox.run\_code()](/sdk/python/sandbox#run_code) | [JavaScript: sandbox.runCode()](/sdk/javascript/sandbox#runcode) * **API**: [POST /execute](/api/vm-agent/execute) ### Rich Output Capture Capture matplotlib plots, pandas DataFrames, and other rich outputs automatically. * **[Rich Output](/core-concepts/code-execution/rich-output)** - Capture plots, DataFrames, and visualizations * **SDK**: [Python: sandbox.run\_code() with rich\_output](/sdk/python/sandbox#run_code) | [JavaScript: sandbox.runCode() with richOutput](/sdk/javascript/sandbox#runcode) * **API**: [POST /execute](/api/vm-agent/execute) with `rich_output` parameter ### Background Execution Run long-running code without blocking. Perfect for training models or processing large datasets. * **[Background Execution](/core-concepts/code-execution/background)** - Run code asynchronously * **SDK**: [Python: sandbox.run\_code\_background()](/sdk/python/sandbox#run_code_background) | [JavaScript: sandbox.runCodeBackground()](/sdk/javascript/sandbox#runcodebackground) * **API**: [POST /execute/background](/api/vm-agent/execute-background) ### Streaming Execution Stream execution results in real-time as code runs. * **[Streaming Execution](/core-concepts/code-execution/streaming)** - Stream results in real-time * **SDK**: [Python: sandbox.run\_code\_stream()](/sdk/python/sandbox#run_code_stream) | [JavaScript: sandbox.runCodeStream()](/sdk/javascript/sandbox#runcodestream) * **API**: [POST /execute/stream](/api/vm-agent/execute-async) ### Process Management List, monitor, and manage background processes. * **[Process Management](/core-concepts/code-execution/process-management)** - Manage background processes * **SDK**: [Python: sandbox.list\_processes()](/sdk/python/sandbox#list_processes) | [JavaScript: sandbox.listProcesses()](/sdk/javascript/sandbox#listprocesses) * **API**: [GET /processes](/api/vm-agent/list-processes) | [DELETE /execute/kill](/api/vm-agent/kill-process) ### Async Webhooks Handle code execution results via webhooks for async workflows. * **[Async Webhooks](/core-concepts/code-execution/async-webhooks)** - Handle results via webhooks * **SDK**: Webhook configuration in SDK | **API**: Webhook endpoints ## SDK Reference ### Python SDK Complete reference for Python code execution. * **[Sandbox.run\_code()](/sdk/python/sandbox#run_code)** - Synchronous execution * **[Sandbox.run\_code\_background()](/sdk/python/sandbox#run_code_background)** - Background execution * **[Sandbox.run\_code\_stream()](/sdk/python/sandbox#run_code_stream)** - Streaming execution * **[Sandbox.list\_processes()](/sdk/python/sandbox#list_processes)** - Process management ### JavaScript SDK Complete reference for JavaScript/TypeScript code execution. * **[Sandbox.runCode()](/sdk/javascript/sandbox#runcode)** - Synchronous execution * **[Sandbox.runCodeBackground()](/sdk/javascript/sandbox#runcodebackground)** - Background execution * **[Sandbox.runCodeStream()](/sdk/javascript/sandbox#runcodestream)** - Streaming execution * **[Sandbox.listProcesses()](/sdk/javascript/sandbox#listprocesses)** - Process management ## API Reference ### VM Agent API REST API endpoints for code execution. * **[VM Agent API Overview](/api/vm-agent/overview)** - API overview * **[Execute Code](/api/vm-agent/execute)** - `POST /execute` - Synchronous execution * **[Execute Background](/api/vm-agent/execute-background)** - `POST /execute/background` - Background execution * **[Execute Async](/api/vm-agent/execute-async)** - `POST /execute/async` - Async execution * **[List Processes](/api/vm-agent/list-processes)** - `GET /processes` - List background processes * **[Kill Process](/api/vm-agent/kill-process)** - `DELETE /execute/kill` - Terminate process ## Quick Start If you're new to code execution, start here: 1. **[Synchronous Execution](/core-concepts/code-execution/synchronous)** - Execute your first code 2. **[Rich Output](/core-concepts/code-execution/rich-output)** - Capture plots and DataFrames 3. **[Background Execution](/core-concepts/code-execution/background)** - Run long-running tasks ## Related Topics * **[Sandboxes](/core-concepts/sandboxes/creating)** - Create and manage sandboxes * **[File Operations](/core-concepts/filesystem/reading)** - Work with files during execution * **[Environment Variables](/core-concepts/environment/getting)** - Configure execution environment * **[Observability](/core-concepts/observability/metrics)** - Monitor execution metrics ## Next Steps * Learn about [File Operations](/core-concepts/filesystem/reading) for working with files * Explore [Environment Variables](/core-concepts/environment/getting) for configuration * Review [Process Management](/core-concepts/code-execution/process-management) for advanced workflows * Check out [Observability](/core-concepts/observability/metrics) for monitoring # Process Management Source: https://docs.hopx.ai/core-concepts/code-execution/process-management List, monitor, and manage background execution processes in HopX sandboxes. Track running processes, check execution status, terminate stuck processes, and manage process lifecycle. Essential for managing long-running code execution and debugging. Includes Python and JavaScript SDK examples and REST API endpoints. Process management allows you to monitor and control background execution processes. You can list running processes, check their status, and terminate them when needed. ## Overview Process management is essential for: * Monitoring background execution progress * Checking process status and output * Terminating long-running or stuck processes * Managing multiple concurrent executions Process management works with processes started via `run_code_background()`. For system processes, see system process listing in the Observability section. ## Listing Processes List all background execution processes: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # List all processes processes = sandbox.list_processes() print(f"Found {len(processes)} processes") for proc in processes: print(f" {proc.get('name', 'unnamed')}: {proc['status']} (ID: {proc['process_id']})") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // List all processes const processes = await sandbox.listProcesses(); console.log(`Found ${processes.length} processes`); for (const proc of processes) { console.log(` ${proc.name || 'unnamed'}: ${proc.status} (ID: ${proc.processId})`); } await sandbox.kill(); ``` ## Process Status Check detailed status of processes: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Start a background process result = sandbox.run_code_background( code='import time; time.sleep(30)', language='python', name='status-demo' ) process_id = result['process_id'] # Check status processes = sandbox.list_processes() proc = next((p for p in processes if p['process_id'] == process_id), None) if proc: print(f"Process: {proc.get('name', 'unnamed')}") print(f"Status: {proc['status']}") print(f"Process ID: {proc['process_id']}") print(f"Execution ID: {proc.get('execution_id', 'N/A')}") if proc['status'] == 'completed': print(f"Output: {proc.get('stdout', '')}") elif proc['status'] == 'failed': print(f"Error: {proc.get('stderr', '')}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Start a background process const result = await sandbox.runCodeBackground( 'import time; time.sleep(30)', { language: 'python', name: 'status-demo' } ); const processId = result.processId; // Check status const processes = await sandbox.listProcesses(); const proc = processes.find(p => p.processId === processId); if (proc) { console.log(`Process: ${proc.name || 'unnamed'}`); console.log(`Status: ${proc.status}`); console.log(`Process ID: ${proc.processId}`); console.log(`Execution ID: ${proc.executionId || 'N/A'}`); if (proc.status === 'completed') { console.log(`Output: ${proc.stdout || ''}`); } else if (proc.status === 'failed') { console.log(`Error: ${proc.stderr || ''}`); } } await sandbox.kill(); ``` ## Process States Processes can be in different states: * **`queued`** - Waiting to start * **`running`** - Currently executing * **`completed`** - Finished successfully * **`failed`** - Execution failed * **`killed`** - Terminated by user ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Start multiple processes proc1 = sandbox.run_code_background('import time; time.sleep(10)', name='task-1') proc2 = sandbox.run_code_background('import time; time.sleep(20)', name='task-2') # Check states processes = sandbox.list_processes() for proc in processes: status = proc['status'] name = proc.get('name', 'unnamed') if status == 'running': print(f"🟢 {name} is running") elif status == 'completed': print(f"✅ {name} completed") elif status == 'failed': print(f"❌ {name} failed") elif status == 'queued': print(f"⏳ {name} is queued") elif status == 'killed': print(f"🛑 {name} was killed") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Start multiple processes const proc1 = await sandbox.runCodeBackground('import time; time.sleep(10)', { name: 'task-1' }); const proc2 = await sandbox.runCodeBackground('import time; time.sleep(20)', { name: 'task-2' }); // Check states const processes = await sandbox.listProcesses(); for (const proc of processes) { const status = proc.status; const name = proc.name || 'unnamed'; if (status === 'running') { console.log(`🟢 ${name} is running`); } else if (status === 'completed') { console.log(`✅ ${name} completed`); } else if (status === 'failed') { console.log(`❌ ${name} failed`); } else if (status === 'queued') { console.log(`⏳ ${name} is queued`); } else if (status === 'killed') { console.log(`🛑 ${name} was killed`); } } await sandbox.kill(); ``` ## Killing Processes Terminate running processes: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Start a long-running process result = sandbox.run_code_background( code='import time; time.sleep(300)', language='python', name='long-task' ) process_id = result['process_id'] print(f"Started process: {process_id}") # Kill the process sandbox.kill_process(process_id) print("Process killed") # Verify it's killed processes = sandbox.list_processes() proc = next((p for p in processes if p['process_id'] == process_id), None) if proc: print(f"Status: {proc['status']}") # Should be 'killed' sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Start a long-running process const result = await sandbox.runCodeBackground( 'import time; time.sleep(300)', { language: 'python', name: 'long-task' } ); const processId = result.processId; console.log(`Started process: ${processId}`); // Kill the process await sandbox.killProcess(processId); console.log('Process killed'); // Verify it's killed const processes = await sandbox.listProcesses(); const proc = processes.find(p => p.processId === processId); if (proc) { console.log(`Status: ${proc.status}`); // Should be 'killed' } await sandbox.kill(); ``` ## Monitoring Multiple Processes Monitor multiple processes simultaneously: ```python theme={null} from hopx_ai import Sandbox import time sandbox = Sandbox.create(template="code-interpreter") # Start multiple processes processes = [] for i in range(3): result = sandbox.run_code_background( code=f'import time; time.sleep({10 + i*5})', language='python', name=f'task-{i+1}' ) processes.append(result['process_id']) print(f"Started {len(processes)} processes") # Monitor all processes while True: all_processes = sandbox.list_processes() active = [p for p in all_processes if p['process_id'] in processes and p['status'] in ['queued', 'running']] if not active: print("All processes completed") break print(f"\nActive processes: {len(active)}") for proc in active: print(f" {proc.get('name')}: {proc['status']}") time.sleep(2) # Show final status all_processes = sandbox.list_processes() for proc in all_processes: if proc['process_id'] in processes: print(f"{proc.get('name')}: {proc['status']}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Start multiple processes const processIds = []; for (let i = 0; i < 3; i++) { const result = await sandbox.runCodeBackground( `import time; time.sleep(${10 + i * 5})`, { language: 'python', name: `task-${i + 1}` } ); processIds.push(result.processId); } console.log(`Started ${processIds.length} processes`); // Monitor all processes while (true) { const allProcesses = await sandbox.listProcesses(); const active = allProcesses.filter( p => processIds.includes(p.processId) && ['queued', 'running'].includes(p.status) ); if (active.length === 0) { console.log('All processes completed'); break; } console.log(`\nActive processes: ${active.length}`); for (const proc of active) { console.log(` ${proc.name}: ${proc.status}`); } await new Promise(resolve => setTimeout(resolve, 2000)); } // Show final status const finalProcesses = await sandbox.listProcesses(); for (const proc of finalProcesses) { if (processIds.includes(proc.processId)) { console.log(`${proc.name}: ${proc.status}`); } } await sandbox.kill(); ``` ## Complete Example Here's a complete process management workflow: ```python theme={null} from hopx_ai import Sandbox import time sandbox = Sandbox.create(template="code-interpreter") # Start multiple background tasks tasks = { 'data-processing': 'import time; time.sleep(20); print("Data processed")', 'ml-training': 'import time; time.sleep(30); print("Model trained")', 'report-generation': 'import time; time.sleep(15); print("Report generated")' } process_ids = {} for name, code in tasks.items(): result = sandbox.run_code_background(code, language='python', name=name) process_ids[name] = result['process_id'] print(f"✅ Started: {name} (ID: {result['process_id']})") # Monitor all processes print("\n📊 Monitoring processes...") while True: all_processes = sandbox.list_processes() active = [ p for p in all_processes if p['process_id'] in process_ids.values() and p['status'] in ['queued', 'running'] ] if not active: break print(f"\nActive: {len(active)}/{len(tasks)}") for proc in active: name = proc.get('name', 'unknown') status = proc['status'] print(f" {name}: {status}") time.sleep(3) # Show final results print("\n📋 Final Status:") all_processes = sandbox.list_processes() for name, proc_id in process_ids.items(): proc = next((p for p in all_processes if p['process_id'] == proc_id), None) if proc: status_icon = { 'completed': '✅', 'failed': '❌', 'killed': '🛑' }.get(proc['status'], '⏳') print(f"{status_icon} {name}: {proc['status']}") if proc['status'] == 'completed' and proc.get('stdout'): print(f" Output: {proc['stdout'].strip()}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Start multiple background tasks const tasks = { 'data-processing': 'import time; time.sleep(20); print("Data processed")', 'ml-training': 'import time; time.sleep(30); print("Model trained")', 'report-generation': 'import time; time.sleep(15); print("Report generated")' }; const processIds = {}; for (const [name, code] of Object.entries(tasks)) { const result = await sandbox.runCodeBackground(code, { language: 'python', name: name }); processIds[name] = result.processId; console.log(`✅ Started: ${name} (ID: ${result.processId})`); } // Monitor all processes console.log('\n📊 Monitoring processes...'); while (true) { const allProcesses = await sandbox.listProcesses(); const active = allProcesses.filter( p => Object.values(processIds).includes(p.processId) && ['queued', 'running'].includes(p.status) ); if (active.length === 0) { break; } console.log(`\nActive: ${active.length}/${Object.keys(tasks).length}`); for (const proc of active) { console.log(` ${proc.name}: ${proc.status}`); } await new Promise(resolve => setTimeout(resolve, 3000)); } // Show final results console.log('\n📋 Final Status:'); const finalProcesses = await sandbox.listProcesses(); for (const [name, procId] of Object.entries(processIds)) { const proc = finalProcesses.find(p => p.processId === procId); if (proc) { const statusIcon = { 'completed': '✅', 'failed': '❌', 'killed': '🛑' }[proc.status] || '⏳'; console.log(`${statusIcon} ${name}: ${proc.status}`); if (proc.status === 'completed' && proc.stdout) { console.log(` Output: ${proc.stdout.trim()}`); } } } await sandbox.kill(); ``` ## Best Practices Always name processes when starting them for easier identification in process lists. Check process status periodically to track progress and detect failures early. Remove or archive completed processes to keep your process list manageable. Check for failed status and access stderr for error details when processes fail. Use `kill_process()` to terminate processes that are stuck or taking too long. ## Related * **[Background Execution](/core-concepts/code-execution/background)** - Start background processes * **[Process Monitoring](/core-concepts/observability/processes)** - Monitor system processes * **SDK**: [sandbox.list\_processes()](/sdk/python/sandbox#list_processes) - Python SDK method * **SDK**: [sandbox.kill\_process()](/sdk/python/sandbox#kill_process) - Python SDK method * **API**: [GET /execute/processes](/api/vm-agent/list-processes) - VM Agent API endpoint * **API**: [DELETE /execute/kill](/api/vm-agent/kill-process) - VM Agent API endpoint * [CLI Code Execution](/cli/commands/run) - Execute code from CLI ## Next Steps * Learn about [Background Execution](/core-concepts/code-execution/background) to start processes * Explore [Synchronous Execution](/core-concepts/code-execution/synchronous) for immediate results * Review [Streaming Execution](/core-concepts/code-execution/streaming) for real-time monitoring # Rich Output Source: https://docs.hopx.ai/core-concepts/code-execution/rich-output Automatically capture plots, DataFrames, and visualizations from code execution in HopX sandboxes. Capture matplotlib plots, pandas DataFrames, plotly charts, and other rich outputs automatically without manual file handling. Perfect for data science workflows and visualization. Includes Python and JavaScript SDK examples and REST API endpoints. Rich output capture automatically detects and captures visual outputs like matplotlib plots, pandas DataFrames, and plotly charts from your code execution. ## Prerequisites Before you begin, make sure you have: * **Active sandbox** - A running sandbox (see [Creating Sandboxes](/core-concepts/sandboxes/creating)) * **Understanding of code execution** - Familiarity with [Synchronous Execution](/core-concepts/code-execution/synchronous) is helpful * **Code that generates visualizations** - Code that creates plots, DataFrames, or charts ## Overview When you execute code with `run_code()`, HopX automatically captures: * **Matplotlib plots** → PNG images (base64-encoded) * **Pandas DataFrames** → HTML tables * **Plotly charts** → HTML interactive visualizations * **JSON outputs** → Structured data Rich output capture is enabled by default in `run_code()`. All visual outputs are automatically detected and included in the `ExecutionResult.rich_outputs` array. ## Automatic Capture Rich outputs are captured automatically: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Execute code that generates a plot result = sandbox.run_code(''' import matplotlib.pyplot as plt import numpy as np x = np.linspace(0, 10, 100) y = np.sin(x) plt.plot(x, y) plt.title("Sine Wave") plt.savefig('/workspace/plot.png') ''') # Check for rich outputs print(f"Rich outputs captured: {len(result.rich_outputs)}") for output in result.rich_outputs: print(f"Type: {output.type}") print(f"Data keys: {list(output.data.keys())}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Execute code that generates a plot const result = await sandbox.runCode(` import matplotlib.pyplot as plt import numpy as np x = np.linspace(0, 10, 100) y = np.sin(x) plt.plot(x, y) plt.title("Sine Wave") plt.savefig('/workspace/plot.png') `); // Check for rich outputs console.log(`Rich outputs captured: ${result.richOutputs?.length || 0}`); for (const output of result.richOutputs || []) { console.log(`Type: ${output.type}`); console.log(`Data keys: ${Object.keys(output.data)}`); } await sandbox.kill(); ``` ## Matplotlib Plots Capture matplotlib plots as PNG images: ```python theme={null} from hopx_ai import Sandbox import base64 sandbox = Sandbox.create(template="code-interpreter") result = sandbox.run_code(''' import matplotlib.pyplot as plt import numpy as np # Create a simple plot x = np.linspace(0, 2*np.pi, 100) y = np.sin(x) plt.figure(figsize=(10, 6)) plt.plot(x, y, 'b-', linewidth=2, label='sin(x)') plt.plot(x, np.cos(x), 'r--', linewidth=2, label='cos(x)') plt.xlabel('x') plt.ylabel('y') plt.title('Trigonometric Functions') plt.legend() plt.grid(True) plt.savefig('/workspace/trig_plot.png') ''') # Access captured plot for output in result.rich_outputs: if 'image/png' in output.data: png_data = output.data['image/png'] print(f"Plot captured: {len(png_data)} bytes") # png_data is base64-encoded PNG image sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); const result = await sandbox.runCode(` import matplotlib.pyplot as plt import numpy as np # Create a simple plot x = np.linspace(0, 2*np.pi, 100) y = np.sin(x) plt.figure(figsize=(10, 6)) plt.plot(x, y, 'b-', linewidth=2, label='sin(x)') plt.plot(x, np.cos(x), 'r--', linewidth=2, label='cos(x)') plt.xlabel('x') plt.ylabel('y') plt.title('Trigonometric Functions') plt.legend() plt.grid(True) plt.savefig('/workspace/trig_plot.png') `); // Access captured plot for (const output of result.richOutputs || []) { if (output.data['image/png']) { const pngData = output.data['image/png']; console.log(`Plot captured: ${pngData.length} bytes`); // pngData is base64-encoded PNG image } } await sandbox.kill(); ``` ## Pandas DataFrames Capture pandas DataFrames as HTML tables: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") result = sandbox.run_code(''' import pandas as pd import numpy as np # Create a DataFrame data = { 'Name': ['Alice', 'Bob', 'Charlie', 'Diana'], 'Age': [25, 30, 35, 28], 'Score': [85, 92, 78, 95] } df = pd.DataFrame(data) print(df) # DataFrame is automatically captured as HTML ''') # Access captured DataFrame for output in result.rich_outputs: if 'text/html' in output.data: html_data = output.data['text/html'] print(f"DataFrame captured as HTML: {len(html_data)} chars") # html_data contains HTML table representation sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); const result = await sandbox.runCode(` import pandas as pd import numpy as np # Create a DataFrame data = { 'Name': ['Alice', 'Bob', 'Charlie', 'Diana'], 'Age': [25, 30, 35, 28], 'Score': [85, 92, 78, 95] } df = pd.DataFrame(data) print(df) # DataFrame is automatically captured as HTML `); // Access captured DataFrame for (const output of result.richOutputs || []) { if (output.data['text/html']) { const htmlData = output.data['text/html']; console.log(`DataFrame captured as HTML: ${htmlData.length} chars`); // htmlData contains HTML table representation } } await sandbox.kill(); ``` ## Plotly Charts Capture interactive Plotly charts as HTML: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") result = sandbox.run_code(''' import plotly.graph_objects as go import numpy as np # Create interactive plot x = np.linspace(0, 10, 100) y = np.sin(x) fig = go.Figure() fig.add_trace(go.Scatter(x=x, y=y, mode='lines', name='sin(x)')) fig.update_layout(title='Interactive Plot', xaxis_title='x', yaxis_title='y') fig.write_html('/workspace/plot.html') ''') # Access captured Plotly chart for output in result.rich_outputs: if 'text/html' in output.data: html_data = output.data['text/html'] print(f"Plotly chart captured: {len(html_data)} chars") # html_data contains interactive HTML chart sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); const result = await sandbox.runCode(` import plotly.graph_objects as go import numpy as np # Create interactive plot x = np.linspace(0, 10, 100) y = np.sin(x) fig = go.Figure() fig.add_trace(go.Scatter(x=x, y=y, mode='lines', name='sin(x)')) fig.update_layout(title='Interactive Plot', xaxis_title='x', yaxis_title='y') fig.write_html('/workspace/plot.html') `); // Access captured Plotly chart for (const output of result.richOutputs || []) { if (output.data['text/html']) { const htmlData = output.data['text/html']; console.log(`Plotly chart captured: ${htmlData.length} chars`); // htmlData contains interactive HTML chart } } await sandbox.kill(); ``` ## Multiple Rich Outputs Capture multiple outputs in a single execution: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") result = sandbox.run_code(''' import matplotlib.pyplot as plt import pandas as pd import numpy as np # Create a plot plt.plot([1, 2, 3, 4], [1, 4, 9, 16]) plt.savefig('/workspace/plot1.png') # Create a DataFrame df = pd.DataFrame({'x': [1, 2, 3], 'y': [4, 5, 6]}) print(df) # Create another plot plt.figure() plt.scatter([1, 2, 3], [4, 5, 6]) plt.savefig('/workspace/plot2.png') ''') # Access all captured outputs print(f"Total rich outputs: {len(result.rich_outputs)}") for i, output in enumerate(result.rich_outputs): print(f"Output {i+1}: {output.type}") print(f" Data types: {list(output.data.keys())}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); const result = await sandbox.runCode(` import matplotlib.pyplot as plt import pandas as pd import numpy as np # Create a plot plt.plot([1, 2, 3, 4], [1, 4, 9, 16]) plt.savefig('/workspace/plot1.png') # Create a DataFrame df = pd.DataFrame({'x': [1, 2, 3], 'y': [4, 5, 6]}) print(df) # Create another plot plt.figure() plt.scatter([1, 2, 3], [4, 5, 6]) plt.savefig('/workspace/plot2.png') `); // Access all captured outputs console.log(`Total rich outputs: ${result.richOutputs?.length || 0}`); for (let i = 0; i < (result.richOutputs?.length || 0); i++) { const output = result.richOutputs[i]; console.log(`Output ${i + 1}: ${output.type}`); console.log(` Data types: ${Object.keys(output.data)}`); } await sandbox.kill(); ``` ## Rich Output Structure Each rich output has the following structure: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") result = sandbox.run_code(''' import matplotlib.pyplot as plt plt.plot([1, 2, 3]) plt.savefig('/workspace/plot.png') ''') # Inspect rich output structure for output in result.rich_outputs: print(f"Type: {output.type}") # e.g., "image/png", "text/html" print(f"Data: {type(output.data)}") # Dict[str, str] # Access specific data format if 'image/png' in output.data: png_base64 = output.data['image/png'] # Decode if needed: import base64; image_bytes = base64.b64decode(png_base64) if 'text/html' in output.data: html_content = output.data['text/html'] # Use HTML content directly sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); const result = await sandbox.runCode(` import matplotlib.pyplot as plt plt.plot([1, 2, 3]) plt.savefig('/workspace/plot.png') `); // Inspect rich output structure for (const output of result.richOutputs || []) { console.log(`Type: ${output.type}`); // e.g., "image/png", "text/html" console.log(`Data: ${typeof output.data}`); // object // Access specific data format if (output.data['image/png']) { const pngBase64 = output.data['image/png']; // Decode if needed: const imageBytes = Buffer.from(pngBase64, 'base64'); } if (output.data['text/html']) { const htmlContent = output.data['text/html']; // Use HTML content directly } } await sandbox.kill(); ``` ## Complete Example Here's a complete example with all rich output types: ```python theme={null} from hopx_ai import Sandbox import base64 sandbox = Sandbox.create(template="code-interpreter") result = sandbox.run_code(''' import matplotlib.pyplot as plt import pandas as pd import numpy as np # 1. Matplotlib plot x = np.linspace(0, 10, 100) plt.plot(x, np.sin(x)) plt.title("Sine Wave") plt.savefig('/workspace/sine.png') # 2. Pandas DataFrame df = pd.DataFrame({ 'x': x[::10], 'sin(x)': np.sin(x[::10]) }) print(df) # 3. Multiple plots plt.figure() plt.subplot(2, 1, 1) plt.plot(x, np.sin(x)) plt.title("Sin") plt.subplot(2, 1, 2) plt.plot(x, np.cos(x)) plt.title("Cos") plt.savefig('/workspace/multiplot.png') ''') # Process all rich outputs print(f"Captured {len(result.rich_outputs)} rich outputs\n") for i, output in enumerate(result.rich_outputs, 1): print(f"Output {i}:") print(f" Type: {output.type}") if 'image/png' in output.data: png_data = output.data['image/png'] print(f" PNG size: {len(png_data)} bytes (base64)") if 'text/html' in output.data: html_data = output.data['text/html'] print(f" HTML size: {len(html_data)} chars") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); const result = await sandbox.runCode(` import matplotlib.pyplot as plt import pandas as pd import numpy as np # 1. Matplotlib plot x = np.linspace(0, 10, 100) plt.plot(x, np.sin(x)) plt.title("Sine Wave") plt.savefig('/workspace/sine.png') # 2. Pandas DataFrame df = pd.DataFrame({ 'x': x[::10], 'sin(x)': np.sin(x[::10]) }) print(df) # 3. Multiple plots plt.figure() plt.subplot(2, 1, 1) plt.plot(x, np.sin(x)) plt.title("Sin") plt.subplot(2, 1, 2) plt.plot(x, np.cos(x)) plt.title("Cos") plt.savefig('/workspace/multiplot.png') `); // Process all rich outputs console.log(`Captured ${result.richOutputs?.length || 0} rich outputs\n`); for (let i = 0; i < (result.richOutputs?.length || 0); i++) { const output = result.richOutputs[i]; console.log(`Output ${i + 1}:`); console.log(` Type: ${output.type}`); if (output.data['image/png']) { const pngData = output.data['image/png']; console.log(` PNG size: ${pngData.length} bytes (base64)`); } if (output.data['text/html']) { const htmlData = output.data['text/html']; console.log(` HTML size: ${htmlData.length} chars`); } } await sandbox.kill(); ``` ## Best Practices Always save plots to files (e.g., `plt.savefig()`) to ensure they're captured. Rich output capture works best when files are explicitly saved. * Matplotlib: Save as PNG for best compatibility * Pandas: Print DataFrames to trigger HTML capture * Plotly: Use `write_html()` for interactive charts Use `len(result.rich_outputs)` to verify all expected outputs were captured. PNG images are base64-encoded. Decode them before displaying or saving locally. You can capture multiple plots/DataFrames in a single execution. All will be included in `rich_outputs`. ## Related * **[Synchronous Execution](/core-concepts/code-execution/synchronous)** - Basic code execution * **[Background Execution](/core-concepts/code-execution/background)** - Long-running tasks * **SDK**: [sandbox.run\_code()](/sdk/python/sandbox#run_code) - Python SDK method (rich output enabled by default) * **API**: [POST /execute](/api/vm-agent/execute) - VM Agent API endpoint * [CLI Code Execution](/cli/commands/run) - Execute code from CLI ## Next Steps * Learn about [Synchronous Execution](/core-concepts/code-execution/synchronous) basics * Explore [Background Execution](/core-concepts/code-execution/background) for long-running visualizations * Review [Streaming Execution](/core-concepts/code-execution/streaming) for real-time output # Streaming Source: https://docs.hopx.ai/core-concepts/code-execution/streaming Execute code with real-time output streaming via WebSocket in HopX sandboxes. Stream execution results in real-time as code runs, monitor progress, and handle long-running operations with live updates. Perfect for interactive development and progress monitoring. Includes Python and JavaScript SDK examples and WebSocket API endpoints. Streaming execution provides real-time output as your code runs. Instead of waiting for completion, you receive stdout and stderr messages as they're generated, perfect for monitoring long-running tasks. ## Overview Streaming execution is ideal for: * Long-running tasks where you want real-time progress * Interactive code that produces output over time * Monitoring execution progress * Building real-time dashboards or UIs Streaming execution uses WebSocket connections for real-time communication. It requires async/await support in your code. ## Basic Streaming Stream execution output in real-time: ```python theme={null} from hopx_ai import Sandbox import asyncio async def stream_execution(): sandbox = Sandbox.create(template="code-interpreter") code = ''' import time for i in range(5): print(f"Step {i+1}/5") time.sleep(1) print("Done!") ''' async for message in sandbox.run_code_stream(code): if message['type'] == 'stdout': print(message['data'], end='') elif message['type'] == 'stderr': print(f"ERROR: {message['data']}", end='', file=sys.stderr) elif message['type'] == 'result': print(f"\nExit code: {message['exit_code']}") print(f"Execution time: {message['execution_time']}s") elif message['type'] == 'complete': print("\n✅ Execution completed") break sandbox.kill() asyncio.run(stream_execution()) ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; async function streamExecution() { const sandbox = await Sandbox.create({ template: 'code-interpreter' }); const code = ` import time for i in range(5): print(f"Step {i+1}/5") time.sleep(1) print("Done!") `; for await (const message of sandbox.runCodeStream(code)) { if (message.type === 'stdout') { process.stdout.write(message.data); } else if (message.type === 'stderr') { process.stderr.write(`ERROR: ${message.data}`); } else if (message.type === 'result') { console.log(`\nExit code: ${message.exit_code}`); console.log(`Execution time: ${message.execution_time}s`); } else if (message.type === 'complete') { console.log('\n✅ Execution completed'); break; } } await sandbox.kill(); } streamExecution(); ``` ## Message Types Stream messages have different types: ```python theme={null} from hopx_ai import Sandbox import asyncio async def handle_all_message_types(): sandbox = Sandbox.create(template="code-interpreter") code = ''' import sys print("This is stdout") print("This is also stdout", file=sys.stdout) print("This is stderr", file=sys.stderr) ''' async for message in sandbox.run_code_stream(code): msg_type = message['type'] if msg_type == 'stdout': print(f"[STDOUT] {message['data']}", end='') elif msg_type == 'stderr': print(f"[STDERR] {message['data']}", end='') elif msg_type == 'result': print(f"\n[RESULT] Exit: {message['exit_code']}, Time: {message['execution_time']}s") elif msg_type == 'complete': print("[COMPLETE] Execution finished") break sandbox.kill() asyncio.run(handle_all_message_types()) ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; async function handleAllMessageTypes() { const sandbox = await Sandbox.create({ template: 'code-interpreter' }); const code = ` import sys print("This is stdout") print("This is also stdout", file=sys.stdout) print("This is stderr", file=sys.stderr) `; for await (const message of sandbox.runCodeStream(code)) { const msgType = message.type; if (msgType === 'stdout') { process.stdout.write(`[STDOUT] ${message.data}`); } else if (msgType === 'stderr') { process.stderr.write(`[STDERR] ${message.data}`); } else if (msgType === 'result') { console.log(`\n[RESULT] Exit: ${message.exit_code}, Time: ${message.execution_time}s`); } else if (msgType === 'complete') { console.log('[COMPLETE] Execution finished'); break; } } await sandbox.kill(); } handleAllMessageTypes(); ``` ## Progress Monitoring Monitor progress of long-running tasks: ```python theme={null} from hopx_ai import Sandbox import asyncio async def monitor_progress(): sandbox = Sandbox.create(template="code-interpreter") code = ''' import time total_steps = 20 for i in range(total_steps): progress = (i + 1) / total_steps * 100 print(f"Progress: {progress:.1f}% ({i+1}/{total_steps})") time.sleep(0.5) print("All steps completed!") ''' async for message in sandbox.run_code_stream(code): if message['type'] == 'stdout': # Display progress in real-time print(message['data'], end='') elif message['type'] == 'complete': print("\n✅ Task completed successfully") break sandbox.kill() asyncio.run(monitor_progress()) ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; async function monitorProgress() { const sandbox = await Sandbox.create({ template: 'code-interpreter' }); const code = ` import time total_steps = 20 for i in range(total_steps): progress = (i + 1) / total_steps * 100 print(f"Progress: {progress:.1f}% ({i+1}/{total_steps})") time.sleep(0.5) print("All steps completed!") `; for await (const message of sandbox.runCodeStream(code)) { if (message.type === 'stdout') { // Display progress in real-time process.stdout.write(message.data); } else if (message.type === 'complete') { console.log('\n✅ Task completed successfully'); break; } } await sandbox.kill(); } monitorProgress(); ``` ## Environment Variables Pass environment variables to streaming execution: ```python theme={null} from hopx_ai import Sandbox import asyncio async def stream_with_env(): sandbox = Sandbox.create(template="code-interpreter") code = ''' import os print(f"API key: {os.getenv('API_KEY', 'not set')}") print(f"Debug mode: {os.getenv('DEBUG', 'false')}") ''' async for message in sandbox.run_code_stream( code, env={"API_KEY": "sk-123", "DEBUG": "true"} ): if message['type'] == 'stdout': print(message['data'], end='') elif message['type'] == 'complete': break sandbox.kill() asyncio.run(stream_with_env()) ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; async function streamWithEnv() { const sandbox = await Sandbox.create({ template: 'code-interpreter' }); const code = ` import os print(f"API key: {os.getenv('API_KEY', 'not set')}") print(f"Debug mode: {os.getenv('DEBUG', 'false')}") `; for await (const message of sandbox.runCodeStream(code, { env: { API_KEY: 'sk-123', DEBUG: 'true' } })) { if (message.type === 'stdout') { process.stdout.write(message.data); } else if (message.type === 'complete') { break; } } await sandbox.kill(); } streamWithEnv(); ``` ## Error Handling Handle errors in streaming execution: ```python theme={null} from hopx_ai import Sandbox import asyncio async def handle_streaming_errors(): sandbox = Sandbox.create(template="code-interpreter") code = ''' print("Starting...") print(undefined_variable) # This will cause an error print("This won't be reached") ''' try: async for message in sandbox.run_code_stream(code): if message['type'] == 'stdout': print(message['data'], end='') elif message['type'] == 'stderr': print(f"ERROR: {message['data']}", end='') elif message['type'] == 'result': if message['exit_code'] != 0: print(f"\n❌ Execution failed with exit code: {message['exit_code']}") elif message['type'] == 'complete': if not message.get('success', False): print("\n❌ Execution completed with errors") break except Exception as e: print(f"Streaming error: {e}") finally: sandbox.kill() asyncio.run(handle_streaming_errors()) ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; async function handleStreamingErrors() { const sandbox = await Sandbox.create({ template: 'code-interpreter' }); const code = ` print("Starting...") print(undefined_variable) # This will cause an error print("This won't be reached") `; try { for await (const message of sandbox.runCodeStream(code)) { if (message.type === 'stdout') { process.stdout.write(message.data); } else if (message.type === 'stderr') { process.stderr.write(`ERROR: ${message.data}`); } else if (message.type === 'result') { if (message.exit_code !== 0) { console.log(`\n❌ Execution failed with exit code: ${message.exit_code}`); } } else if (message.type === 'complete') { if (!message.success) { console.log('\n❌ Execution completed with errors'); } break; } } } catch (error) { console.error(`Streaming error: ${error.message}`); } finally { await sandbox.kill(); } } handleStreamingErrors(); ``` ## Complete Example Here's a complete example with real-time progress: ```python theme={null} from hopx_ai import Sandbox import asyncio async def complete_streaming_example(): sandbox = Sandbox.create(template="code-interpreter") code = ''' import time import random print("Starting data processing...") total_items = 100 for i in range(total_items): # Simulate processing time.sleep(0.1) # Generate some output if i % 10 == 0: print(f"Processed {i}/{total_items} items") # Simulate occasional errors if random.random() < 0.05: print(f"Warning: Issue with item {i}", file=sys.stderr) print("Processing complete!") print(f"Total items processed: {total_items}") ''' print("🔄 Starting streaming execution...\n") async for message in sandbox.run_code_stream( code, language='python', timeout=120, env={"BATCH_SIZE": "10"} ): if message['type'] == 'stdout': print(message['data'], end='') elif message['type'] == 'stderr': print(f"⚠️ {message['data']}", end='') elif message['type'] == 'result': print(f"\n\n📊 Execution Summary:") print(f" Exit code: {message['exit_code']}") print(f" Execution time: {message['execution_time']:.2f}s") elif message['type'] == 'complete': print("\n✅ Streaming completed") break sandbox.kill() asyncio.run(complete_streaming_example()) ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; async function completeStreamingExample() { const sandbox = await Sandbox.create({ template: 'code-interpreter' }); const code = ` import time import random print("Starting data processing...") total_items = 100 for i in range(total_items): # Simulate processing time.sleep(0.1) # Generate some output if i % 10 == 0: print(f"Processed {i}/{total_items} items") # Simulate occasional errors if random.random() < 0.05: print(f"Warning: Issue with item {i}", file=sys.stderr) print("Processing complete!") print(f"Total items processed: {total_items}") `; console.log('🔄 Starting streaming execution...\n'); for await (const message of sandbox.runCodeStream(code, { language: 'python', timeout: 120, env: { BATCH_SIZE: '10' } })) { if (message.type === 'stdout') { process.stdout.write(message.data); } else if (message.type === 'stderr') { process.stderr.write(`⚠️ ${message.data}`); } else if (message.type === 'result') { console.log(`\n\n📊 Execution Summary:`); console.log(` Exit code: ${message.exit_code}`); console.log(` Execution time: ${message.execution_time.toFixed(2)}s`); } else if (message.type === 'complete') { console.log('\n✅ Streaming completed'); break; } } await sandbox.kill(); } completeStreamingExample(); ``` ## Best Practices Streaming execution requires async/await. Make sure your code uses async functions and `async for` loops. Process stdout, stderr, result, and complete messages appropriately for a complete streaming experience. Always break the loop when you receive a 'complete' message to avoid unnecessary processing. Check exit codes and success flags to handle execution failures gracefully. Streaming is best for tasks where real-time output is valuable. For simple scripts, synchronous execution may be simpler. ## Related * **[Synchronous Execution](/core-concepts/code-execution/synchronous)** - Basic code execution * **[Background Execution](/core-concepts/code-execution/background)** - Long-running tasks * **[Rich Output Capture](/core-concepts/code-execution/rich-output)** - Capture plots and visualizations * **SDK**: [sandbox.run\_code\_stream()](/sdk/python/sandbox#run_code_stream) - Python SDK method * [CLI Code Execution](/cli/commands/run) - Execute code from CLI ## Next Steps * Learn about [Synchronous Execution](/core-concepts/code-execution/synchronous) for immediate results * Explore [Background Execution](/core-concepts/code-execution/background) for non-blocking tasks * Review [Process Management](/core-concepts/code-execution/process-management) for monitoring # Synchronous Source: https://docs.hopx.ai/core-concepts/code-execution/synchronous Execute code synchronously and wait for results. Learn how to run Python, JavaScript, Bash, and Go code in HopX sandboxes, handle execution results, manage timeouts, and process outputs. Includes SDK examples and REST API endpoints for synchronous code execution. Synchronous execution is the simplest way to run code in a sandbox. The execution blocks until the code completes, then returns the results immediately. ## Prerequisites Before you begin, make sure you have: * **Active sandbox** - A running sandbox (see [Creating Sandboxes](/core-concepts/sandboxes/creating)) * **Sandbox object** - A `Sandbox` instance connected to your sandbox * **Code to execute** - The code you want to run in the sandbox ## Overview Synchronous execution is ideal for: * Quick scripts and computations * Code that completes in seconds or minutes * When you need immediate results * Simple workflows without complex state management Synchronous execution automatically captures rich outputs (plots, DataFrames) when available. For more control over rich output capture, see [Rich Output](/core-concepts/code-execution/rich-output). ## Basic Execution Execute code and wait for results: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Execute simple code result = sandbox.run_code('print("Hello, World!")') print(result.stdout) # "Hello, World!\n" print(f"Success: {result.success}") print(f"Exit code: {result.exit_code}") print(f"Execution time: {result.execution_time}s") sandbox.kill() ``` **Expected Output:** ``` Hello, World! Success: True Exit code: 0 Execution time: 1.23s ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Execute simple code const result = await sandbox.runCode('print("Hello, World!")'); console.log(result.stdout); // "Hello, World!\n" console.log(`Success: ${result.success}`); console.log(`Exit code: ${result.exitCode}`); console.log(`Execution time: ${result.executionTime}s`); await sandbox.kill(); ``` **Expected Output:** ``` Hello, World! Success: true Exit code: 0 Execution time: 1.23s ``` ## Execution Result The `ExecutionResult` object contains: * **`stdout`** - Standard output from code execution * **`stderr`** - Standard error output (if any) * **`exit_code`** - Exit code (0 = success, non-zero = error) * **`success`** - Boolean indicating if execution succeeded * **`execution_time`** - Time taken in seconds * **`rich_outputs`** - Array of captured rich outputs (plots, DataFrames) ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") result = sandbox.run_code(''' import sys print("Python version:", sys.version) print("Platform:", sys.platform) ''') # Access all result fields print(f"Output: {result.stdout}") print(f"Errors: {result.stderr}") print(f"Success: {result.success}") print(f"Exit code: {result.exit_code}") print(f"Time: {result.execution_time}s") print(f"Rich outputs: {len(result.rich_outputs)}") sandbox.kill() ``` **Expected Output:** ``` Output: Python version: 3.11.0 (main, Oct 24 2023, 00:00:00) [GCC 11.3.0] Platform: linux Errors: Success: True Exit code: 0 Time: 1.45s Rich outputs: 0 ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); const result = await sandbox.runCode(` import sys print("Python version:", sys.version) print("Platform:", sys.platform) `); // Access all result fields console.log(`Output: ${result.stdout}`); console.log(`Errors: ${result.stderr}`); console.log(`Success: ${result.success}`); console.log(`Exit code: ${result.exitCode}`); console.log(`Time: ${result.executionTime}s`); console.log(`Rich outputs: ${result.richOutputs?.length || 0}`); await sandbox.kill(); ``` **Expected Output:** ``` Output: Python version: 3.11.0 (main, Oct 24 2023, 00:00:00) [GCC 11.3.0] Platform: linux Errors: Success: true Exit code: 0 Time: 1.45s Rich outputs: 0 ``` ## Language Support Execute code in different languages: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Python result = sandbox.run_code('print("Hello from Python!")', language='python') print(result.stdout) # JavaScript result = sandbox.run_code('console.log("Hello from JavaScript!")', language='javascript') print(result.stdout) # Bash result = sandbox.run_code('echo "Hello from Bash!"', language='bash') print(result.stdout) sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Python let result = await sandbox.runCode('print("Hello from Python!")', { language: 'python' }); console.log(result.stdout); // JavaScript result = await sandbox.runCode('console.log("Hello from JavaScript!")', { language: 'javascript' }); console.log(result.stdout); // Bash result = await sandbox.runCode('echo "Hello from Bash!"', { language: 'bash' }); console.log(result.stdout); await sandbox.kill(); ``` ## Environment Variables Pass environment variables for execution: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Execute with environment variables result = sandbox.run_code( 'import os; print(os.getenv("API_KEY"))', language='python', env={"API_KEY": "sk-123", "DEBUG": "true"} ) print(result.stdout) # "sk-123" sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Execute with environment variables const result = await sandbox.runCode( 'import os; print(os.getenv("API_KEY"))', { language: 'python', env: { API_KEY: 'sk-123', DEBUG: 'true' } } ); console.log(result.stdout); // "sk-123" await sandbox.kill(); ``` Environment variables passed to `run_code()` have priority over global environment variables set via `sandbox.env.set()`. Priority: Request env > Global env > Agent env. ## Working Directory Specify a custom working directory: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Execute in custom directory result = sandbox.run_code( 'import os; print(os.getcwd())', language='python', working_dir='/tmp/myproject' ) print(result.stdout) # "/tmp/myproject" sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Execute in custom directory const result = await sandbox.runCode( 'import os; print(os.getcwd())', { language: 'python', workingDir: '/tmp/myproject' } ); console.log(result.stdout); // "/tmp/myproject" await sandbox.kill(); ``` ## Timeout Configuration Set execution timeout for long-running code: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Execute with custom timeout (5 minutes) result = sandbox.run_code( 'import time; time.sleep(10); print("Done")', language='python', timeout=300 # 5 minutes ) print(result.stdout) sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Execute with custom timeout (5 minutes) const result = await sandbox.runCode( 'import time; time.sleep(10); print("Done")', { language: 'python', timeout: 300 // 5 minutes } ); console.log(result.stdout); await sandbox.kill(); ``` Default timeout is 60 seconds. Maximum timeout is 300 seconds (5 minutes) for synchronous execution. For longer-running code, use [Background Execution](/core-concepts/code-execution/background) or [Async Webhooks](/core-concepts/code-execution/async-webhooks). ## Error Handling Handle execution errors: ```python theme={null} from hopx_ai import Sandbox from hopx_ai.errors import CodeExecutionError, TimeoutError sandbox = Sandbox.create(template="code-interpreter") try: result = sandbox.run_code('print(undefined_var)', language='python') if not result.success: print(f"Execution failed with exit code: {result.exit_code}") print(f"Error output: {result.stderr}") else: print(f"Output: {result.stdout}") except TimeoutError: print("Execution timed out") except CodeExecutionError as e: print(f"Execution error: {e}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import { CodeExecutionError, TimeoutError } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); try { const result = await sandbox.runCode('print(undefined_var)', { language: 'python' }); if (!result.success) { console.error(`Execution failed with exit code: ${result.exitCode}`); console.error(`Error output: ${result.stderr}`); } else { console.log(`Output: ${result.stdout}`); } } catch (error) { if (error instanceof TimeoutError) { console.error('Execution timed out'); } else if (error instanceof CodeExecutionError) { console.error(`Execution error: ${error.message}`); } } await sandbox.kill(); ``` ## Complete Example Here's a complete example showing all features: ```python theme={null} from hopx_ai import Sandbox # Create sandbox sandbox = Sandbox.create(template="code-interpreter") # Execute code with all options result = sandbox.run_code( ''' import os import sys print(f"Python: {sys.version}") print(f"Working directory: {os.getcwd()}") print(f"API key: {os.getenv('API_KEY', 'not set')}") print(f"Debug mode: {os.getenv('DEBUG', 'false')}") ''', language='python', timeout=120, env={ "API_KEY": "sk-123", "DEBUG": "true" }, working_dir='/workspace' ) # Check results if result.success: print("✅ Execution successful") print(f"Output:\n{result.stdout}") else: print("❌ Execution failed") print(f"Error: {result.stderr}") print(f"Exit code: {result.exit_code}") print(f"Execution time: {result.execution_time}s") # Cleanup sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // Create sandbox const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Execute code with all options const result = await sandbox.runCode( ` import os import sys print(f"Python: {sys.version}") print(f"Working directory: {os.getcwd()}") print(f"API key: {os.getenv('API_KEY', 'not set')}") print(f"Debug mode: {os.getenv('DEBUG', 'false')}") `, { language: 'python', timeout: 120, env: { API_KEY: 'sk-123', DEBUG: 'true' }, workingDir: '/workspace' } ); // Check results if (result.success) { console.log('✅ Execution successful'); console.log(`Output:\n${result.stdout}`); } else { console.error('❌ Execution failed'); console.error(`Error: ${result.stderr}`); console.error(`Exit code: ${result.exitCode}`); } console.log(`Execution time: ${result.executionTime}s`); // Cleanup await sandbox.kill(); ``` ## Best Practices Set timeouts based on expected execution time. Default 60 seconds is good for quick scripts, but increase for longer operations. Always check `result.success` and handle `stderr` appropriately. Use try/catch for exception handling. Pass environment variables via `env` parameter rather than hardcoding values in code. Monitor `execution_time` to optimize code performance and identify slow operations. For code that runs longer than 5 minutes, use [Background Execution](/core-concepts/code-execution/background) instead. ## Implementation * **SDK**: [sandbox.run\_code()](/sdk/python/sandbox#run_code) - Python SDK method * **[CLI](/cli/introduction)** - Command-line interface * **API**: [POST /execute](/api/vm-agent/execute) - VM Agent API endpoint ## Related * **[Background Execution](/core-concepts/code-execution/background)** - Long-running tasks * **[Rich Output Capture](/core-concepts/code-execution/rich-output)** - Capture plots and visualizations * **[Streaming Execution](/core-concepts/code-execution/streaming)** - Real-time output streaming * **[Async Execution with Webhooks](/core-concepts/code-execution/async-webhooks)** - Very long-running tasks ## Next Steps * Learn about [Rich Output](/core-concepts/code-execution/rich-output) capture for plots and DataFrames * Explore [Background Execution](/core-concepts/code-execution/background) for non-blocking operations * Discover [Streaming Execution](/core-concepts/code-execution/streaming) for real-time output * Review [Process Management](/core-concepts/code-execution/process-management) for background processes # Background Source: https://docs.hopx.ai/core-concepts/commands/background Execute shell commands in the background without blocking in HopX sandboxes. Run long-running shell commands asynchronously, monitor process status, and retrieve results when complete. Perfect for package installations, data processing, and time-consuming operations. Includes Python and JavaScript SDK examples and REST API endpoints. Run shell commands in the background and return immediately. This is ideal for long-running commands that you want to monitor and manage separately. ## Overview Background command execution is perfect for: * Long-running commands (>5 minutes) * Server processes that need to keep running * Commands that don't need immediate results * Parallel execution of multiple commands Background commands return immediately with a `process_id`. Use process management to check status and manage background processes. ## Starting Background Commands Start a command in the background: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Start background command result = sandbox.commands.run( 'sleep 30 && echo "Done!"', background=True ) # Extract process ID from output process_id = result.stdout.split('cmd_')[-1].strip() if 'cmd_' in result.stdout else None print(f"Process started: {process_id}") print(f"Status: {result.stdout}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Start background command const result = await sandbox.commands.runBackground( 'sleep 30 && echo "Done!"' ); console.log(`Process started: ${result.processId}`); console.log(`Status: ${result.status || 'running'}`); await sandbox.kill(); ``` ## Checking Process Status Check the status of background commands: ```python theme={null} from hopx_ai import Sandbox import time sandbox = Sandbox.create(template="code-interpreter") # Start background command result = sandbox.commands.run( 'sleep 30 && echo "Task completed"', background=True ) # Extract process ID process_id = result.stdout.split('cmd_')[-1].strip() if 'cmd_' in result.stdout else None # Check status using list_processes for i in range(5): processes = sandbox.list_processes() for proc in processes: if proc.get('process_id') == process_id: print(f"Status: {proc['status']}") if proc['status'] == 'completed': print(f"Output: {proc.get('stdout', '')}") break time.sleep(2) sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Start background command const result = await sandbox.commands.runBackground( 'sleep 30 && echo "Task completed"' ); const processId = result.processId; // Check status using listProcesses for (let i = 0; i < 5; i++) { const processes = await sandbox.listProcesses(); const proc = processes.find(p => p.processId === processId); if (proc) { console.log(`Status: ${proc.status}`); if (proc.status === 'completed') { console.log(`Output: ${proc.stdout || ''}`); break; } } await new Promise(resolve => setTimeout(resolve, 2000)); } await sandbox.kill(); ``` ## Long-Running Servers Start long-running server processes: ```python theme={null} from hopx_ai import Sandbox import time sandbox = Sandbox.create(template="code-interpreter") # Start a web server in background result = sandbox.commands.run( 'python -m http.server 8000', background=True, timeout=3600, # 1 hour env={"PORT": "8000"} ) process_id = result.stdout.split('cmd_')[-1].strip() if 'cmd_' in result.stdout else None print(f"Server started: {process_id}") # Check if server is running time.sleep(2) processes = sandbox.list_processes() for proc in processes: if proc.get('process_id') == process_id: print(f"Server status: {proc['status']}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Start a web server in background const result = await sandbox.commands.runBackground( 'python -m http.server 8000', { timeout: 3600, // 1 hour env: { PORT: '8000' } } ); console.log(`Server started: ${result.processId}`); // Check if server is running await new Promise(resolve => setTimeout(resolve, 2000)); const processes = await sandbox.listProcesses(); const serverProc = processes.find(p => p.processId === result.processId); if (serverProc) { console.log(`Server status: ${serverProc.status}`); } await sandbox.kill(); ``` ## Environment Variables Pass environment variables to background commands: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Start background command with environment variables result = sandbox.commands.run( 'python -c "import os, time; print(os.getenv(\'API_KEY\')); time.sleep(60)"', background=True, env={ "API_KEY": "sk-123456", "DEBUG": "true" } ) print(f"Process started: {result.stdout}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Start background command with environment variables const result = await sandbox.commands.runBackground( 'python -c "import os, time; print(os.getenv(\'API_KEY\')); time.sleep(60)"', { env: { API_KEY: 'sk-123456', DEBUG: 'true' } } ); console.log(`Process started: ${result.processId}`); await sandbox.kill(); ``` ## Timeout Configuration Set timeout for background commands: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Start background command with 10 minute timeout result = sandbox.commands.run( 'long_running_task.sh', background=True, timeout=600 # 10 minutes ) print(f"Process started with {600}s timeout") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Start background command with 10 minute timeout const result = await sandbox.commands.runBackground( 'long_running_task.sh', { timeout: 600 // 10 minutes } ); console.log(`Process started with 600s timeout`); await sandbox.kill(); ``` ## Complete Example Here's a complete example showing background command workflow: ```python theme={null} from hopx_ai import Sandbox import time sandbox = Sandbox.create(template="code-interpreter") # Start multiple background tasks tasks = { 'data-processing': 'python process_data.py', 'ml-training': 'python train_model.py', 'report-generation': 'python generate_report.py' } process_ids = {} print("🚀 Starting background tasks...\n") for name, command in tasks.items(): result = sandbox.commands.run( command, background=True, timeout=600, env={"TASK_NAME": name} ) process_id = result.stdout.split('cmd_')[-1].strip() if 'cmd_' in result.stdout else None process_ids[name] = process_id print(f"✅ Started: {name} (ID: {process_id})") # Monitor all processes print("\n📊 Monitoring processes...") while True: all_processes = sandbox.list_processes() active = [ p for p in all_processes if p.get('process_id') in process_ids.values() and p.get('status') in ['queued', 'running'] ] if not active: break print(f"\nActive: {len(active)}/{len(tasks)}") for proc in active: name = next(k for k, v in process_ids.items() if v == proc.get('process_id')) print(f" {name}: {proc['status']}") time.sleep(3) # Show final results print("\n📋 Final Status:") all_processes = sandbox.list_processes() for name, proc_id in process_ids.items(): proc = next((p for p in all_processes if p.get('process_id') == proc_id), None) if proc: status_icon = { 'completed': '✅', 'failed': '❌', 'killed': '🛑' }.get(proc['status'], '⏳') print(f"{status_icon} {name}: {proc['status']}") if proc['status'] == 'completed' and proc.get('stdout'): print(f" Output: {proc['stdout'].strip()[:50]}...") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Start multiple background tasks const tasks = { 'data-processing': 'python process_data.py', 'ml-training': 'python train_model.py', 'report-generation': 'python generate_report.py' }; const processIds = {}; console.log('🚀 Starting background tasks...\n'); for (const [name, command] of Object.entries(tasks)) { const result = await sandbox.commands.runBackground(command, { timeout: 600, env: { TASK_NAME: name } }); processIds[name] = result.processId; console.log(`✅ Started: ${name} (ID: ${result.processId})`); } // Monitor all processes console.log('\n📊 Monitoring processes...'); while (true) { const allProcesses = await sandbox.listProcesses(); const active = allProcesses.filter( p => Object.values(processIds).includes(p.processId) && ['queued', 'running'].includes(p.status) ); if (active.length === 0) { break; } console.log(`\nActive: ${active.length}/${Object.keys(tasks).length}`); for (const proc of active) { const name = Object.keys(processIds).find(k => processIds[k] === proc.processId); console.log(` ${name}: ${proc.status}`); } await new Promise(resolve => setTimeout(resolve, 3000)); } // Show final results console.log('\n📋 Final Status:'); const finalProcesses = await sandbox.listProcesses(); for (const [name, procId] of Object.entries(processIds)) { const proc = finalProcesses.find(p => p.processId === procId); if (proc) { const statusIcon = { 'completed': '✅', 'failed': '❌', 'killed': '🛑' }[proc.status] || '⏳'; console.log(`${statusIcon} ${name}: ${proc.status}`); if (proc.status === 'completed' && proc.stdout) { console.log(` Output: ${proc.stdout.trim().substring(0, 50)}...`); } } } await sandbox.kill(); ``` ## Best Practices Extract process IDs from the result to track and manage background commands. Set timeouts based on expected execution time. Default is 30 seconds, but increase for longer tasks. Check process status periodically to track progress and detect failures early. Use `list_processes()` and `kill_process()` to monitor and control background commands. Check for failed status and access stderr for error details when commands fail. ## Related * **[Running Commands](/core-concepts/commands/running)** - Execute commands synchronously * **[Process Monitoring](/core-concepts/observability/processes)** - Monitor background processes * **SDK**: [sandbox.commands.run\_background()](/sdk/python/commands#run_background) - Python SDK method * **API**: [POST /commands/background](/api/vm-agent/run-command-background) - VM Agent API endpoint ## Next Steps * Learn about [Running Commands](/core-concepts/commands/running) for synchronous execution * Explore [Process Management](/core-concepts/code-execution/process-management) to monitor background processes * Review [Code Execution](/core-concepts/code-execution/background) for background code execution ## Related * [CLI Commands](/cli/commands/cmd) - Shell commands from CLI # Commands Source: https://docs.hopx.ai/core-concepts/commands/index Complete guide to running shell commands in HopX sandboxes - synchronous and background command execution. Learn how to execute shell commands, run system administration tasks, install packages, and automate workflows using Python and JavaScript SDKs or REST API. Includes examples for synchronous and background command execution. Run shell commands in HopX sandboxes for system administration, package installation, and automation. This hub covers all command execution methods. ## Related * [CLI Commands](/cli/commands/cmd) - Shell commands from CLI ## What You'll Learn * How to run shell commands synchronously * How to run commands in the background * How to handle command output and errors * How to use commands for system administration * How to integrate commands with code execution ## Command Execution Overview | Execution Mode | SDK Method | API Endpoint | | ------------------------------------------------------------- | ----------------------------------- | --------------------------- | | **[Running Commands](/core-concepts/commands/running)** | `sandbox.commands.run()` | `POST /commands/run` | | **[Background Commands](/core-concepts/commands/background)** | `sandbox.commands.run_background()` | `POST /commands/background` | ## Core Concepts ### Running Commands Execute shell commands synchronously and wait for results. * **[Running Commands](/core-concepts/commands/running)** - Run shell commands * **SDK**: [Python: sandbox.commands.run()](/sdk/python/commands#run) | [JavaScript: sandbox.commands.run()](/sdk/javascript/commands#run) * **API**: [POST /commands/run](/api/vm-agent/run-command) ### Background Commands Run long-running commands in the background without blocking. * **[Background Commands](/core-concepts/commands/background)** - Run commands in background * **SDK**: [Python: sandbox.commands.run\_background()](/sdk/python/commands#run_background) | [JavaScript: sandbox.commands.runBackground()](/sdk/javascript/commands#runbackground) * **API**: [POST /commands/background](/api/vm-agent/run-command-background) ## SDK Reference ### Python SDK Complete reference for Python command execution. * **[Commands Module](/sdk/python/commands)** - Complete command API * `commands.run()` - Run commands synchronously * `commands.run_background()` - Run commands in background ### JavaScript SDK Complete reference for JavaScript/TypeScript command execution. * **[Commands Module](/sdk/javascript/commands)** - Complete command API * `commands.run()` - Run commands synchronously * `commands.runBackground()` - Run commands in background ## API Reference ### VM Agent API REST API endpoints for command execution. * **[VM Agent API Overview](/api/vm-agent/overview)** - API overview * **[Run Command](/api/vm-agent/run-command)** - `POST /commands/run` - Run commands synchronously * **[Run Command Background](/api/vm-agent/run-command-background)** - `POST /commands/background` - Run commands in background ## Quick Start If you're new to command execution, start here: 1. **[Running Commands](/core-concepts/commands/running)** - Run your first command 2. **[Background Commands](/core-concepts/commands/background)** - Run long-running commands ## Related Topics * **[Code Execution](/core-concepts/code-execution/synchronous)** - Execute code alongside commands * **[File Operations](/core-concepts/filesystem/reading)** - Work with files via commands * **[Environment Variables](/core-concepts/environment/getting)** - Use variables in commands * **[Process Management](/core-concepts/code-execution/process-management)** - Manage command processes ## Next Steps * Learn about [Running Commands](/core-concepts/commands/running) for system administration * Explore [Background Commands](/core-concepts/commands/background) for long-running tasks * Review [Code Execution](/core-concepts/code-execution/synchronous) to combine with commands * Check out [Process Management](/core-concepts/code-execution/process-management) for advanced workflows # Running Source: https://docs.hopx.ai/core-concepts/commands/running Execute shell commands synchronously in HopX sandboxes. Run shell commands for system administration, package installation, file operations, and automation tasks. Learn how to execute commands, capture output, handle errors, and process command results using Python and JavaScript SDKs or REST API. Includes examples for common use cases. Run shell commands synchronously in your sandbox. Commands execute and return results immediately, making them perfect for quick operations, package installation, and system tasks. ## Overview Synchronous command execution is ideal for: * Quick shell commands and system operations * Package installation (pip, npm, apt, etc.) * File system operations * Environment setup and configuration * Commands that complete in seconds or minutes Commands run in `/bin/sh` by default. For commands that complete quickly, synchronous execution is simpler than background execution. ## Basic Command Execution Run a simple shell command: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Run a simple command result = sandbox.commands.run('ls -la /workspace') print(result.stdout) print(f"Exit code: {result.exit_code}") sandbox.kill() ``` **Expected Output:** ``` total 8 drwxr-xr-x 2 root root 4096 Jan 27 10:30 . drwxr-xr-x 3 root root 4096 Jan 27 10:30 .. Exit code: 0 ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Run a simple command const result = await sandbox.commands.run('ls -la /workspace'); console.log(result.stdout); console.log(`Exit code: ${result.exitCode}`); await sandbox.kill(); ``` **Expected Output:** ``` total 8 drwxr-xr-x 2 root root 4096 Jan 27 10:30 . drwxr-xr-x 3 root root 4096 Jan 27 10:30 .. Exit code: 0 ``` ## Command Result The `CommandResult` object contains: * **`stdout`** - Standard output from command * **`stderr`** - Standard error output (if any) * **`exit_code`** - Exit code (0 = success, non-zero = error) * **`success`** - Boolean indicating if command succeeded * **`execution_time`** - Time taken in seconds ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") result = sandbox.commands.run('echo "Hello, World!"') # Access all result fields print(f"Output: {result.stdout}") print(f"Errors: {result.stderr}") print(f"Success: {result.success}") print(f"Exit code: {result.exit_code}") print(f"Execution time: {result.execution_time}s") sandbox.kill() ``` **Expected Output:** ``` Output: Hello, World! Errors: Success: True Exit code: 0 Execution time: 0.15s ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); const result = await sandbox.commands.run('echo "Hello, World!"'); // Access all result fields console.log(`Output: ${result.stdout}`); console.log(`Errors: ${result.stderr}`); console.log(`Success: ${result.success}`); console.log(`Exit code: ${result.exitCode}`); console.log(`Execution time: ${result.executionTime}s`); await sandbox.kill(); ``` **Expected Output:** ``` Output: Hello, World! Errors: Success: true Exit code: 0 Execution time: 0.15 ``` ## Package Installation Install packages using package managers: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Install Python packages result = sandbox.commands.run('pip install requests pandas numpy', timeout=300) if result.success: print("Packages installed successfully") print(result.stdout) else: print(f"Installation failed: {result.stderr}") # Install Node.js packages result = sandbox.commands.run('npm install express lodash', timeout=300) print(f"npm install exit code: {result.exit_code}") sandbox.kill() ``` **Expected Output:** ``` Packages installed successfully Successfully installed requests-2.31.0 pandas-2.1.0 numpy-1.24.3 npm install exit code: 0 ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Install Python packages const result = await sandbox.commands.run('pip install requests pandas numpy', { timeout: 300 }); if (result.success) { console.log('Packages installed successfully'); console.log(result.stdout); } else { console.error(`Installation failed: ${result.stderr}`); } // Install Node.js packages const npmResult = await sandbox.commands.run('npm install express lodash', { timeout: 300 }); console.log(`npm install exit code: ${npmResult.exitCode}`); await sandbox.kill(); ``` **Expected Output:** ``` Packages installed successfully Successfully installed requests-2.31.0 pandas-2.1.0 numpy-1.24.3 npm install exit code: 0 ``` ## Environment Variables Pass environment variables to commands: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Run command with environment variables result = sandbox.commands.run( 'echo $API_KEY', env={"API_KEY": "sk-123", "DEBUG": "true"} ) print(result.stdout) # "sk-123" # Use environment variables in commands result = sandbox.commands.run( 'python -c "import os; print(os.getenv(\'API_KEY\'))"', env={"API_KEY": "sk-456"} ) print(result.stdout) # "sk-456" sandbox.kill() ``` **Expected Output:** ``` sk-123 sk-456 ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Run command with environment variables const result = await sandbox.commands.run('echo $API_KEY', { env: { API_KEY: 'sk-123', DEBUG: 'true' } }); console.log(result.stdout); // "sk-123" // Use environment variables in commands const pythonResult = await sandbox.commands.run( 'python -c "import os; print(os.getenv(\'API_KEY\'))"', { env: { API_KEY: 'sk-456' } } ); console.log(pythonResult.stdout); // "sk-456" await sandbox.kill(); ``` **Expected Output:** ``` sk-123 sk-456 ``` Environment variables passed to `commands.run()` have priority over global environment variables set via `sandbox.env.set()`. Priority: Request env > Global env > Agent env. ## Working Directory Specify a custom working directory: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Create directory sandbox.files.mkdir('/workspace/myproject') # Run command in specific directory result = sandbox.commands.run( 'pwd', working_dir='/workspace/myproject' ) print(result.stdout) # "/workspace/myproject" # Run multiple commands in same directory result = sandbox.commands.run( 'touch file.txt && ls -la', working_dir='/workspace/myproject' ) print(result.stdout) sandbox.kill() ``` **Expected Output:** ``` /workspace/myproject total 8 drwxr-xr-x 2 root root 4096 Jan 27 10:30 . drwxr-xr-x 3 root root 4096 Jan 27 10:30 .. -rw-r--r-- 1 root root 0 Jan 27 10:30 file.txt ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Create directory await sandbox.files.mkdir('/workspace/myproject'); // Run command in specific directory const result = await sandbox.commands.run('pwd', { workingDir: '/workspace/myproject' }); console.log(result.stdout); // "/workspace/myproject" // Run multiple commands in same directory const multiResult = await sandbox.commands.run('touch file.txt && ls -la', { workingDir: '/workspace/myproject' }); console.log(multiResult.stdout); await sandbox.kill(); ``` **Expected Output:** ``` /workspace/myproject total 8 drwxr-xr-x 2 root root 4096 Jan 27 10:30 . drwxr-xr-x 3 root root 4096 Jan 27 10:30 .. -rw-r--r-- 1 root root 0 Jan 27 10:30 file.txt ``` ## Timeout Configuration Set timeout for long-running commands: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Run command with custom timeout (5 minutes) result = sandbox.commands.run( 'npm install', timeout=300 ) print(f"Installation completed: {result.success}") # For very long operations, use background execution instead sandbox.kill() ``` **Expected Output:** ``` Installation completed: True ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Run command with custom timeout (5 minutes) const result = await sandbox.commands.run('npm install', { timeout: 300 }); console.log(`Installation completed: ${result.success}`); // For very long operations, use background execution instead await sandbox.kill(); ``` **Expected Output:** ``` Installation completed: true ``` Default timeout is 30 seconds. Maximum timeout is typically 300 seconds (5 minutes) for synchronous execution. For longer-running commands, use [Background Commands](/core-concepts/commands/background) instead. ## Error Handling Handle command execution errors: ```python theme={null} from hopx_ai import Sandbox from hopx_ai.errors import CommandExecutionError, TimeoutError sandbox = Sandbox.create(template="code-interpreter") try: result = sandbox.commands.run('nonexistent-command') if not result.success: print(f"Command failed with exit code: {result.exit_code}") print(f"Error output: {result.stderr}") else: print(f"Output: {result.stdout}") except TimeoutError: print("Command timed out") except CommandExecutionError as e: print(f"Command execution error: {e}") sandbox.kill() ``` **Expected Output:** ``` Command failed with exit code: 127 Error output: /bin/sh: nonexistent-command: command not found ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import { CommandExecutionError, TimeoutError } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); try { const result = await sandbox.commands.run('nonexistent-command'); if (!result.success) { console.error(`Command failed with exit code: ${result.exitCode}`); console.error(`Error output: ${result.stderr}`); } else { console.log(`Output: ${result.stdout}`); } } catch (error) { if (error instanceof TimeoutError) { console.error('Command timed out'); } else if (error instanceof CommandExecutionError) { console.error(`Command execution error: ${error.message}`); } } await sandbox.kill(); ``` **Expected Output:** ``` Command failed with exit code: 127 Error output: /bin/sh: nonexistent-command: command not found ``` ## Chaining Commands Chain multiple commands together: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Chain commands with && result = sandbox.commands.run('cd /workspace && mkdir test && ls -la') print(result.stdout) # Chain with pipes result = sandbox.commands.run('ls -la /workspace | grep .txt') print(result.stdout) # Multiple commands with semicolon result = sandbox.commands.run('echo "Step 1"; echo "Step 2"; echo "Step 3"') print(result.stdout) sandbox.kill() ``` **Expected Output:** ``` total 12 drwxr-xr-x 3 root root 4096 Jan 27 10:30 . drwxr-xr-x 3 root root 4096 Jan 27 10:30 .. drwxr-xr-x 2 root root 4096 Jan 27 10:30 test Step 1 Step 2 Step 3 ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Chain commands with && const result = await sandbox.commands.run('cd /workspace && mkdir test && ls -la'); console.log(result.stdout); // Chain with pipes const pipeResult = await sandbox.commands.run('ls -la /workspace | grep .txt'); console.log(pipeResult.stdout); // Multiple commands with semicolon const multiResult = await sandbox.commands.run('echo "Step 1"; echo "Step 2"; echo "Step 3"'); console.log(multiResult.stdout); await sandbox.kill(); ``` **Expected Output:** ``` total 12 drwxr-xr-x 3 root root 4096 Jan 27 10:30 . drwxr-xr-x 3 root root 4096 Jan 27 10:30 .. drwxr-xr-x 2 root root 4096 Jan 27 10:30 test Step 1 Step 2 Step 3 ``` ## Complete Example Here's a complete example showing command execution workflow: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Setup project print("📦 Setting up project...") result = sandbox.commands.run('mkdir -p /workspace/myproject', timeout=10) print(f" Create directory: {'✅' if result.success else '❌'}") # Install dependencies print("\n📥 Installing dependencies...") result = sandbox.commands.run( 'pip install requests pandas', timeout=300, working_dir='/workspace/myproject' ) if result.success: print(" ✅ Dependencies installed") print(f" Output: {result.stdout[:100]}...") else: print(f" ❌ Installation failed: {result.stderr}") # Create project files print("\n📝 Creating project files...") result = sandbox.commands.run( 'echo "import requests" > main.py && echo "import pandas" >> main.py', working_dir='/workspace/myproject' ) print(f" Create files: {'✅' if result.success else '❌'}") # Verify setup print("\n🔍 Verifying setup...") result = sandbox.commands.run( 'ls -la && python -c "import requests, pandas; print(\'All imports OK\')"', working_dir='/workspace/myproject' ) if result.success: print(" ✅ Setup complete") print(f" Output:\n{result.stdout}") else: print(f" ❌ Verification failed: {result.stderr}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Setup project console.log('📦 Setting up project...'); let result = await sandbox.commands.run('mkdir -p /workspace/myproject', { timeout: 10 }); console.log(` Create directory: ${result.success ? '✅' : '❌'}`); // Install dependencies console.log('\n📥 Installing dependencies...'); result = await sandbox.commands.run('pip install requests pandas', { timeout: 300, workingDir: '/workspace/myproject' }); if (result.success) { console.log(' ✅ Dependencies installed'); console.log(` Output: ${result.stdout.substring(0, 100)}...`); } else { console.error(` ❌ Installation failed: ${result.stderr}`); } // Create project files console.log('\n📝 Creating project files...'); result = await sandbox.commands.run( 'echo "import requests" > main.py && echo "import pandas" >> main.py', { workingDir: '/workspace/myproject' } ); console.log(` Create files: ${result.success ? '✅' : '❌'}`); // Verify setup console.log('\n🔍 Verifying setup...'); result = await sandbox.commands.run( 'ls -la && python -c "import requests, pandas; print(\'All imports OK\')"', { workingDir: '/workspace/myproject' } ); if (result.success) { console.log(' ✅ Setup complete'); console.log(` Output:\n${result.stdout}`); } else { console.error(` ❌ Verification failed: ${result.stderr}`); } await sandbox.kill(); ``` ## Best Practices Set timeouts based on expected execution time. Default 30 seconds is good for quick commands, but increase for package installations or long operations. Always check `result.success` and handle `stderr` appropriately. Use try/catch for exception handling. Pass environment variables via `env` parameter rather than hardcoding values in commands. Use `working_dir` to run commands in the correct directory context. For commands that run longer than 5 minutes, use [Background Commands](/core-concepts/commands/background) instead. ## Related * **[Background Commands](/core-concepts/commands/background)** - Run commands in background * **[Code Execution](/core-concepts/code-execution/synchronous)** - Execute code directly * **SDK**: [sandbox.commands.run()](/sdk/python/commands#run) - Python SDK method * **API**: [POST /commands/run](/api/vm-agent/run-command) - VM Agent API endpoint ## Next Steps * Learn about [Background Commands](/core-concepts/commands/background) for non-blocking execution * Explore [Code Execution](/core-concepts/code-execution/synchronous) for running code instead of shell commands * Review [Filesystem Operations](/core-concepts/filesystem/reading) for file management ## Related * [CLI Commands](/cli/commands/cmd) - Shell commands from CLI # Clipboard Operations Source: https://docs.hopx.ai/core-concepts/desktop/clipboard Read and write clipboard content in sandbox desktop environments in HopX. Access and manipulate clipboard contents for data transfer, copy-paste operations, and desktop automation workflows. Learn how to read and write clipboard data using Python and JavaScript SDKs or REST API. Includes examples for clipboard automation. Read and write clipboard content for desktop automation. Clipboard operations enable copying and pasting data between applications. ## Overview Clipboard operations enable: * Reading clipboard content * Setting clipboard content * Accessing clipboard history * Copying data between applications Desktop automation requires a template with desktop support. Ensure your sandbox has desktop capabilities enabled. ## Getting Clipboard Content Read the current clipboard content: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="desktop") # Get clipboard content text = sandbox.desktop.get_clipboard() print(f"Clipboard: {text}") ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'desktop' }); // Get clipboard content const text = await sandbox.desktop.getClipboard(); console.log(`Clipboard: ${text}`); ``` ## Setting Clipboard Content Set clipboard content: ```python theme={null} # Set clipboard content sandbox.desktop.set_clipboard("Hello from clipboard!") # Verify text = sandbox.desktop.get_clipboard() print(text) # "Hello from clipboard!" ``` ```javascript theme={null} // Set clipboard content await sandbox.desktop.setClipboard('Hello from clipboard!'); // Verify const text = await sandbox.desktop.getClipboard(); console.log(text); // "Hello from clipboard!" ``` ## Clipboard History Get clipboard history (if supported): ```python theme={null} # Get clipboard history history = sandbox.desktop.get_clipboard_history() for item in history: print(f"History item: {item}") ``` ```javascript theme={null} // Get clipboard history const history = await sandbox.desktop.getClipboardHistory(); history.forEach(item => { console.log(`History item: ${item}`); }); ``` ## Copy-Paste Workflow Complete copy-paste automation: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="desktop") try: # Select text (using mouse/keyboard) sandbox.desktop.click(100, 100) sandbox.desktop.drag(100, 100, 300, 100) # Copy (Ctrl+C) sandbox.desktop.combination(['ctrl'], 'c') # Get copied text copied_text = sandbox.desktop.get_clipboard() print(f"Copied: {copied_text}") # Click elsewhere sandbox.desktop.click(500, 300) # Paste (Ctrl+V) sandbox.desktop.combination(['ctrl'], 'v') finally: sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'desktop' }); try { // Select text (using mouse/keyboard) await sandbox.desktop.mouseClick(100, 100); await sandbox.desktop.mouseDrag(100, 100, 300, 100); // Copy (Ctrl+C) await sandbox.desktop.keyboardCombination(['ctrl', 'c']); // Get copied text const copiedText = await sandbox.desktop.getClipboard(); console.log(`Copied: ${copiedText}`); // Click elsewhere await sandbox.desktop.mouseClick(500, 300); // Paste (Ctrl+V) await sandbox.desktop.keyboardCombination(['ctrl', 'v']); } finally { await sandbox.kill(); } ``` ## Programmatic Copy-Paste Set clipboard programmatically and paste: ```python theme={null} # Set clipboard programmatically sandbox.desktop.set_clipboard("Programmatic clipboard content") # Click in target application sandbox.desktop.click(400, 300) # Paste sandbox.desktop.combination(['ctrl'], 'v') ``` ```javascript theme={null} // Set clipboard programmatically await sandbox.desktop.setClipboard('Programmatic clipboard content'); // Click in target application await sandbox.desktop.mouseClick(400, 300); // Paste await sandbox.desktop.keyboardCombination(['ctrl', 'v']); ``` ## Related * [Keyboard Control](/core-concepts/desktop/keyboard-control) - Keyboard shortcuts for copy/paste * [CLI Reference](/cli/introduction) - Command-line interface for HopX * [Mouse Control](/core-concepts/desktop/mouse-control) - Mouse operations for selection * **SDK**: [sandbox.desktop.get\_clipboard()](/sdk/python/desktop#get_clipboard) - Python SDK method ## Next Steps * Learn about [Keyboard Control](/core-concepts/desktop/keyboard-control) for copy/paste shortcuts * Explore [Mouse Control](/core-concepts/desktop/mouse-control) for selection operations * Review [VNC Server](/core-concepts/desktop/vnc-server) for remote desktop access # Display Management Source: https://docs.hopx.ai/core-concepts/desktop/display-management Configure sandbox display resolution and settings for desktop environments in HopX sandboxes. Set display resolution, configure display settings, and manage multiple displays for desktop automation and GUI testing. Learn how to configure displays using Python and JavaScript SDKs or REST API. Includes examples for display configuration. Configure display resolution and settings for the desktop environment. ## Overview Display management enables: * Getting current display resolution * Setting display resolution * Listing available resolutions * Configuring display settings Desktop automation requires a template with desktop support. Ensure your sandbox has desktop capabilities enabled. ## Getting Display Information Get current display resolution and settings: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="desktop") # Get display info display = sandbox.desktop.get_display() print(f"Resolution: {display.width}x{display.height}") print(f"Color depth: {display.depth} bits") ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'desktop' }); // Get display info const display = await sandbox.desktop.getDisplayInfo(); console.log(`Resolution: ${display.width}x${display.height}`); console.log(`Color depth: ${display.depth} bits`); ``` ## Setting Resolution Set display resolution: ```python theme={null} # Set resolution to 1920x1080 display = sandbox.desktop.set_resolution(1920, 1080) print(f"New resolution: {display.width}x{display.height}") # Set to 1280x720 display = sandbox.desktop.set_resolution(1280, 720) print(f"Resolution: {display.width}x{display.height}") ``` ```javascript theme={null} // Set resolution to 1920x1080 await sandbox.desktop.setResolution(1920, 1080); // Verify const display = await sandbox.desktop.getDisplayInfo(); console.log(`Resolution: ${display.width}x${display.height}`); // Set to 1280x720 await sandbox.desktop.setResolution(1280, 720); ``` ## Available Resolutions List available display resolutions: ```python theme={null} # Get available resolutions resolutions = sandbox.desktop.get_available_resolutions() print("Available resolutions:") for width, height in resolutions: print(f" {width}x{height}") # Find highest resolution if resolutions: highest = max(resolutions, key=lambda r: r[0] * r[1]) print(f"Highest: {highest[0]}x{highest[1]}") ``` ```javascript theme={null} // Get available resolutions const resolutions = await sandbox.desktop.getAvailableResolutions(); console.log('Available resolutions:'); resolutions.forEach(([width, height]) => { console.log(` ${width}x${height}`); }); // Find highest resolution if (resolutions.length > 0) { const highest = resolutions.reduce((a, b) => (a[0] * a[1] > b[0] * b[1]) ? a : b ); console.log(`Highest: ${highest[0]}x${highest[1]}`); } ``` ## Common Resolutions Common display resolutions: * **1920x1080**: Full HD (1080p) - Recommended * **1280x720**: HD (720p) * **2560x1440**: 2K (1440p) * **3840x2160**: 4K (2160p) ## Complete Example Complete display management workflow: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="desktop") try: # Get current display current = sandbox.desktop.get_display() print(f"Current: {current.width}x{current.height}") # List available resolutions resolutions = sandbox.desktop.get_available_resolutions() print(f"Available: {len(resolutions)} resolutions") # Set to Full HD display = sandbox.desktop.set_resolution(1920, 1080) print(f"Set to: {display.width}x{display.height}") # Verify verify = sandbox.desktop.get_display() assert verify.width == 1920 and verify.height == 1080 print("✅ Resolution verified") finally: sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'desktop' }); try { // Get current display const current = await sandbox.desktop.getDisplayInfo(); console.log(`Current: ${current.width}x${current.height}`); // List available resolutions const resolutions = await sandbox.desktop.getAvailableResolutions(); console.log(`Available: ${resolutions.length} resolutions`); // Set to Full HD await sandbox.desktop.setResolution(1920, 1080); // Verify const verify = await sandbox.desktop.getDisplayInfo(); if (verify.width === 1920 && verify.height === 1080) { console.log('✅ Resolution verified'); } } finally { await sandbox.kill(); } ``` ## Resolution Best Practices Set display resolution before starting VNC server for optimal remote desktop experience. * **Before VNC**: Set resolution before starting VNC for best results * **Standard sizes**: Use common resolutions (1920x1080, 1280x720) for compatibility * **Testing**: Test different resolutions for your use case ## Related * [VNC Server](/core-concepts/desktop/vnc-server) - Remote desktop access * [CLI Reference](/cli/introduction) - Command-line interface for HopX * [Window Management](/core-concepts/desktop/window-management) - Manage windows * **SDK**: [sandbox.desktop.get\_display()](/sdk/python/desktop#get_display) - Python SDK method ## Next Steps * Learn about [VNC Server](/core-concepts/desktop/vnc-server) for remote desktop access * Explore [Window Management](/core-concepts/desktop/window-management) to manage windows * Review [Screenshots](/core-concepts/desktop/screenshots) for visual verification # Desktop Automation Source: https://docs.hopx.ai/core-concepts/desktop/index Complete guide to desktop automation in HopX sandboxes - VNC, screenshots, mouse, keyboard, and window management. Automate desktop interactions with VNC servers, capture screenshots and screen recordings, control mouse and keyboard, manage windows and displays, and use clipboard operations. Includes Python and JavaScript SDK examples. Automate desktop interactions in HopX sandboxes with VNC, screenshots, mouse and keyboard control, and window management. This hub covers all desktop automation features. ## Related * [CLI Reference](/cli/introduction) - Command-line interface ## What You'll Learn * How to set up and use VNC servers * How to capture screenshots and screen recordings * How to control mouse and keyboard * How to manage windows and displays * How to use clipboard and advanced X11 features ## Desktop Automation Overview | Feature | SDK Method | API Endpoint | | ----------------------------------------------------------------- | ------------------------------ | -------------------- | | **[VNC Server](/core-concepts/desktop/vnc-server)** | `sandbox.desktop.vnc` | VNC endpoints | | **[Screenshots](/core-concepts/desktop/screenshots)** | `sandbox.desktop.screenshot()` | Screenshot endpoints | | **[Mouse Control](/core-concepts/desktop/mouse-control)** | `sandbox.desktop.mouse` | Mouse endpoints | | **[Keyboard Control](/core-concepts/desktop/keyboard-control)** | `sandbox.desktop.keyboard` | Keyboard endpoints | | **[Window Management](/core-concepts/desktop/window-management)** | `sandbox.desktop.windows` | Window endpoints | | **[Advanced X11](/core-concepts/desktop/x11-advanced)** | Advanced X11 | X11 endpoints | ## Core Concepts ### VNC Server Set up and connect to VNC servers for remote desktop access. * **[VNC Server](/core-concepts/desktop/vnc-server)** - Set up VNC servers * **SDK**: [Python: sandbox.desktop.vnc](/sdk/python/desktop#vnc) | [JavaScript: sandbox.desktop.vnc](/sdk/javascript/desktop#vnc) * **API**: VNC server endpoints ### Screenshots Capture screenshots and screen recordings from sandboxes. * **[Screenshots](/core-concepts/desktop/screenshots)** - Capture screenshots * **[Screen Recording](/core-concepts/desktop/screen-recording)** - Record screen activity * **SDK**: [Python: sandbox.desktop.screenshot()](/sdk/python/desktop#screenshot) | [JavaScript: sandbox.desktop.screenshot()](/sdk/javascript/desktop#screenshot) * **API**: Screenshot endpoints ### Mouse Control Control mouse movements, clicks, and gestures. * **[Mouse Control](/core-concepts/desktop/mouse-control)** - Control mouse interactions * **SDK**: [Python: sandbox.desktop.mouse](/sdk/python/desktop#mouse) | [JavaScript: sandbox.desktop.mouse](/sdk/javascript/desktop#mouse) * **API**: Mouse control endpoints ### Keyboard Control Send keyboard input and key combinations. * **[Keyboard Control](/core-concepts/desktop/keyboard-control)** - Control keyboard input * **SDK**: [Python: sandbox.desktop.keyboard](/sdk/python/desktop#keyboard) | [JavaScript: sandbox.desktop.keyboard](/sdk/javascript/desktop#keyboard) * **API**: Keyboard control endpoints ### Window Management Manage windows, displays, and desktop layout. * **[Window Management](/core-concepts/desktop/window-management)** - Manage windows * **[Display Management](/core-concepts/desktop/display-management)** - Manage displays * **SDK**: [Python: sandbox.desktop.windows](/sdk/python/desktop#windows) | [JavaScript: sandbox.desktop.windows](/sdk/javascript/desktop#windows) * **API**: Window management endpoints ### Advanced X11 Advanced X11 features for desktop automation. * **[Advanced X11](/core-concepts/desktop/x11-advanced)** - Advanced X11 features * **SDK**: [Python: sandbox.desktop.x11](/sdk/python/desktop#x11) | [JavaScript: sandbox.desktop.x11](/sdk/javascript/desktop#x11) * **API**: X11 endpoints ### Clipboard Access and manipulate clipboard contents. * **[Clipboard](/core-concepts/desktop/clipboard)** - Clipboard operations * **SDK**: [Python: sandbox.desktop.clipboard](/sdk/python/desktop#clipboard) | [JavaScript: sandbox.desktop.clipboard](/sdk/javascript/desktop#clipboard) * **API**: Clipboard endpoints ## SDK Reference ### Python SDK Complete reference for Python desktop automation. * **[Desktop Module](/sdk/python/desktop)** - Complete desktop automation API * `desktop.vnc` - VNC server * `desktop.screenshot()` - Screenshots * `desktop.mouse` - Mouse control * `desktop.keyboard` - Keyboard control * `desktop.windows` - Window management * `desktop.clipboard` - Clipboard * `desktop.x11` - Advanced X11 ### JavaScript SDK Complete reference for JavaScript/TypeScript desktop automation. * **[Desktop Module](/sdk/javascript/desktop)** - Complete desktop automation API * `desktop.vnc` - VNC server * `desktop.screenshot()` - Screenshots * `desktop.mouse` - Mouse control * `desktop.keyboard` - Keyboard control * `desktop.windows` - Window management * `desktop.clipboard` - Clipboard * `desktop.x11` - Advanced X11 ## API Reference ### VM Agent API REST API endpoints for desktop automation. * **[VM Agent API Overview](/api/vm-agent/overview)** - API overview * Desktop automation endpoints (VNC, screenshots, mouse, keyboard, windows) ## Quick Start If you're new to desktop automation, start here: 1. **[VNC Server](/core-concepts/desktop/vnc-server)** - Set up VNC access 2. **[Screenshots](/core-concepts/desktop/screenshots)** - Capture your first screenshot 3. **[Mouse Control](/core-concepts/desktop/mouse-control)** - Control mouse interactions ## Related Topics * **[Sandboxes](/core-concepts/sandboxes/creating)** - Create sandboxes for desktop automation * **[Code Execution](/core-concepts/code-execution/synchronous)** - Execute code with desktop access * **[Terminal](/core-concepts/terminal/websocket)** - Terminal access alongside desktop * **[Observability](/core-concepts/observability/metrics)** - Monitor desktop performance ## Next Steps * Learn about [VNC Server](/core-concepts/desktop/vnc-server) for remote desktop access * Explore [Screenshots](/core-concepts/desktop/screenshots) for visual capture * Review [Mouse Control](/core-concepts/desktop/mouse-control) and [Keyboard Control](/core-concepts/desktop/keyboard-control) for automation * Check out [Advanced X11](/core-concepts/desktop/x11-advanced) for advanced features # Keyboard Control Source: https://docs.hopx.ai/core-concepts/desktop/keyboard-control Control keyboard input for sandbox desktop automation in HopX sandboxes. Send keyboard input, simulate key presses, type text, and handle keyboard shortcuts for desktop automation. Learn how to control keyboard interactions using Python and JavaScript SDKs or REST API. Includes examples for common keyboard operations. Control keyboard input to type text, press keys, and execute key combinations for desktop automation. ## Overview Keyboard control enables: * Typing text into applications * Pressing individual keys * Executing key combinations (Ctrl+C, Alt+Tab, etc.) * Simulating keyboard shortcuts Desktop automation requires a template with desktop support. Ensure your sandbox has desktop capabilities enabled. ## Typing Text Type text as if typed on a keyboard: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="desktop") # Type text sandbox.desktop.type("Hello, World!") # Type with custom delay between keystrokes sandbox.desktop.type("Slow typing", delay_ms=50) ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'desktop' }); // Type text await sandbox.desktop.keyboardType('Hello, World!'); ``` ## Pressing Keys Press individual keys: ```python theme={null} # Press Enter sandbox.desktop.press("Return") # Press Escape sandbox.desktop.press("Escape") # Press Tab sandbox.desktop.press("Tab") # Press function keys sandbox.desktop.press("F1") sandbox.desktop.press("F5") ``` ```javascript theme={null} // Press Enter await sandbox.desktop.keyboardPress('Return'); // Press Escape await sandbox.desktop.keyboardPress('Escape'); // Press Tab await sandbox.desktop.keyboardPress('Tab'); ``` ## Key Combinations Execute key combinations (modifier keys + main key): ```python theme={null} # Ctrl+C (copy) sandbox.desktop.combination(['ctrl'], 'c') # Ctrl+V (paste) sandbox.desktop.combination(['ctrl'], 'v') # Ctrl+Shift+T (new tab) sandbox.desktop.combination(['ctrl', 'shift'], 't') # Alt+F4 (close window) sandbox.desktop.combination(['alt'], 'F4') # Ctrl+Alt+Delete sandbox.desktop.combination(['ctrl', 'alt'], 'Delete') ``` ```javascript theme={null} // Ctrl+C (copy) await sandbox.desktop.keyboardCombination(['ctrl', 'c']); // Ctrl+V (paste) await sandbox.desktop.keyboardCombination(['ctrl', 'v']); // Ctrl+Shift+T (new tab) await sandbox.desktop.keyboardCombination(['ctrl', 'shift', 't']); ``` ## Available Keys Common key names: * **Modifiers**: `'ctrl'`, `'shift'`, `'alt'`, `'meta'` (Command on macOS) * **Function keys**: `'F1'` through `'F12'` * **Special keys**: `'Return'` (Enter), `'Escape'`, `'Tab'`, `'Backspace'`, `'Delete'` * **Arrow keys**: `'Up'`, `'Down'`, `'Left'`, `'Right'` * **Letters and numbers**: `'a'`, `'b'`, `'1'`, `'2'`, etc. ## Typing Speed Control typing speed with delay: ```python theme={null} # Fast typing (default: 10ms delay) sandbox.desktop.type("Fast text", delay_ms=10) # Normal typing sandbox.desktop.type("Normal text", delay_ms=50) # Slow typing (for debugging) sandbox.desktop.type("Slow text", delay_ms=100) ``` ```javascript theme={null} // Note: JavaScript SDK may have different delay parameter await sandbox.desktop.keyboardType('Text to type'); ``` ## Complete Example Automate a form filling workflow: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="desktop") try: # Click on input field (assuming coordinates) sandbox.desktop.click(400, 300) # Type username sandbox.desktop.type("myusername") # Press Tab to move to next field sandbox.desktop.press("Tab") # Type password sandbox.desktop.type("mypassword") # Press Enter to submit sandbox.desktop.press("Return") finally: sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'desktop' }); try { // Click on input field (assuming coordinates) await sandbox.desktop.mouseClick(400, 300); // Type username await sandbox.desktop.keyboardType('myusername'); // Press Tab to move to next field await sandbox.desktop.keyboardPress('Tab'); // Type password await sandbox.desktop.keyboardType('mypassword'); // Press Enter to submit await sandbox.desktop.keyboardPress('Return'); } finally { await sandbox.kill(); } ``` ## Common Shortcuts Common keyboard shortcuts for automation: * **Copy**: `Ctrl+C` (or `Cmd+C` on macOS) * **Paste**: `Ctrl+V` (or `Cmd+V` on macOS) * **Cut**: `Ctrl+X` (or `Cmd+X` on macOS) * **Select All**: `Ctrl+A` (or `Cmd+A` on macOS) * **Undo**: `Ctrl+Z` (or `Cmd+Z` on macOS) * **Redo**: `Ctrl+Y` (or `Cmd+Shift+Z` on macOS) * **Save**: `Ctrl+S` (or `Cmd+S` on macOS) * **Close Tab**: `Ctrl+W` (or `Cmd+W` on macOS) * **New Tab**: `Ctrl+T` (or `Cmd+T` on macOS) ## Related * [Mouse Control](/core-concepts/desktop/mouse-control) - Control mouse input * [CLI Reference](/cli/introduction) - Command-line interface for HopX * [Clipboard](/core-concepts/desktop/clipboard) - Clipboard operations * [X11 Advanced](/core-concepts/desktop/x11-advanced) - Advanced keyboard features * **SDK**: [sandbox.desktop.type()](/sdk/python/desktop#type) - Python SDK method ## Next Steps * Learn about [Mouse Control](/core-concepts/desktop/mouse-control) for clicking and dragging * Explore [Clipboard](/core-concepts/desktop/clipboard) for copy/paste operations * Review [VNC Server](/core-concepts/desktop/vnc-server) for remote desktop access # Mouse Control Source: https://docs.hopx.ai/core-concepts/desktop/mouse-control Control mouse input for sandbox desktop automation in HopX sandboxes. Move mouse cursor, click buttons, perform drag operations, and simulate mouse gestures for desktop automation. Learn how to control mouse interactions using Python and JavaScript SDKs or REST API. Includes examples for common mouse operations. Control mouse input to interact with GUI applications. Mouse control enables clicking, moving, dragging, and scrolling operations. ## Overview Mouse control enables: * Clicking buttons and UI elements * Moving cursor to specific positions * Dragging and dropping elements * Scrolling windows and content Desktop automation requires a template with desktop support. Ensure your sandbox has desktop capabilities enabled. ## Clicking Click at a specific position on the screen: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="desktop") # Single left click sandbox.desktop.click(100, 100) # Right click sandbox.desktop.click(200, 200, button="right") # Middle click sandbox.desktop.click(300, 300, button="middle") # Double click sandbox.desktop.click(150, 150, clicks=2) ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'desktop' }); // Single left click await sandbox.desktop.mouseClick(100, 100); // Right click await sandbox.desktop.mouseClick(200, 200, { button: 'right' }); // Middle click await sandbox.desktop.mouseClick(300, 300, { button: 'middle' }); // Double click await sandbox.desktop.mouseClick(150, 150, { clicks: 2 }); ``` ## Moving Cursor Move the mouse cursor to a specific position: ```python theme={null} # Move cursor to position sandbox.desktop.move(500, 300) ``` ```javascript theme={null} // Move cursor to position await sandbox.desktop.mouseMove(500, 300); ``` ## Dragging Drag from one position to another: ```python theme={null} # Drag from (100, 100) to (200, 200) sandbox.desktop.drag(100, 100, 200, 200) # Drag with right button sandbox.desktop.drag(100, 100, 200, 200, button="right") ``` ```javascript theme={null} // Drag from (100, 100) to (200, 200) await sandbox.desktop.mouseDrag(100, 100, 200, 200); ``` ## Scrolling Scroll the mouse wheel: ```python theme={null} # Scroll down 5 clicks sandbox.desktop.scroll(5, "down") # Scroll up 3 clicks sandbox.desktop.scroll(3, "up") # Scroll left sandbox.desktop.scroll(2, "left") # Scroll right sandbox.desktop.scroll(2, "right") ``` ```javascript theme={null} // Scroll (JavaScript SDK may have different API) // Note: Check SDK documentation for exact scroll method signature await sandbox.desktop.mouseScroll(500, 300, 5); // x, y, deltaY ``` ## Mouse Buttons Available mouse buttons: * `"left"` - Left mouse button (default) * `"right"` - Right mouse button * `"middle"` - Middle mouse button (scroll wheel) ## Complete Example Automate a simple GUI interaction: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="desktop") try: # Move to button sandbox.desktop.move(400, 300) # Click button sandbox.desktop.click(400, 300) # Wait a moment (you might use time.sleep in real scenarios) # Drag a slider sandbox.desktop.drag(100, 200, 300, 200) # Scroll to see more content sandbox.desktop.scroll(10, "down") finally: sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'desktop' }); try { // Move to button await sandbox.desktop.mouseMove(400, 300); // Click button await sandbox.desktop.mouseClick(400, 300); // Wait a moment (you might use setTimeout in real scenarios) // Drag a slider await sandbox.desktop.mouseDrag(100, 200, 300, 200); // Scroll to see more content await sandbox.desktop.mouseScroll(500, 300, 10); } finally { await sandbox.kill(); } ``` ## Coordinate System Mouse coordinates use screen pixels: * **Origin (0, 0)**: Top-left corner of the screen * **X-axis**: Increases from left to right * **Y-axis**: Increases from top to bottom Use screenshots to identify exact coordinates of UI elements before automating interactions. ## Related * [Keyboard Control](/core-concepts/desktop/keyboard-control) - Control keyboard input * [CLI Reference](/cli/introduction) - Command-line interface for HopX * [Screenshots](/core-concepts/desktop/screenshots) - Capture screenshots to find coordinates * [X11 Advanced](/core-concepts/desktop/x11-advanced) - Find elements by text * **SDK**: [sandbox.desktop.click()](/sdk/python/desktop#click) - Python SDK method ## Next Steps * Learn about [Keyboard Control](/core-concepts/desktop/keyboard-control) for text input * Explore [Screenshots](/core-concepts/desktop/screenshots) to find element coordinates * Review [VNC Server](/core-concepts/desktop/vnc-server) for remote desktop access # Screen Recording Source: https://docs.hopx.ai/core-concepts/desktop/screen-recording Record sandbox screen activity as video for desktop automation in HopX sandboxes. Capture screen recordings of desktop interactions, GUI workflows, and visual demonstrations. Learn how to start and stop recordings, download video files, and use recordings for documentation or testing. Includes Python and JavaScript SDK examples. Record screen activity as video files for documentation, testing, and debugging. ## Overview Screen recording enables: * Recording desktop activity as video * Configurable frame rate and quality * Downloading recorded videos * Monitoring recording status Desktop automation requires a template with desktop support. Ensure your sandbox has desktop capabilities enabled. ## Starting Recording Start a screen recording: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="desktop") # Start recording with default settings recording = sandbox.desktop.start_recording() # Start with custom settings recording = sandbox.desktop.start_recording( fps=30, # 30 frames per second format="mp4", # MP4 format quality="high" # High quality ) print(f"Recording ID: {recording.recording_id}") print(f"Status: {recording.status}") ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'desktop' }); // Start recording await sandbox.desktop.startRecording(); // Note: JavaScript SDK may have different parameters // Check SDK documentation for exact API ``` ## Recording Options Configure recording settings: ```python theme={null} # Low quality, low FPS (smaller file) recording = sandbox.desktop.start_recording( fps=10, format="mp4", quality="low" ) # Medium quality (balanced) recording = sandbox.desktop.start_recording( fps=15, format="mp4", quality="medium" ) # High quality, high FPS (larger file) recording = sandbox.desktop.start_recording( fps=30, format="mp4", quality="high" ) ``` ```javascript theme={null} // Note: JavaScript SDK may have different parameters await sandbox.desktop.startRecording('output.mp4'); ``` ## Stopping Recording Stop a recording and get final information: ```python theme={null} # Start recording recording = sandbox.desktop.start_recording() # ... perform actions ... # Stop recording final_recording = sandbox.desktop.stop_recording(recording.recording_id) print(f"Duration: {final_recording.duration}s") print(f"File size: {final_recording.file_size} bytes") print(f"Format: {final_recording.format}") ``` ```javascript theme={null} // Start recording await sandbox.desktop.startRecording(); // ... perform actions ... // Stop recording await sandbox.desktop.stopRecording(); // Get status const status = await sandbox.desktop.getRecordingStatus(); console.log(`Duration: ${status.duration}s`); console.log(`File size: ${status.fileSize} bytes`); ``` ## Recording Status Check recording status: ```python theme={null} # Get recording status status = sandbox.desktop.get_recording_status(recording.recording_id) print(f"Status: {status.status}") print(f"Duration: {status.duration}s") print(f"File size: {status.file_size} bytes") # Check if ready if status.status == "stopped": video = sandbox.desktop.download_recording(recording.recording_id) ``` ```javascript theme={null} // Get recording status const status = await sandbox.desktop.getRecordingStatus(); console.log(`Status: ${status.status}`); console.log(`Duration: ${status.duration}s`); console.log(`File size: ${status.fileSize} bytes`); ``` ## Downloading Recording Download the recorded video: ```python theme={null} # Download recording video_bytes = sandbox.desktop.download_recording(recording.recording_id) # Save to file with open('recording.mp4', 'wb') as f: f.write(video_bytes) print(f"Video saved: {len(video_bytes)} bytes") ``` ```javascript theme={null} // Download recording const video = await sandbox.desktop.downloadRecording(recordingId); // Save to file fs.writeFileSync('recording.mp4', video); console.log(`Video saved: ${video.length} bytes`); ``` ## Complete Example Complete recording workflow: ```python theme={null} from hopx_ai import Sandbox import time sandbox = Sandbox.create(template="desktop") try: # Start recording recording = sandbox.desktop.start_recording( fps=30, format="mp4", quality="high" ) print(f"Recording started: {recording.recording_id}") # Perform actions to record sandbox.desktop.click(400, 300) time.sleep(1) sandbox.desktop.type("Hello, World!") time.sleep(2) # Stop recording final = sandbox.desktop.stop_recording(recording.recording_id) print(f"Recording stopped: {final.duration}s") # Wait for processing time.sleep(2) # Download video video = sandbox.desktop.download_recording(recording.recording_id) with open('demo.mp4', 'wb') as f: f.write(video) print(f"Video saved: {len(video)} bytes") finally: sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import fs from 'fs'; const sandbox = await Sandbox.create({ template: 'desktop' }); try { // Start recording await sandbox.desktop.startRecording(); console.log('Recording started'); // Perform actions to record await sandbox.desktop.mouseClick(400, 300); await new Promise(resolve => setTimeout(resolve, 1000)); await sandbox.desktop.keyboardType('Hello, World!'); await new Promise(resolve => setTimeout(resolve, 2000)); // Stop recording await sandbox.desktop.stopRecording(); console.log('Recording stopped'); // Wait for processing await new Promise(resolve => setTimeout(resolve, 2000)); // Get status and download const status = await sandbox.desktop.getRecordingStatus(); if (status.recordingId) { const video = await sandbox.desktop.downloadRecording(status.recordingId); fs.writeFileSync('demo.mp4', video); console.log(`Video saved: ${video.length} bytes`); } } finally { await sandbox.kill(); } ``` ## Recording Formats Supported video formats: * **MP4**: H.264 encoded MP4 (recommended) * **WebM**: WebM format (if supported) ## Quality Settings Quality options: * **low**: Lower file size, lower quality * **medium**: Balanced quality and file size (default) * **high**: Higher quality, larger file size ## Frame Rate Frame rate options: * **10 fps**: Lower file size, choppier video * **15 fps**: Balanced (default) * **30 fps**: Smooth video, larger file size Use lower FPS and quality for longer recordings to reduce file size. Use higher settings for short, high-quality demos. ## Related * [Screenshots](/core-concepts/desktop/screenshots) - Capture static screenshots * [VNC Server](/core-concepts/desktop/vnc-server) - Remote desktop access * **SDK**: [sandbox.desktop.start\_recording()](/sdk/python/desktop#start_recording) - Python SDK method ## Next Steps * Learn about [Screenshots](/core-concepts/desktop/screenshots) for static image capture * Explore [VNC Server](/core-concepts/desktop/vnc-server) for live remote access * Review [Mouse Control](/core-concepts/desktop/mouse-control) and [Keyboard Control](/core-concepts/desktop/keyboard-control) for automation * [Screenshots](/core-concepts/desktop/screenshots) - Capture static screenshots * [Window Management](/core-concepts/desktop/window-management) - Manage windows during recording * **[CLI System Commands](/cli/commands/system)** - System operations from CLI # Screenshots Source: https://docs.hopx.ai/core-concepts/desktop/screenshots Capture screenshots of the sandbox desktop environment in HopX sandboxes. Take screenshots of desktop applications, GUIs, and visual outputs for documentation, testing, or monitoring. Learn how to capture screenshots using Python and JavaScript SDKs or REST API. Includes examples for screenshot capture and image processing. Capture screenshots of the desktop for visual verification, debugging, and documentation. ## Overview Screenshot capture enables: * Full screen screenshots * Region-specific screenshots * Visual verification of GUI state * Documentation and debugging Desktop automation requires a template with desktop support. Ensure your sandbox has desktop capabilities enabled. ## Full Screen Screenshot Capture the entire screen: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="desktop") # Capture full screen img_bytes = sandbox.desktop.screenshot() # Save to file with open('screenshot.png', 'wb') as f: f.write(img_bytes) ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import fs from 'fs'; const sandbox = await Sandbox.create({ template: 'desktop' }); // Capture full screen const screenshot = await sandbox.desktop.screenshot(); // Save to file (screenshot may be Buffer or object with data property) if (screenshot instanceof Buffer) { fs.writeFileSync('screenshot.png', screenshot); } else { fs.writeFileSync('screenshot.png', Buffer.from(screenshot.data, 'base64')); } ``` ## Region Screenshot Capture a specific region of the screen: ```python theme={null} # Capture region: x=100, y=100, width=500, height=300 img_bytes = sandbox.desktop.screenshot_region(100, 100, 500, 300) # Save to file with open('region.png', 'wb') as f: f.write(img_bytes) ``` ```javascript theme={null} // Capture region: x=100, y=100, width=500, height=300 const region = await sandbox.desktop.screenshotRegion(100, 100, 500, 300); // Save to file fs.writeFileSync('region.png', region); ``` ## Window Screenshot Capture a specific window (X11 advanced feature): ```python theme={null} # Capture active window img_bytes = sandbox.desktop.capture_window() # Capture specific window windows = sandbox.desktop.get_windows() if windows: window_id = windows[0].id img_bytes = sandbox.desktop.capture_window(window_id) # Save to file with open('window.png', 'wb') as f: f.write(img_bytes) ``` ```javascript theme={null} // Capture active window const windowImg = await sandbox.desktop.captureWindow(); // Capture specific window const windows = await sandbox.desktop.listWindows(); if (windows.length > 0) { const windowId = windows[0].id; const windowImg = await sandbox.desktop.captureWindow(windowId); } // Save to file fs.writeFileSync('window.png', windowImg); ``` ## Screenshot Workflow Complete screenshot workflow: ```python theme={null} from hopx_ai import Sandbox import time sandbox = Sandbox.create(template="desktop") try: # Start application (example) # ... application setup ... # Wait for application to load time.sleep(2) # Capture initial state initial = sandbox.desktop.screenshot() with open('initial.png', 'wb') as f: f.write(initial) # Perform actions sandbox.desktop.click(400, 300) time.sleep(1) # Capture after action after = sandbox.desktop.screenshot() with open('after.png', 'wb') as f: f.write(after) # Capture specific region region = sandbox.desktop.screenshot_region(100, 100, 400, 300) with open('region.png', 'wb') as f: f.write(region) finally: sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import fs from 'fs'; const sandbox = await Sandbox.create({ template: 'desktop' }); try { // Start application (example) // ... application setup ... // Wait for application to load await new Promise(resolve => setTimeout(resolve, 2000)); // Capture initial state const initial = await sandbox.desktop.screenshot(); fs.writeFileSync('initial.png', Buffer.from(initial.data, 'base64')); // Perform actions await sandbox.desktop.mouseClick(400, 300); await new Promise(resolve => setTimeout(resolve, 1000)); // Capture after action const after = await sandbox.desktop.screenshot(); fs.writeFileSync('after.png', Buffer.from(after.data, 'base64')); // Capture specific region const region = await sandbox.desktop.screenshotRegion(100, 100, 400, 300); fs.writeFileSync('region.png', region); } finally { await sandbox.kill(); } ``` ## Image Format Screenshots are returned as PNG image bytes: * **Format**: PNG * **Color depth**: 24-bit RGB * **Compression**: PNG compression ## Finding Coordinates Use screenshots to find coordinates for mouse operations: ```python theme={null} # Take screenshot img_bytes = sandbox.desktop.screenshot() # Save and inspect in image viewer with open('reference.png', 'wb') as f: f.write(img_bytes) # Use coordinates from image viewer sandbox.desktop.click(400, 300) # Coordinates from reference.png ``` ```javascript theme={null} // Take screenshot const screenshot = await sandbox.desktop.screenshot(); // Save and inspect in image viewer fs.writeFileSync('reference.png', Buffer.from(screenshot.data, 'base64')); // Use coordinates from image viewer await sandbox.desktop.mouseClick(400, 300); // Coordinates from reference.png ``` ## Related * [Screen Recording](/core-concepts/desktop/screen-recording) - Record screen activity * [CLI Reference](/cli/introduction) - Command-line interface for HopX * [Window Management](/core-concepts/desktop/window-management) - Manage windows * [X11 Advanced](/core-concepts/desktop/x11-advanced) - Advanced screenshot features * **SDK**: [sandbox.desktop.screenshot()](/sdk/python/desktop#screenshot) - Python SDK method ## Next Steps * Learn about [Screen Recording](/core-concepts/desktop/screen-recording) for video capture * Explore [Mouse Control](/core-concepts/desktop/mouse-control) to interact with GUI elements * Review [VNC Server](/core-concepts/desktop/vnc-server) for remote desktop access # VNC Server Source: https://docs.hopx.ai/core-concepts/desktop/vnc-server Start and manage VNC server for remote desktop access in HopX sandboxes. Set up VNC servers for graphical desktop environments, connect via VNC clients, and manage remote desktop sessions. Learn how to configure VNC settings, access desktop environments, and use VNC for desktop automation. Includes Python and JavaScript SDK examples. Access and control the graphical desktop environment through VNC (Virtual Network Computing). VNC provides remote desktop access to your sandbox, allowing you to see and interact with GUI applications. ## Prerequisites Before you begin, make sure you have: * **Desktop template** - A sandbox created from a template with desktop support (e.g., `desktop` template) * **Active sandbox** - A running sandbox (see [Creating Sandboxes](/core-concepts/sandboxes/creating)) * **VNC client** - A VNC viewer application (optional, for manual access) ## Overview VNC server enables: * Remote desktop access to sandbox GUI * Visual debugging of GUI applications * Interactive testing of desktop software * Screen sharing and collaboration Desktop automation requires a template with desktop support. Templates like `desktop` or custom templates with X11/VNC dependencies are required. ## Starting VNC Server Start a VNC server to enable remote desktop access: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="desktop") # Start VNC server vnc_info = sandbox.desktop.start_vnc() print(f"VNC URL: {vnc_info.url}") print(f"Display: {vnc_info.display}") print(f"Port: {vnc_info.port}") ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'desktop' }); // Start VNC server const vncInfo = await sandbox.desktop.startVnc(); console.log(`VNC URL: ${vncInfo.url}`); console.log(`Display: ${vncInfo.display}`); console.log(`Port: ${vncInfo.port}`); ``` ## VNC Server with Password Start VNC server with a password for security: ```python theme={null} # Start VNC with password vnc_info = sandbox.desktop.start_vnc(display=1, password="my-secure-password") print(f"Connect to: {vnc_info.url}") ``` ```javascript theme={null} // Note: JavaScript SDK may have different password parameter const vncInfo = await sandbox.desktop.startVnc(); console.log(`Connect to: ${vncInfo.url}`); ``` ## Getting VNC Status Check if VNC server is running and get connection details: ```python theme={null} # Get VNC status vnc_info = sandbox.desktop.get_vnc_status() if vnc_info.running: print(f"VNC is running at {vnc_info.url}") print(f"Display: {vnc_info.display}") else: print("VNC server is not running") ``` ```javascript theme={null} // Get VNC info const vncInfo = await sandbox.desktop.getVncInfo(); if (vncInfo.running) { console.log(`VNC is running at ${vncInfo.url}`); console.log(`Display: ${vncInfo.display}`); } else { console.log('VNC server is not running'); } ``` ## Getting VNC URL Get just the VNC URL string (convenience method): ```python theme={null} # Get VNC URL url = sandbox.desktop.get_vnc_url() print(f"Connect to: {url}") ``` ```javascript theme={null} // Get VNC URL const url = await sandbox.desktop.getVncUrl(); console.log(`Connect to: ${url}`); ``` ## Stopping VNC Server Stop the VNC server: ```python theme={null} # Stop VNC server sandbox.desktop.stop_vnc() print("VNC server stopped") ``` ```javascript theme={null} // Stop VNC server await sandbox.desktop.stopVnc(); console.log('VNC server stopped'); ``` ## Connecting to VNC Once VNC is started, connect using a VNC client: 1. **Get the VNC URL** from `vnc_info.url` or `get_vnc_url()` 2. **Use a VNC client** such as: * **TigerVNC Viewer** (Windows, macOS, Linux) * **RealVNC Viewer** (Windows, macOS, Linux) * **Remmina** (Linux) * **Built-in Screen Sharing** (macOS) 3. **Connect** using the URL (e.g., `vnc://sandbox-id.region.hopx.dev:5901`) For web-based access, some VNC clients support WebSocket connections. Check your VNC client documentation for WebSocket support. ## VNC Display Numbers VNC servers use display numbers (e.g., `:1`, `:2`). The default is display `1`: ```python theme={null} # Start VNC on display 2 vnc_info = sandbox.desktop.start_vnc(display=2) print(f"Display: {vnc_info.display}") # :2 ``` ```javascript theme={null} // Note: JavaScript SDK may use different parameter const vncInfo = await sandbox.desktop.startVnc(); console.log(`Display: ${vncInfo.display}`); ``` ## Complete Example Complete workflow for VNC access: ```python theme={null} from hopx_ai import Sandbox # Create sandbox with desktop support sandbox = Sandbox.create(template="desktop") try: # Start VNC vnc_info = sandbox.desktop.start_vnc(password="secure-password") print(f"✅ VNC started: {vnc_info.url}") print(f" Display: {vnc_info.display}") print(f" Port: {vnc_info.port}") # Check status status = sandbox.desktop.get_vnc_status() if status.running: print("✅ VNC is running") # Use VNC URL to connect with VNC client print(f"\nConnect using: {vnc_info.url}") finally: # Cleanup sandbox.desktop.stop_vnc() sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // Create sandbox with desktop support const sandbox = await Sandbox.create({ template: 'desktop' }); try { // Start VNC const vncInfo = await sandbox.desktop.startVnc(); console.log(`✅ VNC started: ${vncInfo.url}`); console.log(` Display: ${vncInfo.display}`); console.log(` Port: ${vncInfo.port}`); // Check status const status = await sandbox.desktop.getVncInfo(); if (status.running) { console.log('✅ VNC is running'); } // Use VNC URL to connect with VNC client console.log(`\nConnect using: ${vncInfo.url}`); } finally { // Cleanup await sandbox.desktop.stopVnc(); await sandbox.kill(); } ``` ## Troubleshooting ### VNC Not Available If VNC methods raise `DesktopNotAvailableError`, your template may be missing required dependencies: Desktop automation requires specific dependencies. Ensure your template includes: * `tigervnc-standalone-server` * `xvfb` * `xdotool` * `wmctrl` ### Connection Issues * **Check VNC status**: Verify server is running with `get_vnc_status()` * **Verify URL**: Ensure you're using the correct VNC URL * **Firewall**: Check if ports are accessible * **Password**: If using password, ensure it's correct ### Display Issues * **Multiple displays**: Use different display numbers for multiple VNC sessions * **Resolution**: Set display resolution before starting VNC (see Display Management) ## Related * [Mouse Control](/core-concepts/desktop/mouse-control) - Control mouse input * [CLI Reference](/cli/introduction) - Command-line interface for HopX * [Keyboard Control](/core-concepts/desktop/keyboard-control) - Control keyboard input * [Screenshots](/core-concepts/desktop/screenshots) - Capture screenshots * [Display Management](/core-concepts/desktop/display-management) - Configure display settings * **SDK**: [sandbox.desktop.start\_vnc()](/sdk/python/desktop#start_vnc) - Python SDK method ## Next Steps * Learn about [Mouse Control](/core-concepts/desktop/mouse-control) to interact with GUI * Explore [Keyboard Control](/core-concepts/desktop/keyboard-control) for text input * Review [Screenshots](/core-concepts/desktop/screenshots) for visual verification # Window Management Source: https://docs.hopx.ai/core-concepts/desktop/window-management Manage windows on the sandbox desktop including resizing, moving, and focusing windows in HopX sandboxes. Control window positions, sizes, focus, and visibility for desktop automation workflows. Learn how to manage windows using Python and JavaScript SDKs or REST API. Includes examples for window automation and GUI testing. Manage windows on the desktop: list, focus, resize, minimize, and close windows. ## Overview Window management enables: * Listing all windows * Focusing (activating) windows * Resizing windows * Minimizing windows * Closing windows Desktop automation requires a template with desktop support. Ensure your sandbox has desktop capabilities enabled. ## Listing Windows Get list of all windows: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="desktop") # Get all windows windows = sandbox.desktop.get_windows() for window in windows: print(f"Window: {window.title}") print(f" ID: {window.id}") print(f" Position: ({window.x}, {window.y})") print(f" Size: {window.width}x{window.height}") print(f" PID: {window.pid}") ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'desktop' }); // Get all windows const windows = await sandbox.desktop.listWindows(); windows.forEach(window => { console.log(`Window: ${window.title}`); console.log(` ID: ${window.id}`); console.log(` Position: (${window.x}, ${window.y})`); console.log(` Size: ${window.width}x${window.height}`); console.log(` PID: ${window.pid}`); }); ``` ## Focusing Windows Focus (activate) a window: ```python theme={null} # Get windows windows = sandbox.desktop.get_windows() # Focus first window if windows: sandbox.desktop.focus_window(windows[0].id) # Find and focus window by title for window in windows: if "Firefox" in window.title: sandbox.desktop.focus_window(window.id) break ``` ```javascript theme={null} // Get windows const windows = await sandbox.desktop.listWindows(); // Focus first window if (windows.length > 0) { await sandbox.desktop.focusWindow(windows[0].id); } // Find and focus window by title for (const window of windows) { if (window.title.includes('Firefox')) { await sandbox.desktop.focusWindow(window.id); break; } } ``` ## Resizing Windows Resize a window: ```python theme={null} # Get windows windows = sandbox.desktop.get_windows() # Resize first window to 800x600 if windows: sandbox.desktop.resize_window(windows[0].id, 800, 600) # Resize window by title for window in windows: if "My App" in window.title: sandbox.desktop.resize_window(window.id, 1024, 768) break ``` ```javascript theme={null} // Get windows const windows = await sandbox.desktop.listWindows(); // Resize first window to 800x600 if (windows.length > 0) { await sandbox.desktop.resizeWindow(windows[0].id, 800, 600); } // Resize window by title for (const window of windows) { if (window.title.includes('My App')) { await sandbox.desktop.resizeWindow(window.id, 1024, 768); break; } } ``` ## Minimizing Windows Minimize a window: ```python theme={null} # Minimize first window windows = sandbox.desktop.get_windows() if windows: sandbox.desktop.minimize_window(windows[0].id) ``` ```javascript theme={null} // Minimize first window const windows = await sandbox.desktop.listWindows(); if (windows.length > 0) { await sandbox.desktop.minimizeWindow(windows[0].id); } ``` ## Closing Windows Close a window: ```python theme={null} # Close window by title windows = sandbox.desktop.get_windows() for window in windows: if "Firefox" in window.title: sandbox.desktop.close_window(window.id) break ``` ```javascript theme={null} // Close window by title const windows = await sandbox.desktop.listWindows(); for (const window of windows) { if (window.title.includes('Firefox')) { await sandbox.desktop.closeWindow(window.id); break; } } ``` ## Window Information Window objects contain: * **id**: Unique window identifier * **title**: Window title/name * **x, y**: Window position (top-left corner) * **width, height**: Window size * **desktop**: Desktop number (for multi-desktop) * **pid**: Process ID of the window ## Complete Example Complete window management workflow: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="desktop") try: # List all windows windows = sandbox.desktop.get_windows() print(f"Found {len(windows)} windows") # Find specific window target_window = None for window in windows: if "My Application" in window.title: target_window = window break if target_window: # Focus window sandbox.desktop.focus_window(target_window.id) print(f"Focused: {target_window.title}") # Resize window sandbox.desktop.resize_window(target_window.id, 1024, 768) print("Resized to 1024x768") # Minimize sandbox.desktop.minimize_window(target_window.id) print("Minimized") # Close sandbox.desktop.close_window(target_window.id) print("Closed") finally: sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'desktop' }); try { // List all windows const windows = await sandbox.desktop.listWindows(); console.log(`Found ${windows.length} windows`); // Find specific window const targetWindow = windows.find(w => w.title.includes('My Application')); if (targetWindow) { // Focus window await sandbox.desktop.focusWindow(targetWindow.id); console.log(`Focused: ${targetWindow.title}`); // Resize window await sandbox.desktop.resizeWindow(targetWindow.id, 1024, 768); console.log('Resized to 1024x768'); // Minimize await sandbox.desktop.minimizeWindow(targetWindow.id); console.log('Minimized'); // Close await sandbox.desktop.closeWindow(targetWindow.id); console.log('Closed'); } } finally { await sandbox.kill(); } ``` ## Related * [Display Management](/core-concepts/desktop/display-management) - Configure display settings * [VNC Server](/core-concepts/desktop/vnc-server) - Remote desktop access * **SDK**: [sandbox.desktop.get\_windows()](/sdk/python/desktop#get_windows) - Python SDK method ## Next Steps * Learn about [Display Management](/core-concepts/desktop/display-management) to configure display * Explore [VNC Server](/core-concepts/desktop/vnc-server) for remote desktop access * Review [Screenshots](/core-concepts/desktop/screenshots) for visual verification * [Display Management](/core-concepts/desktop/display-management) - Configure display settings * [Screenshots](/core-concepts/desktop/screenshots) - Capture window screenshots * **[CLI System Commands](/cli/commands/system)** - System operations from CLI # X11 Advanced Features Source: https://docs.hopx.ai/core-concepts/desktop/x11-advanced Advanced X11 desktop automation features for sandbox environments in HopX. Access advanced X11 capabilities for complex desktop automation, window management, and GUI interactions. Learn about X11-specific features, advanced automation techniques, and low-level desktop control. Includes Python and JavaScript SDK examples and X11 API endpoints. Advanced X11 desktop automation features including OCR, element finding, and advanced interactions. ## Prerequisites Before you begin, make sure you have: * **VNC server running** - A VNC server must be started (see [VNC Server](/core-concepts/desktop/vnc-server)) * **Desktop template** - A sandbox with desktop support enabled * **Active sandbox** - A running sandbox with desktop capabilities * **Basic desktop automation** - Familiarity with basic desktop operations is helpful ## Overview X11 advanced features enable: * OCR (Optical Character Recognition) text extraction * Finding UI elements by text * Waiting for elements to appear * Advanced drag and drop * Window capture * Hotkey execution Desktop automation requires a template with desktop support. Ensure your sandbox has desktop capabilities enabled. ## OCR (Optical Character Recognition) Extract text from screen regions using OCR: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="desktop") # Extract text from region text = sandbox.desktop.ocr(100, 100, 400, 200) print(f"Extracted text: {text}") # OCR with custom language text = sandbox.desktop.ocr(100, 100, 400, 200, language="eng") print(f"Text: {text}") ``` **Expected Output:** ``` Extracted text: Hello World Text: Hello World ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'desktop' }); // Extract text from region const text = await sandbox.desktop.ocr(100, 100, 400, 200); console.log(`Extracted text: ${text}`); // OCR with custom language const text2 = await sandbox.desktop.ocr(100, 100, 400, 200, { language: 'eng' }); console.log(`Text: ${text2}`); ``` **Expected Output:** ``` Extracted text: Hello World Text: Hello World ``` ## Finding Elements Find UI elements by text: ```python theme={null} # Find element by text element = sandbox.desktop.find_element("Submit") if element: print(f"Found at: ({element['x']}, {element['y']})") print(f"Size: {element['width']}x{element['height']}") # Click the element sandbox.desktop.click(element['x'], element['y']) else: print("Element not found") ``` **Expected Output:** ``` Found at: (150, 200) Size: 100x30 ``` ```javascript theme={null} // Find element by text const element = await sandbox.desktop.findElement('Submit'); if (element) { console.log(`Found at: (${element.x}, ${element.y})`); console.log(`Size: ${element.width}x${element.height}`); // Click the element await sandbox.desktop.mouseClick(element.x, element.y); } else { console.log('Element not found'); } ``` **Expected Output:** ``` Found at: (150, 200) Size: 100x30 ``` ## Waiting for Elements Wait for an element to appear: ```python theme={null} # Wait for element to appear (default: 30 seconds) element = sandbox.desktop.wait_for("Loading complete", timeout=60) print(f"Element found at: ({element['x']}, {element['y']})") # Click when found sandbox.desktop.click(element['x'], element['y']) ``` **Expected Output:** ``` Element found at: (200, 300) ``` ```javascript theme={null} // Wait for element to appear (default: 30 seconds) const element = await sandbox.desktop.waitFor('Loading complete', 60); console.log(`Element found at: (${element.x}, ${element.y})`); // Click when found await sandbox.desktop.mouseClick(element.x, element.y); ``` **Expected Output:** ``` Element found at: (200, 300) ``` ## Getting Element Bounds Get bounding box of an element: ```python theme={null} # Get element bounds bounds = sandbox.desktop.get_bounds("OK Button") print(f"Button at: {bounds['x']}, {bounds['y']}") print(f"Size: {bounds['width']}x{bounds['height']}") # Click center of button center_x = bounds['x'] + bounds['width'] // 2 center_y = bounds['y'] + bounds['height'] // 2 sandbox.desktop.click(center_x, center_y) ``` **Expected Output:** ``` Button at: 300, 400 Size: 80x25 ``` ```javascript theme={null} // Get element bounds const bounds = await sandbox.desktop.getBounds('OK Button'); console.log(`Button at: ${bounds.x}, ${bounds.y}`); console.log(`Size: ${bounds.width}x${bounds.height}`); // Click center of button const centerX = bounds.x + bounds.width / 2; const centerY = bounds.y + bounds.height / 2; await sandbox.desktop.mouseClick(centerX, centerY); ``` **Expected Output:** ``` Button at: 300, 400 Size: 80x25 ``` ## Advanced Drag and Drop Drag and drop operations: ```python theme={null} # Drag and drop sandbox.desktop.drag_drop(100, 200, 500, 300) # Drag file to folder sandbox.desktop.drag_drop(50, 50, 400, 300) ``` **Expected Output:** ``` (Drag and drop operation completed) ``` ```javascript theme={null} // Drag and drop await sandbox.desktop.dragDrop(100, 200, 500, 300); // Drag file to folder await sandbox.desktop.dragDrop(50, 50, 400, 300); ``` **Expected Output:** ``` (Drag and drop operation completed) ``` ## Window Capture Capture specific window: ```python theme={null} # Capture active window img_bytes = sandbox.desktop.capture_window() # Capture specific window windows = sandbox.desktop.get_windows() if windows: window_id = windows[0].id img_bytes = sandbox.desktop.capture_window(window_id) # Save to file with open('window.png', 'wb') as f: f.write(img_bytes) ``` **Expected Output:** ``` (Window captured and saved to window.png) ``` ```javascript theme={null} // Capture active window const windowImg = await sandbox.desktop.captureWindow(); // Capture specific window const windows = await sandbox.desktop.listWindows(); if (windows.length > 0) { const windowId = windows[0].id; const windowImg = await sandbox.desktop.captureWindow(windowId); } // Save to file fs.writeFileSync('window.png', windowImg); ``` **Expected Output:** ``` (Window captured and saved to window.png) ``` ## Hotkeys Execute hotkey combinations: ```python theme={null} # Copy: Ctrl+C sandbox.desktop.hotkey(['ctrl'], 'c') # Paste: Ctrl+V sandbox.desktop.hotkey(['ctrl'], 'v') # Switch window: Alt+Tab sandbox.desktop.hotkey(['alt'], 'tab') # Screenshot: Ctrl+Shift+P sandbox.desktop.hotkey(['ctrl', 'shift'], 'p') ``` **Expected Output:** ``` (Hotkey combinations executed) ``` ```javascript theme={null} // Note: JavaScript SDK may use keyboardCombination // Copy: Ctrl+C await sandbox.desktop.keyboardCombination(['ctrl', 'c']); // Paste: Ctrl+V await sandbox.desktop.keyboardCombination(['ctrl', 'v']); ``` **Expected Output:** ``` (Hotkey combinations executed) ``` ## Complete Example Complete workflow using advanced features: ```python theme={null} from hopx_ai import Sandbox import time sandbox = Sandbox.create(template="desktop") try: # Wait for application to load element = sandbox.desktop.wait_for("Application Ready", timeout=30) print("Application loaded") # Find and click button button = sandbox.desktop.find_element("Start") if button: sandbox.desktop.click(button['x'], button['y']) # Wait for dialog dialog = sandbox.desktop.wait_for("Confirm", timeout=10) # Extract text from dialog using OCR dialog_text = sandbox.desktop.ocr( dialog['x'], dialog['y'], dialog['width'], dialog['height'] ) print(f"Dialog text: {dialog_text}") # Find OK button ok_bounds = sandbox.desktop.get_bounds("OK") center_x = ok_bounds['x'] + ok_bounds['width'] // 2 center_y = ok_bounds['y'] + ok_bounds['height'] // 2 sandbox.desktop.click(center_x, center_y) finally: sandbox.kill() ``` **Expected Output:** ``` Application loaded Dialog text: Please confirm this action ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'desktop' }); try { // Wait for application to load const element = await sandbox.desktop.waitFor('Application Ready', 30); console.log('Application loaded'); // Find and click button const button = await sandbox.desktop.findElement('Start'); if (button) { await sandbox.desktop.mouseClick(button.x, button.y); } // Wait for dialog const dialog = await sandbox.desktop.waitFor('Confirm', 10); // Extract text from dialog using OCR const dialogText = await sandbox.desktop.ocr( dialog.x, dialog.y, dialog.width, dialog.height ); console.log(`Dialog text: ${dialogText}`); // Find OK button const okBounds = await sandbox.desktop.getBounds('OK'); const centerX = okBounds.x + okBounds.width / 2; const centerY = okBounds.y + okBounds.height / 2; await sandbox.desktop.mouseClick(centerX, centerY); } finally { await sandbox.kill(); } ``` **Expected Output:** ``` Application loaded Dialog text: Please confirm this action ``` ## OCR Languages Supported OCR languages: * **eng**: English (default) * **spa**: Spanish * **fra**: French * **deu**: German * And more (check Tesseract language support) ## Related * [Screenshots](/core-concepts/desktop/screenshots) - Basic screenshot capture * [Mouse Control](/core-concepts/desktop/mouse-control) - Mouse operations * [Keyboard Control](/core-concepts/desktop/keyboard-control) - Keyboard operations * **SDK**: [sandbox.desktop.ocr()](/sdk/python/desktop#ocr) - Python SDK method ## Next Steps * Learn about [Screenshots](/core-concepts/desktop/screenshots) for basic image capture * Explore [Mouse Control](/core-concepts/desktop/mouse-control) and [Keyboard Control](/core-concepts/desktop/keyboard-control) for interactions * Review [VNC Server](/core-concepts/desktop/vnc-server) for remote desktop access * [Mouse Control](/core-concepts/desktop/mouse-control) - Basic mouse operations * [Keyboard Control](/core-concepts/desktop/keyboard-control) - Basic keyboard operations * [Screenshots](/core-concepts/desktop/screenshots) - Screenshot capture * **[CLI System Commands](/cli/commands/system)** - System operations from CLI # Clearing Source: https://docs.hopx.ai/core-concepts/environment/clearing Remove environment variables from sandboxes. Clear all environment variables to reset configuration, remove sensitive data, or start with a clean environment. Learn how to clear variables using Python and JavaScript SDKs or REST API. Includes examples for cleanup and security best practices. Remove environment variables from your sandbox. You can delete individual variables or clear all custom variables at once. ## Overview Clearing environment variables is useful for: * Removing sensitive data * Resetting configuration * Cleaning up temporary variables * Preparing sandbox for reuse Deleting individual variables preserves other variables. System variables (like `PATH`, `HOME`) are typically preserved and cannot be deleted. ## Delete Single Variable Delete a specific environment variable: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Set some variables sandbox.env.set_all({ "API_KEY": "sk-123", "DEBUG": "true", "TEMP_TOKEN": "temp-xyz" }) # Delete a single variable sandbox.env.delete("TEMP_TOKEN") print("TEMP_TOKEN deleted") # Verify deletion env = sandbox.env.get_all() print(f"TEMP_TOKEN exists: {'TEMP_TOKEN' in env}") print(f"API_KEY still exists: {'API_KEY' in env}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Set some variables await sandbox.env.setAll({ API_KEY: 'sk-123', DEBUG: 'true', TEMP_TOKEN: 'temp-xyz' }); // Delete a single variable await sandbox.env.delete('TEMP_TOKEN'); console.log('TEMP_TOKEN deleted'); // Verify deletion const env = await sandbox.env.getAll(); console.log(`TEMP_TOKEN exists: ${'TEMP_TOKEN' in env}`); console.log(`API_KEY still exists: ${'API_KEY' in env}`); await sandbox.kill(); ``` ## Delete Multiple Variables Delete multiple variables one by one: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Set multiple variables sandbox.env.set_all({ "API_KEY": "sk-123", "DATABASE_URL": "postgres://localhost/db", "DEBUG": "true", "TEMP_TOKEN": "temp-xyz", "OLD_CONFIG": "deprecated" }) # Delete multiple variables variables_to_delete = ["TEMP_TOKEN", "OLD_CONFIG", "DEBUG"] for var in variables_to_delete: sandbox.env.delete(var) print(f"Deleted: {var}") # Verify remaining variables env = sandbox.env.get_all() print(f"\nRemaining variables: {list(env.keys())}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Set multiple variables await sandbox.env.setAll({ API_KEY: 'sk-123', DATABASE_URL: 'postgres://localhost/db', DEBUG: 'true', TEMP_TOKEN: 'temp-xyz', OLD_CONFIG: 'deprecated' }); // Delete multiple variables const variablesToDelete = ['TEMP_TOKEN', 'OLD_CONFIG', 'DEBUG']; for (const varName of variablesToDelete) { await sandbox.env.delete(varName); console.log(`Deleted: ${varName}`); } // Verify remaining variables const env = await sandbox.env.getAll(); console.log(`\nRemaining variables: ${Object.keys(env)}`); await sandbox.kill(); ``` ## Clear All Custom Variables Clear all custom environment variables: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Set custom variables sandbox.env.set_all({ "API_KEY": "sk-123", "DATABASE_URL": "postgres://localhost/db", "DEBUG": "true" }) # Get current variables before = sandbox.env.get_all() print(f"Variables before: {len(before)}") # Clear all custom variables (set empty dict) sandbox.env.set_all({}) # Get variables after clearing after = sandbox.env.get_all() print(f"Variables after: {len(after)}") # System variables may still exist system_vars = ['PATH', 'HOME', 'USER', 'SHELL'] remaining = [v for v in after.keys() if v in system_vars] print(f"System variables preserved: {remaining}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Set custom variables await sandbox.env.setAll({ API_KEY: 'sk-123', DATABASE_URL: 'postgres://localhost/db', DEBUG: 'true' }); // Get current variables const before = await sandbox.env.getAll(); console.log(`Variables before: ${Object.keys(before).length}`); // Clear all custom variables (set empty dict) await sandbox.env.setAll({}); // Get variables after clearing const after = await sandbox.env.getAll(); console.log(`Variables after: ${Object.keys(after).length}`); // System variables may still exist const systemVars = ['PATH', 'HOME', 'USER', 'SHELL']; const remaining = Object.keys(after).filter(v => systemVars.includes(v)); console.log(`System variables preserved: ${remaining}`); await sandbox.kill(); ``` ## Clean Up Temporary Variables Remove temporary or sensitive variables: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Set up environment with temporary variables sandbox.env.set_all({ "API_KEY": "sk-prod-xyz", "DATABASE_URL": "postgres://localhost/db", "TEMP_TOKEN": "temp-abc123", "SESSION_ID": "session-xyz", "DEBUG": "true" }) # Clean up temporary variables temp_vars = ["TEMP_TOKEN", "SESSION_ID"] for var in temp_vars: sandbox.env.delete(var) print(f"Cleaned up: {var}") # Verify cleanup env = sandbox.env.get_all() print(f"\nRemaining variables: {list(env.keys())}") # Production variables should still exist print(f"API_KEY exists: {'API_KEY' in env}") print(f"DATABASE_URL exists: {'DATABASE_URL' in env}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Set up environment with temporary variables await sandbox.env.setAll({ API_KEY: 'sk-prod-xyz', DATABASE_URL: 'postgres://localhost/db', TEMP_TOKEN: 'temp-abc123', SESSION_ID: 'session-xyz', DEBUG: 'true' }); // Clean up temporary variables const tempVars = ['TEMP_TOKEN', 'SESSION_ID']; for (const varName of tempVars) { await sandbox.env.delete(varName); console.log(`Cleaned up: ${varName}`); } // Verify cleanup const env = await sandbox.env.getAll(); console.log(`\nRemaining variables: ${Object.keys(env)}`); // Production variables should still exist console.log(`API_KEY exists: ${'API_KEY' in env}`); console.log(`DATABASE_URL exists: ${'DATABASE_URL' in env}`); await sandbox.kill(); ``` ## Complete Example Here's a complete example showing environment variable cleanup: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Set up complete environment print("🔧 Setting up environment...") sandbox.env.set_all({ "API_KEY": "sk-prod-xyz", "DATABASE_URL": "postgres://localhost/prod", "REDIS_URL": "redis://localhost:6379", "TEMP_TOKEN": "temp-abc123", "SESSION_ID": "session-xyz", "DEBUG": "true", "LOG_LEVEL": "info" }) env = sandbox.env.get_all() print(f"✅ Environment set up with {len(env)} variables\n") # Use environment in code print("💻 Using environment in code...") result = sandbox.run_code(''' import os print(f"API key: {os.getenv('API_KEY', 'not set')[:10]}...") print(f"Database: {os.getenv('DATABASE_URL', 'not set')}") print(f"Temp Token: {os.getenv('TEMP_TOKEN', 'not set')}") ''') print(result.stdout) # Clean up temporary variables print("\n🧹 Cleaning up temporary variables...") temp_vars = ["TEMP_TOKEN", "SESSION_ID"] for var in temp_vars: sandbox.env.delete(var) print(f" ✅ Deleted: {var}") # Verify cleanup print("\n📋 Final environment:") final_env = sandbox.env.get_all() for key in sorted(final_env.keys()): if key not in ['PATH', 'HOME', 'USER', 'SHELL', 'PWD']: if any(sensitive in key.upper() for sensitive in ['KEY', 'SECRET', 'PASSWORD']): print(f" {key}=***MASKED***") else: print(f" {key}={final_env[key]}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Set up complete environment console.log('🔧 Setting up environment...'); await sandbox.env.setAll({ API_KEY: 'sk-prod-xyz', DATABASE_URL: 'postgres://localhost/prod', REDIS_URL: 'redis://localhost:6379', TEMP_TOKEN: 'temp-abc123', SESSION_ID: 'session-xyz', DEBUG: 'true', LOG_LEVEL: 'info' }); const env = await sandbox.env.getAll(); console.log(`✅ Environment set up with ${Object.keys(env).length} variables\n`); // Use environment in code console.log('💻 Using environment in code...'); const result = await sandbox.runCode(` import os print(f"API key: {os.getenv('API_KEY', 'not set')[:10]}...") print(f"Database: {os.getenv('DATABASE_URL', 'not set')}") print(f"Temp Token: {os.getenv('TEMP_TOKEN', 'not set')}") `); console.log(result.stdout); // Clean up temporary variables console.log('\n🧹 Cleaning up temporary variables...'); const tempVars = ['TEMP_TOKEN', 'SESSION_ID']; for (const varName of tempVars) { await sandbox.env.delete(varName); console.log(` ✅ Deleted: ${varName}`); } // Verify cleanup console.log('\n📋 Final environment:'); const finalEnv = await sandbox.env.getAll(); for (const key of Object.keys(finalEnv).sort()) { if (!['PATH', 'HOME', 'USER', 'SHELL', 'PWD'].includes(key)) { const isSensitive = ['KEY', 'SECRET', 'PASSWORD'].some( s => key.toUpperCase().includes(s) ); if (isSensitive) { console.log(` ${key}=***MASKED***`); } else { console.log(` ${key}=${finalEnv[key]}`); } } } await sandbox.kill(); ``` ## Best Practices Use `delete(key)` to remove specific variables while preserving others. Regularly delete temporary variables (tokens, session IDs) to reduce security risk. Clear all custom variables before reusing a sandbox for a different purpose. Always verify variables are deleted using `get_all()` or `get()` after deletion. System variables (PATH, HOME, etc.) are typically preserved and cannot be deleted. ## Related * **[Getting Environment Variables](/core-concepts/environment/getting)** - Retrieve environment variables * **[Setting Environment Variables](/core-concepts/environment/setting)** - Set or replace variables * **[Updating Environment Variables](/core-concepts/environment/updating)** - Update variables without replacing * **SDK**: [sandbox.env.clear()](/sdk/python/environment-variables#clear) - Python SDK method * **API**: [DELETE /env](/api/vm-agent/clear-env) - VM Agent API endpoint * [CLI Environment Variables](/cli/commands/env) - Environment variables from CLI ## Next Steps * Learn about [Getting Environment Variables](/core-concepts/environment/getting) to retrieve variables * Explore [Setting Environment Variables](/core-concepts/environment/setting) to configure your sandbox * Review [Updating Environment Variables](/core-concepts/environment/updating) to modify existing variables # Getting Source: https://docs.hopx.ai/core-concepts/environment/getting Retrieve environment variables from sandboxes. Learn how to get single or all environment variables from HopX sandboxes using Python and JavaScript SDKs or REST API. Includes examples for reading variables, handling missing variables, and processing environment data. Essential for configuring code execution environments. Retrieve environment variables from your sandbox. You can get all variables at once or fetch specific variables by name. ## Overview Getting environment variables is useful for: * Inspecting current environment configuration * Verifying variables are set correctly * Accessing system and custom variables * Debugging environment-related issues Environment variables include both system variables (like `PATH`, `HOME`) and custom variables you've set. Sensitive values may be masked in responses. ## Get All Environment Variables Retrieve all environment variables: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Get all environment variables env = sandbox.env.get_all() print(f"Total variables: {len(env)}") # Access specific variables print(f"PATH: {env.get('PATH', 'not set')}") print(f"HOME: {env.get('HOME', 'not set')}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Get all environment variables const env = await sandbox.env.getAll(); console.log(`Total variables: ${Object.keys(env).length}`); // Access specific variables console.log(`PATH: ${env.PATH || 'not set'}`); console.log(`HOME: ${env.HOME || 'not set'}`); await sandbox.kill(); ``` ## Get Specific Variable Get a single environment variable: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Get a specific variable api_key = sandbox.env.get("API_KEY") if api_key: print(f"API key: {api_key[:10]}...") else: print("API_KEY not set") # Get with default value db_url = sandbox.env.get("DATABASE_URL", "postgres://localhost/db") print(f"Database URL: {db_url}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Get a specific variable const apiKey = await sandbox.env.get('API_KEY'); if (apiKey) { console.log(`API key: ${apiKey.substring(0, 10)}...`); } else { console.log('API_KEY not set'); } // Get with default value const dbUrl = await sandbox.env.get('DATABASE_URL', 'postgres://localhost/db'); console.log(`Database URL: ${dbUrl}`); await sandbox.kill(); ``` ## List All Variables Iterate through all environment variables: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Get all variables env = sandbox.env.get_all() # List all variables print("Environment Variables:") for key, value in sorted(env.items()): # Mask sensitive values if any(sensitive in key.upper() for sensitive in ['KEY', 'SECRET', 'PASSWORD', 'TOKEN']): print(f" {key}=***MASKED***") else: print(f" {key}={value}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Get all variables const env = await sandbox.env.getAll(); // List all variables console.log('Environment Variables:'); for (const [key, value] of Object.entries(env).sort()) { // Mask sensitive values const isSensitive = ['KEY', 'SECRET', 'PASSWORD', 'TOKEN'].some( s => key.toUpperCase().includes(s) ); if (isSensitive) { console.log(` ${key}=***MASKED***`); } else { console.log(` ${key}=${value}`); } } await sandbox.kill(); ``` ## Filter Variables Filter environment variables by prefix or pattern: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Get all variables env = sandbox.env.get_all() # Filter by prefix api_vars = {k: v for k, v in env.items() if k.startswith('API_')} print(f"API variables: {list(api_vars.keys())}") # Filter by pattern debug_vars = {k: v for k, v in env.items() if 'DEBUG' in k.upper()} print(f"Debug variables: {list(debug_vars.keys())}") # Filter custom variables (exclude system vars) system_vars = {'PATH', 'HOME', 'USER', 'SHELL', 'PWD'} custom_vars = {k: v for k, v in env.items() if k not in system_vars} print(f"Custom variables: {list(custom_vars.keys())}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Get all variables const env = await sandbox.env.getAll(); // Filter by prefix const apiVars = Object.fromEntries( Object.entries(env).filter(([k]) => k.startsWith('API_')) ); console.log(`API variables: ${Object.keys(apiVars)}`); // Filter by pattern const debugVars = Object.fromEntries( Object.entries(env).filter(([k]) => k.toUpperCase().includes('DEBUG')) ); console.log(`Debug variables: ${Object.keys(debugVars)}`); // Filter custom variables (exclude system vars) const systemVars = new Set(['PATH', 'HOME', 'USER', 'SHELL', 'PWD']); const customVars = Object.fromEntries( Object.entries(env).filter(([k]) => !systemVars.has(k)) ); console.log(`Custom variables: ${Object.keys(customVars)}`); await sandbox.kill(); ``` ## Check Variable Existence Check if a variable exists: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Check if variable exists api_key = sandbox.env.get("API_KEY") if api_key: print("API_KEY is set") else: print("API_KEY is not set") # Check multiple variables required_vars = ["API_KEY", "DATABASE_URL", "NODE_ENV"] env = sandbox.env.get_all() missing = [var for var in required_vars if var not in env] if missing: print(f"Missing variables: {missing}") else: print("All required variables are set") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Check if variable exists const apiKey = await sandbox.env.get('API_KEY'); if (apiKey) { console.log('API_KEY is set'); } else { console.log('API_KEY is not set'); } // Check multiple variables const requiredVars = ['API_KEY', 'DATABASE_URL', 'NODE_ENV']; const env = await sandbox.env.getAll(); const missing = requiredVars.filter(v => !(v in env)); if (missing.length > 0) { console.log(`Missing variables: ${missing}`); } else { console.log('All required variables are set'); } await sandbox.kill(); ``` ## Verify Variables in Code Verify environment variables are accessible in code execution: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Set some variables sandbox.env.set("API_KEY", "sk-123") sandbox.env.set("DEBUG", "true") # Verify they're accessible in code result = sandbox.run_code(''' import os print(f"API_KEY: {os.getenv('API_KEY')}") print(f"DEBUG: {os.getenv('DEBUG')}") ''') print(result.stdout) # Get variables via env API env = sandbox.env.get_all() print(f"\nVia API - API_KEY: {env.get('API_KEY')}") print(f"Via API - DEBUG: {env.get('DEBUG')}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Set some variables await sandbox.env.set('API_KEY', 'sk-123'); await sandbox.env.set('DEBUG', 'true'); // Verify they're accessible in code const result = await sandbox.runCode(` import os print(f"API_KEY: {os.getenv('API_KEY')}") print(f"DEBUG: {os.getenv('DEBUG')}") `); console.log(result.stdout); // Get variables via env API const env = await sandbox.env.getAll(); console.log(`\nVia API - API_KEY: ${env.API_KEY}`); console.log(`Via API - DEBUG: ${env.DEBUG}`); await sandbox.kill(); ``` ## Complete Example Here's a complete example showing environment variable retrieval: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Set up environment sandbox.env.set_all({ "API_KEY": "sk-prod-xyz", "DATABASE_URL": "postgres://localhost/db", "NODE_ENV": "production", "DEBUG": "false" }) # Get all variables print("📋 All Environment Variables:") env = sandbox.env.get_all() for key, value in sorted(env.items()): if any(sensitive in key.upper() for sensitive in ['KEY', 'SECRET', 'PASSWORD']): print(f" {key}=***MASKED***") else: print(f" {key}={value}") # Get specific variables print("\n🔍 Specific Variables:") api_key = sandbox.env.get("API_KEY") print(f" API_KEY: {'Set' if api_key else 'Not set'}") db_url = sandbox.env.get("DATABASE_URL") print(f" DATABASE_URL: {db_url}") node_env = sandbox.env.get("NODE_ENV", "development") print(f" NODE_ENV: {node_env}") # Verify in code execution print("\n✅ Verification in Code:") result = sandbox.run_code(''' import os print(f"API_KEY: {os.getenv('API_KEY', 'not set')[:10]}...") print(f"DATABASE_URL: {os.getenv('DATABASE_URL', 'not set')}") print(f"NODE_ENV: {os.getenv('NODE_ENV', 'not set')}") ''') print(result.stdout) sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Set up environment await sandbox.env.setAll({ API_KEY: 'sk-prod-xyz', DATABASE_URL: 'postgres://localhost/db', NODE_ENV: 'production', DEBUG: 'false' }); // Get all variables console.log('📋 All Environment Variables:'); const env = await sandbox.env.getAll(); for (const [key, value] of Object.entries(env).sort()) { const isSensitive = ['KEY', 'SECRET', 'PASSWORD'].some( s => key.toUpperCase().includes(s) ); if (isSensitive) { console.log(` ${key}=***MASKED***`); } else { console.log(` ${key}=${value}`); } } // Get specific variables console.log('\n🔍 Specific Variables:'); const apiKey = await sandbox.env.get('API_KEY'); console.log(` API_KEY: ${apiKey ? 'Set' : 'Not set'}`); const dbUrl = await sandbox.env.get('DATABASE_URL'); console.log(` DATABASE_URL: ${dbUrl}`); const nodeEnv = await sandbox.env.get('NODE_ENV', 'development'); console.log(` NODE_ENV: ${nodeEnv}`); // Verify in code execution console.log('\n✅ Verification in Code:'); const result = await sandbox.runCode(` import os print(f"API_KEY: {os.getenv('API_KEY', 'not set')[:10]}...") print(f"DATABASE_URL: {os.getenv('DATABASE_URL', 'not set')}") print(f"NODE_ENV: {os.getenv('NODE_ENV', 'not set')}") `); console.log(result.stdout); await sandbox.kill(); ``` ## Best Practices Use `env.get(key)` for retrieving individual variables with optional defaults. Use `env.get_all()` when you need to access multiple variables or iterate through all. Always check if variables exist or provide defaults when retrieving. When displaying environment variables, mask sensitive values (keys, secrets, passwords, tokens). Test that environment variables are accessible in code execution to ensure they're set correctly. ## Related * **[Setting Environment Variables](/core-concepts/environment/setting)** - Set environment variables * **[Updating Environment Variables](/core-concepts/environment/updating)** - Update variables * **SDK**: [sandbox.env.get()](/sdk/python/environment-variables#get) - Python SDK method * **API**: [GET /env](/api/vm-agent/get-env) - VM Agent API endpoint * [CLI Environment Variables](/cli/commands/env) - Environment variables from CLI ## Next Steps * Learn about [Setting Environment Variables](/core-concepts/environment/setting) to configure your sandbox * Explore [Updating Environment Variables](/core-concepts/environment/updating) to modify existing variables * Review [Clearing Environment Variables](/core-concepts/environment/clearing) to remove variables # Environment Variables Source: https://docs.hopx.ai/core-concepts/environment/index Complete guide to managing environment variables in HopX sandboxes - getting, setting, updating, and clearing environment variables. Learn how to configure execution environments, set variables for code execution, manage variables across sandbox sessions, and use environment variables in Python and JavaScript SDKs or REST API. Manage environment variables in HopX sandboxes to configure execution environments. This hub covers all environment variable operations, from basic get/set to advanced bulk updates. ## Related * [CLI Environment Variables](/cli/commands/env) - Environment variables from CLI ## What You'll Learn * How to get and set environment variables * How to update existing variables * How to clear all environment variables * How to use environment variables in code execution * How to manage variables across sandbox sessions ## Environment Variables Overview | Operation | SDK Method | API Endpoint | | --------------------------------------------------- | ------------------------------------- | ------------- | | **[Getting](/core-concepts/environment/getting)** | `sandbox.env.get()` / `env.get_all()` | `GET /env` | | **[Setting](/core-concepts/environment/setting)** | `sandbox.env.set()` / `env.set_all()` | `PUT /env` | | **[Updating](/core-concepts/environment/updating)** | `sandbox.env.update()` | `PATCH /env` | | **[Clearing](/core-concepts/environment/clearing)** | `sandbox.env.clear()` | `DELETE /env` | ## Core Concepts ### Getting Environment Variables Retrieve environment variables from sandboxes. * **[Getting Environment Variables](/core-concepts/environment/getting)** - Get environment variables * **SDK**: [Python: sandbox.env.get()](/sdk/python/environment-variables#get) | [Python: sandbox.env.get\_all()](/sdk/python/environment-variables#get_all) | [JavaScript: sandbox.env.get()](/sdk/javascript/environment-variables#get) | [JavaScript: sandbox.env.getAll()](/sdk/javascript/environment-variables#getall) * **API**: [GET /env](/api/vm-agent/get-env) ### Setting Environment Variables Set environment variables in sandboxes. * **[Setting Environment Variables](/core-concepts/environment/setting)** - Set environment variables * **SDK**: [Python: sandbox.env.set()](/sdk/python/environment-variables#set) | [Python: sandbox.env.set\_all()](/sdk/python/environment-variables#set_all) | [JavaScript: sandbox.env.set()](/sdk/javascript/environment-variables#set) | [JavaScript: sandbox.env.setAll()](/sdk/javascript/environment-variables#setall) * **API**: [PUT /env](/api/vm-agent/set-env) | [POST /env](/api/vm-agent/set-env) ### Updating Environment Variables Update existing environment variables without clearing others. * **[Updating Environment Variables](/core-concepts/environment/updating)** - Update environment variables * **SDK**: [Python: sandbox.env.update()](/sdk/python/environment-variables#update) | [JavaScript: sandbox.env.update()](/sdk/javascript/environment-variables#update) * **API**: [PATCH /env](/api/vm-agent/update-env) ### Clearing Environment Variables Remove all environment variables from sandboxes. * **[Clearing Environment Variables](/core-concepts/environment/clearing)** - Clear all environment variables * **SDK**: [Python: sandbox.env.clear()](/sdk/python/environment-variables#clear) | [JavaScript: sandbox.env.clear()](/sdk/javascript/environment-variables#clear) * **API**: [DELETE /env](/api/vm-agent/clear-env) ## SDK Reference ### Python SDK Complete reference for Python environment variable operations. * **[Environment Variables Module](/sdk/python/environment-variables)** - Complete environment API * `env.get()` - Get single variable * `env.get_all()` - Get all variables * `env.set()` - Set single variable * `env.set_all()` - Set all variables * `env.update()` - Update variables * `env.clear()` - Clear all variables ### JavaScript SDK Complete reference for JavaScript/TypeScript environment variable operations. * **[Environment Variables Module](/sdk/javascript/environment-variables)** - Complete environment API * `env.get()` - Get single variable * `env.getAll()` - Get all variables * `env.set()` - Set single variable * `env.setAll()` - Set all variables * `env.update()` - Update variables * `env.clear()` - Clear all variables ## API Reference ### VM Agent API REST API endpoints for environment variable operations. * **[VM Agent API Overview](/api/vm-agent/overview)** - API overview * **[Get Environment Variables](/api/vm-agent/get-env)** - `GET /env` - Get all variables * **[Set Environment Variables](/api/vm-agent/set-env)** - `PUT /env` - Set all variables * **[Update Environment Variables](/api/vm-agent/update-env)** - `PATCH /env` - Update variables * **[Clear Environment Variables](/api/vm-agent/clear-env)** - `DELETE /env` - Clear all variables ## Quick Start If you're new to environment variables, start here: 1. **[Getting Environment Variables](/core-concepts/environment/getting)** - Read environment variables 2. **[Setting Environment Variables](/core-concepts/environment/setting)** - Set your first variable 3. **[Updating Environment Variables](/core-concepts/environment/updating)** - Update existing variables ## Related Topics * **[Code Execution](/core-concepts/code-execution/synchronous)** - Use environment variables in code * **[Sandboxes](/core-concepts/sandboxes/creating)** - Set variables when creating sandboxes * **[File Operations](/core-concepts/filesystem/reading)** - Configure file paths with variables * **[Commands](/core-concepts/commands/running)** - Use variables in shell commands ## Next Steps * Learn about [Code Execution](/core-concepts/code-execution/synchronous) to use variables in code * Explore [Setting Environment Variables](/core-concepts/environment/setting) for configuration * Review [Updating Environment Variables](/core-concepts/environment/updating) for incremental changes * Check out [Sandboxes](/core-concepts/sandboxes/creating) for initial configuration # Setting Source: https://docs.hopx.ai/core-concepts/environment/setting Set and replace environment variables in sandboxes. Configure execution environments by setting environment variables for code execution, API keys, database connections, and other configuration values. Learn how to set single or multiple variables using Python and JavaScript SDKs or REST API. Includes examples for common use cases. Set environment variables in your sandbox. You can set individual variables or replace all variables at once. ## Overview Setting environment variables is essential for: * Configuring application settings * Providing API keys and secrets * Setting up database connections * Configuring runtime behavior `set_all()` replaces ALL existing environment variables. Use [Updating Environment Variables](/core-concepts/environment/updating) if you want to merge with existing variables instead. ## Set Single Variable Set a single environment variable: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Set a single variable sandbox.env.set("API_KEY", "sk-prod-xyz") print("API_KEY set") # Verify it's set api_key = sandbox.env.get("API_KEY") print(f"API_KEY value: {api_key}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Set a single variable await sandbox.env.set('API_KEY', 'sk-prod-xyz'); console.log('API_KEY set'); // Verify it's set const apiKey = await sandbox.env.get('API_KEY'); console.log(`API_KEY value: ${apiKey}`); await sandbox.kill(); ``` ## Set Multiple Variables Set multiple environment variables at once: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Set multiple variables (replaces all existing) sandbox.env.set_all({ "API_KEY": "sk-prod-xyz", "DATABASE_URL": "postgres://localhost/db", "NODE_ENV": "production", "DEBUG": "false" }) # Verify all are set env = sandbox.env.get_all() print(f"Set {len(env)} variables") for key in ["API_KEY", "DATABASE_URL", "NODE_ENV", "DEBUG"]: print(f" {key}: {env.get(key, 'not set')}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Set multiple variables (replaces all existing) await sandbox.env.setAll({ API_KEY: 'sk-prod-xyz', DATABASE_URL: 'postgres://localhost/db', NODE_ENV: 'production', DEBUG: 'false' }); // Verify all are set const env = await sandbox.env.getAll(); console.log(`Set ${Object.keys(env).length} variables`); for (const key of ['API_KEY', 'DATABASE_URL', 'NODE_ENV', 'DEBUG']) { console.log(` ${key}: ${env[key] || 'not set'}`); } await sandbox.kill(); ``` ## Replace All Variables Replace all environment variables (removes existing ones): ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Get current variables current_env = sandbox.env.get_all() print(f"Current variables: {len(current_env)}") # Replace all with new set sandbox.env.set_all({ "API_KEY": "sk-new-key", "DATABASE_URL": "postgres://new-host/db" }) # Verify replacement new_env = sandbox.env.get_all() print(f"New variables: {len(new_env)}") print(f"Variables: {list(new_env.keys())}") # Note: System variables like PATH may still exist sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Get current variables const currentEnv = await sandbox.env.getAll(); console.log(`Current variables: ${Object.keys(currentEnv).length}`); // Replace all with new set await sandbox.env.setAll({ API_KEY: 'sk-new-key', DATABASE_URL: 'postgres://new-host/db' }); // Verify replacement const newEnv = await sandbox.env.getAll(); console.log(`New variables: ${Object.keys(newEnv).length}`); console.log(`Variables: ${Object.keys(newEnv)}`); // Note: System variables like PATH may still exist await sandbox.kill(); ``` ## Use in Code Execution Set variables and use them in code: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Set environment variables sandbox.env.set_all({ "API_KEY": "sk-123", "DATABASE_URL": "postgres://localhost/mydb", "DEBUG": "true" }) # Use in code execution result = sandbox.run_code(''' import os print(f"API key: {os.getenv('API_KEY')}") print(f"Database: {os.getenv('DATABASE_URL')}") print(f"Debug mode: {os.getenv('DEBUG')}") ''') print(result.stdout) sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Set environment variables await sandbox.env.setAll({ API_KEY: 'sk-123', DATABASE_URL: 'postgres://localhost/mydb', DEBUG: 'true' }); // Use in code execution const result = await sandbox.runCode(` import os print(f"API key: {os.getenv('API_KEY')}") print(f"Database: {os.getenv('DATABASE_URL')}") print(f"Debug mode: {os.getenv('DEBUG')}") `); console.log(result.stdout); await sandbox.kill(); ``` ## Use in Commands Set variables and use them in shell commands: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Set environment variables sandbox.env.set_all({ "API_KEY": "sk-123", "NODE_ENV": "production" }) # Use in commands result = sandbox.commands.run('echo $API_KEY') print(f"Command output: {result.stdout}") result = sandbox.commands.run('echo $NODE_ENV') print(f"Command output: {result.stdout}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Set environment variables await sandbox.env.setAll({ API_KEY: 'sk-123', NODE_ENV: 'production' }); // Use in commands let result = await sandbox.commands.run('echo $API_KEY'); console.log(`Command output: ${result.stdout}`); result = await sandbox.commands.run('echo $NODE_ENV'); console.log(`Command output: ${result.stdout}`); await sandbox.kill(); ``` ## Complete Example Here's a complete example showing environment variable setup: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Configure application environment print("🔧 Setting up environment...") sandbox.env.set_all({ "API_KEY": "sk-prod-xyz123", "DATABASE_URL": "postgres://localhost/production", "REDIS_URL": "redis://localhost:6379", "NODE_ENV": "production", "DEBUG": "false", "LOG_LEVEL": "info" }) # Verify setup env = sandbox.env.get_all() print(f"\n✅ Environment configured with {len(env)} variables") # Use in application code print("\n💻 Testing in code execution...") result = sandbox.run_code(''' import os config = { "api_key": os.getenv("API_KEY", "not set"), "database": os.getenv("DATABASE_URL", "not set"), "redis": os.getenv("REDIS_URL", "not set"), "node_env": os.getenv("NODE_ENV", "development"), "debug": os.getenv("DEBUG", "false"), "log_level": os.getenv("LOG_LEVEL", "debug") } for key, value in config.items(): if 'key' in key.lower(): print(f"{key}: {value[:10]}...") else: print(f"{key}: {value}") ''') print(result.stdout) sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Configure application environment console.log('🔧 Setting up environment...'); await sandbox.env.setAll({ API_KEY: 'sk-prod-xyz123', DATABASE_URL: 'postgres://localhost/production', REDIS_URL: 'redis://localhost:6379', NODE_ENV: 'production', DEBUG: 'false', LOG_LEVEL: 'info' }); // Verify setup const env = await sandbox.env.getAll(); console.log(`\n✅ Environment configured with ${Object.keys(env).length} variables`); // Use in application code console.log('\n💻 Testing in code execution...'); const result = await sandbox.runCode(` import os config = { "api_key": os.getenv("API_KEY", "not set"), "database": os.getenv("DATABASE_URL", "not set"), "redis": os.getenv("REDIS_URL", "not set"), "node_env": os.getenv("NODE_ENV", "development"), "debug": os.getenv("DEBUG", "false"), "log_level": os.getenv("LOG_LEVEL", "debug") } for key, value in config.items(): if 'key' in key.lower(): print(f"{key}: {value[:10]}...") else: print(f"{key}: {value}") `); console.log(result.stdout); await sandbox.kill(); ``` ## Best Practices Use `env.set(key, value)` for setting individual variables. This merges with existing variables. `set_all()` replaces ALL variables. Only use when you want to completely replace the environment. For setting multiple variables while preserving existing ones, use [Updating Environment Variables](/core-concepts/environment/updating) instead. Set environment variables before running code or commands that need them. Always verify variables are set correctly using `get()` or `get_all()` after setting. ## Related * **[Getting Environment Variables](/core-concepts/environment/getting)** - Retrieve environment variables * **[Updating Environment Variables](/core-concepts/environment/updating)** - Update variables without replacing * **SDK**: [sandbox.env.set()](/sdk/python/environment-variables#set) - Python SDK method * **API**: [PUT /env](/api/vm-agent/set-env) - VM Agent API endpoint * [CLI Environment Variables](/cli/commands/env) - Environment variables from CLI ## Next Steps * Learn about [Getting Environment Variables](/core-concepts/environment/getting) to retrieve variables * Explore [Updating Environment Variables](/core-concepts/environment/updating) to merge with existing variables * Review [Clearing Environment Variables](/core-concepts/environment/clearing) to remove variables # Updating Source: https://docs.hopx.ai/core-concepts/environment/updating Update and merge environment variables without replacing existing ones in HopX sandboxes. Incrementally update environment configuration, add new variables, or modify existing ones without clearing the entire environment. Essential for dynamic configuration management. Includes Python and JavaScript SDK examples and REST API endpoints. Update environment variables by merging new values with existing ones. This preserves existing variables while adding or updating specific ones. ## Overview Updating environment variables is ideal for: * Adding new variables without removing existing ones * Updating specific variables while preserving others * Incrementally building environment configuration * Modifying configuration without full replacement `update()` merges new variables with existing ones. Existing variables not specified in the update are preserved. This is safer than `set_all()` which replaces everything. ## Update Single Variable Update a single environment variable: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Set initial variables sandbox.env.set_all({ "API_KEY": "sk-123", "DEBUG": "true" }) # Update a single variable sandbox.env.update({"DEBUG": "false"}) # Verify update env = sandbox.env.get_all() print(f"API_KEY: {env.get('API_KEY')}") # Still "sk-123" print(f"DEBUG: {env.get('DEBUG')}") # Now "false" sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Set initial variables await sandbox.env.setAll({ API_KEY: 'sk-123', DEBUG: 'true' }); // Update a single variable await sandbox.env.update({ DEBUG: 'false' }); // Verify update const env = await sandbox.env.getAll(); console.log(`API_KEY: ${env.API_KEY}`); // Still "sk-123" console.log(`DEBUG: ${env.DEBUG}`); // Now "false" await sandbox.kill(); ``` ## Update Multiple Variables Update multiple variables at once: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Set initial configuration sandbox.env.set_all({ "API_KEY": "sk-123", "DATABASE_URL": "postgres://localhost/db" }) # Update multiple variables sandbox.env.update({ "NODE_ENV": "production", "DEBUG": "false", "LOG_LEVEL": "info" }) # Verify all variables env = sandbox.env.get_all() print("All environment variables:") for key in ["API_KEY", "DATABASE_URL", "NODE_ENV", "DEBUG", "LOG_LEVEL"]: print(f" {key}: {env.get(key, 'not set')}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Set initial configuration await sandbox.env.setAll({ API_KEY: 'sk-123', DATABASE_URL: 'postgres://localhost/db' }); // Update multiple variables await sandbox.env.update({ NODE_ENV: 'production', DEBUG: 'false', LOG_LEVEL: 'info' }); // Verify all variables const env = await sandbox.env.getAll(); console.log('All environment variables:'); for (const key of ['API_KEY', 'DATABASE_URL', 'NODE_ENV', 'DEBUG', 'LOG_LEVEL']) { console.log(` ${key}: ${env[key] || 'not set'}`); } await sandbox.kill(); ``` ## Incremental Configuration Build environment configuration incrementally: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Step 1: Set base configuration sandbox.env.set_all({ "NODE_ENV": "production" }) # Step 2: Add API configuration sandbox.env.update({ "API_KEY": "sk-prod-xyz", "API_URL": "https://api.example.com" }) # Step 3: Add database configuration sandbox.env.update({ "DATABASE_URL": "postgres://localhost/prod", "DB_POOL_SIZE": "10" }) # Step 4: Add logging configuration sandbox.env.update({ "LOG_LEVEL": "info", "LOG_FORMAT": "json" }) # Verify final configuration env = sandbox.env.get_all() print(f"Final configuration: {len(env)} variables") for key in sorted(env.keys()): if key not in ['PATH', 'HOME', 'USER', 'SHELL']: # Skip system vars print(f" {key}: {env[key]}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Step 1: Set base configuration await sandbox.env.setAll({ NODE_ENV: 'production' }); // Step 2: Add API configuration await sandbox.env.update({ API_KEY: 'sk-prod-xyz', API_URL: 'https://api.example.com' }); // Step 3: Add database configuration await sandbox.env.update({ DATABASE_URL: 'postgres://localhost/prod', DB_POOL_SIZE: '10' }); // Step 4: Add logging configuration await sandbox.env.update({ LOG_LEVEL: 'info', LOG_FORMAT: 'json' }); // Verify final configuration const env = await sandbox.env.getAll(); console.log(`Final configuration: ${Object.keys(env).length} variables`); for (const key of Object.keys(env).sort()) { if (!['PATH', 'HOME', 'USER', 'SHELL'].includes(key)) { // Skip system vars console.log(` ${key}: ${env[key]}`); } } await sandbox.kill(); ``` ## Override Existing Variables Update existing variables with new values: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Set initial values sandbox.env.set_all({ "API_KEY": "sk-dev-123", "DEBUG": "true", "LOG_LEVEL": "debug" }) # Override with production values sandbox.env.update({ "API_KEY": "sk-prod-xyz", "DEBUG": "false", "LOG_LEVEL": "info" }) # Verify overrides env = sandbox.env.get_all() print(f"API_KEY: {env.get('API_KEY')}") # "sk-prod-xyz" print(f"DEBUG: {env.get('DEBUG')}") # "false" print(f"LOG_LEVEL: {env.get('LOG_LEVEL')}") # "info" sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Set initial values await sandbox.env.setAll({ API_KEY: 'sk-dev-123', DEBUG: 'true', LOG_LEVEL: 'debug' }); // Override with production values await sandbox.env.update({ API_KEY: 'sk-prod-xyz', DEBUG: 'false', LOG_LEVEL: 'info' }); // Verify overrides const env = await sandbox.env.getAll(); console.log(`API_KEY: ${env.API_KEY}`); // "sk-prod-xyz" console.log(`DEBUG: ${env.DEBUG}`); // "false" console.log(`LOG_LEVEL: ${env.LOG_LEVEL}`); // "info" await sandbox.kill(); ``` ## Complete Example Here's a complete example showing incremental environment setup: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Start with base configuration print("🔧 Setting up environment incrementally...\n") # Step 1: Base environment sandbox.env.set_all({"NODE_ENV": "production"}) print("✅ Step 1: Base environment set") # Step 2: API configuration sandbox.env.update({ "API_KEY": "sk-prod-xyz", "API_URL": "https://api.example.com", "API_TIMEOUT": "30" }) print("✅ Step 2: API configuration added") # Step 3: Database configuration sandbox.env.update({ "DATABASE_URL": "postgres://localhost/prod", "DB_POOL_SIZE": "10", "DB_TIMEOUT": "5" }) print("✅ Step 3: Database configuration added") # Step 4: Feature flags sandbox.env.update({ "FEATURE_NEW_UI": "true", "FEATURE_ANALYTICS": "true", "FEATURE_BETA": "false" }) print("✅ Step 4: Feature flags added") # Step 5: Update existing variable sandbox.env.update({"NODE_ENV": "staging"}) print("✅ Step 5: NODE_ENV updated to staging") # Final verification env = sandbox.env.get_all() custom_vars = {k: v for k, v in env.items() if k not in ['PATH', 'HOME', 'USER', 'SHELL', 'PWD']} print(f"\n📋 Final environment ({len(custom_vars)} custom variables):") for key, value in sorted(custom_vars.items()): if any(sensitive in key.upper() for sensitive in ['KEY', 'SECRET', 'PASSWORD']): print(f" {key}=***MASKED***") else: print(f" {key}={value}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Start with base configuration console.log('🔧 Setting up environment incrementally...\n'); // Step 1: Base environment await sandbox.env.setAll({ NODE_ENV: 'production' }); console.log('✅ Step 1: Base environment set'); // Step 2: API configuration await sandbox.env.update({ API_KEY: 'sk-prod-xyz', API_URL: 'https://api.example.com', API_TIMEOUT: '30' }); console.log('✅ Step 2: API configuration added'); // Step 3: Database configuration await sandbox.env.update({ DATABASE_URL: 'postgres://localhost/prod', DB_POOL_SIZE: '10', DB_TIMEOUT: '5' }); console.log('✅ Step 3: Database configuration added'); // Step 4: Feature flags await sandbox.env.update({ FEATURE_NEW_UI: 'true', FEATURE_ANALYTICS: 'true', FEATURE_BETA: 'false' }); console.log('✅ Step 4: Feature flags added'); // Step 5: Update existing variable await sandbox.env.update({ NODE_ENV: 'staging' }); console.log('✅ Step 5: NODE_ENV updated to staging'); // Final verification const env = await sandbox.env.getAll(); const systemVars = new Set(['PATH', 'HOME', 'USER', 'SHELL', 'PWD']); const customVars = Object.fromEntries( Object.entries(env).filter(([k]) => !systemVars.has(k)) ); console.log(`\n📋 Final environment (${Object.keys(customVars).length} custom variables):`); for (const [key, value] of Object.entries(customVars).sort()) { const isSensitive = ['KEY', 'SECRET', 'PASSWORD'].some( s => key.toUpperCase().includes(s) ); if (isSensitive) { console.log(` ${key}=***MASKED***`); } else { console.log(` ${key}=${value}`); } } await sandbox.kill(); ``` ## Best Practices Prefer `update()` over `set_all()` to preserve existing variables unless you want to replace everything. Build environment configuration incrementally by updating variables in logical groups. Use `update()` to override existing variables with new values without affecting others. Update related variables together (e.g., all API config, all database config) for better organization. Always verify variables are updated correctly using `get_all()` after updates. ## Related * **[Getting Environment Variables](/core-concepts/environment/getting)** - Retrieve environment variables * **[Setting Environment Variables](/core-concepts/environment/setting)** - Set or replace variables * **SDK**: [sandbox.env.update()](/sdk/python/environment-variables#update) - Python SDK method * **API**: [PATCH /env](/api/vm-agent/update-env) - VM Agent API endpoint * [CLI Environment Variables](/cli/commands/env) - Environment variables from CLI ## Next Steps * Learn about [Getting Environment Variables](/core-concepts/environment/getting) to retrieve variables * Explore [Setting Environment Variables](/core-concepts/environment/setting) to replace all variables * Review [Clearing Environment Variables](/core-concepts/environment/clearing) to remove variables # Downloading Source: https://docs.hopx.ai/core-concepts/filesystem/downloading Download files from sandboxes to your local filesystem. Retrieve files from HopX sandboxes to your local machine for further processing, analysis, or storage. Learn how to download single files or bulk download multiple files using Python and JavaScript SDKs or REST API. Includes examples for file downloads and progress tracking. Download files from sandboxes to your local filesystem. This is useful for retrieving generated outputs, results, plots, or any files created in your sandbox. ## Overview File downloading is essential for: * Retrieving generated outputs and results * Saving plots and visualizations * Downloading processed data files * Archiving sandbox contents Download supports both text and binary files. Large files may take longer to download - set appropriate timeouts for large transfers. ## Basic Download Download a file from sandbox to local: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Create a file in sandbox sandbox.files.write('/workspace/output.txt', 'Hello from sandbox!') # Download to local filesystem sandbox.files.download('/workspace/output.txt', './downloaded_output.txt') print("File downloaded successfully") # Verify download with open('./downloaded_output.txt', 'r') as f: content = f.read() print(f"Downloaded content: {content}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import * as fs from 'fs'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Create a file in sandbox await sandbox.files.write('/workspace/output.txt', 'Hello from sandbox!'); // Download to local filesystem const content = await sandbox.files.download('/workspace/output.txt'); fs.writeFileSync('./downloaded_output.txt', content); console.log('File downloaded successfully'); // Verify download const downloadedContent = fs.readFileSync('./downloaded_output.txt', 'utf-8'); console.log(`Downloaded content: ${downloadedContent}`); await sandbox.kill(); ``` ## Download with Timeout Set timeout for large file downloads: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Generate a large file sandbox.run_code(''' with open('/workspace/large_data.txt', 'w') as f: f.write('x' * 1000000) # 1MB ''') # Download with extended timeout sandbox.files.download('/workspace/large_data.txt', './large_data.txt', timeout=300) print("Large file downloaded") # Verify import os file_size = os.path.getsize('./large_data.txt') / 1024 / 1024 print(f"Downloaded file size: {file_size:.2f} MB") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import * as fs from 'fs'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Generate a large file await sandbox.runCode(` with open('/workspace/large_data.txt', 'w') as f: f.write('x' * 1000000) # 1MB `); // Download const content = await sandbox.files.download('/workspace/large_data.txt'); fs.writeFileSync('./large_data.txt', content); console.log('Large file downloaded'); // Verify const stats = fs.statSync('./large_data.txt'); const fileSize = stats.size / 1024 / 1024; console.log(`Downloaded file size: ${fileSize.toFixed(2)} MB`); await sandbox.kill(); ``` ## Download Binary Files Download binary files (images, PDFs, etc.): ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Generate a plot sandbox.run_code(''' import matplotlib.pyplot as plt plt.plot([1, 2, 3, 4]) plt.savefig('/workspace/plot.png') ''') # Download the image sandbox.files.download('/workspace/plot.png', './local_plot.png') print("Plot downloaded") # Verify it's a valid image with open('./local_plot.png', 'rb') as f: header = f.read(8) print(f"PNG header: {header[:8]}") # Should start with PNG signature sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import * as fs from 'fs'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Generate a plot await sandbox.runCode(` import matplotlib.pyplot as plt plt.plot([1, 2, 3, 4]) plt.savefig('/workspace/plot.png') `); // Download the image const imageData = await sandbox.files.download('/workspace/plot.png'); fs.writeFileSync('./local_plot.png', imageData); console.log('Plot downloaded'); // Verify it's a valid image const buffer = fs.readFileSync('./local_plot.png'); console.log(`PNG header: ${buffer.slice(0, 8)}`); // Should start with PNG signature await sandbox.kill(); ``` ## Download Multiple Files Download multiple files: ```python theme={null} from hopx_ai import Sandbox import os sandbox = Sandbox.create(template="code-interpreter") # Generate multiple files sandbox.run_code(''' import json import matplotlib.pyplot as plt # Create data file with open('/workspace/data.json', 'w') as f: json.dump({"values": [1, 2, 3]}, f) # Create plot plt.plot([1, 2, 3]) plt.savefig('/workspace/plot.png') # Create text file with open('/workspace/readme.txt', 'w') as f: f.write("Generated files") ''') # Download all files files_to_download = [ ('/workspace/data.json', './downloaded_data.json'), ('/workspace/plot.png', './downloaded_plot.png'), ('/workspace/readme.txt', './downloaded_readme.txt') ] print("📥 Downloading files...") for remote_path, local_path in files_to_download: try: sandbox.files.download(remote_path, local_path) file_size = os.path.getsize(local_path) / 1024 print(f" ✅ {remote_path} → {local_path} ({file_size:.2f} KB)") except Exception as e: print(f" ❌ Failed to download {remote_path}: {e}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import * as fs from 'fs'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Generate multiple files await sandbox.runCode(` import json import matplotlib.pyplot as plt # Create data file with open('/workspace/data.json', 'w') as f: json.dump({"values": [1, 2, 3]}, f) # Create plot plt.plot([1, 2, 3]) plt.savefig('/workspace/plot.png') # Create text file with open('/workspace/readme.txt', 'w') as f: f.write("Generated files") `); // Download all files const filesToDownload = [ ['/workspace/data.json', './downloaded_data.json'], ['/workspace/plot.png', './downloaded_plot.png'], ['/workspace/readme.txt', './downloaded_readme.txt'] ]; console.log('📥 Downloading files...'); for (const [remotePath, localPath] of filesToDownload) { try { const content = await sandbox.files.download(remotePath); fs.writeFileSync(localPath, content); const stats = fs.statSync(localPath); const fileSize = stats.size / 1024; console.log(` ✅ ${remotePath} → ${localPath} (${fileSize.toFixed(2)} KB)`); } catch (error) { console.error(` ❌ Failed to download ${remotePath}: ${error.message}`); } } await sandbox.kill(); ``` ## Download All Files in Directory Download all files from a directory: ```python theme={null} from hopx_ai import Sandbox import os sandbox = Sandbox.create(template="code-interpreter") # Create multiple files for i in range(3): sandbox.files.write(f'/workspace/file_{i}.txt', f'Content {i}') # Create local directory os.makedirs('./downloads', exist_ok=True) # Download all files files = sandbox.files.list('/workspace') print("📥 Downloading all files...") for file in files: if file.is_file: local_path = f'./downloads/{file.name}' try: sandbox.files.download(file.path, local_path) print(f" ✅ {file.name} ({file.size_kb:.2f} KB)") except Exception as e: print(f" ❌ Failed to download {file.name}: {e}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import * as fs from 'fs'; import * as path from 'path'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Create multiple files for (let i = 0; i < 3; i++) { await sandbox.files.write(`/workspace/file_${i}.txt`, `Content ${i}`); } // Create local directory if (!fs.existsSync('./downloads')) { fs.mkdirSync('./downloads'); } // Download all files const files = await sandbox.files.list('/workspace'); console.log('📥 Downloading all files...'); for (const file of files) { if (file.isFile) { const localPath = `./downloads/${file.name}`; try { const content = await sandbox.files.download(file.path); fs.writeFileSync(localPath, content); console.log(` ✅ ${file.name} (${(file.size / 1024).toFixed(2)} KB)`); } catch (error) { console.error(` ❌ Failed to download ${file.name}: ${error.message}`); } } } await sandbox.kill(); ``` ## Error Handling Handle download errors: ```python theme={null} from hopx_ai import Sandbox from hopx_ai.errors import FileNotFoundError, FileOperationError sandbox = Sandbox.create(template="code-interpreter") try: # Try to download non-existent file sandbox.files.download('/workspace/nonexistent.txt', './downloaded.txt') except FileNotFoundError: print("File not found in sandbox") except FileOperationError as e: print(f"Download failed: {e}") # Check if file exists first if sandbox.files.exists('/workspace/data.txt'): sandbox.files.download('/workspace/data.txt', './data.txt') print("Download successful") else: print("File does not exist") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import { FileNotFoundError, FileOperationError } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); try { // Try to download non-existent file await sandbox.files.download('/workspace/nonexistent.txt'); } catch (error) { if (error instanceof FileNotFoundError) { console.error('File not found in sandbox'); } else if (error instanceof FileOperationError) { console.error(`Download failed: ${error.message}`); } } // Check if file exists first const exists = await sandbox.files.exists('/workspace/data.txt'); if (exists) { const content = await sandbox.files.download('/workspace/data.txt'); fs.writeFileSync('./data.txt', content); console.log('Download successful'); } else { console.log('File does not exist'); } await sandbox.kill(); ``` ## Complete Example Here's a complete download workflow: ```python theme={null} from hopx_ai import Sandbox import os sandbox = Sandbox.create(template="code-interpreter") # Generate outputs sandbox.run_code(''' import json import matplotlib.pyplot as plt import pandas as pd # Generate JSON data data = {"results": [1, 2, 3, 4, 5]} with open('/workspace/results.json', 'w') as f: json.dump(data, f, indent=2) # Generate plot plt.figure(figsize=(10, 6)) plt.plot([1, 2, 3, 4, 5], [1, 4, 9, 16, 25]) plt.title("Results Visualization") plt.savefig('/workspace/results.png') # Generate CSV df = pd.DataFrame({"x": [1, 2, 3], "y": [4, 5, 6]}) df.to_csv('/workspace/data.csv', index=False) ''') # Create local output directory os.makedirs('./outputs', exist_ok=True) # Download all generated files print("📥 Downloading generated outputs...") files = sandbox.files.list('/workspace') total_size = 0 for file in files: if file.is_file and file.name in ['results.json', 'results.png', 'data.csv']: local_path = f'./outputs/{file.name}' try: sandbox.files.download(file.path, local_path, timeout=120) total_size += file.size print(f" ✅ {file.name} ({file.size_kb:.2f} KB)") except Exception as e: print(f" ❌ Failed to download {file.name}: {e}") print(f"\n✅ Total downloaded: {total_size / 1024:.2f} KB") print(f"📁 Files saved to: ./outputs/") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import * as fs from 'fs'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Generate outputs await sandbox.runCode(` import json import matplotlib.pyplot as plt import pandas as pd # Generate JSON data data = {"results": [1, 2, 3, 4, 5]} with open('/workspace/results.json', 'w') as f: json.dump(data, f, indent=2) # Generate plot plt.figure(figsize=(10, 6)) plt.plot([1, 2, 3, 4, 5], [1, 4, 9, 16, 25]) plt.title("Results Visualization") plt.savefig('/workspace/results.png') # Generate CSV df = pd.DataFrame({"x": [1, 2, 3], "y": [4, 5, 6]}) df.to_csv('/workspace/data.csv', index=False) `); // Create local output directory if (!fs.existsSync('./outputs')) { fs.mkdirSync('./outputs'); } // Download all generated files console.log('📥 Downloading generated outputs...'); const files = await sandbox.files.list('/workspace'); let totalSize = 0; for (const file of files) { if (file.isFile && ['results.json', 'results.png', 'data.csv'].includes(file.name)) { const localPath = `./outputs/${file.name}`; try { const content = await sandbox.files.download(file.path); fs.writeFileSync(localPath, content); totalSize += file.size; console.log(` ✅ ${file.name} (${(file.size / 1024).toFixed(2)} KB)`); } catch (error) { console.error(` ❌ Failed to download ${file.name}: ${error.message}`); } } } console.log(`\n✅ Total downloaded: ${(totalSize / 1024).toFixed(2)} KB`); console.log('📁 Files saved to: ./outputs/'); await sandbox.kill(); ``` ## Best Practices Use `files.exists()` before downloading to avoid errors, or handle `FileNotFoundError` appropriately. For large files, set extended timeouts (60+ seconds) to avoid connection timeouts. Create local directories before downloading to ensure files are saved correctly. Wrap downloads in try/catch blocks to handle network errors, file not found, etc. After downloading, verify files exist locally and check their sizes to ensure successful transfer. ## Related * **[Reading Files](/core-concepts/filesystem/reading)** - Read file contents * **[Uploading Files](/core-concepts/filesystem/uploading)** - Upload files to sandboxes * **[Listing Files](/core-concepts/filesystem/listing)** - List directory contents * **SDK**: [sandbox.files.download()](/sdk/python/files#download) - Python SDK method * [CLI File Operations](/cli/commands/files) - File operations from CLI ## Next Steps * Learn about [Uploading Files](/core-concepts/filesystem/uploading) to transfer files to sandboxes * Explore [Reading Files](/core-concepts/filesystem/reading) to access file contents * Review [Watching Files](/core-concepts/filesystem/watching) for real-time file monitoring # Filesystem Source: https://docs.hopx.ai/core-concepts/filesystem/index Complete guide to file operations in HopX sandboxes - reading, writing, listing, uploading, downloading, and watching files. Work with files in sandboxes using comprehensive file operations, from basic read/write to advanced file watching and bulk transfers. Includes Python and JavaScript SDK examples and REST API endpoints for all file operations. Work with files in HopX sandboxes using comprehensive file operations. This hub covers all filesystem operations, from basic read/write to advanced file watching and bulk transfers. ## Related * [CLI File Operations](/cli/commands/files) - File operations from CLI ## What You'll Learn * How to read and write files in sandboxes * How to list directories and navigate the filesystem * How to upload and download files to/from sandboxes * How to watch files for changes * How to manage file permissions and metadata ## File Operations Overview | Operation | SDK Method | API Endpoint | | -------------------------------------------------------- | -------------------------- | ------------------------ | | **[Reading](/core-concepts/filesystem/reading)** | `sandbox.files.read()` | `GET /files/read` | | **[Writing](/core-concepts/filesystem/writing)** | `sandbox.files.write()` | `POST /files/write` | | **[Listing](/core-concepts/filesystem/listing)** | `sandbox.files.list()` | `GET /files/list` | | **[Uploading](/core-concepts/filesystem/uploading)** | `sandbox.files.upload()` | `POST /files/upload` | | **[Downloading](/core-concepts/filesystem/downloading)** | `sandbox.files.download()` | `GET /files/download` | | **[Watching](/core-concepts/filesystem/watching)** | `sandbox.files.watch()` | `WebSocket /files/watch` | ## Core Concepts ### Reading Files Read file contents from sandboxes as text or binary data. * **[Reading Files](/core-concepts/filesystem/reading)** - Read file contents * **SDK**: [Python: sandbox.files.read()](/sdk/python/files#read) | [JavaScript: sandbox.files.read()](/sdk/javascript/files#read) * **API**: [GET /files/read](/api/vm-agent/read-file) ### Writing Files Write text or binary data to files in sandboxes. * **[Writing Files](/core-concepts/filesystem/writing)** - Write file contents * **SDK**: [Python: sandbox.files.write()](/sdk/python/files#write) | [JavaScript: sandbox.files.write()](/sdk/javascript/files#write) * **API**: [POST /files/write](/api/vm-agent/write-file) ### Listing Files List directory contents and navigate the filesystem. * **[Listing Files](/core-concepts/filesystem/listing)** - List directories and files * **SDK**: [Python: sandbox.files.list()](/sdk/python/files#list) | [JavaScript: sandbox.files.list()](/sdk/javascript/files#list) * **API**: [GET /files/list](/api/vm-agent/list-files) ### Uploading Files Upload files from your local machine to sandboxes. * **[Uploading Files](/core-concepts/filesystem/uploading)** - Upload files to sandboxes * **SDK**: [Python: sandbox.files.upload()](/sdk/python/files#upload) | [JavaScript: sandbox.files.upload()](/sdk/javascript/files#upload) * **API**: [POST /files/upload](/api/vm-agent/upload-file) ### Downloading Files Download files from sandboxes to your local machine. * **[Downloading Files](/core-concepts/filesystem/downloading)** - Download files from sandboxes * **SDK**: [Python: sandbox.files.download()](/sdk/python/files#download) | [JavaScript: sandbox.files.download()](/sdk/javascript/files#download) * **API**: [GET /files/download](/api/vm-agent/download-file) ### Watching Files Watch files and directories for changes in real-time. * **[Watching Files](/core-concepts/filesystem/watching)** - Monitor file changes * **SDK**: [Python: sandbox.files.watch()](/sdk/python/files#watch) | [JavaScript: sandbox.files.watch()](/sdk/javascript/files#watch) * **API**: [WebSocket /files/watch](/api/vm-agent/watch-file) ## SDK Reference ### Python SDK Complete reference for Python file operations. * **[Files Module](/sdk/python/files)** - Complete filesystem API * `files.read()` - Read files * `files.write()` - Write files * `files.list()` - List directories * `files.upload()` - Upload files * `files.download()` - Download files * `files.watch()` - Watch files * `files.exists()` - Check existence * `files.remove()` - Delete files * `files.mkdir()` - Create directories ### JavaScript SDK Complete reference for JavaScript/TypeScript file operations. * **[Files Module](/sdk/javascript/files)** - Complete filesystem API * `files.read()` - Read files * `files.write()` - Write files * `files.list()` - List directories * `files.upload()` - Upload files * `files.download()` - Download files * `files.watch()` - Watch files * `files.exists()` - Check existence * `files.remove()` - Delete files * `files.mkdir()` - Create directories ## API Reference ### VM Agent API REST API endpoints for file operations. * **[VM Agent API Overview](/api/vm-agent/overview)** - API overview * **[Read File](/api/vm-agent/read-file)** - `GET /files/read` - Read file contents * **[Write File](/api/vm-agent/write-file)** - `POST /files/write` - Write file contents * **[List Files](/api/vm-agent/list-files)** - `GET /files/list` - List directory contents * **[File Exists](/api/vm-agent/file-exists)** - `GET /files/exists` - Check file existence * **[Remove File](/api/vm-agent/remove-file)** - `DELETE /files/remove` - Delete files * **[Create Directory](/api/vm-agent/mkdir)** - `POST /files/mkdir` - Create directories ## Quick Start If you're new to file operations, start here: 1. **[Reading Files](/core-concepts/filesystem/reading)** - Read your first file 2. **[Writing Files](/core-concepts/filesystem/writing)** - Write files to sandboxes 3. **[Listing Files](/core-concepts/filesystem/listing)** - Navigate directories ## Related Topics * **[Code Execution](/core-concepts/code-execution/synchronous)** - Execute code that works with files * **[Sandboxes](/core-concepts/sandboxes/creating)** - Create sandboxes for file operations * **[Commands](/core-concepts/commands/running)** - Run shell commands for file operations * **[Environment Variables](/core-concepts/environment/getting)** - Configure file paths ## Next Steps * Learn about [Code Execution](/core-concepts/code-execution/synchronous) to process files * Explore [Commands](/core-concepts/commands/running) for shell-based file operations * Review [Uploading Files](/core-concepts/filesystem/uploading) for bulk transfers * Check out [Watching Files](/core-concepts/filesystem/watching) for real-time monitoring # Listing Source: https://docs.hopx.ai/core-concepts/filesystem/listing List directory contents and browse the filesystem in HopX sandboxes. Navigate directories, view file metadata, filter files by name or pattern, and discover generated outputs. Learn how to list files and directories using Python and JavaScript SDKs or REST API. Includes examples for directory navigation and file discovery. List directory contents to browse your sandbox filesystem. Get file metadata including size, permissions, and modification times. ## Overview Directory listing is useful for: * Browsing sandbox filesystem structure * Finding files by name or pattern * Checking file sizes and metadata * Discovering generated outputs You can list contents of allowed paths like `/workspace` and `/tmp`. Listing system directories may be restricted for security. ## Basic Listing List files in a directory: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Create some files sandbox.files.write('/workspace/file1.txt', 'Content 1') sandbox.files.write('/workspace/file2.txt', 'Content 2') sandbox.files.mkdir('/workspace/subdir') # List directory contents files = sandbox.files.list('/workspace') print(f"Found {len(files)} items") for file in files: if file.is_file: print(f"📄 {file.name} ({file.size_kb:.2f} KB)") else: print(f"📁 {file.name}/") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Create some files await sandbox.files.write('/workspace/file1.txt', 'Content 1'); await sandbox.files.write('/workspace/file2.txt', 'Content 2'); await sandbox.files.mkdir('/workspace/subdir'); // List directory contents const files = await sandbox.files.list('/workspace'); console.log(`Found ${files.length} items`); for (const file of files) { if (file.isFile) { console.log(`📄 ${file.name} (${(file.size / 1024).toFixed(2)} KB)`); } else { console.log(`📁 ${file.name}/`); } } await sandbox.kill(); ``` ## File Information Access detailed file information: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Create a file sandbox.files.write('/workspace/data.txt', 'Some content') # List and get file info files = sandbox.files.list('/workspace') for file in files: if file.name == 'data.txt': print(f"Name: {file.name}") print(f"Path: {file.path}") print(f"Size: {file.size} bytes") print(f"Size (KB): {file.size_kb:.2f} KB") print(f"Size (MB): {file.size_mb:.2f} MB") print(f"Is file: {file.is_file}") print(f"Is directory: {file.is_dir}") print(f"Permissions: {file.permissions}") print(f"Modified: {file.modified_time}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Create a file await sandbox.files.write('/workspace/data.txt', 'Some content'); // List and get file info const files = await sandbox.files.list('/workspace'); for (const file of files) { if (file.name === 'data.txt') { console.log(`Name: ${file.name}`); console.log(`Path: ${file.path}`); console.log(`Size: ${file.size} bytes`); console.log(`Size (KB): ${(file.size / 1024).toFixed(2)} KB`); console.log(`Size (MB): ${(file.size / 1024 / 1024).toFixed(2)} MB`); console.log(`Is file: ${file.isFile}`); console.log(`Is directory: ${file.isDirectory}`); console.log(`Permissions: ${file.permissions}`); console.log(`Modified: ${file.modifiedTime}`); } } await sandbox.kill(); ``` ## Filtering Files Filter files by type or pattern: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Create various files sandbox.files.write('/workspace/script.py', 'print("Hello")') sandbox.files.write('/workspace/data.json', '{"key": "value"}') sandbox.files.write('/workspace/readme.txt', 'Documentation') # List only Python files files = sandbox.files.list('/workspace') python_files = [f for f in files if f.is_file and f.name.endswith('.py')] print(f"Python files: {len(python_files)}") for f in python_files: print(f" {f.name}") # List only directories directories = [f for f in files if f.is_dir] print(f"\nDirectories: {len(directories)}") for d in directories: print(f" {d.name}/") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Create various files await sandbox.files.write('/workspace/script.py', 'print("Hello")'); await sandbox.files.write('/workspace/data.json', '{"key": "value"}'); await sandbox.files.write('/workspace/readme.txt', 'Documentation'); // List only Python files const files = await sandbox.files.list('/workspace'); const pythonFiles = files.filter(f => f.isFile && f.name.endsWith('.py')); console.log(`Python files: ${pythonFiles.length}`); for (const f of pythonFiles) { console.log(` ${f.name}`); } // List only directories const directories = files.filter(f => f.isDirectory); console.log(`\nDirectories: ${directories.length}`); for (const d of directories) { console.log(` ${d.name}/`); } await sandbox.kill(); ``` ## Recursive Listing List files recursively by traversing directories: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Create nested structure sandbox.files.mkdir('/workspace/project') sandbox.files.mkdir('/workspace/project/src') sandbox.files.write('/workspace/project/src/main.py', 'print("Hello")') sandbox.files.write('/workspace/project/README.md', '# Project') def list_recursive(files, path='/workspace', indent=0): """Recursively list directory contents""" items = sandbox.files.list(path) for item in items: prefix = " " * indent if item.is_dir: print(f"{prefix}📁 {item.name}/") list_recursive(files, item.path, indent + 1) else: print(f"{prefix}📄 {item.name} ({item.size_kb:.2f} KB)") print("Directory structure:") list_recursive(sandbox.files.list('/workspace')) sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Create nested structure await sandbox.files.mkdir('/workspace/project'); await sandbox.files.mkdir('/workspace/project/src'); await sandbox.files.write('/workspace/project/src/main.py', 'print("Hello")'); await sandbox.files.write('/workspace/project/README.md', '# Project'); async function listRecursive(path = '/workspace', indent = 0) { const items = await sandbox.files.list(path); for (const item of items) { const prefix = ' '.repeat(indent); if (item.isDirectory) { console.log(`${prefix}📁 ${item.name}/`); await listRecursive(item.path, indent + 1); } else { console.log(`${prefix}📄 ${item.name} (${(item.size / 1024).toFixed(2)} KB)`); } } } console.log('Directory structure:'); await listRecursive('/workspace'); await sandbox.kill(); ``` ## Sorting and Filtering Sort files by size, name, or date: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Create files of different sizes sandbox.files.write('/workspace/small.txt', 'small') sandbox.files.write('/workspace/medium.txt', 'x' * 1000) sandbox.files.write('/workspace/large.txt', 'x' * 10000) # List and sort by size files = sandbox.files.list('/workspace') files_only = [f for f in files if f.is_file] # Sort by size (largest first) sorted_by_size = sorted(files_only, key=lambda f: f.size, reverse=True) print("Files sorted by size:") for f in sorted_by_size: print(f" {f.name}: {f.size_kb:.2f} KB") # Sort by name sorted_by_name = sorted(files_only, key=lambda f: f.name) print("\nFiles sorted by name:") for f in sorted_by_name: print(f" {f.name}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Create files of different sizes await sandbox.files.write('/workspace/small.txt', 'small'); await sandbox.files.write('/workspace/medium.txt', 'x'.repeat(1000)); await sandbox.files.write('/workspace/large.txt', 'x'.repeat(10000)); // List and sort by size const files = await sandbox.files.list('/workspace'); const filesOnly = files.filter(f => f.isFile); // Sort by size (largest first) const sortedBySize = filesOnly.sort((a, b) => b.size - a.size); console.log('Files sorted by size:'); for (const f of sortedBySize) { console.log(` ${f.name}: ${(f.size / 1024).toFixed(2)} KB`); } // Sort by name const sortedByName = filesOnly.sort((a, b) => a.name.localeCompare(b.name)); console.log('\nFiles sorted by name:'); for (const f of sortedByName) { console.log(` ${f.name}`); } await sandbox.kill(); ``` ## Complete Example Here's a complete example showing directory listing: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Create a project structure sandbox.files.mkdir('/workspace/myproject') sandbox.files.mkdir('/workspace/myproject/src') sandbox.files.mkdir('/workspace/myproject/tests') sandbox.files.mkdir('/workspace/myproject/data') # Create files sandbox.files.write('/workspace/myproject/src/main.py', 'print("Hello")') sandbox.files.write('/workspace/myproject/src/utils.py', 'def helper(): pass') sandbox.files.write('/workspace/myproject/tests/test_main.py', 'def test(): pass') sandbox.files.write('/workspace/myproject/data/input.csv', '1,2,3') sandbox.files.write('/workspace/myproject/README.md', '# My Project') # List and display structure def display_tree(path, prefix=""): files = sandbox.files.list(path) files.sort(key=lambda f: (f.is_dir, f.name)) for i, file in enumerate(files): is_last = i == len(files) - 1 current_prefix = "└── " if is_last else "├── " print(f"{prefix}{current_prefix}{file.name}") if file.is_dir: next_prefix = prefix + (" " if is_last else "│ ") display_tree(file.path, next_prefix) print("Project structure:") display_tree('/workspace/myproject') # Summary all_files = sandbox.files.list('/workspace/myproject') total_size = sum(f.size for f in all_files if f.is_file) print(f"\nTotal files: {len([f for f in all_files if f.is_file])}") print(f"Total size: {total_size / 1024:.2f} KB") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Create a project structure await sandbox.files.mkdir('/workspace/myproject'); await sandbox.files.mkdir('/workspace/myproject/src'); await sandbox.files.mkdir('/workspace/myproject/tests'); await sandbox.files.mkdir('/workspace/myproject/data'); // Create files await sandbox.files.write('/workspace/myproject/src/main.py', 'print("Hello")'); await sandbox.files.write('/workspace/myproject/src/utils.py', 'def helper(): pass'); await sandbox.files.write('/workspace/myproject/tests/test_main.py', 'def test(): pass'); await sandbox.files.write('/workspace/myproject/data/input.csv', '1,2,3'); await sandbox.files.write('/workspace/myproject/README.md', '# My Project'); // List and display structure async function displayTree(path, prefix = '') { const files = await sandbox.files.list(path); files.sort((a, b) => { if (a.isDirectory !== b.isDirectory) { return a.isDirectory ? -1 : 1; } return a.name.localeCompare(b.name); }); for (let i = 0; i < files.length; i++) { const file = files[i]; const isLast = i === files.length - 1; const currentPrefix = isLast ? '└── ' : '├── '; console.log(`${prefix}${currentPrefix}${file.name}`); if (file.isDirectory) { const nextPrefix = prefix + (isLast ? ' ' : '│ '); await displayTree(file.path, nextPrefix); } } } console.log('Project structure:'); await displayTree('/workspace/myproject'); // Summary const allFiles = await sandbox.files.list('/workspace/myproject'); const totalSize = allFiles.filter(f => f.isFile).reduce((sum, f) => sum + f.size, 0); console.log(`\nTotal files: ${allFiles.filter(f => f.isFile).length}`); console.log(`Total size: ${(totalSize / 1024).toFixed(2)} KB`); await sandbox.kill(); ``` ## Best Practices Use `files.exists()` before listing to avoid errors, or handle `FileNotFoundError` appropriately. Use `is_file` and `is_dir` properties to filter files and directories. Sort files by name, size, or date for better user experience. For nested structures, implement recursive listing to show complete directory trees. For directories with many files, consider pagination or filtering to avoid performance issues. ## Related * **[Reading Files](/core-concepts/filesystem/reading)** - Read file contents * **[Writing Files](/core-concepts/filesystem/writing)** - Write files to sandboxes * **SDK**: [sandbox.files.list()](/sdk/python/files#list) - Python SDK method * **API**: [GET /files/list](/api/vm-agent/list-files) - VM Agent API endpoint * [CLI File Operations](/cli/commands/files) - File operations from CLI ## Next Steps * Learn about [Reading Files](/core-concepts/filesystem/reading) to access file contents * Explore [Writing Files](/core-concepts/filesystem/writing) to create files * Review [Watching Files](/core-concepts/filesystem/watching) for real-time file monitoring # Reading Source: https://docs.hopx.ai/core-concepts/filesystem/reading Read text and binary files from sandboxes. Learn how to read file contents from HopX sandboxes using Python and JavaScript SDKs or REST API. Includes examples for reading text files, binary files, handling encoding, and processing file contents in your applications. Read files from your sandbox filesystem. HopX supports both text and binary file reading with automatic encoding handling. ## Overview File reading is essential for: * Accessing generated outputs from code execution * Reading configuration files * Processing data files * Retrieving logs and results Files can be read from allowed paths like `/workspace` and `/tmp`. Reading from system directories may be restricted for security. ## Reading Text Files Read text files as strings: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Write a file first sandbox.files.write('/workspace/data.txt', 'Hello, World!\nLine 2\nLine 3') # Read the file content = sandbox.files.read('/workspace/data.txt') print(content) # Output: # Hello, World! # Line 2 # Line 3 sandbox.kill() ``` **Expected Output:** ``` Hello, World! Line 2 Line 3 ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Write a file first await sandbox.files.write('/workspace/data.txt', 'Hello, World!\nLine 2\nLine 3'); // Read the file const content = await sandbox.files.read('/workspace/data.txt'); console.log(content); // Output: // Hello, World! // Line 2 // Line 3 await sandbox.kill(); ``` **Expected Output:** ``` Hello, World! Line 2 Line 3 ``` ## Reading Binary Files Read binary files (images, PDFs, etc.) as bytes: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Generate a plot and save it sandbox.run_code(''' import matplotlib.pyplot as plt plt.plot([1, 2, 3, 4]) plt.savefig('/workspace/plot.png') ''') # Read the binary image file image_data = sandbox.files.read_bytes('/workspace/plot.png') print(f"Image size: {len(image_data)} bytes") # Save to local file with open('local_plot.png', 'wb') as f: f.write(image_data) sandbox.kill() ``` **Expected Output:** ``` Image size: 245760 bytes ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import * as fs from 'fs'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Generate a plot and save it await sandbox.runCode(` import matplotlib.pyplot as plt plt.plot([1, 2, 3, 4]) plt.savefig('/workspace/plot.png') `); // Read the binary image file const imageData = await sandbox.files.readBytes('/workspace/plot.png'); console.log(`Image size: ${imageData.length} bytes`); // Save to local file fs.writeFileSync('local_plot.png', imageData); await sandbox.kill(); ``` **Expected Output:** ``` Image size: 245760 bytes ``` ## Reading Code Files Read and execute code files: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Write a Python script sandbox.files.write('/workspace/script.py', ''' def greet(name): return f"Hello, {name}!" print(greet("World")) ''') # Read and execute script_content = sandbox.files.read('/workspace/script.py') result = sandbox.run_code(script_content, language='python') print(result.stdout) # "Hello, World!" sandbox.kill() ``` **Expected Output:** ``` Hello, World! ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Write a Python script await sandbox.files.write('/workspace/script.py', ` def greet(name): return f"Hello, {name}!" print(greet("World")) `); // Read and execute const scriptContent = await sandbox.files.read('/workspace/script.py'); const result = await sandbox.runCode(scriptContent, { language: 'python' }); console.log(result.stdout); // "Hello, World!" await sandbox.kill(); ``` **Expected Output:** ``` Hello, World! ``` ## Reading Configuration Files Read JSON, YAML, or other configuration files: ```python theme={null} from hopx_ai import Sandbox import json sandbox = Sandbox.create(template="code-interpreter") # Write a config file sandbox.files.write('/workspace/config.json', ''' { "api_key": "sk-123", "debug": true, "timeout": 30 } ''') # Read and parse config_content = sandbox.files.read('/workspace/config.json') config = json.loads(config_content) print(f"API key: {config['api_key']}") print(f"Debug: {config['debug']}") sandbox.kill() ``` **Expected Output:** ``` API key: sk-123 Debug: True ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Write a config file await sandbox.files.write('/workspace/config.json', ` { "api_key": "sk-123", "debug": true, "timeout": 30 } `); // Read and parse const configContent = await sandbox.files.read('/workspace/config.json'); const config = JSON.parse(configContent); console.log(`API key: ${config.api_key}`); console.log(`Debug: ${config.debug}`); await sandbox.kill(); ``` **Expected Output:** ``` API key: sk-123 Debug: true ``` ## Reading Large Files For large files, consider using timeouts: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Read large file with custom timeout try: content = sandbox.files.read('/workspace/large_file.txt', timeout=120) print(f"Read {len(content)} characters") except Exception as e: print(f"Error reading file: {e}") sandbox.kill() ``` **Expected Output:** ``` Read 1000000 characters ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Read large file (timeout handled by HTTP client) try { const content = await sandbox.files.read('/workspace/large_file.txt'); console.log(`Read ${content.length} characters`); } catch (error) { console.error(`Error reading file: ${error.message}`); } await sandbox.kill(); ``` **Expected Output:** ``` Read 1000000 characters ``` ## Error Handling Handle file reading errors: ```python theme={null} from hopx_ai import Sandbox from hopx_ai.errors import FileNotFoundError, FileOperationError sandbox = Sandbox.create(template="code-interpreter") try: content = sandbox.files.read('/workspace/nonexistent.txt') except FileNotFoundError: print("File not found") except FileOperationError as e: print(f"File operation error: {e}") # Check if file exists first if sandbox.files.exists('/workspace/data.txt'): content = sandbox.files.read('/workspace/data.txt') print(content) else: print("File does not exist") sandbox.kill() ``` **Expected Output:** ``` File not found File does not exist ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import { FileNotFoundError, FileOperationError } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); try { const content = await sandbox.files.read('/workspace/nonexistent.txt'); } catch (error) { if (error instanceof FileNotFoundError) { console.error('File not found'); } else if (error instanceof FileOperationError) { console.error(`File operation error: ${error.message}`); } } // Check if file exists first const exists = await sandbox.files.exists('/workspace/data.txt'); if (exists) { const content = await sandbox.files.read('/workspace/data.txt'); console.log(content); } else { console.log('File does not exist'); } await sandbox.kill(); ``` **Expected Output:** ``` File not found File does not exist ``` ## Reading Multiple Files Read multiple files in a loop: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Create multiple files for i in range(3): sandbox.files.write(f'/workspace/file_{i}.txt', f'Content {i}') # Read all files files = sandbox.files.list('/workspace') for file in files: if file.is_file and file.name.endswith('.txt'): content = sandbox.files.read(file.path) print(f"{file.name}: {content}") sandbox.kill() ``` **Expected Output:** ``` file_0.txt: Content 0 file_1.txt: Content 1 file_2.txt: Content 2 ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Create multiple files for (let i = 0; i < 3; i++) { await sandbox.files.write(`/workspace/file_${i}.txt`, `Content ${i}`); } // Read all files const files = await sandbox.files.list('/workspace'); for (const file of files) { if (file.isFile && file.name.endsWith('.txt')) { const content = await sandbox.files.read(file.path); console.log(`${file.name}: ${content}`); } } await sandbox.kill(); ``` **Expected Output:** ``` file_0.txt: Content 0 file_1.txt: Content 1 file_2.txt: Content 2 ``` ## Complete Example Here's a complete example showing file reading workflow: ```python theme={null} from hopx_ai import Sandbox import json sandbox = Sandbox.create(template="code-interpreter") # Generate some files sandbox.run_code(''' import json import matplotlib.pyplot as plt # Create data file data = {"values": [1, 2, 3, 4, 5]} with open('/workspace/data.json', 'w') as f: json.dump(data, f) # Create plot plt.plot([1, 2, 3, 4, 5]) plt.savefig('/workspace/plot.png') # Create text file with open('/workspace/readme.txt', 'w') as f: f.write("Generated files:\n- data.json\n- plot.png") ''') # Read all generated files print("📄 Reading generated files:\n") # Read JSON data json_content = sandbox.files.read('/workspace/data.json') data = json.loads(json_content) print(f"Data: {data}") # Read binary plot plot_data = sandbox.files.read_bytes('/workspace/plot.png') print(f"Plot size: {len(plot_data)} bytes") # Read text file readme = sandbox.files.read('/workspace/readme.txt') print(f"\nReadme:\n{readme}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Generate some files await sandbox.runCode(` import json import matplotlib.pyplot as plt # Create data file data = {"values": [1, 2, 3, 4, 5]} with open('/workspace/data.json', 'w') as f: json.dump(data, f) # Create plot plt.plot([1, 2, 3, 4, 5]) plt.savefig('/workspace/plot.png') # Create text file with open('/workspace/readme.txt', 'w') as f: f.write("Generated files:\\n- data.json\\n- plot.png") `); // Read all generated files console.log('📄 Reading generated files:\n'); // Read JSON data const jsonContent = await sandbox.files.read('/workspace/data.json'); const data = JSON.parse(jsonContent); console.log(`Data: ${JSON.stringify(data)}`); // Read binary plot const plotData = await sandbox.files.readBytes('/workspace/plot.png'); console.log(`Plot size: ${plotData.length} bytes`); // Read text file const readme = await sandbox.files.read('/workspace/readme.txt'); console.log(`\nReadme:\n${readme}`); await sandbox.kill(); ``` ## Best Practices Use `files.exists()` before reading to avoid errors, or handle `FileNotFoundError` appropriately. Use `read()` for text files and `read_bytes()` for binary files (images, PDFs, etc.). For large files, set appropriate timeouts to avoid connection timeouts. Text files are automatically decoded. Binary files return raw bytes. Only read from allowed paths like `/workspace` and `/tmp`. System directories may be restricted. ## Related * **[Writing Files](/core-concepts/filesystem/writing)** - Write files to sandboxes * **[Listing Files](/core-concepts/filesystem/listing)** - List directory contents * **SDK**: [sandbox.files.read()](/sdk/python/files#read) - Python SDK method * **API**: [GET /files/read](/api/vm-agent/read-file) - VM Agent API endpoint ## Next Steps * Learn about [Writing Files](/core-concepts/filesystem/writing) to create files * Explore [Listing Files](/core-concepts/filesystem/listing) to browse directories * Review [Downloading Files](/core-concepts/filesystem/downloading) to save files locally # Uploading Source: https://docs.hopx.ai/core-concepts/filesystem/uploading Upload files from your local filesystem to sandboxes. Transfer files from your local machine to HopX sandboxes for processing, configuration, or data input. Learn how to upload single files or bulk upload multiple files using Python and JavaScript SDKs or REST API. Includes examples for file uploads and progress tracking. Upload files from your local filesystem to sandboxes. This is useful for transferring data files, scripts, or any local files you want to use in your sandbox. ## Overview File uploading is ideal for: * Transferring local data files to sandboxes * Uploading scripts and code files * Moving configuration files * Transferring datasets or models Upload supports both text and binary files. Large files may take longer to upload - set appropriate timeouts for large transfers. ## Basic Upload Upload a file from local to sandbox: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Upload a local file sandbox.files.upload('./local_data.csv', '/workspace/data.csv') print("File uploaded successfully") # Verify upload if sandbox.files.exists('/workspace/data.csv'): content = sandbox.files.read('/workspace/data.csv') print(f"Uploaded content: {content[:100]}...") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Note: JavaScript SDK upload may require FormData implementation // For now, use write() with file content import * as fs from 'fs'; const localContent = fs.readFileSync('./local_data.csv', 'utf-8'); await sandbox.files.write('/workspace/data.csv', localContent); console.log('File uploaded successfully'); // Verify upload const exists = await sandbox.files.exists('/workspace/data.csv'); if (exists) { const content = await sandbox.files.read('/workspace/data.csv'); console.log(`Uploaded content: ${content.substring(0, 100)}...`); } await sandbox.kill(); ``` ## Upload with Timeout Set timeout for large file uploads: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Upload large file with extended timeout sandbox.files.upload('./large_dataset.zip', '/workspace/dataset.zip', timeout=300) print("Large file uploaded") # Verify files = sandbox.files.list('/workspace') for f in files: if f.name == 'dataset.zip': print(f"Uploaded: {f.name} ({f.size_mb:.2f} MB)") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import * as fs from 'fs'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Upload large file (use writeBytes for binary) const largeContent = fs.readFileSync('./large_dataset.zip'); await sandbox.files.writeBytes('/workspace/dataset.zip', largeContent); console.log('Large file uploaded'); // Verify const files = await sandbox.files.list('/workspace'); const datasetFile = files.find(f => f.name === 'dataset.zip'); if (datasetFile) { console.log(`Uploaded: ${datasetFile.name} (${(datasetFile.size / 1024 / 1024).toFixed(2)} MB)`); } await sandbox.kill(); ``` ## Upload Multiple Files Upload multiple files in a loop: ```python theme={null} from hopx_ai import Sandbox import os sandbox = Sandbox.create(template="code-interpreter") # List of files to upload files_to_upload = [ ('./config.json', '/workspace/config.json'), ('./data.csv', '/workspace/data.csv'), ('./script.py', '/workspace/script.py') ] # Upload all files for local_path, remote_path in files_to_upload: if os.path.exists(local_path): sandbox.files.upload(local_path, remote_path) print(f"✅ Uploaded: {local_path} → {remote_path}") else: print(f"⚠️ File not found: {local_path}") # Verify all uploads files = sandbox.files.list('/workspace') print(f"\nUploaded {len(files)} files") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import * as fs from 'fs'; import * as path from 'path'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // List of files to upload const filesToUpload = [ ['./config.json', '/workspace/config.json'], ['./data.csv', '/workspace/data.csv'], ['./script.py', '/workspace/script.py'] ]; // Upload all files for (const [localPath, remotePath] of filesToUpload) { try { if (fs.existsSync(localPath)) { const content = fs.readFileSync(localPath, 'utf-8'); await sandbox.files.write(remotePath, content); console.log(`✅ Uploaded: ${localPath} → ${remotePath}`); } else { console.log(`⚠️ File not found: ${localPath}`); } } catch (error) { console.error(`Error uploading ${localPath}: ${error.message}`); } } // Verify all uploads const files = await sandbox.files.list('/workspace'); console.log(`\nUploaded ${files.length} files`); await sandbox.kill(); ``` ## Upload Binary Files Upload binary files (images, PDFs, etc.): ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Upload image file sandbox.files.upload('./image.png', '/workspace/image.png', timeout=60) print("Image uploaded") # Upload PDF sandbox.files.upload('./document.pdf', '/workspace/document.pdf', timeout=60) print("PDF uploaded") # Verify binary files files = sandbox.files.list('/workspace') for f in files: if f.name.endswith(('.png', '.pdf')): print(f"Binary file: {f.name} ({f.size_kb:.2f} KB)") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import * as fs from 'fs'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Upload image file const imageData = fs.readFileSync('./image.png'); await sandbox.files.writeBytes('/workspace/image.png', imageData); console.log('Image uploaded'); // Upload PDF const pdfData = fs.readFileSync('./document.pdf'); await sandbox.files.writeBytes('/workspace/document.pdf', pdfData); console.log('PDF uploaded'); // Verify binary files const files = await sandbox.files.list('/workspace'); for (const f of files) { if (f.name.endsWith('.png') || f.name.endsWith('.pdf')) { console.log(`Binary file: ${f.name} (${(f.size / 1024).toFixed(2)} KB)`); } } await sandbox.kill(); ``` ## Upload to Specific Directory Upload files to specific directories: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Create directory structure sandbox.files.mkdir('/workspace/project') sandbox.files.mkdir('/workspace/project/data') sandbox.files.mkdir('/workspace/project/src') # Upload to specific directories sandbox.files.upload('./dataset.csv', '/workspace/project/data/dataset.csv') sandbox.files.upload('./main.py', '/workspace/project/src/main.py') sandbox.files.upload('./config.json', '/workspace/project/config.json') # Verify structure print("Project structure:") for path in ['/workspace/project', '/workspace/project/data', '/workspace/project/src']: files = sandbox.files.list(path) print(f"\n{path}:") for f in files: print(f" {f.name}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import * as fs from 'fs'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Create directory structure await sandbox.files.mkdir('/workspace/project'); await sandbox.files.mkdir('/workspace/project/data'); await sandbox.files.mkdir('/workspace/project/src'); // Upload to specific directories const datasetContent = fs.readFileSync('./dataset.csv', 'utf-8'); await sandbox.files.write('/workspace/project/data/dataset.csv', datasetContent); const mainContent = fs.readFileSync('./main.py', 'utf-8'); await sandbox.files.write('/workspace/project/src/main.py', mainContent); const configContent = fs.readFileSync('./config.json', 'utf-8'); await sandbox.files.write('/workspace/project/config.json', configContent); // Verify structure console.log('Project structure:'); for (const dirPath of ['/workspace/project', '/workspace/project/data', '/workspace/project/src']) { const files = await sandbox.files.list(dirPath); console.log(`\n${dirPath}:`); for (const f of files) { console.log(` ${f.name}`); } } await sandbox.kill(); ``` ## Error Handling Handle upload errors: ```python theme={null} from hopx_ai import Sandbox from hopx_ai.errors import FileOperationError import os sandbox = Sandbox.create(template="code-interpreter") local_file = './data.csv' try: # Check if local file exists if not os.path.exists(local_file): print(f"Local file not found: {local_file}") else: # Upload with error handling sandbox.files.upload(local_file, '/workspace/data.csv', timeout=120) print("Upload successful") except FileOperationError as e: print(f"Upload failed: {e}") except Exception as e: print(f"Error: {e}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import * as fs from 'fs'; import { FileOperationError } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); const localFile = './data.csv'; try { // Check if local file exists if (!fs.existsSync(localFile)) { console.error(`Local file not found: ${localFile}`); } else { // Upload with error handling const content = fs.readFileSync(localFile, 'utf-8'); await sandbox.files.write('/workspace/data.csv', content); console.log('Upload successful'); } } catch (error) { if (error instanceof FileOperationError) { console.error(`Upload failed: ${error.message}`); } else { console.error(`Error: ${error.message}`); } } await sandbox.kill(); ``` ## Complete Example Here's a complete upload workflow: ```python theme={null} from hopx_ai import Sandbox import os sandbox = Sandbox.create(template="code-interpreter") # Create project structure sandbox.files.mkdir('/workspace/ml-project') sandbox.files.mkdir('/workspace/ml-project/data') sandbox.files.mkdir('/workspace/ml-project/models') # Upload project files files_to_upload = { './train.py': '/workspace/ml-project/train.py', './data/train.csv': '/workspace/ml-project/data/train.csv', './data/test.csv': '/workspace/ml-project/data/test.csv', './config.yaml': '/workspace/ml-project/config.yaml' } print("📤 Uploading files...") for local_path, remote_path in files_to_upload.items(): if os.path.exists(local_path): try: sandbox.files.upload(local_path, remote_path, timeout=120) file_size = os.path.getsize(local_path) / 1024 print(f" ✅ {local_path} → {remote_path} ({file_size:.2f} KB)") except Exception as e: print(f" ❌ Failed to upload {local_path}: {e}") else: print(f" ⚠️ File not found: {local_path}") # Verify uploads print("\n📋 Verifying uploads...") files = sandbox.files.list('/workspace/ml-project') total_size = 0 for f in files: if f.is_file: total_size += f.size print(f" 📄 {f.path} ({f.size_kb:.2f} KB)") print(f"\n✅ Total uploaded: {total_size / 1024:.2f} KB") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import * as fs from 'fs'; import * as path from 'path'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Create project structure await sandbox.files.mkdir('/workspace/ml-project'); await sandbox.files.mkdir('/workspace/ml-project/data'); await sandbox.files.mkdir('/workspace/ml-project/models'); // Upload project files const filesToUpload = { './train.py': '/workspace/ml-project/train.py', './data/train.csv': '/workspace/ml-project/data/train.csv', './data/test.csv': '/workspace/ml-project/data/test.csv', './config.yaml': '/workspace/ml-project/config.yaml' }; console.log('📤 Uploading files...'); let totalSize = 0; for (const [localPath, remotePath] of Object.entries(filesToUpload)) { try { if (fs.existsSync(localPath)) { const stats = fs.statSync(localPath); const content = fs.readFileSync(localPath, 'utf-8'); await sandbox.files.write(remotePath, content); const fileSize = stats.size / 1024; console.log(` ✅ ${localPath} → ${remotePath} (${fileSize.toFixed(2)} KB)`); totalSize += stats.size; } else { console.log(` ⚠️ File not found: ${localPath}`); } } catch (error) { console.error(` ❌ Failed to upload ${localPath}: ${error.message}`); } } // Verify uploads console.log('\n📋 Verifying uploads...'); const files = await sandbox.files.list('/workspace/ml-project'); for (const f of files) { if (f.isFile) { console.log(` 📄 ${f.path} (${(f.size / 1024).toFixed(2)} KB)`); } } console.log(`\n✅ Total uploaded: ${(totalSize / 1024).toFixed(2)} KB`); await sandbox.kill(); ``` ## Best Practices Always verify local files exist before attempting upload to avoid errors. For large files, set extended timeouts (60+ seconds) to avoid connection timeouts. Use `files.mkdir()` to create target directories before uploading files. Wrap uploads in try/catch blocks to handle network errors, file not found, etc. After uploading, verify files exist and check their sizes to ensure successful transfer. ## Related * **[Writing Files](/core-concepts/filesystem/writing)** - Write files directly in sandboxes * **[Downloading Files](/core-concepts/filesystem/downloading)** - Download files from sandboxes * **[Listing Files](/core-concepts/filesystem/listing)** - List directory contents * **SDK**: [sandbox.files.upload()](/sdk/python/files#upload) - Python SDK method * [CLI File Operations](/cli/commands/files) - File operations from CLI ## Next Steps * Learn about [Downloading Files](/core-concepts/filesystem/downloading) to retrieve files from sandboxes * Explore [Writing Files](/core-concepts/filesystem/writing) for programmatic file creation * Review [Listing Files](/core-concepts/filesystem/listing) to browse uploaded files # Watching Source: https://docs.hopx.ai/core-concepts/filesystem/watching Watch filesystem for real-time changes via WebSocket in HopX sandboxes. Monitor file and directory changes in real-time, receive notifications for file modifications, and react to filesystem events. Perfect for build systems, file processing pipelines, and real-time monitoring. Includes Python and JavaScript SDK examples and WebSocket API endpoints. Watch filesystem for real-time changes. Get notified immediately when files are created, modified, deleted, or renamed in your sandbox. ## Overview File watching is perfect for: * Real-time monitoring of file changes * Building reactive applications * Detecting when outputs are generated * Implementing file-based workflows File watching uses WebSocket connections for real-time communication. It requires async/await support and the websockets library (Python). ## Basic File Watching Watch a directory for changes: ```python theme={null} from hopx_ai import Sandbox import asyncio async def watch_files(): sandbox = Sandbox.create(template="code-interpreter") # Start watching print("👀 Watching /workspace for changes...") event_count = 0 async for event in sandbox.files.watch("/workspace"): event_type = event.get('event', 'unknown') path = event.get('path', '') print(f"{event_type}: {path}") event_count += 1 if event_count >= 10: print("Stopping after 10 events") break sandbox.kill() asyncio.run(watch_files()) ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; async function watchFiles() { const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Start watching console.log('👀 Watching /workspace for changes...'); let eventCount = 0; for await (const event of sandbox.files.watch('/workspace')) { const eventType = event.event || 'unknown'; const path = event.path || ''; console.log(`${eventType}: ${path}`); eventCount++; if (eventCount >= 10) { console.log('Stopping after 10 events'); break; } } await sandbox.kill(); } watchFiles(); ``` ## Event Types Handle different file system events: ```python theme={null} from hopx_ai import Sandbox import asyncio async def handle_all_events(): sandbox = Sandbox.create(template="code-interpreter") async for event in sandbox.files.watch("/workspace"): event_type = event.get('event', 'unknown') path = event.get('path', '') timestamp = event.get('timestamp', '') if event_type == 'created': print(f"📄 Created: {path}") elif event_type == 'modified': print(f"✏️ Modified: {path}") elif event_type == 'deleted': print(f"🗑️ Deleted: {path}") elif event_type == 'renamed': old_path = event.get('old_path', '') print(f"📝 Renamed: {old_path} → {path}") else: print(f"❓ Unknown event: {event_type} - {path}") asyncio.run(handle_all_events()) ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; async function handleAllEvents() { const sandbox = await Sandbox.create({ template: 'code-interpreter' }); for await (const event of sandbox.files.watch('/workspace')) { const eventType = event.event || 'unknown'; const path = event.path || ''; const timestamp = event.timestamp || ''; if (eventType === 'created') { console.log(`📄 Created: ${path}`); } else if (eventType === 'modified') { console.log(`✏️ Modified: ${path}`); } else if (eventType === 'deleted') { console.log(`🗑️ Deleted: ${path}`); } else if (eventType === 'renamed') { const oldPath = event.old_path || ''; console.log(`📝 Renamed: ${oldPath} → ${path}`); } else { console.log(`❓ Unknown event: ${eventType} - ${path}`); } } await sandbox.kill(); } handleAllEvents(); ``` ## Monitoring File Generation Watch for generated output files: ```python theme={null} from hopx_ai import Sandbox import asyncio async def monitor_outputs(): sandbox = Sandbox.create(template="code-interpreter") # Start background task that generates files sandbox.run_code_background(''' import time import json for i in range(5): data = {"step": i, "value": i * 2} with open(f'/workspace/output_{i}.json', 'w') as f: json.dump(data, f) time.sleep(2) ''', name='file-generator') # Watch for new files print("👀 Watching for output files...") output_files = [] async for event in sandbox.files.watch("/workspace"): if event.get('event') == 'created': path = event.get('path', '') if path.startswith('/workspace/output_'): output_files.append(path) print(f"✅ New output: {path}") if len(output_files) >= 5: print("All outputs generated!") break print(f"\nGenerated {len(output_files)} files") sandbox.kill() asyncio.run(monitor_outputs()) ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; async function monitorOutputs() { const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Start background task that generates files await sandbox.runCodeBackground(` import time import json for i in range(5): data = {"step": i, "value": i * 2} with open(f'/workspace/output_{i}.json', 'w') as f: json.dump(data, f) time.sleep(2) `, { name: 'file-generator' }); // Watch for new files console.log('👀 Watching for output files...'); const outputFiles = []; for await (const event of sandbox.files.watch('/workspace')) { if (event.event === 'created') { const path = event.path || ''; if (path.startsWith('/workspace/output_')) { outputFiles.push(path); console.log(`✅ New output: ${path}`); if (outputFiles.length >= 5) { console.log('All outputs generated!'); break; } } } } console.log(`\nGenerated ${outputFiles.length} files`); await sandbox.kill(); } monitorOutputs(); ``` ## Filtering Events Filter events by type or path: ```python theme={null} from hopx_ai import Sandbox import asyncio async def filter_events(): sandbox = Sandbox.create(template="code-interpreter") # Only watch for Python files async for event in sandbox.files.watch("/workspace"): event_type = event.get('event', '') path = event.get('path', '') # Only process Python files if path.endswith('.py'): if event_type == 'created': print(f"📄 New Python file: {path}") elif event_type == 'modified': print(f"✏️ Python file modified: {path}") elif event_type == 'deleted': print(f"🗑️ Python file deleted: {path}") asyncio.run(filter_events()) ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; async function filterEvents() { const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Only watch for Python files for await (const event of sandbox.files.watch('/workspace')) { const eventType = event.event || ''; const path = event.path || ''; // Only process Python files if (path.endsWith('.py')) { if (eventType === 'created') { console.log(`📄 New Python file: ${path}`); } else if (eventType === 'modified') { console.log(`✏️ Python file modified: ${path}`); } else if (eventType === 'deleted') { console.log(`🗑️ Python file deleted: ${path}`); } } } await sandbox.kill(); } filterEvents(); ``` ## Complete Example Here's a complete file watching workflow: ```python theme={null} from hopx_ai import Sandbox import asyncio async def complete_watch_example(): sandbox = Sandbox.create(template="code-interpreter") # Start a task that creates/modifies files sandbox.run_code_background(''' import time import json # Create initial file with open('/workspace/status.json', 'w') as f: json.dump({"status": "starting"}, f) time.sleep(1) # Modify file with open('/workspace/status.json', 'w') as f: json.dump({"status": "processing"}, f) time.sleep(1) # Create output file with open('/workspace/result.txt', 'w') as f: f.write("Processing complete") time.sleep(1) # Delete status file import os os.remove('/workspace/status.json') ''', name='file-operations') # Watch for all events print("👀 Watching filesystem...\n") events_received = [] async for event in sandbox.files.watch("/workspace"): event_type = event.get('event', 'unknown') path = event.get('path', '') timestamp = event.get('timestamp', '') events_received.append({ 'type': event_type, 'path': path, 'timestamp': timestamp }) # Display event icons = { 'created': '📄', 'modified': '✏️', 'deleted': '🗑️', 'renamed': '📝' } icon = icons.get(event_type, '❓') print(f"{icon} {event_type.upper()}: {path}") # Stop after receiving all expected events if len(events_received) >= 4: print("\n✅ All events received") break # Summary print(f"\n📊 Summary: Received {len(events_received)} events") for e in events_received: print(f" - {e['type']}: {e['path']}") sandbox.kill() asyncio.run(complete_watch_example()) ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; async function completeWatchExample() { const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Start a task that creates/modifies files await sandbox.runCodeBackground(` import time import json # Create initial file with open('/workspace/status.json', 'w') as f: json.dump({"status": "starting"}, f) time.sleep(1) # Modify file with open('/workspace/status.json', 'w') as f: json.dump({"status": "processing"}, f) time.sleep(1) # Create output file with open('/workspace/result.txt', 'w') as f: f.write("Processing complete") time.sleep(1) # Delete status file import os os.remove('/workspace/status.json') `, { name: 'file-operations' }); // Watch for all events console.log('👀 Watching filesystem...\n'); const eventsReceived = []; for await (const event of sandbox.files.watch('/workspace')) { const eventType = event.event || 'unknown'; const path = event.path || ''; const timestamp = event.timestamp || ''; eventsReceived.push({ type: eventType, path: path, timestamp: timestamp }); // Display event const icons = { 'created': '📄', 'modified': '✏️', 'deleted': '🗑️', 'renamed': '📝' }; const icon = icons[eventType] || '❓'; console.log(`${icon} ${eventType.toUpperCase()}: ${path}`); // Stop after receiving all expected events if (eventsReceived.length >= 4) { console.log('\n✅ All events received'); break; } } // Summary console.log(`\n📊 Summary: Received ${eventsReceived.length} events`); for (const e of eventsReceived) { console.log(` - ${e.type}: ${e.path}`); } await sandbox.kill(); } completeWatchExample(); ``` ## Best Practices File watching requires async/await. Make sure your code uses async functions and `async for` loops. Filter events by type or path pattern to process only relevant changes. Process created, modified, deleted, and renamed events appropriately for your use case. Consider setting timeouts or event count limits to avoid infinite watching. Always break the watch loop and clean up connections when done. ## Related * **[Listing Files](/core-concepts/filesystem/listing)** - List directory contents * **[Reading Files](/core-concepts/filesystem/reading)** - Read file contents * **[Writing Files](/core-concepts/filesystem/writing)** - Write files to sandboxes * **SDK**: [sandbox.files.watch()](/sdk/python/files#watch) - Python SDK method * [CLI File Operations](/cli/commands/files) - File operations from CLI ## Next Steps * Learn about [Reading Files](/core-concepts/filesystem/reading) to access file contents * Explore [Writing Files](/core-concepts/filesystem/writing) to create files * Review [Listing Files](/core-concepts/filesystem/listing) to browse directories # Writing Source: https://docs.hopx.ai/core-concepts/filesystem/writing Write text and binary files to sandboxes. Learn how to create and write files in HopX sandboxes using Python and JavaScript SDKs or REST API. Includes examples for writing text files, binary files, handling encoding, appending content, and managing file permissions. Perfect for creating configuration files, data files, and scripts. Write files to your sandbox filesystem. HopX supports both text and binary file writing with automatic encoding and permission handling. ## Overview File writing is essential for: * Creating scripts and code files * Saving generated data and results * Writing configuration files * Storing outputs from computations Files can be written to allowed paths like `/workspace` and `/tmp`. Writing to system directories may be restricted for security. ## Writing Text Files Write text files as strings: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Write a simple text file sandbox.files.write('/workspace/hello.txt', 'Hello, World!') print("File written successfully") # Read it back content = sandbox.files.read('/workspace/hello.txt') print(f"Content: {content}") sandbox.kill() ``` **Expected Output:** ``` File written successfully Content: Hello, World! ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Write a simple text file await sandbox.files.write('/workspace/hello.txt', 'Hello, World!'); console.log('File written successfully'); // Read it back const content = await sandbox.files.read('/workspace/hello.txt'); console.log(`Content: ${content}`); await sandbox.kill(); ``` **Expected Output:** ``` File written successfully Content: Hello, World! ``` ## Writing Multi-line Files Write files with multiple lines: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Write multi-line content content = '''Line 1 Line 2 Line 3 ''' sandbox.files.write('/workspace/multiline.txt', content) # Verify read_content = sandbox.files.read('/workspace/multiline.txt') print(read_content) sandbox.kill() ``` **Expected Output:** ``` Line 1 Line 2 Line 3 ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Write multi-line content const content = `Line 1 Line 2 Line 3 `; await sandbox.files.write('/workspace/multiline.txt', content); // Verify const readContent = await sandbox.files.read('/workspace/multiline.txt'); console.log(readContent); await sandbox.kill(); ``` **Expected Output:** ``` Line 1 Line 2 Line 3 ``` ## Writing Binary Files Write binary files (images, PDFs, etc.): ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Read binary data from local file with open('local_image.png', 'rb') as f: image_data = f.read() # Write to sandbox sandbox.files.write_bytes('/workspace/image.png', image_data) print("Binary file written") # Verify read_data = sandbox.files.read_bytes('/workspace/image.png') print(f"Read back: {len(read_data)} bytes") sandbox.kill() ``` **Expected Output:** ``` Binary file written Read back: 245760 bytes ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import * as fs from 'fs'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Read binary data from local file const imageData = fs.readFileSync('local_image.png'); // Write to sandbox await sandbox.files.writeBytes('/workspace/image.png', imageData); console.log('Binary file written'); // Verify const readData = await sandbox.files.readBytes('/workspace/image.png'); console.log(`Read back: ${readData.length} bytes`); await sandbox.kill(); ``` **Expected Output:** ``` Binary file written Read back: 245760 bytes ``` ## Writing Code Files Write and execute code files: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Write a Python script script = ''' def calculate_sum(numbers): return sum(numbers) result = calculate_sum([1, 2, 3, 4, 5]) print(f"Sum: {result}") ''' sandbox.files.write('/workspace/calculator.py', script) # Execute the script result = sandbox.run_code( 'exec(open("/workspace/calculator.py").read())', language='python' ) print(result.stdout) # "Sum: 15" sandbox.kill() ``` **Expected Output:** ``` Sum: 15 ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Write a Python script const script = ` def calculate_sum(numbers): return sum(numbers) result = calculate_sum([1, 2, 3, 4, 5]) print(f"Sum: {result}") `; await sandbox.files.write('/workspace/calculator.py', script); // Execute the script const result = await sandbox.runCode( 'exec(open("/workspace/calculator.py").read())', { language: 'python' } ); console.log(result.stdout); // "Sum: 15" await sandbox.kill(); ``` **Expected Output:** ``` Sum: 15 ``` ## File Permissions Set file permissions when writing: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Write executable script with permissions script = '#!/bin/bash\necho "Hello from bash!"' sandbox.files.write('/workspace/script.sh', script, mode='0755') print("Executable script created") # Write regular file with default permissions sandbox.files.write('/workspace/data.txt', 'Some data', mode='0644') print("Regular file created") sandbox.kill() ``` **Expected Output:** ``` Executable script created Regular file created ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Write executable script (permissions handled automatically) const script = '#!/bin/bash\necho "Hello from bash!"'; await sandbox.files.write('/workspace/script.sh', script); console.log('Script created'); // Write regular file await sandbox.files.write('/workspace/data.txt', 'Some data'); console.log('Regular file created'); await sandbox.kill(); ``` **Expected Output:** ``` Script created Regular file created ``` ## Writing Configuration Files Write JSON, YAML, or other configuration files: ```python theme={null} from hopx_ai import Sandbox import json sandbox = Sandbox.create(template="code-interpreter") # Write JSON config config = { "api_key": "sk-123", "debug": True, "timeout": 30 } config_json = json.dumps(config, indent=2) sandbox.files.write('/workspace/config.json', config_json) # Read and verify read_config = json.loads(sandbox.files.read('/workspace/config.json')) print(f"Config written: {read_config}") sandbox.kill() ``` **Expected Output:** ``` Config written: {'api_key': 'sk-123', 'debug': True, 'timeout': 30} ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Write JSON config const config = { api_key: 'sk-123', debug: true, timeout: 30 }; const configJson = JSON.stringify(config, null, 2); await sandbox.files.write('/workspace/config.json', configJson); // Read and verify const readConfig = JSON.parse(await sandbox.files.read('/workspace/config.json')); console.log(`Config written: ${JSON.stringify(readConfig)}`); await sandbox.kill(); ``` **Expected Output:** ``` Config written: {"api_key":"sk-123","debug":true,"timeout":30} ``` ## Writing Large Files For large files, consider chunking or using upload: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Write large content large_content = "x" * 1000000 # 1MB of data sandbox.files.write('/workspace/large.txt', large_content, timeout=120) print("Large file written") # Verify size files = sandbox.files.list('/workspace') for f in files: if f.name == 'large.txt': print(f"File size: {f.size_kb:.2f} KB") sandbox.kill() ``` **Expected Output:** ``` Large file written File size: 976.56 KB ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Write large content const largeContent = 'x'.repeat(1000000); // 1MB of data await sandbox.files.write('/workspace/large.txt', largeContent); console.log('Large file written'); // Verify size const files = await sandbox.files.list('/workspace'); const largeFile = files.find(f => f.name === 'large.txt'); if (largeFile) { console.log(`File size: ${(largeFile.size / 1024).toFixed(2)} KB`); } await sandbox.kill(); ``` **Expected Output:** ``` Large file written File size: 976.56 KB ``` ## Complete Example Here's a complete example showing file writing workflow: ```python theme={null} from hopx_ai import Sandbox import json sandbox = Sandbox.create(template="code-interpreter") # Create directory structure sandbox.files.mkdir('/workspace/project') sandbox.files.mkdir('/workspace/project/src') sandbox.files.mkdir('/workspace/project/data') # Write code file code = ''' def process_data(data): return [x * 2 for x in data] if __name__ == "__main__": result = process_data([1, 2, 3]) print(result) ''' sandbox.files.write('/workspace/project/src/main.py', code) # Write config file config = {"batch_size": 32, "epochs": 10} sandbox.files.write('/workspace/project/config.json', json.dumps(config, indent=2)) # Write data file data = "1,2,3\n4,5,6\n7,8,9\n" sandbox.files.write('/workspace/project/data/input.csv', data) # List all files files = sandbox.files.list('/workspace/project') print("Created files:") for f in files: if f.is_file: print(f" 📄 {f.path} ({f.size_kb:.2f} KB)") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Create directory structure await sandbox.files.mkdir('/workspace/project'); await sandbox.files.mkdir('/workspace/project/src'); await sandbox.files.mkdir('/workspace/project/data'); // Write code file const code = ` def process_data(data): return [x * 2 for x in data] if __name__ == "__main__": result = process_data([1, 2, 3]) print(result) `; await sandbox.files.write('/workspace/project/src/main.py', code); // Write config file const config = { batch_size: 32, epochs: 10 }; await sandbox.files.write('/workspace/project/config.json', JSON.stringify(config, null, 2)); // Write data file const data = '1,2,3\n4,5,6\n7,8,9\n'; await sandbox.files.write('/workspace/project/data/input.csv', data); // List all files const files = await sandbox.files.list('/workspace/project'); console.log('Created files:'); for (const f of files) { if (f.isFile) { console.log(` 📄 ${f.path} (${(f.size / 1024).toFixed(2)} KB)`); } } await sandbox.kill(); ``` ## Best Practices Use `write()` for text files and `write_bytes()` for binary files (images, PDFs, etc.). Set appropriate file permissions (e.g., '0755' for executables, '0644' for regular files). Use `files.mkdir()` to create directories before writing files in them. For very large files, consider using [Upload](/core-concepts/filesystem/uploading) instead of writing directly. Only write to allowed paths like `/workspace` and `/tmp`. System directories may be restricted. ## Related * **[Reading Files](/core-concepts/filesystem/reading)** - Read files from sandboxes * **[Listing Files](/core-concepts/filesystem/listing)** - List directory contents * **SDK**: [sandbox.files.write()](/sdk/python/files#write) - Python SDK method * **API**: [POST /files/write](/api/vm-agent/write-file) - VM Agent API endpoint * [CLI File Operations](/cli/commands/files) - File operations from CLI ## Next Steps * Learn about [Reading Files](/core-concepts/filesystem/reading) to retrieve file contents * Explore [Listing Files](/core-concepts/filesystem/listing) to browse directories * Review [Uploading Files](/core-concepts/filesystem/uploading) for local file transfers # Observability Source: https://docs.hopx.ai/core-concepts/observability/index Complete guide to monitoring HopX sandboxes - metrics, processes, and system information for observability and debugging. Monitor CPU, memory, and disk usage, list and track running processes, view system metrics, and use observability features for performance optimization and troubleshooting. Includes SDK and API examples. Monitor and observe HopX sandboxes with comprehensive metrics, process monitoring, and system information. This hub covers all observability features for debugging and performance optimization. ## Related * [CLI System Commands](/cli/commands/system) - System operations from CLI ## What You'll Learn * How to monitor sandbox metrics (CPU, memory, disk) * How to list and monitor processes * How to track system information and health * How to use observability for debugging * How to optimize performance based on metrics ## Observability Overview | Feature | SDK Method | API Endpoint | | --------------------------------------------------------- | ----------------------------- | --------------------- | | **[Metrics](/core-concepts/observability/metrics)** | `sandbox.get_agent_metrics()` | `GET /system/metrics` | | **[Processes](/core-concepts/observability/processes)** | `sandbox.list_processes()` | `GET /processes` | | **[Monitoring](/core-concepts/observability/monitoring)** | Monitoring utilities | Monitoring endpoints | ## Core Concepts ### Metrics Monitor CPU, memory, disk, and other system metrics. * **[Metrics](/core-concepts/observability/metrics)** - Monitor system metrics * **SDK**: [Python: sandbox.get\_agent\_metrics()](/sdk/python/sandbox#get_agent_metrics) | [JavaScript: sandbox.getAgentMetrics()](/sdk/javascript/sandbox#getagentmetrics) * **API**: [GET /system/metrics](/api/vm-agent/get-system-metrics) ### Processes List and monitor running processes in sandboxes. * **[Processes](/core-concepts/observability/processes)** - Monitor processes * **SDK**: [Python: sandbox.list\_processes()](/sdk/python/sandbox#list_processes) | [JavaScript: sandbox.listProcesses()](/sdk/javascript/sandbox#listprocesses) * **API**: [GET /processes](/api/vm-agent/list-processes) | [GET /processes/system](/api/vm-agent/list-system-processes) ### Monitoring Comprehensive monitoring strategies and best practices. * **[Monitoring](/core-concepts/observability/monitoring)** - Monitoring strategies * **SDK**: Monitoring utilities | **API**: Monitoring endpoints ## SDK Reference ### Python SDK Complete reference for Python observability operations. * **[Sandbox.get\_agent\_metrics()](/sdk/python/sandbox#get_agent_metrics)** - Get system metrics * **[Sandbox.list\_processes()](/sdk/python/sandbox#list_processes)** - List processes * **[Sandbox.get\_metrics\_snapshot()](/sdk/python/sandbox#get_metrics_snapshot)** - Get metrics snapshot ### JavaScript SDK Complete reference for JavaScript/TypeScript observability operations. * **[Sandbox.getAgentMetrics()](/sdk/javascript/sandbox#getagentmetrics)** - Get system metrics * **[Sandbox.listProcesses()](/sdk/javascript/sandbox#listprocesses)** - List processes * **[Sandbox.getMetricsSnapshot()](/sdk/javascript/sandbox#getmetricssnapshot)** - Get metrics snapshot ## API Reference ### VM Agent API REST API endpoints for observability. * **[VM Agent API Overview](/api/vm-agent/overview)** - API overview * **[Get System Metrics](/api/vm-agent/get-system-metrics)** - `GET /system/metrics` - Get metrics * **[List Processes](/api/vm-agent/list-processes)** - `GET /processes` - List background processes * **[List System Processes](/api/vm-agent/list-system-processes)** - `GET /processes/system` - List all processes ## Quick Start If you're new to observability, start here: 1. **[Metrics](/core-concepts/observability/metrics)** - Monitor system metrics 2. **[Processes](/core-concepts/observability/processes)** - Monitor running processes 3. **[Monitoring](/core-concepts/observability/monitoring)** - Set up monitoring ## Related Topics * **[Code Execution](/core-concepts/code-execution/background)** - Monitor background execution * **[Sandboxes](/core-concepts/sandboxes/managing-state)** - Monitor sandbox state * **[Process Management](/core-concepts/code-execution/process-management)** - Manage processes * **[Cache Management](/core-concepts/cache/statistics)** - Monitor cache usage ## Next Steps * Learn about [Metrics](/core-concepts/observability/metrics) for system monitoring * Explore [Processes](/core-concepts/observability/processes) for process monitoring * Review [Monitoring](/core-concepts/observability/monitoring) for comprehensive strategies * Check out [Code Execution](/core-concepts/code-execution/background) for execution monitoring # System Metrics Source: https://docs.hopx.ai/core-concepts/observability/metrics Get agent performance metrics including uptime, execution counts, and error rates. Monitor CPU, memory, and disk usage in HopX sandboxes to optimize performance and troubleshoot issues. Learn how to retrieve system metrics, track resource usage over time, and use metrics for capacity planning. Includes Python and JavaScript SDK examples and REST API endpoints. Monitor your sandbox's agent performance in real-time with execution metrics. Track uptime, execution counts, error rates, and per-endpoint statistics to optimize your workloads and troubleshoot issues. ## Overview HopX provides agent performance metrics to monitor sandbox execution performance: * **Agent Metrics**: Agent performance metrics including uptime, execution counts, error rates, and per-endpoint statistics Both `get_metrics_snapshot()` and `get_agent_metrics()` return agent performance metrics. They provide the same data structure. ## Agent Metrics Snapshot Get a snapshot of current agent performance metrics: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Get agent metrics snapshot metrics = sandbox.get_metrics_snapshot() print(f"Uptime: {metrics['uptime_seconds']} seconds") print(f"Total Executions: {metrics['total_executions']}") print(f"Active Executions: {metrics['active_executions']}") print(f"Error Count: {metrics['error_count']}") # Per-endpoint statistics if 'requests_total' in metrics: print("\nRequests by Endpoint:") for endpoint, count in metrics['requests_total'].items(): print(f" {endpoint}: {count}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Get agent metrics snapshot const metrics = await sandbox.getMetricsSnapshot(); console.log(`Uptime: ${metrics.uptime_seconds} seconds`); console.log(`Total Executions: ${metrics.total_executions}`); console.log(`Active Executions: ${metrics.active_executions}`); console.log(`Error Count: ${metrics.error_count}`); // Per-endpoint statistics if (metrics.requests_total) { console.log('\nRequests by Endpoint:'); for (const [endpoint, count] of Object.entries(metrics.requests_total)) { console.log(` ${endpoint}: ${count}`); } } await sandbox.kill(); ``` ## Agent Performance Metrics Get detailed agent performance metrics: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Get agent metrics agent_metrics = sandbox.get_agent_metrics() print(f"Agent Uptime: {agent_metrics['uptime_seconds']} seconds") print(f"Total Executions: {agent_metrics['total_executions']}") print(f"Active Executions: {agent_metrics['active_executions']}") print(f"Error Count: {agent_metrics['error_count']}") # Per-endpoint metrics if 'requests_total' in agent_metrics: print("\nRequests by Endpoint:") for endpoint, count in agent_metrics['requests_total'].items(): print(f" {endpoint}: {count}") if 'avg_duration_ms' in agent_metrics: print("\nAverage Duration by Endpoint:") for endpoint, duration in agent_metrics['avg_duration_ms'].items(): print(f" {endpoint}: {duration:.2f} ms") if 'p95_duration_ms' in agent_metrics: print("\nP95 Duration by Endpoint:") for endpoint, duration in agent_metrics['p95_duration_ms'].items(): print(f" {endpoint}: {duration:.2f} ms") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Get agent metrics const agentMetrics = await sandbox.getAgentMetrics(); console.log(`Agent Uptime: ${agentMetrics.uptime_seconds} seconds`); console.log(`Total Executions: ${agentMetrics.total_executions}`); console.log(`Active Executions: ${agentMetrics.active_executions}`); console.log(`Error Count: ${agentMetrics.error_count}`); // Per-endpoint metrics if (agentMetrics.requests_total) { console.log('\nRequests by Endpoint:'); for (const [endpoint, count] of Object.entries(agentMetrics.requests_total)) { console.log(` ${endpoint}: ${count}`); } } if (agentMetrics.avg_duration_ms) { console.log('\nAverage Duration by Endpoint:'); for (const [endpoint, duration] of Object.entries(agentMetrics.avg_duration_ms)) { console.log(` ${endpoint}: ${duration.toFixed(2)} ms`); } } if (agentMetrics.p95_duration_ms) { console.log('\nP95 Duration by Endpoint:'); for (const [endpoint, duration] of Object.entries(agentMetrics.p95_duration_ms)) { console.log(` ${endpoint}: ${duration.toFixed(2)} ms`); } } await sandbox.kill(); ``` ## Monitoring Agent Performance Monitor agent metrics over time to track performance: ```python theme={null} from hopx_ai import Sandbox import time sandbox = Sandbox.create(template="code-interpreter") # Monitor metrics every 5 seconds for i in range(5): metrics = sandbox.get_metrics_snapshot() print(f"Snapshot {i+1}:") print(f" Uptime: {metrics['uptime_seconds']}s") print(f" Total Executions: {metrics['total_executions']}") print(f" Active Executions: {metrics['active_executions']}") print(f" Error Count: {metrics['error_count']}") if i < 4: # Don't sleep after last iteration time.sleep(5) sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Monitor metrics every 5 seconds for (let i = 0; i < 5; i++) { const metrics = await sandbox.getMetricsSnapshot(); console.log(`Snapshot ${i+1}:`); console.log(` Uptime: ${metrics.uptime_seconds}s`); console.log(` Total Executions: ${metrics.total_executions}`); console.log(` Active Executions: ${metrics.active_executions}`); console.log(` Error Count: ${metrics.error_count}`); if (i < 4) { // Don't sleep after last iteration await new Promise(resolve => setTimeout(resolve, 5000)); } } await sandbox.kill(); ``` ## Metrics Structure ### Agent Metrics Response Both `get_metrics_snapshot()` and `get_agent_metrics()` return the same structure: ```json theme={null} { "uptime_seconds": 1234, "total_executions": 1250, "active_executions": 2, "error_count": 3, "requests_total": { "/execute": 800, "/files/read": 300, "/files/write": 150 }, "avg_duration_ms": { "/execute": 1250.5, "/files/read": 45.2, "/files/write": 78.9 }, "p95_duration_ms": { "/execute": 2500.0, "/files/read": 100.0, "/files/write": 150.0 } } ``` ### Field Descriptions * **`uptime_seconds`**: Agent uptime in seconds * **`total_executions`**: Total number of code executions processed * **`active_executions`**: Currently running executions * **`error_count`**: Total number of errors encountered * **`requests_total`**: Per-endpoint request counts * **`avg_duration_ms`**: Average request duration by endpoint (milliseconds) * **`p95_duration_ms`**: 95th percentile request duration by endpoint (milliseconds) ## Use Cases ### Monitoring Execution Performance Monitor agent performance during code execution: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Get baseline metrics baseline = sandbox.get_metrics_snapshot() print(f"Baseline Executions: {baseline['total_executions']}") print(f"Baseline Errors: {baseline['error_count']}") # Run some code sandbox.run_code(""" import time for i in range(5): print(f"Step {i+1}") time.sleep(0.1) """) # Check metrics after execution after = sandbox.get_metrics_snapshot() print(f"After Execution - Total: {after['total_executions']}") print(f"After Execution - Errors: {after['error_count']}") print(f"Executions Added: {after['total_executions'] - baseline['total_executions']}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Get baseline metrics const baseline = await sandbox.getMetricsSnapshot(); console.log(`Baseline Executions: ${baseline.total_executions}`); console.log(`Baseline Errors: ${baseline.error_count}`); // Run some code await sandbox.runCode(` import time for i in range(5): print(f"Step {i+1}") time.sleep(0.1) `); // Check metrics after execution const after = await sandbox.getMetricsSnapshot(); console.log(`After Execution - Total: ${after.total_executions}`); console.log(`After Execution - Errors: ${after.error_count}`); console.log(`Executions Added: ${after.total_executions - baseline.total_executions}`); await sandbox.kill(); ``` ### Performance Analysis Analyze agent performance to identify bottlenecks: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Get agent metrics metrics = sandbox.get_agent_metrics() # Calculate error rate if metrics['total_executions'] > 0: error_rate = (metrics['error_count'] / metrics['total_executions']) * 100 print(f"Error Rate: {error_rate:.2f}%") else: print("No executions yet") # Find slowest endpoint if 'avg_duration_ms' in metrics and metrics['avg_duration_ms']: slowest = max(metrics['avg_duration_ms'].items(), key=lambda x: x[1]) print(f"Slowest Endpoint: {slowest[0]} ({slowest[1]:.2f} ms)") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Get agent metrics const metrics = await sandbox.getAgentMetrics(); // Calculate error rate if (metrics.total_executions > 0) { const errorRate = (metrics.error_count / metrics.total_executions) * 100; console.log(`Error Rate: ${errorRate.toFixed(2)}%`); } else { console.log('No executions yet'); } // Find slowest endpoint if (metrics.avg_duration_ms && Object.keys(metrics.avg_duration_ms).length > 0) { const slowest = Object.entries(metrics.avg_duration_ms) .reduce((a, b) => a[1] > b[1] ? a : b); console.log(`Slowest Endpoint: ${slowest[0]} (${slowest[1].toFixed(2)} ms)`); } await sandbox.kill(); ``` ## Best Practices **Monitor metrics before and after operations** to track execution performance and identify bottlenecks or error patterns. **Use agent metrics** to identify frequently used endpoints and optimize your code patterns accordingly. **Metrics are snapshots**, not continuous monitoring. For real-time streaming metrics, use the [monitoring endpoint](/core-concepts/observability/monitoring) with SSE. **Check agent version** before using agent metrics. Use `sandbox.get_agent_info()` to verify v3.1.0+ support. ## API Reference ### Python SDK * `sandbox.get_metrics_snapshot()` - Get agent performance metrics snapshot * `sandbox.get_agent_metrics()` - Get agent performance metrics (same as get\_metrics\_snapshot) ### JavaScript SDK * `sandbox.getMetricsSnapshot()` - Get agent performance metrics snapshot * `sandbox.getAgentMetrics()` - Get agent performance metrics (same as getMetricsSnapshot) ### API Endpoints * **GET** `/metrics/snapshot` - Get agent performance metrics snapshot ## Related * **[Process Monitoring](/core-concepts/observability/processes)** - Monitor running processes * **SDK**: [sandbox.get\_agent\_metrics()](/sdk/python/sandbox#get_agent_metrics) - Python SDK method * **API**: [GET /system](/api/vm-agent/get-system-metrics) - VM Agent API endpoint * [CLI System Commands](/cli/commands/system) - System operations from CLI ## Next Steps * Learn about [Process Monitoring](/core-concepts/observability/processes) to track running processes * Explore [Code Execution](/core-concepts/code-execution/synchronous) to execute code in sandboxes * Review [Managing Sandbox State](/core-concepts/sandboxes/managing-state) for lifecycle control # Monitoring Source: https://docs.hopx.ai/core-concepts/observability/monitoring Real-time monitoring and streaming metrics via Server-Sent Events (SSE) in HopX sandboxes. Stream sandbox events, monitor system metrics in real-time, track resource usage, and receive live updates via SSE. Perfect for dashboards, alerting, and real-time monitoring. Includes Python and JavaScript SDK examples and SSE endpoints. Stream real-time metrics from your sandbox using Server-Sent Events (SSE). This provides continuous monitoring of agent performance metrics without polling. ## Overview SSE monitoring is ideal for: * Real-time dashboards and visualizations * Continuous agent performance monitoring * Alerting on threshold breaches * Long-term performance tracking SSE monitoring is available through the Control Plane API endpoint `/v1/sandboxes/:id/metrics/stream`. This streams metrics from the VM agent to your application. ## Basic Streaming Connect to the metrics stream and receive real-time updates: ```python theme={null} import requests from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") info = sandbox.get_info() # Get API key and base URL api_key = sandbox._api_key # Access internal API key base_url = "https://api.hopx.dev" # Stream metrics via SSE headers = { "Authorization": f"Bearer {api_key}", "Accept": "text/event-stream" } stream_url = f"{base_url}/v1/sandboxes/{sandbox.sandbox_id}/metrics/stream" with requests.get(stream_url, headers=headers, stream=True) as response: for line in response.iter_lines(): if line and line.startswith(b"data: "): import json data = json.loads(line[6:]) # Skip "data: " prefix print(f"Uptime: {data.get('uptime_seconds', 0)}s") print(f"Total Executions: {data.get('total_executions', 0)}") print(f"Active Executions: {data.get('active_executions', 0)}") print(f"Error Count: {data.get('error_count', 0)}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import EventSource from 'eventsource'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); const info = await sandbox.getInfo(); // Get API key and base URL const apiKey = sandbox.apiKey; // Access API key const baseUrl = 'https://api.hopx.dev'; // Stream metrics via SSE const streamUrl = `${baseUrl}/v1/sandboxes/${sandbox.sandboxId}/metrics/stream?token=${apiKey}`; const eventSource = new EventSource(streamUrl); eventSource.onmessage = (event) => { const data = JSON.parse(event.data); console.log(`Uptime: ${data.uptime_seconds || 0}s`); console.log(`Total Executions: ${data.total_executions || 0}`); console.log(`Active Executions: ${data.active_executions || 0}`); console.log(`Error Count: ${data.error_count || 0}`); }; eventSource.onerror = (error) => { console.error('SSE error:', error); eventSource.close(); }; // Close after 30 seconds setTimeout(() => { eventSource.close(); sandbox.kill(); }, 30000); ``` ## Processing Stream Events Handle different event types from the SSE stream: ```python theme={null} import requests import json from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") info = sandbox.get_info() api_key = sandbox._api_key base_url = "https://api.hopx.dev" headers = { "Authorization": f"Bearer {api_key}", "Accept": "text/event-stream" } stream_url = f"{base_url}/v1/sandboxes/{sandbox.sandbox_id}/metrics/stream" with requests.get(stream_url, headers=headers, stream=True) as response: for line in response.iter_lines(): if not line: continue line_str = line.decode('utf-8') # Handle different SSE event types if line_str.startswith("event: "): event_type = line_str[7:] print(f"Event type: {event_type}") elif line_str.startswith("data: "): data = json.loads(line_str[6:]) # Process metrics data print(f"Metrics - Uptime: {data.get('uptime_seconds', 0)}s") print(f" Total Executions: {data.get('total_executions', 0)}") print(f" Active Executions: {data.get('active_executions', 0)}") print(f" Error Count: {data.get('error_count', 0)}") elif line_str.startswith("id: "): event_id = line_str[4:] # Use event ID for reconnection logic if needed sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import EventSource from 'eventsource'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); const info = await sandbox.getInfo(); const apiKey = sandbox.apiKey; const baseUrl = 'https://api.hopx.dev'; const streamUrl = `${baseUrl}/v1/sandboxes/${sandbox.sandboxId}/metrics/stream?token=${apiKey}`; const eventSource = new EventSource(streamUrl); // Handle different event types eventSource.addEventListener('message', (event) => { const data = JSON.parse(event.data); console.log(`Metrics - Uptime: ${data.uptime_seconds || 0}s`); console.log(` Total Executions: ${data.total_executions || 0}`); console.log(` Active Executions: ${data.active_executions || 0}`); console.log(` Error Count: ${data.error_count || 0}`); }); eventSource.addEventListener('error', (event) => { console.error('SSE error:', event); eventSource.close(); }); // Close after 30 seconds setTimeout(() => { eventSource.close(); sandbox.kill(); }, 30000); ``` ## Building a Metrics Dashboard Create a simple dashboard that displays real-time metrics: ```python theme={null} import requests import json import time from datetime import datetime from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") api_key = sandbox._api_key base_url = "https://api.hopx.dev" headers = { "Authorization": f"Bearer {api_key}", "Accept": "text/event-stream" } stream_url = f"{base_url}/v1/sandboxes/{sandbox.sandbox_id}/metrics/stream" print("=== Real-Time Metrics Dashboard ===") print("Press Ctrl+C to stop\n") try: with requests.get(stream_url, headers=headers, stream=True) as response: for line in response.iter_lines(): if line and line.startswith(b"data: "): data = json.loads(line[6:]) timestamp = datetime.now().strftime("%H:%M:%S") uptime = data.get('uptime_seconds', 0) total_exec = data.get('total_executions', 0) active_exec = data.get('active_executions', 0) errors = data.get('error_count', 0) # Simple text-based dashboard print(f"[{timestamp}] Uptime: {uptime:6d}s | Executions: {total_exec:4d} | Active: {active_exec:2d} | Errors: {errors:3d}") time.sleep(0.1) # Throttle output except KeyboardInterrupt: print("\nStopping monitoring...") finally: sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import EventSource from 'eventsource'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); const apiKey = sandbox.apiKey; const baseUrl = 'https://api.hopx.dev'; const streamUrl = `${baseUrl}/v1/sandboxes/${sandbox.sandboxId}/metrics/stream?token=${apiKey}`; console.log('=== Real-Time Metrics Dashboard ==='); console.log('Press Ctrl+C to stop\n'); const eventSource = new EventSource(streamUrl); eventSource.addEventListener('message', (event) => { const data = JSON.parse(event.data); const timestamp = new Date().toLocaleTimeString(); const uptime = data.uptime_seconds || 0; const totalExec = data.total_executions || 0; const activeExec = data.active_executions || 0; const errors = data.error_count || 0; // Simple text-based dashboard console.log(`[${timestamp}] Uptime: ${uptime.toString().padStart(6)}s | Executions: ${totalExec.toString().padStart(4)} | Active: ${activeExec.toString().padStart(2)} | Errors: ${errors.toString().padStart(3)}`); }); eventSource.addEventListener('error', (error) => { console.error('Stream error:', error); eventSource.close(); sandbox.kill(); }); // Handle graceful shutdown process.on('SIGINT', () => { console.log('\nStopping monitoring...'); eventSource.close(); sandbox.kill(); process.exit(0); }); ``` ## Alerting on Thresholds Set up alerts when metrics exceed thresholds: ```python theme={null} import requests import json from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") api_key = sandbox._api_key base_url = "https://api.hopx.dev" headers = { "Authorization": f"Bearer {api_key}", "Accept": "text/event-stream" } stream_url = f"{base_url}/v1/sandboxes/{sandbox.sandbox_id}/metrics/stream" # Thresholds ERROR_COUNT_THRESHOLD = 10 ACTIVE_EXECUTIONS_THRESHOLD = 5 print("Monitoring for threshold breaches...") with requests.get(stream_url, headers=headers, stream=True) as response: for line in response.iter_lines(): if line and line.startswith(b"data: "): data = json.loads(line[6:]) error_count = data.get('error_count', 0) active_executions = data.get('active_executions', 0) # Check thresholds if error_count > ERROR_COUNT_THRESHOLD: print(f"⚠️ ALERT: Error count {error_count} exceeds threshold {ERROR_COUNT_THRESHOLD}") if active_executions > ACTIVE_EXECUTIONS_THRESHOLD: print(f"⚠️ ALERT: Active executions {active_executions} exceeds threshold {ACTIVE_EXECUTIONS_THRESHOLD}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import EventSource from 'eventsource'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); const apiKey = sandbox.apiKey; const baseUrl = 'https://api.hopx.dev'; const streamUrl = `${baseUrl}/v1/sandboxes/${sandbox.sandboxId}/metrics/stream?token=${apiKey}`; // Thresholds const ERROR_COUNT_THRESHOLD = 10; const ACTIVE_EXECUTIONS_THRESHOLD = 5; console.log('Monitoring for threshold breaches...'); const eventSource = new EventSource(streamUrl); eventSource.addEventListener('message', (event) => { const data = JSON.parse(event.data); const errorCount = data.error_count || 0; const activeExecutions = data.active_executions || 0; // Check thresholds if (errorCount > ERROR_COUNT_THRESHOLD) { console.log(`⚠️ ALERT: Error count ${errorCount} exceeds threshold ${ERROR_COUNT_THRESHOLD}`); } if (activeExecutions > ACTIVE_EXECUTIONS_THRESHOLD) { console.log(`⚠️ ALERT: Active executions ${activeExecutions} exceeds threshold ${ACTIVE_EXECUTIONS_THRESHOLD}`); } }); eventSource.addEventListener('error', (error) => { console.error('Stream error:', error); eventSource.close(); sandbox.kill(); }); ``` ## Best Practices **Use SSE for real-time monitoring** when you need continuous updates. For one-time snapshots, use `get_metrics_snapshot()` instead. **Handle reconnection logic** in production applications. SSE connections can drop, and you should reconnect automatically. **SSE streams consume resources**. Close connections when no longer needed to free up server resources. **Throttle processing** if you're receiving metrics faster than you can process them. The stream sends updates frequently. ## API Reference ### Control Plane API * **GET** `/v1/sandboxes/:id/metrics/stream` - Stream metrics via SSE * **Headers**: `Authorization: Bearer {token}`, `Accept: text/event-stream` * **Response**: Server-Sent Events stream with JSON metrics data ### SSE Event Format ``` event: message data: {"system": {"cpu": {"usage_percent": 25.5}, ...}} id: 12345 ``` ## Related * [System Metrics](/core-concepts/observability/metrics) - Get snapshot metrics * [Process Monitoring](/core-concepts/observability/processes) - Monitor processes * **API**: [GET /v1/sandboxes/:id/metrics/stream](/api/control-plane/stream-metrics) - Control Plane API endpoint ## Next Steps * Learn about [System Metrics](/core-concepts/observability/metrics) for snapshot metrics * Explore [Process Monitoring](/core-concepts/observability/processes) to monitor processes * Review [Code Execution](/core-concepts/code-execution/synchronous) to generate metrics * [Metrics](/core-concepts/observability/metrics) - Get metrics snapshots * [Processes](/core-concepts/observability/processes) - Monitor processes * **[CLI Reference](/cli/introduction)** - Use HopX from the command line # Process Monitoring Source: https://docs.hopx.ai/core-concepts/observability/processes List and monitor system processes and background executions in HopX sandboxes. Track running processes, monitor background code execution, check process status, and manage process lifecycle. Essential for debugging, performance monitoring, and resource management. Includes Python and JavaScript SDK examples and REST API endpoints. Monitor all processes running in your sandbox, including system processes and background code executions. This helps you track resource usage, debug issues, and manage long-running tasks. ## Overview HopX provides two types of process listings: * **System Processes**: All processes running in the sandbox (requires Agent v3.2.0+) * **Background Executions**: Processes started via `execute_code_background()` or `run_code_background()` System process listing requires VM Agent v3.2.0 or later. Check your agent version using `sandbox.get_agent_info()`. ## System Processes List all system processes running in the sandbox: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # List all system processes processes = sandbox.list_system_processes() print(f"Total Processes: {len(processes)}") print("\nProcess List:") for proc in processes[:10]: # Show first 10 print(f"PID {proc['pid']}: {proc['command']} (User: {proc['user']})") sandbox.kill() ``` **Expected Output:** ``` Total Processes: 45 Process List: PID 1: /sbin/init (User: root) PID 2: [kthreadd] (User: root) PID 3: [rcu_gp] (User: root) PID 4: [rcu_par_gp] (User: root) PID 5: [kworker/0:0] (User: root) PID 6: [mm_percpu_wq] (User: root) PID 7: [ksoftirqd/0] (User: root) PID 8: [rcu_sched] (User: root) PID 9: [migration/0] (User: root) PID 10: [idle_inject/0] (User: root) ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // List all system processes const processes = await sandbox.listSystemProcesses(); console.log(`Total Processes: ${processes.length}`); console.log('\nProcess List:'); for (const proc of processes.slice(0, 10)) { // Show first 10 console.log(`PID ${proc.pid}: ${proc.command} (User: ${proc.user})`); } await sandbox.kill(); ``` **Expected Output:** ``` Total Processes: 45 Process List: PID 1: /sbin/init (User: root) PID 2: [kthreadd] (User: root) PID 3: [rcu_gp] (User: root) PID 4: [rcu_par_gp] (User: root) PID 5: [kworker/0:0] (User: root) PID 6: [mm_percpu_wq] (User: root) PID 7: [ksoftirqd/0] (User: root) PID 8: [rcu_sched] (User: root) PID 9: [migration/0] (User: root) PID 10: [idle_inject/0] (User: root) ``` ## Background Execution Processes List processes started via background execution: ```python theme={null} from hopx_ai import Sandbox import time sandbox = Sandbox.create(template="code-interpreter") # Start a background process process_id = sandbox.run_code_async(""" import time for i in range(10): print(f"Step {i+1}") time.sleep(2) """) print(f"Started background process: {process_id}") # Wait a moment time.sleep(3) # List background processes processes = sandbox.list_processes() print(f"\nBackground Processes: {len(processes)}") for proc in processes: print(f"Process ID: {proc['process_id']}") print(f"Status: {proc['status']}") if 'stdout' in proc: print(f"Output: {proc['stdout'][:100]}...") sandbox.kill() ``` **Expected Output:** ``` Started background process: proc_abc123xyz Background Processes: 1 Process ID: proc_abc123xyz Status: running Output: Step 1 Step 2 ... ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Start a background process const processId = await sandbox.runCodeAsync(` import time for i in range(10): print(f"Step {i+1}") time.sleep(2) `); console.log(`Started background process: ${processId}`); // Wait a moment await new Promise(resolve => setTimeout(resolve, 3000)); // List background processes const processes = await sandbox.listProcesses(); console.log(`\nBackground Processes: ${processes.length}`); for (const proc of processes) { console.log(`Process ID: ${proc.process_id}`); console.log(`Status: ${proc.status}`); if (proc.stdout) { console.log(`Output: ${proc.stdout.substring(0, 100)}...`); } } await sandbox.kill(); ``` **Expected Output:** ``` Started background process: proc_abc123xyz Background Processes: 1 Process ID: proc_abc123xyz Status: running Output: Step 1 Step 2 ... ``` ## Process Structure ### System Process Object ```json theme={null} { "pid": 1234, "name": "python3", "command": "/usr/bin/python3 /workspace/script.py", "user": "root", "cpu_percent": 2.5, "memory_mb": 45, "status": "running", "start_time": "2025-01-27T10:00:00Z" } ``` ### Background Process Object ```json theme={null} { "process_id": "proc_abc123", "status": "running", "stdout": "Step 1\nStep 2\n", "stderr": "", "exit_code": null, "created_at": "2025-01-27T10:00:00Z" } ``` ## Filtering and Searching Filter processes by command or user: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # List all system processes all_processes = sandbox.list_system_processes() # Filter Python processes python_processes = [ p for p in all_processes if 'python' in p['command'].lower() ] print(f"Python Processes: {len(python_processes)}") for proc in python_processes: print(f"PID {proc['pid']}: {proc['command']}") print(f" CPU: {proc.get('cpu_percent', 0):.1f}%, Memory: {proc.get('memory_mb', 0)} MB") # Filter by user root_processes = [ p for p in all_processes if p['user'] == 'root' ] print(f"\nRoot Processes: {len(root_processes)}") sandbox.kill() ``` **Expected Output:** ``` Python Processes: 2 PID 1234: /usr/bin/python3 /workspace/script.py CPU: 2.5%, Memory: 45 MB PID 1235: /usr/bin/python3 -m http.server CPU: 0.8%, Memory: 32 MB Root Processes: 42 ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // List all system processes const allProcesses = await sandbox.listSystemProcesses(); // Filter Python processes const pythonProcesses = allProcesses.filter( p => p.command.toLowerCase().includes('python') ); console.log(`Python Processes: ${pythonProcesses.length}`); for (const proc of pythonProcesses) { console.log(`PID ${proc.pid}: ${proc.command}`); console.log(` CPU: ${(proc.cpu_percent || 0).toFixed(1)}%, Memory: ${proc.memory_mb || 0} MB`); } // Filter by user const rootProcesses = allProcesses.filter( p => p.user === 'root' ); console.log(`\nRoot Processes: ${rootProcesses.length}`); await sandbox.kill(); ``` **Expected Output:** ``` Python Processes: 2 PID 1234: /usr/bin/python3 /workspace/script.py CPU: 2.5%, Memory: 45 MB PID 1235: /usr/bin/python3 -m http.server CPU: 0.8%, Memory: 32 MB Root Processes: 42 ``` ## Monitoring Process Status Monitor background processes to track their progress: ```python theme={null} from hopx_ai import Sandbox import time sandbox = Sandbox.create(template="code-interpreter") # Start long-running background process process_id = sandbox.run_code_async(""" import time for i in range(5): print(f"Processing item {i+1}/5") time.sleep(3) print("Complete!") """) print(f"Started process: {process_id}") # Monitor until complete while True: processes = sandbox.list_processes() proc = next((p for p in processes if p['process_id'] == process_id), None) if not proc: print("Process not found") break print(f"Status: {proc['status']}") if proc['status'] == 'completed': print(f"Exit Code: {proc.get('exit_code', 'N/A')}") if 'stdout' in proc: print(f"Output:\n{proc['stdout']}") break elif proc['status'] == 'failed': print(f"Error: {proc.get('stderr', 'Unknown error')}") break time.sleep(2) sandbox.kill() ``` **Expected Output:** ``` Started process: proc_abc123xyz Status: running Status: running Status: completed Exit Code: 0 Output: Processing item 1/5 Processing item 2/5 Processing item 3/5 Processing item 4/5 Processing item 5/5 Complete! ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Start long-running background process const processId = await sandbox.runCodeAsync(` import time for i in range(5): print(f"Processing item {i+1}/5") time.sleep(3) print("Complete!") `); console.log(`Started process: ${processId}`); // Monitor until complete while (true) { const processes = await sandbox.listProcesses(); const proc = processes.find(p => p.process_id === processId); if (!proc) { console.log('Process not found'); break; } console.log(`Status: ${proc.status}`); if (proc.status === 'completed') { console.log(`Exit Code: ${proc.exit_code || 'N/A'}`); if (proc.stdout) { console.log(`Output:\n${proc.stdout}`); } break; } else if (proc.status === 'failed') { console.log(`Error: ${proc.stderr || 'Unknown error'}`); break; } await new Promise(resolve => setTimeout(resolve, 2000)); } await sandbox.kill(); ``` **Expected Output:** ``` Started process: proc_abc123xyz Status: running Status: running Status: completed Exit Code: 0 Output: Processing item 1/5 Processing item 2/5 Processing item 3/5 Processing item 4/5 Processing item 5/5 Complete! ``` ## Process Limits Control the number of processes returned: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # List system processes with limit # Note: list_system_processes() doesn't support max_results parameter # The API defaults to 200 processes processes = sandbox.list_system_processes() print(f"Returned {len(processes)} processes") if len(processes) >= 200: print("Note: Results may be truncated (max 200)") sandbox.kill() ``` **Expected Output:** ``` Returned 45 processes ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // List system processes // Note: listSystemProcesses() doesn't support maxResults parameter // The API defaults to 200 processes const processes = await sandbox.listSystemProcesses(); console.log(`Returned ${processes.length} processes`); if (processes.length >= 200) { console.log('Note: Results may be truncated (max 200)'); } await sandbox.kill(); ``` **Expected Output:** ``` Returned 45 processes ``` ## Use Cases ### Debugging Hanging Processes Identify processes that might be causing issues: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # List all processes processes = sandbox.list_system_processes() # Find processes consuming resources print("All Running Processes:") for proc in processes: print(f"PID {proc['pid']}: {proc['command']}") print(f" CPU: {proc.get('cpu_percent', 0):.1f}%, Memory: {proc.get('memory_mb', 0)} MB, Status: {proc.get('status', 'N/A')}") # Check for specific problematic processes zombie_processes = [p for p in processes if 'defunct' in p['command']] if zombie_processes: print(f"\nFound {len(zombie_processes)} zombie processes") sandbox.kill() ``` **Expected Output:** ``` All Running Processes: PID 1: /sbin/init CPU: 0.0%, Memory: 0 MB, Status: running PID 2: [kthreadd] CPU: 0.0%, Memory: 0 MB, Status: running ... ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // List all processes const processes = await sandbox.listSystemProcesses(); // Find processes consuming resources console.log('All Running Processes:'); for (const proc of processes) { console.log(`PID ${proc.pid}: ${proc.command}`); console.log(` CPU: ${(proc.cpu_percent || 0).toFixed(1)}%, Memory: ${proc.memory_mb || 0} MB, Status: ${proc.status || 'N/A'}`); } // Check for specific problematic processes const zombieProcesses = processes.filter( p => p.command.includes('defunct') ); if (zombieProcesses.length > 0) { console.log(`\nFound ${zombieProcesses.length} zombie processes`); } await sandbox.kill(); ``` **Expected Output:** ``` All Running Processes: PID 1: /sbin/init CPU: 0.0%, Memory: 0 MB, Status: running PID 2: [kthreadd] CPU: 0.0%, Memory: 0 MB, Status: running ... ``` ### Tracking Background Jobs Monitor multiple background executions: ```python theme={null} from hopx_ai import Sandbox import time sandbox = Sandbox.create(template="code-interpreter") # Start multiple background processes process_ids = [] for i in range(3): pid = sandbox.run_code_async(f""" import time print("Task {i+1} starting") time.sleep(5) print("Task {i+1} complete") """) process_ids.append(pid) print(f"Started task {i+1}: {pid}") # Monitor all processes time.sleep(2) processes = sandbox.list_processes() print(f"\nActive Background Processes: {len(processes)}") for proc in processes: if proc['process_id'] in process_ids: print(f" {proc['process_id']}: {proc['status']}") sandbox.kill() ``` **Expected Output:** ``` Started task 1: proc_task1_xyz Started task 2: proc_task2_abc Started task 3: proc_task3_def Active Background Processes: 3 proc_task1_xyz: running proc_task2_abc: running proc_task3_def: running ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Start multiple background processes const processIds = []; for (let i = 0; i < 3; i++) { const pid = await sandbox.runCodeAsync(` import time print("Task ${i+1} starting") time.sleep(5) print("Task ${i+1} complete") `); processIds.push(pid); console.log(`Started task ${i+1}: ${pid}`); } // Monitor all processes await new Promise(resolve => setTimeout(resolve, 2000)); const processes = await sandbox.listProcesses(); console.log(`\nActive Background Processes: ${processes.length}`); for (const proc of processes) { if (processIds.includes(proc.process_id)) { console.log(` ${proc.process_id}: ${proc.status}`); } } await sandbox.kill(); ``` **Expected Output:** ``` Started task 1: proc_task1_xyz Started task 2: proc_task2_abc Started task 3: proc_task3_def Active Background Processes: 3 proc_task1_xyz: running proc_task2_abc: running proc_task3_def: running ``` ## Best Practices **Use system processes** to debug issues and understand what's running in your sandbox environment. **Use background process listing** to monitor and manage long-running code executions started via `run_code_async()` or `execute_code_background()`. **System process listing is limited to 200 processes** by default. If you have more processes, results may be truncated. **Check process status regularly** for background executions to detect completion or failures early. ## API Reference ### Python SDK * `sandbox.list_system_processes()` - List all system processes (v3.2.0+) * `sandbox.list_processes()` - List background execution processes ### JavaScript SDK * `sandbox.listSystemProcesses()` - List all system processes (v3.2.0+) * `sandbox.listProcesses()` - List background execution processes ### API Endpoints * **GET** `/processes` - List all system processes (max 200, v3.2.0+) * **GET** `/execute/processes` - List background execution processes ## Related * **[System Metrics](/core-concepts/observability/metrics)** - Monitor agent performance metrics * **[Background Execution](/core-concepts/code-execution/background)** - Start background processes * **SDK**: [sandbox.list\_processes()](/sdk/python/sandbox#list_processes) - Python SDK method * **API**: [GET /execute/processes](/api/vm-agent/list-processes) - VM Agent API endpoint * [CLI System Commands](/cli/commands/system) - System operations from CLI ## Next Steps * Learn about [System Metrics](/core-concepts/observability/metrics) to monitor agent performance * Explore [Background Execution](/core-concepts/code-execution/background) to start background processes * Review [Process Management](/core-concepts/code-execution/process-management) for advanced process control # Connecting Source: https://docs.hopx.ai/core-concepts/sandboxes/connecting Learn how to connect to running HopX sandboxes and establish communication channels. Connect to existing sandboxes by ID, retrieve sandbox information, and resume work with previously created sandboxes. Essential for managing long-running sandboxes and resuming interrupted sessions. Includes Python and JavaScript SDK examples and REST API endpoints. Connect to sandboxes that are already running. This is useful when you need to reconnect to a sandbox after your application restarts, or when working with sandboxes created by other processes. ## Prerequisites Before you begin, make sure you have: * **Existing sandbox** - A sandbox that was previously created (see [Creating Sandboxes](/core-concepts/sandboxes/creating)) * **Sandbox ID** - The ID of the sandbox you want to connect to * **API key** - Your HopX API key configured ## Overview The `connect()` method allows you to reconnect to an existing sandbox by its ID. When connecting: * **If sandbox is paused** → Automatically resumes it and refreshes JWT token * **If sandbox is stopped** → Raises an error (cannot connect to stopped sandbox) * **If sandbox is running** → Refreshes JWT token for agent authentication * **JWT token** → Automatically refreshed and stored for agent operations You cannot connect to a stopped sandbox. Use `sandbox.start()` first, or create a new sandbox. ## Basic Connection Connect to an existing sandbox by ID: ```python theme={null} from hopx_ai import Sandbox # Connect to existing sandbox sandbox = Sandbox.connect("1763309903rt5vs4lm") # Get current information info = sandbox.get_info() print(f"Status: {info.status}") print(f"URL: {info.public_host}") ``` **Expected Output:** ``` Status: running URL: https://1763309903rt5vs4lm.hopx.dev ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // Connect to existing sandbox const sandbox = await Sandbox.connect('1763309903rt5vs4lm'); // Get current information const info = await sandbox.getInfo(); console.log(`Status: ${info.status}`); console.log(`URL: ${info.publicHost}`); ``` **Expected Output:** ``` Status: running URL: https://1763309903rt5vs4lm.hopx.dev ``` ## Finding Sandbox IDs You can find sandbox IDs by listing your sandboxes: ```python theme={null} from hopx_ai import Sandbox # List sandboxes to find IDs sandboxes = Sandbox.list(status="running") for sandbox in sandboxes: info = sandbox.get_info() print(f"ID: {sandbox.sandbox_id}, Status: {info.status}") # Connect to the first one if sandboxes: sandbox = Sandbox.connect(sandboxes[0].sandbox_id) print(f"Connected to: {sandbox.sandbox_id}") ``` **Expected Output:** ``` ID: 1763309903rt5vs4lm, Status: running ID: 1763309904rt5vs4ln, Status: running Connected to: 1763309903rt5vs4lm ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // List sandboxes to find IDs const sandboxes = await Sandbox.list({ status: 'running' }); for (const sandbox of sandboxes) { const info = await sandbox.getInfo(); console.log(`ID: ${sandbox.sandboxId}, Status: ${info.status}`); } // Connect to the first one if (sandboxes.length > 0) { const sandbox = await Sandbox.connect(sandboxes[0].sandboxId); console.log(`Connected to: ${sandbox.sandboxId}`); } ``` ## Handling Different States The `connect()` method handles different sandbox states automatically: ```python theme={null} from hopx_ai import Sandbox from hopx_ai.errors import HopxError try: sandbox = Sandbox.connect("sandbox_id") info = sandbox.get_info() if info.status == "paused": print("Sandbox was paused - automatically resumed") elif info.status == "running": print("Sandbox is running - ready to use") except HopxError as e: if "stopped" in str(e).lower(): print("Cannot connect to stopped sandbox") print("Use sandbox.start() first, or create a new sandbox") ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; try { const sandbox = await Sandbox.connect('sandbox_id'); const info = await sandbox.getInfo(); if (info.status === 'paused') { console.log('Sandbox was paused - automatically resumed'); } else if (info.status === 'running') { console.log('Sandbox is running - ready to use'); } } catch (error) { if (error.message.includes('stopped')) { console.error('Cannot connect to stopped sandbox'); console.error('Use sandbox.start() first, or create a new sandbox'); } } ``` ## Complete Workflow Example Here's a complete example showing the connect workflow: ```python theme={null} from hopx_ai import Sandbox # Step 1: List running sandboxes sandboxes = Sandbox.list(status="running") print(f"Found {len(sandboxes)} running sandboxes") # Step 2: Connect to a specific sandbox if sandboxes: sandbox_id = sandboxes[0].sandbox_id print(f"\nConnecting to: {sandbox_id}") sandbox = Sandbox.connect(sandbox_id) info = sandbox.get_info() print(f"✅ Connected successfully") print(f" Status: {info.status}") print(f" Template: {info.template_name}") print(f" URL: {info.public_host}") # Step 3: Use the sandbox result = sandbox.run_code('print("Reconnected!")') print(f" Output: {result.stdout}") ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // Step 1: List running sandboxes const sandboxes = await Sandbox.list({ status: 'running' }); console.log(`Found ${sandboxes.length} running sandboxes`); // Step 2: Connect to a specific sandbox if (sandboxes.length > 0) { const sandboxId = sandboxes[0].sandboxId; console.log(`\nConnecting to: ${sandboxId}`); const sandbox = await Sandbox.connect(sandboxId); const info = await sandbox.getInfo(); console.log('✅ Connected successfully'); console.log(` Status: ${info.status}`); console.log(` Template: ${info.templateName}`); console.log(` URL: ${info.publicHost}`); // Step 3: Use the sandbox const result = await sandbox.runCode('print("Reconnected!")'); console.log(` Output: ${result.stdout}`); } ``` ## Error Handling Handle connection errors appropriately: ```python theme={null} from hopx_ai import Sandbox from hopx_ai.errors import NotFoundError, HopxError try: sandbox = Sandbox.connect("invalid_id") except NotFoundError: print("Sandbox not found") except HopxError as e: if "stopped" in str(e).lower(): print("Sandbox is stopped - cannot connect") print("Start it first: sandbox.start()") else: print(f"Connection error: {e}") ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import { NotFoundError, HopxError } from '@hopx-ai/sdk'; try { const sandbox = await Sandbox.connect('invalid_id'); } catch (error) { if (error instanceof NotFoundError) { console.error('Sandbox not found'); } else if (error instanceof HopxError) { if (error.message.includes('stopped')) { console.error('Sandbox is stopped - cannot connect'); console.error('Start it first: sandbox.start()'); } else { console.error(`Connection error: ${error.message}`); } } } ``` ## Use Cases ### Reconnecting After Application Restart ```python theme={null} from hopx_ai import Sandbox import os # Store sandbox ID (e.g., in environment variable or database) sandbox_id = os.getenv("SANDBOX_ID") if sandbox_id: # Reconnect to existing sandbox sandbox = Sandbox.connect(sandbox_id) print(f"Reconnected to: {sandbox.sandbox_id}") else: # Create new sandbox sandbox = Sandbox.create(template="code-interpreter") print(f"Created new: {sandbox.sandbox_id}") # Store ID for later os.environ["SANDBOX_ID"] = sandbox.sandbox_id ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // Store sandbox ID (e.g., in environment variable or database) const sandboxId = process.env.SANDBOX_ID; if (sandboxId) { // Reconnect to existing sandbox const sandbox = await Sandbox.connect(sandboxId); console.log(`Reconnected to: ${sandbox.sandboxId}`); } else { // Create new sandbox const sandbox = await Sandbox.create({ template: 'code-interpreter' }); console.log(`Created new: ${sandbox.sandboxId}`); // Store ID for later process.env.SANDBOX_ID = sandbox.sandboxId; } ``` ### Working with Shared Sandboxes ```python theme={null} from hopx_ai import Sandbox # Multiple processes can connect to the same sandbox # Process 1: Creates sandbox sandbox1 = Sandbox.create(template="code-interpreter") sandbox_id = sandbox1.sandbox_id print(f"Created: {sandbox_id}") # Process 2: Connects to same sandbox sandbox2 = Sandbox.connect(sandbox_id) print(f"Connected: {sandbox2.sandbox_id}") # Both can use the same sandbox result1 = sandbox1.run_code('x = 1') result2 = sandbox2.run_code('print(x)') # Can access shared state ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // Multiple processes can connect to the same sandbox // Process 1: Creates sandbox const sandbox1 = await Sandbox.create({ template: 'code-interpreter' }); const sandboxId = sandbox1.sandboxId; console.log(`Created: ${sandboxId}`); // Process 2: Connects to same sandbox const sandbox2 = await Sandbox.connect(sandboxId); console.log(`Connected: ${sandbox2.sandboxId}`); // Both can use the same sandbox await sandbox1.runCode('x = 1'); await sandbox2.runCode('print(x)'); // Can access shared state ``` ## JWT Token Management When you connect to a sandbox, the SDK automatically: 1. **Refreshes the JWT token** for agent authentication 2. **Stores the token** for subsequent agent operations 3. **Handles token expiration** automatically You don't need to manage tokens manually - the SDK handles this for you. ```python theme={null} from hopx_ai import Sandbox # Connect - token is automatically refreshed sandbox = Sandbox.connect("sandbox_id") # Token is stored and used automatically for agent calls result = sandbox.run_code('print("Hello")') # Uses stored token # Manually refresh if needed sandbox.refresh_token() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // Connect - token is automatically refreshed const sandbox = await Sandbox.connect('sandbox_id'); // Token is stored and used automatically for agent calls const result = await sandbox.runCode('print("Hello")'); // Uses stored token // Manually refresh if needed await sandbox.refreshToken(); ``` ## Implementation * **SDK**: [Sandbox.connect()](/sdk/python/sandbox#connect) - Python SDK method * **[CLI](/cli/introduction)** - Command-line interface * **SDK**: [sandbox.get\_info()](/sdk/python/sandbox#get_info) - Python SDK method * **API**: [GET /v1/sandboxes/:id](/api/control-plane/get-sandbox) - Control Plane API endpoint ## Related * **[Listing Sandboxes](/core-concepts/sandboxes/listing)** - Find sandboxes to connect to * **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Create new sandboxes * **[Managing Sandbox State](/core-concepts/sandboxes/managing-state)** - Control sandbox lifecycle ## Next Steps * Learn about [Managing State](/core-concepts/sandboxes/managing-state) to start/stop/pause/resume sandboxes * Explore [Timeout Management](/core-concepts/sandboxes/timeout) for connected sandboxes * Review [Creating Sandboxes](/core-concepts/sandboxes/creating) for creating new sandboxes # Creating Source: https://docs.hopx.ai/core-concepts/sandboxes/creating Create new sandboxes from templates with custom configuration. Learn how to create isolated cloud environments using HopX templates, configure resources, set environment variables, and manage sandbox lifecycle. Includes Python and JavaScript SDK examples and REST API endpoints. Sandboxes are isolated, ephemeral cloud environments where your code runs. This guide shows you how to create sandboxes from templates with custom configuration options. ## Prerequisites Before you begin, make sure you have: * **HopX API key** - Get one from [console.hopx.dev](https://console.hopx.dev) or see \[API key Management]\(/API key) * **SDK installed** - Python SDK (`pip install hopx-ai`) or JavaScript SDK (`npm install @hopx-ai/sdk`) * **Basic understanding** - Familiarity with the [Quickstart Guide](/quickstart) is helpful ## Overview When you create a sandbox, HopX: * Spins up a lightweight VM in seconds (\~100ms) * Loads resources (CPU, memory, disk) from the template * Provides a persistent filesystem during the sandbox lifecycle * Auto-destroys the sandbox after timeout (if configured) Resources (vcpu, memory, disk) are **always** loaded from the template. You cannot specify custom resources when creating a sandbox. To use different resources, create a custom template first. ## Basic Creation The simplest way to create a sandbox is using a template name: ```python theme={null} from hopx_ai import Sandbox # Create sandbox from template name sandbox = Sandbox.create(template="code-interpreter") print(f"Sandbox ID: {sandbox.sandbox_id}") info = sandbox.get_info() print(f"Status: {info.status}") print(f"URL: {info.public_host}") # Clean up when done sandbox.kill() ``` **Expected Output:** ``` Sandbox ID: sandbox_abc123xyz Status: running URL: https://sandbox_abc123xyz.hopx.dev ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // Create sandbox from template name const sandbox = await Sandbox.create({ template: 'code-interpreter' }); console.log(`Sandbox ID: ${sandbox.sandboxId}`); const info = await sandbox.getInfo(); console.log(`Status: ${info.status}`); console.log(`URL: ${info.publicHost}`); // Clean up when done await sandbox.kill(); ``` **Expected Output:** ``` Sandbox ID: sandbox_abc123xyz Status: running URL: https://sandbox_abc123xyz.hopx.dev ``` ## Using Template ID You can also create a sandbox using a template ID instead of a name: ```python theme={null} from hopx_ai import Sandbox # Create from template ID sandbox = Sandbox.create(template_id="119") # Cleanup when done sandbox.kill() ``` **Expected Output:** ``` Sandbox created successfully ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // Create from template ID const sandbox = await Sandbox.create({ templateId: '119' }); // Cleanup when done await sandbox.kill(); ``` **Expected Output:** ``` Sandbox created successfully ``` ## Configuration Options When creating a sandbox, you can configure several options: ### Timeout Set an auto-kill timeout to automatically destroy the sandbox after a specified duration: ```python theme={null} from hopx_ai import Sandbox # Create with 1 hour timeout sandbox = Sandbox.create( template="code-interpreter", timeout_seconds=3600 # 1 hour ) info = sandbox.get_info() if info.expires_at: print(f"Sandbox expires at: {info.expires_at}") ``` **Expected Output:** ``` Sandbox expires at: 2025-01-27T11:30:00Z ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // Create with 1 hour timeout const sandbox = await Sandbox.create({ template: 'code-interpreter', timeoutSeconds: 3600 // 1 hour }); const info = await sandbox.getInfo(); if (info.expiresAt) { console.log(`Sandbox expires at: ${info.expiresAt}`); } ``` **Expected Output:** ``` Sandbox expires at: 2025-01-27T11:30:00Z ``` ### Internet Access Control whether the sandbox has internet access: ```python theme={null} from hopx_ai import Sandbox # Create without internet access (isolated) sandbox = Sandbox.create( template="code-interpreter", internet_access=False ) info = sandbox.get_info() print(f"Internet access: {info.internet_access}") # Try to fetch an online resource to demonstrate lack of internet connectivity result = sandbox.run_code(""" import urllib.request import urllib.error try: response = urllib.request.urlopen('https://www.hopx.ai', timeout=10) print(f"✅ Successfully fetched hopx.ai - Status: {response.status}") print(f"Content-Type: {response.headers.get('Content-Type')}") except urllib.error.URLError as e: print(f"❌ Failed to fetch URL: {e.reason}") except Exception as e: print(f"❌ Error: {type(e).__name__}: {e}") """, language="python") print("Fetch attempt output:") print(result.stdout) if result.stderr: print("Errors:") print(result.stderr) if result.exit_code != 0: print("\n❌ Code execution failed") elif "Failed to fetch" in result.stdout or "Error:" in result.stdout: print("\n❌ As expected, the fetch failed. Sandbox does not have internet access.") else: print("\n✅ Unexpected: fetch succeeded, internet access is enabled!") # Clean up when done sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // Create without internet access (isolated) const sandbox = await Sandbox.create({ template: 'code-interpreter', internetAccess: false }); const info = await sandbox.getInfo(); console.log(`Internet access: ${info.internetAccess}`); // Try to fetch an online resource to demonstrate lack of internet connectivity const result = await sandbox.runCode(` const https = require('https'); function fetchUrl(url) { return new Promise((resolve, reject) => { https.get(url, (res) => { console.log(\`✅ Successfully fetched hopx.ai - Status: \${res.statusCode}\`); console.log(\`Content-Type: \${res.headers['content-type']}\`); resolve(); }).on('error', (err) => { console.log(\`❌ Failed to fetch URL: \${err.message}\`); reject(err); }); }); } fetchUrl('https://www.hopx.ai').catch((err) => { console.log(\`❌ Error: \${err.name}: \${err.message}\`); }); `, { language: 'javascript' }); console.log('Fetch attempt output:'); console.log(result.stdout); if (result.stderr) { console.log('Errors:'); console.log(result.stderr); } if (result.exitCode !== 0) { console.log('\n❌ Code execution failed'); } else if (result.stdout.includes('Failed to fetch') || result.stdout.includes('Error:')) { console.log('\n❌ As expected, the fetch failed. Sandbox does not have internet access.'); } else { console.log('\n✅ Unexpected: fetch succeeded, internet access is enabled!'); } // Clean up when done await sandbox.kill(); ``` ### Environment Variables Set initial environment variables when creating the sandbox: ```python theme={null} from hopx_ai import Sandbox # Create with environment variables sandbox = Sandbox.create( template="code-interpreter", env_vars={ "API_KEY": "sk-123", "DEBUG": "true", "ENVIRONMENT": "production" } ) # Verify environment variables result = sandbox.run_code( "import os; print(dict(os.environ))", language="python" ) print(result.stdout) # Clean up when done sandbox.kill() ``` **Expected Output:** ``` {'API_KEY': 'sk-123', 'DEBUG': 'true', 'ENVIRONMENT': 'production', 'PATH': '/usr/local/bin:/usr/bin:/bin', ...} ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // Create with environment variables const sandbox = await Sandbox.create({ template: 'code-interpreter', envVars: { API_KEY: 'sk-123', DEBUG: 'true', ENVIRONMENT: 'production' } }); // Verify environment variables const result = await sandbox.runCode( "import os; print(os.getenv('API_KEY'))", { language: 'python' } ); console.log(result.stdout); // sk-123 // Clean up when done await sandbox.kill(); ``` **Expected Output:** ``` sk-123 ``` ## Using Context Managers (Python) Python SDK supports context managers for automatic cleanup: ```python theme={null} from hopx_ai import Sandbox # Automatically cleans up when exiting the context with Sandbox.create(template="code-interpreter") as sandbox: result = sandbox.run_code('print("Hello from HopX!")') print(result.stdout) # Sandbox is automatically deleted when exiting the block ``` **Expected Output:** ``` Hello from HopX! ``` The context manager automatically calls `sandbox.kill()` when exiting the `with` block, even if an error occurs. This ensures proper cleanup. ## Finding Available Templates Before creating a sandbox, you may want to list available templates: ```python theme={null} from hopx_ai import Sandbox # List all templates templates = Sandbox.list_templates() for template in templates: print(f"{template.name}: {template.display_name}") # Get specific template details template = Sandbox.get_template("code-interpreter") print(f"Description: {template.description}") print(f"Default resources: {template.default_resources.vcpu} vCPU") ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // List all templates const templates = await Sandbox.listTemplates(); for (const template of templates) { console.log(`${template.name}: ${template.displayName}`); } // Get specific template details const template = await Sandbox.getTemplate('code-interpreter'); console.log(`Description: ${template.description}`); console.log(`Default resources: ${template.defaultResources.vcpu} vCPU`); ``` ## Best Practices Use context managers (Python) or try/finally blocks to ensure sandboxes are cleaned up, even if errors occur. Set timeouts based on your use case. For quick scripts, use shorter timeouts. For long-running tasks, set longer timeouts or use timeout management. Set environment variables at creation time rather than later for better performance and consistency. Select templates that match your needs. Use `list_templates()` to find available options. Always handle potential errors (template not found, resource limits, etc.) in your code. ## Implementation * **SDK**: [Sandbox.create()](/sdk/python/sandbox#create) - Python SDK method * **[CLI](/cli/introduction)** - Command-line interface * **API**: [POST /v1/sandboxes](/api/control-plane/create-sandbox) - Control Plane API endpoint ## Related * **[Listing Templates](/core-concepts/templates/listing)** - Find available templates * **[Getting Template Details](/core-concepts/templates/getting-details)** - View template information * **[Connecting to Sandboxes](/core-concepts/sandboxes/connecting)** - Connect to existing sandboxes * **[Managing Sandbox State](/core-concepts/sandboxes/managing-state)** - Control sandbox lifecycle ## Next Steps * Learn how to [List Sandboxes](/core-concepts/sandboxes/listing) to find existing sandboxes * Understand [Connecting to Existing](/core-concepts/sandboxes/connecting) sandboxes * Explore [Managing State](/core-concepts/sandboxes/managing-state) (start, stop, pause, resume) * Configure [Timeout Management](/core-concepts/sandboxes/timeout) for long-running sandboxes # Sandboxes Source: https://docs.hopx.ai/core-concepts/sandboxes/index Complete guide to creating, managing, and working with HopX sandboxes - isolated cloud environments for code execution. Learn how to create sandboxes from templates, list and filter existing sandboxes, connect to sandboxes, manage state, and configure timeouts using Python and JavaScript SDKs or REST API. Sandboxes are isolated, ephemeral cloud environments where your code runs. This hub provides a complete overview of sandbox lifecycle management, from creation to cleanup. ## Related * [CLI Sandbox Commands](/cli/commands/sandbox) - Manage sandboxes from CLI ## What You'll Learn * How to create sandboxes from templates * How to list and filter existing sandboxes * How to connect to sandboxes and manage their state * How to configure timeouts and lifecycle management * SDK and API methods for sandbox operations ## Sandbox Lifecycle Overview | Operation | SDK Method | API Endpoint | | ------------------------------------------------------------- | --------------------------------------------- | -------------------------------- | | **[Creating](/core-concepts/sandboxes/creating)** | `Sandbox.create()` | `POST /v1/sandboxes` | | **[Listing](/core-concepts/sandboxes/listing)** | `Sandbox.list()` / `Sandbox.iter()` | `GET /v1/sandboxes` | | **[Connecting](/core-concepts/sandboxes/connecting)** | `Sandbox.connect()` | `GET /v1/sandboxes/:id` | | **[Managing State](/core-concepts/sandboxes/managing-state)** | `start()` / `stop()` / `pause()` / `resume()` | `POST /v1/sandboxes/:id/:action` | | **[Timeout](/core-concepts/sandboxes/timeout)** | `set_timeout()` | `PUT /v1/sandboxes/:id/timeout` | ## Core Concepts ### Creating Sandboxes Learn how to create new sandboxes from templates with custom configuration. * **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Create new sandboxes from templates * **SDK**: [Python: Sandbox.create()](/sdk/python/sandbox#create) | [JavaScript: Sandbox.create()](/sdk/javascript/sandbox#create) * **API**: [POST /v1/sandboxes](/api/control-plane/create-sandbox) ### Listing Sandboxes Discover how to list, filter, and iterate through existing sandboxes. * **[Listing Sandboxes](/core-concepts/sandboxes/listing)** - List and filter sandboxes * **SDK**: [Python: Sandbox.list()](/sdk/python/sandbox#list) | [Python: Sandbox.iter()](/sdk/python/sandbox#iter) | [JavaScript: Sandbox.list()](/sdk/javascript/sandbox#list) * **API**: [GET /v1/sandboxes](/api/control-plane/list-sandboxes) ### Connecting to Sandboxes Connect to existing sandboxes by ID or from previous sessions. * **[Connecting to Sandboxes](/core-concepts/sandboxes/connecting)** - Connect to existing sandboxes * **SDK**: [Python: Sandbox.connect()](/sdk/python/sandbox#connect) | [JavaScript: Sandbox.connect()](/sdk/javascript/sandbox#connect) * **API**: [GET /v1/sandboxes/:id](/api/control-plane/get-sandbox) ### Managing Sandbox State Control sandbox lifecycle: start, stop, pause, and resume operations. * **[Managing Sandbox State](/core-concepts/sandboxes/managing-state)** - Control sandbox lifecycle * **SDK**: [Python: start/stop/pause/resume](/sdk/python/sandbox#start) | [JavaScript: start/stop/pause/resume](/sdk/javascript/sandbox#start) * **API**: [POST /v1/sandboxes/:id/start](/api/control-plane/start-sandbox) | [POST /v1/sandboxes/:id/stop](/api/control-plane/stop-sandbox) | [POST /v1/sandboxes/:id/pause](/api/control-plane/pause-sandbox) | [POST /v1/sandboxes/:id/resume](/api/control-plane/resume-sandbox) ### Timeout Management Configure and manage sandbox auto-shutdown timers. * **[Timeout Management](/core-concepts/sandboxes/timeout)** - Set and extend sandbox timeouts * **SDK**: [Python: set\_timeout()](/sdk/python/sandbox#set_timeout) | [JavaScript: setTimeout()](/sdk/javascript/sandbox#settimeout) * **API**: [PUT /v1/sandboxes/:id/timeout](/api/control-plane/set-timeout) ## SDK Reference ### Python SDK Complete reference for Python sandbox operations. * **[Sandbox Class](/sdk/python/sandbox)** - Complete Python SDK reference * **[AsyncSandbox Class](/sdk/python/async-sandbox)** - Async/await support ### JavaScript SDK Complete reference for JavaScript/TypeScript sandbox operations. * **[Sandbox Class](/sdk/javascript/sandbox)** - Complete JavaScript SDK reference ## API Reference ### Control Plane API REST API endpoints for sandbox lifecycle management. * **[Control Plane API Overview](/api/control-plane/overview)** - API overview * **[Create Sandbox](/api/control-plane/create-sandbox)** - `POST /v1/sandboxes` * **[Get Sandbox](/api/control-plane/get-sandbox)** - `GET /v1/sandboxes/:id` * **[List Sandboxes](/api/control-plane/list-sandboxes)** - `GET /v1/sandboxes` * **[Delete Sandbox](/api/control-plane/delete-sandbox)** - `DELETE /v1/sandboxes/:id` * **[Pause Sandbox](/api/control-plane/pause-sandbox)** - `POST /v1/sandboxes/:id/pause` * **[Resume Sandbox](/api/control-plane/resume-sandbox)** - `POST /v1/sandboxes/:id/resume` * **[Set Timeout](/api/control-plane/set-timeout)** - `PUT /v1/sandboxes/:id/timeout` ## Quick Start If you're new to sandboxes, start here: 1. **[Quickstart Guide](/quickstart)** - Get started in 5 minutes 2. **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Create your first sandbox 3. **[Listing Sandboxes](/core-concepts/sandboxes/listing)** - Find existing sandboxes 4. **[Managing State](/core-concepts/sandboxes/managing-state)** - Control sandbox lifecycle ## Related Topics * **[Templates](/core-concepts/templates/listing)** - Learn about sandbox templates * **[Code Execution](/core-concepts/code-execution/synchronous)** - Execute code in sandboxes * **[File Operations](/core-concepts/filesystem/reading)** - Work with files in sandboxes * **[Environment Variables](/core-concepts/environment/getting)** - Manage environment variables ## Next Steps * Explore [Code Execution](/core-concepts/code-execution/synchronous) to run code in sandboxes * Learn about [File Operations](/core-concepts/filesystem/reading) for working with files * Understand [Template Management](/core-concepts/templates/listing) for custom environments * Review [Observability](/core-concepts/observability/metrics) for monitoring sandboxes # Listing Source: https://docs.hopx.ai/core-concepts/sandboxes/listing List and filter your sandboxes by status, region, template, and other criteria. Discover how to query existing sandboxes, filter by status or region, iterate through sandbox lists, and find specific sandboxes using Python and JavaScript SDKs or REST API endpoints. Includes pagination and filtering examples. List and filter your sandboxes to find existing environments, monitor their status, and manage multiple sandboxes efficiently. ## Prerequisites Before you begin, make sure you have: * **HopX API key** - Get one from [console.hopx.dev](https://console.hopx.dev) or see \[API key Management]\(/API key) * **SDK installed** - Python SDK (`pip install hopx-ai`) or JavaScript SDK (`npm install @hopx-ai/sdk`) * **At least one sandbox** - You should have created at least one sandbox (see [Creating Sandboxes](/core-concepts/sandboxes/creating)) ## Basic Listing List all your sandboxes: ```python theme={null} from hopx_ai import Sandbox # List all sandboxes sandboxes = Sandbox.list() print(f"Found {len(sandboxes)} sandboxes") for sandbox in sandboxes: info = sandbox.get_info() print(f"{sandbox.sandbox_id}: {info.status}") ``` **Expected Output:** ``` Found 3 sandboxes sandbox_abc123xyz: running sandbox_def456uvw: paused sandbox_ghi789rst: running ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // List all sandboxes const sandboxes = await Sandbox.list(); console.log(`Found ${sandboxes.length} sandboxes`); for (const sandbox of sandboxes) { const info = await sandbox.getInfo(); console.log(`${sandbox.sandboxId}: ${info.status}`); } ``` **Expected Output:** ``` Found 3 sandboxes sandbox_abc123xyz: running sandbox_def456uvw: paused sandbox_ghi789rst: running ``` ## Filtering by Status Filter sandboxes by their current status: ```python theme={null} from hopx_ai import Sandbox # List only running sandboxes running = Sandbox.list(status="running") print(f"Running sandboxes: {len(running)}") # List paused sandboxes paused = Sandbox.list(status="paused") print(f"Paused sandboxes: {len(paused)}") ``` **Expected Output:** ``` Running sandboxes: 2 Paused sandboxes: 1 ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // List only running sandboxes const running = await Sandbox.list({ status: 'running' }); console.log(`Running sandboxes: ${running.length}`); // List paused sandboxes const paused = await Sandbox.list({ status: 'paused' }); console.log(`Paused sandboxes: ${paused.length}`); ``` **Expected Output:** ``` Running sandboxes: 2 Paused sandboxes: 1 ``` ## Combining Filters Combine multiple filters: ```python theme={null} from hopx_ai import Sandbox # List running sandboxes in EU region running_eu = Sandbox.list(status="running", region="eu-west") print(f"Running EU sandboxes: {len(running_eu)}") # List with limit limited = Sandbox.list(status="running", limit=10) print(f"First 10 running sandboxes: {len(limited)}") ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // List running sandboxes in EU region const runningEu = await Sandbox.list({ status: 'running', region: 'eu-west' }); console.log(`Running EU sandboxes: ${runningEu.length}`); // List with limit const limited = await Sandbox.list({ status: 'running', limit: 10 }); console.log(`First 10 running sandboxes: ${limited.length}`); ``` ## Lazy Iteration (Python) For better memory usage with many sandboxes, use the iterator: ```python theme={null} from hopx_ai import Sandbox found_it_flag = False # Lazy loading - fetches pages as needed for sandbox in Sandbox.iter(status="running"): info = sandbox.get_info() print(f"{sandbox.sandbox_id}: {info.public_host}") # Can break early without fetching remaining pages if found_it_flag: break ``` The `iter()` method is more memory-efficient for large numbers of sandboxes because it fetches pages on-demand rather than loading all sandboxes into memory at once. ## Getting Detailed Information Get detailed information for each sandbox: ```python theme={null} from hopx_ai import Sandbox sandboxes = Sandbox.list(status="running") for sandbox in sandboxes: info = sandbox.get_info() print(f"\nSandbox: {sandbox.sandbox_id}") print(f" Status: {info.status}") print(f" Template: {info.template_name}") print(f" URL: {info.public_host}") print(f" Resources: {info.vcpu} vCPU, {info.memory_mb}MB RAM") print(f" Internet: {info.internet_access}") if info.expires_at: print(f" Expires: {info.expires_at}") ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandboxes = await Sandbox.list({ status: 'running' }); for (const sandbox of sandboxes) { const info = await sandbox.getInfo(); console.log(`\nSandbox: ${sandbox.sandboxId}`); console.log(` Status: ${info.status}`); console.log(` Template: ${info.templateName}`); console.log(` URL: ${info.publicHost}`); console.log(` Resources: ${info.vcpu} vCPU, ${info.memoryMb}MB RAM`); console.log(` Internet: ${info.internetAccess}`); if (info.expiresAt) { console.log(` Expires: ${info.expiresAt}`); } } ``` ## Common Use Cases ### Find a Specific Sandbox ```python theme={null} from hopx_ai import Sandbox # Find sandbox by ID pattern sandboxes = Sandbox.list() target_id = "1763309903rt5vs4lm" for sandbox in sandboxes: if sandbox.sandbox_id == target_id: print(f"Found: {sandbox.sandbox_id}") info = sandbox.get_info() print(f"Status: {info.status}") break ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // Find sandbox by ID pattern const sandboxes = await Sandbox.list(); const targetId = '1763309903rt5vs4lm'; for (const sandbox of sandboxes) { if (sandbox.sandboxId === targetId) { console.log(`Found: ${sandbox.sandboxId}`); const info = await sandbox.getInfo(); console.log(`Status: ${info.status}`); break; } } ``` ### Count Sandboxes by Status ```python theme={null} from hopx_ai import Sandbox from collections import Counter # Count sandboxes by status sandboxes = Sandbox.list() status_counts = Counter(sb.get_info().status for sb in sandboxes) print("Sandbox status summary:") for status, count in status_counts.items(): print(f" {status}: {count}") ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // Count sandboxes by status const sandboxes = await Sandbox.list(); const statusCounts = {}; for (const sandbox of sandboxes) { const info = await sandbox.getInfo(); statusCounts[info.status] = (statusCounts[info.status] || 0) + 1; } console.log('Sandbox status summary:'); for (const [status, count] of Object.entries(statusCounts)) { console.log(` ${status}: ${count}`); } ``` ### Clean Up Old Sandboxes ```python theme={null} from hopx_ai import Sandbox from datetime import datetime, timedelta # Find and clean up sandboxes older than 1 hour sandboxes = Sandbox.list() cutoff = datetime.now() - timedelta(hours=1) for sandbox in sandboxes: info = sandbox.get_info() created = datetime.fromisoformat(info.created_at.replace('Z', '+00:00')) if created < cutoff: print(f"Cleaning up old sandbox: {sandbox.sandbox_id}") sandbox.kill() ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // Find and clean up sandboxes older than 1 hour const sandboxes = await Sandbox.list(); const cutoff = new Date(Date.now() - 60 * 60 * 1000); // 1 hour ago for (const sandbox of sandboxes) { const info = await sandbox.getInfo(); const created = new Date(info.createdAt); if (created < cutoff) { console.log(`Cleaning up old sandbox: ${sandbox.sandboxId}`); await sandbox.kill(); } } ``` ## API Direct Access You can also list sandboxes using direct API calls: ```bash theme={null} # List all sandboxes curl https://api.hopx.dev/v1/sandboxes \ -H "Authorization: Bearer your-API key" # Filter by status curl "https://api.hopx.dev/v1/sandboxes?status=running" \ -H "Authorization: Bearer your-API key" # Filter by region curl "https://api.hopx.dev/v1/sandboxes?region=eu-west" \ -H "Authorization: Bearer your-API key" # Combine filters curl "https://api.hopx.dev/v1/sandboxes?status=running®ion=us-east&limit=10" \ -H "Authorization: Bearer your-API key" ``` ## Implementation * **SDK**: [Sandbox.list()](/sdk/python/sandbox#list) - Python SDK method * **[CLI](/cli/introduction)** - Command-line interface * **SDK**: [Sandbox.iter()](/sdk/python/sandbox#iter) - Python SDK iterator method * **API**: [GET /v1/sandboxes](/api/control-plane/list-sandboxes) - Control Plane API endpoint ## Related * **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Create new sandboxes * **[Connecting to Sandboxes](/core-concepts/sandboxes/connecting)** - Connect to existing sandboxes * **[Managing Sandbox State](/core-concepts/sandboxes/managing-state)** - Control sandbox lifecycle * **[API Pagination](/api/concepts/pagination)** - Understand pagination in list results ## Next Steps * Learn about [Connecting to Existing](/core-concepts/sandboxes/connecting) sandboxes from the list * Understand [Managing State](/core-concepts/sandboxes/managing-state) operations * Explore [Timeout Management](/core-concepts/sandboxes/timeout) for listed sandboxes # Managing State Source: https://docs.hopx.ai/core-concepts/sandboxes/managing-state Start, stop, pause, and resume sandboxes to control their lifecycle. Learn how to manage sandbox state transitions, free resources when not in use, pause execution temporarily, and resume paused sandboxes. Essential for resource management and workflow control. Includes Python and JavaScript SDK examples and REST API endpoints. Control the lifecycle of your sandboxes by starting, stopping, pausing, and resuming them. This allows you to manage resources efficiently and maintain state across sessions. ## Prerequisites Before you begin, make sure you have: * **Existing sandbox** - A sandbox that was created (see [Creating Sandboxes](/core-concepts/sandboxes/creating)) * **Sandbox object** - A `Sandbox` instance connected to your sandbox * **Basic understanding** - Familiarity with sandbox states and lifecycle ## Sandbox States Sandboxes can be in one of these states: * **`running`** - Active and ready to execute code * **`stopped`** - Shut down but can be restarted * **`paused`** - Temporarily suspended, can be resumed * **`creating`** - Currently being created When you pause a sandbox, its state is preserved. When you resume it, everything continues from where it left off. Stopped sandboxes lose their runtime state but can be restarted. ## Getting Current State Check the current state of a sandbox: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") info = sandbox.get_info() print(f"Status: {info.status}") print(f"Sandbox ID: {info.sandbox_id}") ``` **Expected Output:** ``` Status: running Sandbox ID: 1763309903rt5vs4lm ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); const info = await sandbox.getInfo(); console.log(`Status: ${info.status}`); console.log(`Sandbox ID: ${info.sandboxId}`); ``` **Expected Output:** ``` Status: running Sandbox ID: 1763309903rt5vs4lm ``` ## Starting a Sandbox Start a stopped sandbox: ```python theme={null} from hopx_ai import Sandbox # Connect to a stopped sandbox sandbox = Sandbox.connect("sandbox_id") # Check current status info = sandbox.get_info() print(f"Current status: {info.status}") # "stopped" # Start the sandbox sandbox.start() # Verify it's running info = sandbox.get_info() print(f"New status: {info.status}") # "running" ``` **Expected Output:** ``` Current status: stopped New status: running ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // Connect to a stopped sandbox const sandbox = await Sandbox.connect('sandbox_id'); // Check current status let info = await sandbox.getInfo(); console.log(`Current status: ${info.status}`); // "stopped" // Start the sandbox await sandbox.start(); // Verify it's running info = await sandbox.getInfo(); console.log(`New status: ${info.status}`); // "running" ``` **Expected Output:** ``` Current status: stopped New status: running ``` ## Stopping a Sandbox Stop a running sandbox (preserves filesystem but loses runtime state): ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Stop the sandbox sandbox.stop() # Verify it's stopped info = sandbox.get_info() print(f"Status: {info.status}") # "stopped" # Can start it again later sandbox.start() ``` **Expected Output:** ``` Status: stopped ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Stop the sandbox await sandbox.stop(); // Verify it's stopped let info = await sandbox.getInfo(); console.log(`Status: ${info.status}`); // "stopped" // Can start it again later await sandbox.start(); ``` **Expected Output:** ``` Status: stopped ``` ## Pausing a Sandbox Pause a running sandbox (preserves full state including memory): ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Set some state sandbox.run_code('x = 42', language="python") # Pause the sandbox sandbox.pause() # Verify it's paused info = sandbox.get_info() print(f"Status: {info.status}") # "paused" ``` **Expected Output:** ``` Status: paused ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Set some state await sandbox.runCode('x = 42', { language: 'python' }); // Pause the sandbox await sandbox.pause(); // Verify it's paused const info = await sandbox.getInfo(); console.log(`Status: ${info.status}`); // "paused" ``` **Expected Output:** ``` Status: paused ``` ## Resuming a Sandbox Resume a paused sandbox (restores full state): ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.connect("sandbox_id") # Automatically resumes if paused # Or manually resume sandbox.resume() # Verify it's running info = sandbox.get_info() print(f"Status: {info.status}") # "running" # State is preserved result = sandbox.run_code('print(x)', language="python") print(result.stdout) # "42" - state preserved! ``` **Expected Output:** ``` Status: running 42 ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.connect('sandbox_id'); // Automatically resumes if paused // Or manually resume await sandbox.resume(); // Verify it's running const info = await sandbox.getInfo(); console.log(`Status: ${info.status}`); // "running" // State is preserved const result = await sandbox.runCode('print(x)', { language: 'python' }); console.log(result.stdout); // "42" - state preserved! ``` **Expected Output:** ``` Status: running 42 ``` ## Complete State Management Example Here's a complete example showing all state operations: ```python theme={null} from hopx_ai import Sandbox # Create sandbox sandbox = Sandbox.create(template="code-interpreter") print(f"Created: {sandbox.get_info().status}") # "running" # Set some state sandbox.run_code('data = [1, 2, 3, 4, 5]', language="python") # Pause sandbox.pause() print(f"After pause: {sandbox.get_info().status}") # "paused" # Resume (state preserved) sandbox.resume() print(f"After resume: {sandbox.get_info().status}") # "running" # Verify state preserved result = sandbox.run_code('print(sum(data))', language="python") print(f"Sum: {result.stdout}") # "15" - state preserved! # Stop sandbox.stop() print(f"After stop: {sandbox.get_info().status}") # "stopped" # Start again (state lost) sandbox.start() result = sandbox.run_code('print(data)', language="python") print(f"Data: {result.stderr}") # Error - state lost on stop ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // Create sandbox const sandbox = await Sandbox.create({ template: 'code-interpreter' }); let info = await sandbox.getInfo(); console.log(`Created: ${info.status}`); // "running" // Set some state await sandbox.runCode('data = [1, 2, 3, 4, 5]', { language: 'python' }); // Pause await sandbox.pause(); info = await sandbox.getInfo(); console.log(`After pause: ${info.status}`); // "paused" // Resume (state preserved) await sandbox.resume(); info = await sandbox.getInfo(); console.log(`After resume: ${info.status}`); // "running" // Verify state preserved let result = await sandbox.runCode('print(sum(data))', { language: 'python' }); console.log(`Sum: ${result.stdout}`); // "15" - state preserved! // Stop await sandbox.stop(); info = await sandbox.getInfo(); console.log(`After stop: ${info.status}`); // "stopped" // Start again (state lost) await sandbox.start(); result = await sandbox.runCode('print(data)', { language: 'python' }); console.log(`Data: ${result.stderr}`); // Error - state lost on stop ``` ## State Transitions Understanding state transitions helps you manage sandboxes effectively: ``` creating → running → paused → running ↓ ↓ stopped → running ↓ (deleted) ``` **Pause**: Preserves full state (memory, variables, running processes). Fast resume. **Stop**: Preserves filesystem only. Runtime state is lost. Requires full restart. **Pause**: When you need to temporarily suspend work but keep everything in memory. **Stop**: When you want to free resources but keep files for later. ## Error Handling Handle state transition errors: ```python theme={null} from hopx_ai import Sandbox from hopx_ai.errors import APIError sandbox = Sandbox.create(template="code-interpreter") try: # Try to pause sandbox.pause() except APIError as e: print(f"Failed to pause: {e}") try: # Try to start (might already be running) sandbox.start() except APIError as e: print(f"Failed to start: {e}") ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import { APIError } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); try { // Try to pause await sandbox.pause(); } catch (error) { if (error instanceof APIError) { console.error(`Failed to pause: ${error.message}`); } } try { // Try to start (might already be running) await sandbox.start(); } catch (error) { if (error instanceof APIError) { console.error(`Failed to start: ${error.message}`); } } ``` ## Best Practices Use `pause()` when you need to temporarily suspend work but want to preserve all state. Resume is fast and preserves everything. Use `stop()` when you want to free resources but keep the filesystem. Files are preserved, but runtime state is lost. Always check the sandbox status before performing operations to avoid errors. Handle errors when transitioning states - a sandbox might already be in the desired state. Always call `kill()` when you're completely done with a sandbox to free resources. ## Implementation * **SDK**: [sandbox.start()](/sdk/python/sandbox#start) - Python SDK method * **[CLI](/cli/introduction)** - Command-line interface * **SDK**: [sandbox.stop()](/sdk/python/sandbox#stop) - Python SDK method * **SDK**: [sandbox.pause()](/sdk/python/sandbox#pause) - Python SDK method * **SDK**: [sandbox.resume()](/sdk/python/sandbox#resume) - Python SDK method * **API**: [POST /v1/sandboxes/:id/start](/api/control-plane/start-sandbox) - Control Plane API endpoint * **API**: [POST /v1/sandboxes/:id/stop](/api/control-plane/stop-sandbox) - Control Plane API endpoint * **API**: [POST /v1/sandboxes/:id/pause](/api/control-plane/pause-sandbox) - Control Plane API endpoint * **API**: [POST /v1/sandboxes/:id/resume](/api/control-plane/resume-sandbox) - Control Plane API endpoint ## Related * **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Create new sandboxes * **[Connecting to Sandboxes](/core-concepts/sandboxes/connecting)** - Connect to existing sandboxes * **[Timeout Management](/core-concepts/sandboxes/timeout)** - Set sandbox timeouts ## Next Steps * Learn about [Timeout Management](/core-concepts/sandboxes/timeout) to control sandbox lifetime * Review [Creating Sandboxes](/core-concepts/sandboxes/creating) for creating new sandboxes * Explore [Listing Sandboxes](/core-concepts/sandboxes/listing) to find sandboxes by status # Timeout Source: https://docs.hopx.ai/core-concepts/sandboxes/timeout Set and extend sandbox timeouts to control when sandboxes are automatically destroyed. Configure auto-shutdown timers to manage resources, extend timeouts for long-running tasks, and check remaining time. Essential for cost management and resource optimization. Includes Python and JavaScript SDK examples and REST API endpoints. Sandboxes can be configured with automatic timeout values that determine when they are automatically destroyed. This helps manage resources and costs while ensuring sandboxes don't run indefinitely. ## Overview Timeout management allows you to: * Set an initial timeout when creating a sandbox * Extend the timeout for running sandboxes * Automatically destroy sandboxes after the timeout expires When a timeout expires, the sandbox is automatically destroyed. All data in the sandbox is lost. Make sure to save important data before the timeout expires. ## Setting Timeout on Creation Set a timeout when creating a sandbox: ```python theme={null} from hopx_ai import Sandbox # Create sandbox with 1 hour timeout sandbox = Sandbox.create( template="code-interpreter", timeout_seconds=3600 # 1 hour in seconds ) info = sandbox.get_info() if info.expires_at: print(f"Sandbox expires at: {info.expires_at}") ``` **Expected Output:** ``` Sandbox expires at: 2025-01-27T11:00:00Z ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // Create sandbox with 1 hour timeout const sandbox = await Sandbox.create({ template: 'code-interpreter', timeoutSeconds: 3600 // 1 hour in seconds }); const info = await sandbox.getInfo(); if (info.expiresAt) { console.log(`Sandbox expires at: ${info.expiresAt}`); } ``` **Expected Output:** ``` Sandbox expires at: 2025-01-27T11:00:00Z ``` ## Extending Timeout Extend the timeout for an existing sandbox: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Extend timeout to 2 hours from now sandbox.set_timeout(7200) # 2 hours in seconds # Verify new timeout info = sandbox.get_info() if info.expires_at: print(f"New expiration: {info.expires_at}") ``` **Expected Output:** ``` New expiration: 2025-01-27T12:00:00Z ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Extend timeout to 2 hours from now await sandbox.setTimeout(7200); // 2 hours in seconds // Verify new timeout const info = await sandbox.getInfo(); if (info.expiresAt) { console.log(`New expiration: ${info.expiresAt}`); } ``` **Expected Output:** ``` New expiration: 2025-01-27T12:00:00Z ``` The `set_timeout()` method sets a new timeout duration **from the current time**, not from the original expiration. Each call resets the timer. ## Common Timeout Values Use these common timeout values: ```python theme={null} from hopx_ai import Sandbox # Quick tasks (5 minutes) sandbox = Sandbox.create( template="code-interpreter", timeout_seconds=300 ) # Standard tasks (30 minutes) sandbox = Sandbox.create( template="code-interpreter", timeout_seconds=1800 ) # Long-running tasks (1 hour) sandbox = Sandbox.create( template="code-interpreter", timeout_seconds=3600 ) # Extended tasks (4 hours) sandbox = Sandbox.create( template="code-interpreter", timeout_seconds=14400 ) ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // Quick tasks (5 minutes) const sandbox1 = await Sandbox.create({ template: 'code-interpreter', timeoutSeconds: 300 }); // Standard tasks (30 minutes) const sandbox2 = await Sandbox.create({ template: 'code-interpreter', timeoutSeconds: 1800 }); // Long-running tasks (1 hour) const sandbox3 = await Sandbox.create({ template: 'code-interpreter', timeoutSeconds: 3600 }); // Extended tasks (4 hours) const sandbox4 = await Sandbox.create({ template: 'code-interpreter', timeoutSeconds: 14400 }); ``` ## Checking Expiration Check when a sandbox will expire: ```python theme={null} from hopx_ai import Sandbox from datetime import datetime sandbox = Sandbox.create( template="code-interpreter", timeout_seconds=3600 ) info = sandbox.get_info() if info.expires_at: expires = datetime.fromisoformat(info.expires_at.replace('Z', '+00:00')) now = datetime.now(expires.tzinfo) remaining = expires - now print(f"Expires at: {info.expires_at}") print(f"Time remaining: {remaining.total_seconds() / 60:.1f} minutes") ``` **Expected Output:** ``` Expires at: 2025-01-27T11:00:00Z Time remaining: 55.2 minutes ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter', timeoutSeconds: 3600 }); const info = await sandbox.getInfo(); if (info.expiresAt) { const expires = new Date(info.expiresAt); const now = new Date(); const remaining = (expires - now) / 1000 / 60; // minutes console.log(`Expires at: ${info.expiresAt}`); console.log(`Time remaining: ${remaining.toFixed(1)} minutes`); } ``` **Expected Output:** ``` Expires at: 2025-01-27T11:00:00Z Time remaining: 55.2 minutes ``` ## Extending Before Expiration Extend timeout before it expires to prevent automatic destruction: ```python theme={null} from hopx_ai import Sandbox from datetime import datetime sandbox = Sandbox.create( template="code-interpreter", timeout_seconds=3600 ) # Check remaining time info = sandbox.get_info() if info.expires_at: expires = datetime.fromisoformat(info.expires_at.replace('Z', '+00:00')) now = datetime.now(expires.tzinfo) remaining_minutes = (expires - now).total_seconds() / 60 # Extend if less than 10 minutes remaining if remaining_minutes < 10: print("Extending timeout...") sandbox.set_timeout(3600) # Extend by 1 hour print("Timeout extended") ``` **Expected Output:** ``` Extending timeout... Timeout extended ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter', timeoutSeconds: 3600 }); // Check remaining time let info = await sandbox.getInfo(); if (info.expiresAt) { const expires = new Date(info.expiresAt); const now = new Date(); const remainingMinutes = (expires - now) / 1000 / 60; // Extend if less than 10 minutes remaining if (remainingMinutes < 10) { console.log('Extending timeout...'); await sandbox.setTimeout(3600); // Extend by 1 hour console.log('Timeout extended'); } } ``` **Expected Output:** ``` Extending timeout... Timeout extended ``` ## No Timeout (Indefinite) Create a sandbox without a timeout (runs until manually killed): ```python theme={null} from hopx_ai import Sandbox # Create without timeout (or set to None) sandbox = Sandbox.create( template="code-interpreter" # timeout_seconds not specified = no timeout ) info = sandbox.get_info() if info.expires_at: print(f"Expires: {info.expires_at}") else: print("No timeout - runs indefinitely") ``` **Expected Output:** ``` No timeout - runs indefinitely ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // Create without timeout const sandbox = await Sandbox.create({ template: 'code-interpreter' // timeoutSeconds not specified = no timeout }); const info = await sandbox.getInfo(); if (info.expiresAt) { console.log(`Expires: ${info.expiresAt}`); } else { console.log('No timeout - runs indefinitely'); } ``` **Expected Output:** ``` No timeout - runs indefinitely ``` ## Complete Example Here's a complete example showing timeout management: ```python theme={null} from hopx_ai import Sandbox from datetime import datetime # Create with initial timeout sandbox = Sandbox.create( template="code-interpreter", timeout_seconds=1800 # 30 minutes ) info = sandbox.get_info() print(f"Initial timeout: {info.expires_at}") # Do some work sandbox.run_code('print("Working...")', language="python") # Extend timeout before expiration sandbox.set_timeout(3600) # Extend to 1 hour from now info = sandbox.get_info() print(f"Extended timeout: {info.expires_at}") # Check remaining time if info.expires_at: expires = datetime.fromisoformat(info.expires_at.replace('Z', '+00:00')) remaining = (expires - datetime.now(expires.tzinfo)).total_seconds() print(f"Time remaining: {remaining / 60:.1f} minutes") ``` **Expected Output:** ``` Initial timeout: 2025-01-27T10:30:00Z Working... Extended timeout: 2025-01-27T11:30:00Z Time remaining: 60.0 minutes ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // Create with initial timeout const sandbox = await Sandbox.create({ template: 'code-interpreter', timeoutSeconds: 1800 // 30 minutes }); let info = await sandbox.getInfo(); console.log(`Initial timeout: ${info.expiresAt}`); // Do some work await sandbox.runCode('print("Working...")', { language: 'python' }); // Extend timeout before expiration await sandbox.setTimeout(3600); // Extend to 1 hour from now info = await sandbox.getInfo(); console.log(`Extended timeout: ${info.expiresAt}`); // Check remaining time if (info.expiresAt) { const expires = new Date(info.expiresAt); const remaining = (expires - new Date()) / 1000 / 60; console.log(`Time remaining: ${remaining.toFixed(1)} minutes`); } ``` **Expected Output:** ``` Initial timeout: 2025-01-27T10:30:00Z Working... Extended timeout: 2025-01-27T11:30:00Z Time remaining: 60.0 minutes ``` ## API Direct Access You can also manage timeouts using direct API calls: ```bash theme={null} # Set timeout when creating curl -X POST https://api.hopx.dev/v1/sandboxes \ -H "Authorization: Bearer your-API key" \ -H "Content-Type: application/json" \ -d '{ "template_name": "code-interpreter", "timeout_seconds": 3600 }' # Update timeout for existing sandbox curl -X PUT https://api.hopx.dev/v1/sandboxes/{sandbox_id}/timeout \ -H "Authorization: Bearer your-API key" \ -H "Content-Type: application/json" \ -d '{ "timeout_seconds": 7200 }' ``` ## Best Practices Set timeouts based on expected task duration. For quick scripts, use shorter timeouts. For long-running tasks, set longer timeouts. Check expiration time regularly for long-running sandboxes to avoid unexpected destruction. Extend timeouts before they expire to prevent data loss. Consider setting up monitoring to alert when time is running low. Always save important data before timeout expires. Consider downloading files or storing results externally. For development and debugging, consider creating sandboxes without timeouts, but remember to clean them up manually. ## Timeout vs Manual Cleanup Set `timeout_seconds` when creating or use `set_timeout()` to automatically destroy sandboxes after a specified duration. Best for production workloads. Call `sandbox.kill()` when done. Best for development or when you need precise control over when sandboxes are destroyed. ## Implementation * **SDK**: [sandbox.set\_timeout()](/sdk/python/sandbox#set_timeout) - Python SDK method * **[CLI](/cli/introduction)** - Command-line interface * **API**: [PUT /v1/sandboxes/:id/timeout](/api/control-plane/set-timeout) - Control Plane API endpoint ## Related * **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Set timeout on creation * **[Managing Sandbox State](/core-concepts/sandboxes/managing-state)** - Control sandbox lifecycle * **[Connecting to Sandboxes](/core-concepts/sandboxes/connecting)** - Connect to existing sandboxes ## Next Steps * Learn about [Creating Sandboxes](/core-concepts/sandboxes/creating) with timeout configuration * Explore [Managing State](/core-concepts/sandboxes/managing-state) for lifecycle control * Review [Listing Sandboxes](/core-concepts/sandboxes/listing) to monitor sandbox status # Building Source: https://docs.hopx.ai/core-concepts/templates/building Create custom templates with dependencies in HopX. Build custom sandbox templates from Docker images, configure resources, add build steps, and install dependencies. Learn how to use TemplateBuilder to create templates tailored to your needs. Includes Python and JavaScript SDK examples and REST API endpoints. Build custom templates with pre-configured environments, dependencies, and settings. Templates allow you to create reusable sandbox configurations. ## Prerequisites Before you begin, make sure you have: * **HopX API key** - Get one from [console.hopx.dev](https://console.hopx.dev) or see \[API key Management]\(/API key) * **Understanding of templates** - Familiarity with [Listing Templates](/core-concepts/templates/listing) is helpful * **Base image or template** - Decide on a base image (Python, Node.js, Ubuntu, etc.) * **Dependencies list** - Know what packages or tools you want pre-installed ## Overview Building templates enables you to: * Pre-install packages and dependencies * Configure environment variables * Set up working directories and users * Create reusable sandbox configurations * Optimize sandbox creation time Template building is an async operation that can take several minutes. The build process includes uploading files, executing build steps, and waiting for template activation. ## Basic Template Building Create a simple template from a base image: ```python theme={null} from hopx_ai.template import Template, BuildOptions import os # Create template from base image template = Template() template.from_python_image("3.11-slim") # Add build steps template.run_cmd("pip install numpy pandas matplotlib") # Build template options = BuildOptions( name="my-python-template", api_key=os.getenv("HOPX_API_KEY"), cpu=2, memory=2048, disk_gb=10, context_path=os.getcwd() # Required: working directory for file operations ) result = await Template.build(template, options) print(f"Template built: {result.template_id}") print(f"Build ID: {result.build_id}") ``` ```javascript theme={null} // Note: JavaScript SDK template building may have different API // This is a conceptual example based on Python SDK patterns import { Template, BuildOptions } from '@hopx-ai/sdk'; // Create template from base image const template = new Template('python:3.11-slim'); // Add build steps template.runCmd('pip install numpy pandas matplotlib'); // Build template const options = new BuildOptions({ name: 'my-python-template', apiKey: process.env.HOPX_API_KEY, cpu: 2, memory: 2048, diskGb: 10 }); const result = await Template.build(template, options); console.log(`Template built: ${result.templateId}`); ``` ## Using Base Image Helpers Use convenient base image helpers: ```python theme={null} from hopx_ai.template import Template, BuildOptions import os # From Ubuntu template = Template().from_ubuntu_image("22.04") template.apt_install("curl", "git", "vim") # From Python template = Template().from_python_image("3.11") template.pip_install("numpy", "pandas") # From Node.js template = Template().from_node_image("20") template.npm_install("typescript", "tsx") # Build options = BuildOptions( name="my-template", api_key=os.getenv("HOPX_API_KEY"), context_path=os.getcwd() ) result = await Template.build(template, options) ``` ```javascript theme={null} // Conceptual example import { Template, BuildOptions } from '@hopx-ai/sdk'; // From Ubuntu const template = new Template().fromUbuntuImage('22.04'); template.aptInstall('curl', 'git', 'vim'); // From Python const template2 = new Template().fromPythonImage('3.11'); template2.pipInstall('numpy', 'pandas'); // From Node.js const template3 = new Template().fromNodeImage('20'); template3.npmInstall('typescript', 'tsx'); ``` ## Complete Template Example Build a complete template with multiple steps: ```python theme={null} from hopx_ai.template import Template, BuildOptions from hopx_ai.template.ready_checks import wait_for_port import os # Create template template = Template() template.from_python_image("3.11-slim") # Install system packages template.apt_install("curl", "git", "build-essential") # Set working directory template.set_workdir("/app") # Install Python packages template.pip_install("flask", "gunicorn", "redis") # Set environment variables template.set_env("FLASK_ENV", "production") template.set_env("PORT", "8000") # Copy files (requires file upload) # template.copy("/local/path", "/app", options=CopyOptions(owner="appuser")) # Set start command and ready check template.set_start_cmd( "gunicorn -w 4 -b 0.0.0.0:8000 app:app", ready=wait_for_port(8000, timeout=30000) ) # Build template options = BuildOptions( name="flask-app-template", api_key=os.getenv("HOPX_API_KEY"), cpu=2, memory=2048, disk_gb=10, context_path=os.getcwd() # Required for file operations ) result = await Template.build(template, options) print(f"✅ Template built: {result.template_id}") print(f" Build ID: {result.build_id}") print(f" Duration: {result.duration}s") ``` ```javascript theme={null} // Conceptual example import { Template, BuildOptions, waitForPort } from '@hopx-ai/sdk'; const template = new Template('python:3.11-slim'); // Install system packages template.aptInstall('curl', 'git', 'build-essential'); // Set working directory template.setWorkdir('/app'); // Install Python packages template.pipInstall('flask', 'gunicorn', 'redis'); // Set environment variables template.setEnv('FLASK_ENV', 'production'); template.setEnv('PORT', '8000'); // Set start command and ready check template.setStartCmd( 'gunicorn -w 4 -b 0.0.0.0:8000 app:app', waitForPort(8000, { timeout: 30000 }) ); // Build template const options = new BuildOptions({ name: 'flask-app-template', apiKey: process.env.HOPX_API_KEY, cpu: 2, memory: 2048, diskGb: 10 }); const result = await Template.build(template, options); console.log(`✅ Template built: ${result.templateId}`); ``` ## Build Options Configure build options: ```python theme={null} from hopx_ai.template import BuildOptions import os options = BuildOptions( name="my-template", # Required: Template name api_key=os.getenv("HOPX_API_KEY"), # Required: API key cpu=2, # CPU cores (default: 2) memory=2048, # Memory in MB (default: 2048) disk_gb=10, # Disk in GB (default: 10) context_path=os.getcwd(), # Required: Working directory for file operations skip_cache=False, # Skip build cache (default: False) update=False, # Update existing template (default: False) template_activation_timeout=2700 # Max wait for activation in seconds (default: 2700) ) # With progress callbacks def on_progress(progress: int): print(f"Build progress: {progress}%") def on_log(log_entry: dict): print(f"[{log_entry['level']}] {log_entry['message']}") options.on_progress = on_progress options.on_log = on_log ``` ```javascript theme={null} // Conceptual example const options = new BuildOptions({ name: 'my-template', // Required: Template name apiKey: process.env.HOPX_API_KEY, // Required: API key cpu: 2, // CPU cores (default: 2) memory: 2048, // Memory in MB (default: 2048) diskGb: 10, // Disk in GB (default: 10) skipCache: false, // Skip build cache (default: false) update: false, // Update existing template (default: false) templateActivationTimeout: 2700, // Max wait for activation in seconds onProgress: (progress) => { console.log(`Build progress: ${progress}%`); }, onLog: (logEntry) => { console.log(`[${logEntry.level}] ${logEntry.message}`); } }); ``` ## Build Result and Logs Access build results and logs: ```python theme={null} from hopx_ai.template import Template, BuildOptions import os # Build template template = Template() template.from_python_image("3.11-slim") template.pip_install("numpy") options = BuildOptions( name="test-template", api_key=os.getenv("HOPX_API_KEY"), context_path=os.getcwd() ) result = await Template.build(template, options) # Access build information print(f"Build ID: {result.build_id}") print(f"Template ID: {result.template_id}") print(f"Duration: {result.duration}s") # Get build logs logs = await result.get_logs() print(f"Logs:\n{logs.logs}") # Poll for new logs if not logs.complete: new_logs = await result.get_logs(offset=logs.offset) print(f"New logs:\n{new_logs.logs}") ``` ```javascript theme={null} // Conceptual example const result = await Template.build(template, options); // Access build information console.log(`Build ID: ${result.buildId}`); console.log(`Template ID: ${result.templateId}`); console.log(`Duration: ${result.duration}s`); // Get build logs const logs = await result.getLogs(); console.log(`Logs:\n${logs.logs}`); // Poll for new logs if (!logs.complete) { const newLogs = await result.getLogs({ offset: logs.offset }); console.log(`New logs:\n${newLogs.logs}`); } ``` ## Best Practices Use base image helpers (from\_python\_image, from\_node\_image) for common environments. Use fluent API to chain operations for readable template definitions. Configure CPU, memory, and disk based on your application needs. Set ready checks for services that need to be ready before sandbox is usable. Use progress and log callbacks to monitor long-running builds. ## Related * **[Listing Templates](/core-concepts/templates/listing)** - List available templates * **[Getting Template Details](/core-concepts/templates/getting-details)** - View template information * **[Template Configuration](/core-concepts/templates/configuration)** - Configure template resources and steps * **API**: [POST /v1/templates/build](/api/control-plane/build-template) - Control Plane API endpoint * [CLI Template Commands](/cli/commands/template) - Template management from CLI ## Next Steps * Learn about [Template Configuration](/core-concepts/templates/configuration) for advanced setup * Explore [Template Caching](/core-concepts/templates/caching) for build optimization * Review [Listing Templates](/core-concepts/templates/listing) to see your built templates # Caching Source: https://docs.hopx.ai/core-concepts/templates/caching Template build caching and optimization in HopX. Optimize template loading with caching strategies, reduce sandbox creation time, and manage template cache for improved performance. Learn how caching works, when to clear cache, and best practices for template optimization. Includes caching examples and performance tips. Optimize template builds with caching strategies. Template caching speeds up builds by reusing layers and steps that haven't changed. ## Overview Template caching helps you: * Speed up template builds * Reduce build costs * Reuse unchanged layers * Optimize build performance Template builds use Docker layer caching. Steps that haven't changed are cached and reused, significantly speeding up rebuilds. ## How Caching Works Template builds cache each step: ```python theme={null} from hopx_ai.template import Template template = Template() template.from_python_image("3.11-slim") # These steps are cached if unchanged template.apt_install("curl", "git") # Cached if packages unchanged template.pip_install("numpy", "pandas") # Cached if packages unchanged template.set_env("DEBUG", "true") # Cached if value unchanged # Only changed steps are rebuilt template.pip_install("matplotlib") # Only this step rebuilds if added ``` ```javascript theme={null} // Conceptual example const template = new Template('python:3.11-slim'); // These steps are cached if unchanged template.aptInstall('curl', 'git'); // Cached if packages unchanged template.pipInstall('numpy', 'pandas'); // Cached if packages unchanged template.setEnv('DEBUG', 'true'); // Cached if value unchanged // Only changed steps are rebuilt template.pipInstall('matplotlib'); // Only this step rebuilds if added ``` ## Skip Cache for Steps Skip caching for specific steps: ```python theme={null} from hopx_ai.template import Template template = Template() template.from_python_image("3.11-slim") # Install packages (cached) template.pip_install("numpy", "pandas") # Run command that should always execute (skip cache) template.run_cmd("git clone https://github.com/user/repo.git /app") template.skip_cache() # Skip cache for previous step # Next steps are cached again template.pip_install("flask") ``` ```javascript theme={null} // Conceptual example const template = new Template('python:3.11-slim'); // Install packages (cached) template.pipInstall('numpy', 'pandas'); // Run command that should always execute (skip cache) template.runCmd('git clone https://github.com/user/repo.git /app'); template.skipCache(); // Skip cache for previous step // Next steps are cached again template.pipInstall('flask'); ``` ## Skip Cache for Entire Build Skip all caching for a build: ```python theme={null} from hopx_ai.template import BuildOptions import os # Skip all caching options = BuildOptions( name="my-template", api_key=os.getenv("HOPX_API_KEY"), skip_cache=True # Skip all caching ) # Useful for: # - Debugging build issues # - Ensuring fresh builds # - Testing build steps ``` ```javascript theme={null} // Conceptual example const options = new BuildOptions({ name: 'my-template', apiKey: process.env.HOPX_API_KEY, skipCache: true // Skip all caching }); ``` ## Optimizing Build Order Order steps for optimal caching: ```python theme={null} from hopx_ai.template import Template template = Template() template.from_python_image("3.11-slim") # ✅ Good: Stable steps first (cached longer) template.apt_install("curl", "git") # Rarely changes template.pip_install("numpy", "pandas") # Changes less frequently template.set_env("NODE_ENV", "production") # Rarely changes # ✅ Good: Frequently changing steps last template.run_cmd("git clone repo /app") # Changes often template.run_cmd("cp config.json /app") # Changes often # ❌ Bad: Frequently changing steps first # template.run_cmd("git clone repo /app") # Invalidates all cache # template.apt_install("curl") # Never cached ``` ```javascript theme={null} // Conceptual example const template = new Template('python:3.11-slim'); // ✅ Good: Stable steps first (cached longer) template.aptInstall('curl', 'git'); // Rarely changes template.pipInstall('numpy', 'pandas'); // Changes less frequently template.setEnv('NODE_ENV', 'production'); // Rarely changes // ✅ Good: Frequently changing steps last template.runCmd('git clone repo /app'); // Changes often template.runCmd('cp config.json /app'); // Changes often ``` ## Cache Invalidation Understand when cache is invalidated: ```python theme={null} from hopx_ai.template import Template template = Template() template.from_python_image("3.11-slim") # Cache is invalidated when: # 1. Step arguments change template.pip_install("numpy", "pandas") # Cached template.pip_install("numpy", "pandas", "matplotlib") # Cache invalidated # 2. Step order changes template.apt_install("curl") template.pip_install("numpy") # vs template.pip_install("numpy") template.apt_install("curl") # Different cache key # 3. Base image changes template = create_template("python:3.11-slim") # One cache template = create_template("python:3.12-slim") # Different cache # 4. Files change (for COPY steps) # template.copy("/local/src", "/app") # Cache invalidated if files change ``` ```javascript theme={null} // Conceptual example const template = new Template('python:3.11-slim'); // Cache is invalidated when: // 1. Step arguments change template.pipInstall('numpy', 'pandas'); // Cached template.pipInstall('numpy', 'pandas', 'matplotlib'); // Cache invalidated // 2. Step order changes template.aptInstall('curl'); template.pipInstall('numpy'); // vs template.pipInstall('numpy'); template.aptInstall('curl'); // Different cache key // 3. Base image changes const template1 = new Template('python:3.11-slim'); // One cache const template2 = new Template('python:3.12-slim'); // Different cache ``` ## Best Practices Place stable steps (system packages, language packages) before frequently changing steps (file copies, git clones). Group related steps together to maximize cache hits. Only skip cache for steps that must always execute (e.g., git clones with latest changes). Minimize changes to early steps to preserve cache for later steps. Test builds to understand cache behavior and optimize step ordering. ## Related * **[Building Templates](/core-concepts/templates/building)** - Create templates with caching * **[Template Configuration](/core-concepts/templates/configuration)** - Configure template resources * **[Getting Template Details](/core-concepts/templates/getting-details)** - View template information * [CLI Template Commands](/cli/commands/template) - Template management from CLI ## Next Steps * Learn about [Building Templates](/core-concepts/templates/building) to create templates * Explore [Template Configuration](/core-concepts/templates/configuration) for advanced setup * Review [Listing Templates](/core-concepts/templates/listing) to see your templates # Configuration Source: https://docs.hopx.ai/core-concepts/templates/configuration Configure templates with resources, steps, and commands in HopX. Set vCPU, memory, and disk limits, define build steps, install packages, and configure template environments. Learn how to configure templates for optimal performance and functionality. Includes Python and JavaScript SDK examples and configuration options. Configure templates with resources, build steps, commands, environment variables, and ready checks. Template configuration determines the final sandbox environment. ## Prerequisites Before you begin, make sure you have: * **Understanding of template building** - Familiarity with [Building Templates](/core-concepts/templates/building) is required * **Template builder SDK** - Python SDK with template builder (`from hopx_ai.template import Template`) * **Resource requirements** - Know your CPU, memory, and disk requirements * **Build steps** - Plan your installation commands and file operations ## Overview Template configuration includes: * Resource specifications (CPU, memory, disk) * Build steps (commands, file operations) * Environment variables * Working directories and users * Start commands and ready checks * Port exposure and health checks Template configuration is set during template building. Once built, templates are immutable - create a new template to change configuration. ## Resource Configuration Configure template resources: ```python theme={null} from hopx_ai.template import BuildOptions import os # Configure resources in BuildOptions options = BuildOptions( name="my-template", api_key=os.getenv("HOPX_API_KEY"), cpu=4, # 4 vCPU cores memory=4096, # 4GB RAM disk_gb=20, # 20GB disk context_path=os.getcwd() # Required: Working directory ) # Resource limits depend on your plan # Typical ranges: # - CPU: 1-64 cores # - Memory: 512MB-64GB # - Disk: 1GB-250GB ``` ```javascript theme={null} // Conceptual example const options = new BuildOptions({ name: 'my-template', apiKey: process.env.HOPX_API_KEY, cpu: 4, // 4 vCPU cores memory: 4096, // 4GB RAM diskGb: 20 // 20GB disk }); ``` ## Build Steps Configure build steps for template: ```python theme={null} from hopx_ai.template import Template template = Template() template.from_python_image("3.11-slim") # Run commands template.run_cmd("apt-get update") template.run_cmd("apt-get install -y git curl") # Install packages (convenience methods) template.apt_install("vim", "nano") template.pip_install("numpy", "pandas") template.npm_install("typescript", "tsx") # Set working directory template.set_workdir("/app") # Set user template.set_user("appuser") # Set environment variables template.set_env("NODE_ENV", "production") template.set_env("DEBUG", "false") # Copy files (requires file upload) # template.copy("/local/src", "/app", options=CopyOptions(owner="appuser")) ``` ```javascript theme={null} // Conceptual example const template = new Template('python:3.11-slim'); // Run commands template.runCmd('apt-get update'); template.runCmd('apt-get install -y git curl'); // Install packages template.aptInstall('vim', 'nano'); template.pipInstall('numpy', 'pandas'); template.npmInstall('typescript', 'tsx'); // Set working directory template.setWorkdir('/app'); // Set user template.setUser('appuser'); // Set environment variables template.setEnv('NODE_ENV', 'production'); template.setEnv('DEBUG', 'false'); ``` ## Start Command and Ready Checks Configure start command and ready checks: ```python theme={null} from hopx_ai.template import Template from hopx_ai.template.ready_checks import ( wait_for_port, wait_for_url, wait_for_file, wait_for_process, wait_for_command ) template = Template() template.from_python_image("3.11-slim") template.pip_install("flask", "gunicorn") # Start command with port ready check template.set_start_cmd( "gunicorn -w 4 -b 0.0.0.0:8000 app:app", ready=wait_for_port(8000, timeout=30000) ) # Alternative ready checks # Wait for URL template.set_start_cmd( "python app.py", ready=wait_for_url("http://localhost:8000/health", timeout=30000) ) # Wait for file template.set_start_cmd( "python app.py", ready=wait_for_file("/app/ready.txt", timeout=30000) ) # Wait for process template.set_start_cmd( "python app.py", ready=wait_for_process("python", timeout=30000) ) # Wait for command template.set_start_cmd( "python app.py", ready=wait_for_command("curl -f http://localhost:8000/health", timeout=30000) ) ``` ```javascript theme={null} // Conceptual example import { waitForPort, waitForUrl } from '@hopx-ai/sdk'; const template = new Template('python:3.11-slim'); template.pipInstall('flask', 'gunicorn'); // Start command with port ready check template.setStartCmd( 'gunicorn -w 4 -b 0.0.0.0:8000 app:app', waitForPort(8000, { timeout: 30000 }) ); // Wait for URL template.setStartCmd( 'python app.py', waitForUrl('http://localhost:8000/health', { timeout: 30000 }) ); ``` ## Port Exposure Expose ports for services: ```python theme={null} from hopx_ai.template import Template template = Template() template.from_python_image("3.11-slim") # Expose ports template.expose(8000) # HTTP server template.expose(5432) # PostgreSQL template.expose(6379) # Redis # Ports are automatically exposed when sandbox is created # Access via: https://{port}-{sandbox_id}.{region}.vms.hopx.dev/ ``` ```javascript theme={null} // Conceptual example const template = new Template('python:3.11-slim'); // Expose ports template.expose(8000); // HTTP server template.expose(5432); // PostgreSQL template.expose(6379); // Redis ``` ## Complete Configuration Example Here's a complete template configuration: ```python theme={null} from hopx_ai.template import Template, BuildOptions from hopx_ai.template.ready_checks import wait_for_port import os # Create template template = Template() template.from_python_image("3.11-slim") # System packages template.apt_install("curl", "git", "build-essential", "postgresql-client") # Working directory template.set_workdir("/app") # Python packages template.pip_install("flask", "gunicorn", "psycopg2", "redis") # Environment variables template.set_env("FLASK_ENV", "production") template.set_env("DATABASE_URL", "postgresql://localhost/db") template.set_env("REDIS_URL", "redis://localhost:6379") # Expose ports template.expose(8000) # Start command with ready check template.set_start_cmd( "gunicorn -w 4 -b 0.0.0.0:8000 app:app", ready=wait_for_port(8000, timeout=30000) ) # Build with resource configuration options = BuildOptions( name="flask-production-template", api_key=os.getenv("HOPX_API_KEY"), cpu=4, memory=4096, disk_gb=20, context_path=os.getcwd() ) result = await Template.build(template, options) print(f"Template configured and built: {result.template_id}") ``` ```javascript theme={null} // Conceptual example import { Template, BuildOptions, waitForPort } from '@hopx-ai/sdk'; const template = new Template('python:3.11-slim'); // System packages template.aptInstall('curl', 'git', 'build-essential', 'postgresql-client'); // Working directory template.setWorkdir('/app'); // Python packages template.pipInstall('flask', 'gunicorn', 'psycopg2', 'redis'); // Environment variables template.setEnv('FLASK_ENV', 'production'); template.setEnv('DATABASE_URL', 'postgresql://localhost/db'); template.setEnv('REDIS_URL', 'redis://localhost:6379'); // Expose ports template.expose(8000); // Start command with ready check template.setStartCmd( 'gunicorn -w 4 -b 0.0.0.0:8000 app:app', waitForPort(8000, { timeout: 30000 }) ); // Build with resource configuration const options = new BuildOptions({ name: 'flask-production-template', apiKey: process.env.HOPX_API_KEY, cpu: 4, memory: 4096, diskGb: 20 }); const result = await Template.build(template, options); console.log(`Template configured and built: ${result.templateId}`); ``` ## Best Practices Set appropriate CPU, memory, and disk based on your application requirements. Order build steps logically: system packages → language packages → application setup. Always set ready checks for services that need to be ready before use. Configure environment variables during template build for consistency. Expose all ports your application needs to be accessible. ## Related * **[Building Templates](/core-concepts/templates/building)** - Build custom templates * **[Listing Templates](/core-concepts/templates/listing)** - List available templates * **[Getting Template Details](/core-concepts/templates/getting-details)** - View template information * **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Create sandboxes from templates * [CLI Template Commands](/cli/commands/template) - Template management from CLI ## Next Steps * Learn about [Building Templates](/core-concepts/templates/building) to create templates * Explore [Template Caching](/core-concepts/templates/caching) for build optimization * Review [Getting Template Details](/core-concepts/templates/getting-details) to verify configuration # Getting Details Source: https://docs.hopx.ai/core-concepts/templates/getting-details Get detailed information about templates in HopX. View template configuration, resources (vCPU, memory, disk), build steps, pre-installed packages, and metadata. Essential for choosing the right template and understanding available resources. Includes Python and JavaScript SDK examples and REST API endpoints. Retrieve detailed information about a specific template, including full configuration, resources, features, and build information. ## Overview Getting template details helps you: * View complete template configuration * Check resource specifications (min/max/default) * Review available features and capabilities * Access build information and status * Verify template availability before use Template details include more information than the list view, including full configuration, build steps, and organization-specific details. ## Get Template by Name Get detailed information about a specific template: ```python theme={null} from hopx_ai import Sandbox # Get template details template = Sandbox.get_template("code-interpreter") print(f"Template: {template.display_name}") print(f"Name: {template.name}") print(f"Description: {template.description}") print(f"Category: {template.category}") print(f"Language: {template.language}") print(f"Status: {template.status}") ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // Get template details const template = await Sandbox.getTemplate('code-interpreter'); console.log(`Template: ${template.displayName}`); console.log(`Name: ${template.name}`); console.log(`Description: ${template.description}`); console.log(`Category: ${template.category}`); console.log(`Language: ${template.language}`); console.log(`Status: ${template.status}`); ``` ## Resource Specifications View resource specifications (default, min, max): ```python theme={null} from hopx_ai import Sandbox template = Sandbox.get_template("code-interpreter") # Default resources if template.default_resources: res = template.default_resources print(f"Default Resources:") print(f" vCPU: {res.vcpu}") print(f" Memory: {res.memory_mb}MB") print(f" Disk: {res.disk_gb}GB") # Minimum resources if template.min_resources: min_res = template.min_resources print(f"\nMinimum Resources:") print(f" vCPU: {min_res.vcpu}") print(f" Memory: {min_res.memory_mb}MB") print(f" Disk: {min_res.disk_gb}GB") # Maximum resources if template.max_resources: max_res = template.max_resources print(f"\nMaximum Resources:") print(f" vCPU: {max_res.vcpu}") print(f" Memory: {max_res.memory_mb}MB") print(f" Disk: {max_res.disk_gb}GB") ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const template = await Sandbox.getTemplate('code-interpreter'); // Default resources if (template.defaultResources) { const res = template.defaultResources; console.log('Default Resources:'); console.log(` vCPU: ${res.vcpu}`); console.log(` Memory: ${res.memoryMb}MB`); console.log(` Disk: ${res.diskGb}GB`); } // Minimum resources if (template.minResources) { const minRes = template.minResources; console.log('\nMinimum Resources:'); console.log(` vCPU: ${minRes.vcpu}`); console.log(` Memory: ${minRes.memoryMb}MB`); console.log(` Disk: ${minRes.diskGb}GB`); } // Maximum resources if (template.maxResources) { const maxRes = template.maxResources; console.log('\nMaximum Resources:'); console.log(` vCPU: ${maxRes.vcpu}`); console.log(` Memory: ${maxRes.memoryMb}MB`); console.log(` Disk: ${maxRes.diskGb}GB`); } ``` ## Features and Tags View template features and tags: ```python theme={null} from hopx_ai import Sandbox template = Sandbox.get_template("code-interpreter") # Features if template.features: print("Features:") for feature in template.features: print(f" • {feature}") # Tags if template.tags: print("\nTags:") for tag in template.tags: print(f" • {tag}") # Popularity if template.popularity_score: print(f"\nPopularity Score: {template.popularity_score}") ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const template = await Sandbox.getTemplate('code-interpreter'); // Features if (template.features) { console.log('Features:'); for (const feature of template.features) { console.log(` • ${feature}`); } } // Tags if (template.tags) { console.log('\nTags:'); for (const tag of template.tags) { console.log(` • ${tag}`); } } // Popularity if (template.popularityScore) { console.log(`\nPopularity Score: ${template.popularityScore}`); } ``` ## Template Status and Availability Check template status and availability: ```python theme={null} from hopx_ai import Sandbox from hopx_ai.errors import NotFoundError try: template = Sandbox.get_template("code-interpreter") print(f"Status: {template.status}") print(f"Active: {template.is_active}") print(f"Public: {template.is_public}") if template.status == "active": print("✅ Template is available for use") elif template.status == "building": print("⏳ Template is currently being built") elif template.status == "failed": print("❌ Template build failed") else: print(f"⚠️ Template status: {template.status}") except NotFoundError: print("❌ Template not found") ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import { NotFoundError } from '@hopx-ai/sdk'; try { const template = await Sandbox.getTemplate('code-interpreter'); console.log(`Status: ${template.status}`); console.log(`Active: ${template.isActive}`); console.log(`Public: ${template.isPublic}`); if (template.status === 'active') { console.log('✅ Template is available for use'); } else if (template.status === 'building') { console.log('⏳ Template is currently being built'); } else if (template.status === 'failed') { console.log('❌ Template build failed'); } else { console.log(`⚠️ Template status: ${template.status}`); } } catch (error) { if (error instanceof NotFoundError) { console.log('❌ Template not found'); } else { throw error; } } ``` ## Organization-Specific Templates Check if template is organization-specific: ```python theme={null} from hopx_ai import Sandbox template = Sandbox.get_template("my-custom-template") if template.organization_id: print(f"Organization Template: {template.organization_id}") print("This is a custom template for your organization") else: print("Public Template") print("Available to all users") ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const template = await Sandbox.getTemplate('my-custom-template'); if (template.organizationId) { console.log(`Organization Template: ${template.organizationId}`); console.log('This is a custom template for your organization'); } else { console.log('Public Template'); console.log('Available to all users'); } ``` ## Complete Example Here's a complete example showing template details: ```python theme={null} from hopx_ai import Sandbox from hopx_ai.errors import NotFoundError def show_template_details(template_name: str): try: template = Sandbox.get_template(template_name) print(f"📋 {template.display_name}") print(f" Name: {template.name}") print(f" ID: {template.id}") print() if template.description: print(f"📝 Description:") print(f" {template.description}") print() print(f"🏷️ Metadata:") print(f" Category: {template.category or 'N/A'}") print(f" Language: {template.language or 'N/A'}") print(f" Status: {template.status}") print(f" Active: {template.is_active}") print(f" Public: {template.is_public}") print() if template.default_resources: res = template.default_resources print(f"💻 Default Resources:") print(f" vCPU: {res.vcpu}") print(f" Memory: {res.memory_mb}MB") print(f" Disk: {res.disk_gb}GB") print() if template.min_resources or template.max_resources: print(f"📊 Resource Limits:") if template.min_resources: min_res = template.min_resources print(f" Min: {min_res.vcpu}vCPU, {min_res.memory_mb}MB RAM") if template.max_resources: max_res = template.max_resources print(f" Max: {max_res.vcpu}vCPU, {max_res.memory_mb}MB RAM") print() if template.features: print(f"✨ Features:") for feature in template.features: print(f" • {feature}") print() if template.tags: print(f"🏷️ Tags:") for tag in template.tags: print(f" • {tag}") print() if template.docs_url: print(f"📚 Documentation: {template.docs_url}") print() if template.organization_id: print(f"🏢 Organization: {template.organization_id}") print(" (Custom template)") except NotFoundError: print(f"❌ Template '{template_name}' not found") # Show details for a template show_template_details("code-interpreter") ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import { NotFoundError } from '@hopx-ai/sdk'; async function showTemplateDetails(templateName) { try { const template = await Sandbox.getTemplate(templateName); console.log(`📋 ${template.displayName}`); console.log(` Name: ${template.name}`); console.log(` ID: ${template.id}`); console.log(); if (template.description) { console.log('📝 Description:'); console.log(` ${template.description}`); console.log(); } console.log('🏷️ Metadata:'); console.log(` Category: ${template.category || 'N/A'}`); console.log(` Language: ${template.language || 'N/A'}`); console.log(` Status: ${template.status}`); console.log(` Active: ${template.isActive}`); console.log(` Public: ${template.isPublic}`); console.log(); if (template.defaultResources) { const res = template.defaultResources; console.log('💻 Default Resources:'); console.log(` vCPU: ${res.vcpu}`); console.log(` Memory: ${res.memoryMb}MB`); console.log(` Disk: ${res.diskGb}GB`); console.log(); } if (template.minResources || template.maxResources) { console.log('📊 Resource Limits:'); if (template.minResources) { const minRes = template.minResources; console.log(` Min: ${minRes.vcpu}vCPU, ${minRes.memoryMb}MB RAM`); } if (template.maxResources) { const maxRes = template.maxResources; console.log(` Max: ${maxRes.vcpu}vCPU, ${maxRes.memoryMb}MB RAM`); } console.log(); } if (template.features) { console.log('✨ Features:'); for (const feature of template.features) { console.log(` • ${feature}`); } console.log(); } if (template.tags) { console.log('🏷️ Tags:'); for (const tag of template.tags) { console.log(` • ${tag}`); } console.log(); } if (template.docsUrl) { console.log(`📚 Documentation: ${template.docsUrl}`); console.log(); } if (template.organizationId) { console.log(`🏢 Organization: ${template.organizationId}`); console.log(' (Custom template)'); } } catch (error) { if (error instanceof NotFoundError) { console.log(`❌ Template '${templateName}' not found`); } else { throw error; } } } // Show details for a template await showTemplateDetails('code-interpreter'); ``` ## Best Practices Always get template details to verify resources and features before creating sandboxes. Verify template status is "active" before using it to create sandboxes. Check default, min, and max resources to ensure they meet your requirements. Review features list to confirm template has capabilities you need. Always handle NotFoundError when getting template details. ## Related * **[Listing Templates](/core-concepts/templates/listing)** - List all available templates * **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Create sandboxes from templates * **SDK**: [Sandbox.get\_template()](/sdk/python/sandbox#get_template) - Python SDK method * **API**: [GET /v1/templates/:name](/api/control-plane/get-template) - Control Plane API endpoint * [CLI Template Commands](/cli/commands/template) - Template management from CLI ## Next Steps * Learn about [Listing Templates](/core-concepts/templates/listing) to discover available templates * Explore [Building Templates](/core-concepts/templates/building) to create custom templates * Review [Template Configuration](/core-concepts/templates/configuration) for advanced setup # Templates Source: https://docs.hopx.ai/core-concepts/templates/index Complete guide to HopX templates - listing, viewing, building, and configuring templates for sandbox creation. Templates define the base environment for HopX sandboxes. Learn how to list pre-built templates, view template details, build custom templates from Docker images, configure resources, and optimize with caching strategies. Templates define the base environment for HopX sandboxes. This hub covers all template operations, from listing pre-built templates to building custom templates with Docker images. ## Related * [CLI Template Commands](/cli/commands/template) - Template management from CLI ## What You'll Learn * How to list and view available templates * How to get detailed template information * How to build custom templates from Docker images * How to configure template resources and settings * How to cache and optimize templates ## Template Management Overview | Operation | SDK Method | API Endpoint | | --------------------------------------------------------------- | ----------------------------- | -------------------------- | | **[Listing](/core-concepts/templates/listing)** | `Sandbox.list_templates()` | `GET /v1/templates` | | **[Getting Details](/core-concepts/templates/getting-details)** | `Sandbox.get_template()` | `GET /v1/templates/:name` | | **[Building](/core-concepts/templates/building)** | `TemplateBuilder` | `POST /v1/templates/build` | | **[Configuration](/core-concepts/templates/configuration)** | `TemplateBuilder.configure()` | Template configuration | | **[Caching](/core-concepts/templates/caching)** | Template caching | Cache management | ## Core Concepts ### Listing Templates Discover available pre-built and custom templates. * **[Listing Templates](/core-concepts/templates/listing)** - List available templates * **SDK**: [Python: Sandbox.list\_templates()](/sdk/python/sandbox#list_templates) | [JavaScript: Sandbox.listTemplates()](/sdk/javascript/sandbox#listtemplates) * **API**: [GET /v1/templates](/api/control-plane/list-templates) ### Getting Template Details View detailed information about specific templates. * **[Getting Template Details](/core-concepts/templates/getting-details)** - View template information * **SDK**: [Python: Sandbox.get\_template()](/sdk/python/sandbox#get_template) | [JavaScript: Sandbox.getTemplate()](/sdk/javascript/sandbox#gettemplate) * **API**: [GET /v1/templates/:name](/api/control-plane/get-template) ### Building Templates Create custom templates from Docker images and build steps. * **[Building Templates](/core-concepts/templates/building)** - Build custom templates * **SDK**: [Python: TemplateBuilder](/sdk/python/template-builder) | [JavaScript: TemplateBuilder](/sdk/javascript/template-builder) * **API**: [POST /v1/templates/build](/api/control-plane/build-template) ### Template Configuration Configure template resources, environment, and build steps. * **[Template Configuration](/core-concepts/templates/configuration)** - Configure templates * **SDK**: [Python: TemplateBuilder.configure()](/sdk/python/template-builder#configure) | [JavaScript: TemplateBuilder.configure()](/sdk/javascript/template-builder#configure) * **API**: Template configuration in build endpoint ### Template Caching Optimize template loading with caching strategies. * **[Template Caching](/core-concepts/templates/caching)** - Cache templates for faster creation * **SDK**: Template caching options | **API**: Cache management endpoints ## SDK Reference ### Python SDK Complete reference for Python template operations. * **[Sandbox.list\_templates()](/sdk/python/sandbox#list_templates)** - List templates * **[Sandbox.get\_template()](/sdk/python/sandbox#get_template)** - Get template details * **[TemplateBuilder](/sdk/python/template-builder)** - Build custom templates * `from_image()` - Create from Docker image * `configure()` - Configure resources * `build()` - Build template ### JavaScript SDK Complete reference for JavaScript/TypeScript template operations. * **[Sandbox.listTemplates()](/sdk/javascript/sandbox#listtemplates)** - List templates * **[Sandbox.getTemplate()](/sdk/javascript/sandbox#gettemplate)** - Get template details * **[TemplateBuilder](/sdk/javascript/template-builder)** - Build custom templates * `fromImage()` - Create from Docker image * `configure()` - Configure resources * `build()` - Build template ## API Reference ### Control Plane API REST API endpoints for template operations. * **[Control Plane API Overview](/api/control-plane/overview)** - API overview * **[List Templates](/api/control-plane/list-templates)** - `GET /v1/templates` - List all templates * **[Get Template](/api/control-plane/get-template)** - `GET /v1/templates/:name` - Get template details * **[Build Template](/api/control-plane/build-template)** - `POST /v1/templates/build` - Build custom template ## Quick Start If you're new to templates, start here: 1. **[Listing Templates](/core-concepts/templates/listing)** - Discover available templates 2. **[Getting Template Details](/core-concepts/templates/getting-details)** - View template information 3. **[Building Templates](/core-concepts/templates/building)** - Create your first custom template ## Related Topics * **[Sandboxes](/core-concepts/sandboxes/creating)** - Create sandboxes from templates * **[Code Execution](/core-concepts/code-execution/synchronous)** - Execute code in template environments * **[Environment Variables](/core-concepts/environment/getting)** - Configure template environments * **[File Operations](/core-concepts/filesystem/reading)** - Work with files in template-based sandboxes ## Next Steps * Learn about [Creating Sandboxes](/core-concepts/sandboxes/creating) from templates * Explore [Building Templates](/core-concepts/templates/building) for custom environments * Review [Template Configuration](/core-concepts/templates/configuration) for advanced setup * Check out [Template Caching](/core-concepts/templates/caching) for optimization # Listing Source: https://docs.hopx.ai/core-concepts/templates/listing List available HopX sandbox templates and view their configurations. Discover pre-built templates for Python, JavaScript, Ubuntu, and other environments. Learn how to filter templates by category, language, or features, view template details, and choose the right template for your use case. Includes Python and JavaScript SDK examples and REST API endpoints. List all available templates to discover pre-configured environments for your sandboxes. Templates define the base system, default resources, and pre-installed packages. ## Overview Listing templates helps you: * Discover available pre-configured environments * Find templates by category or language * Compare template resources and features * Choose the right template for your use case Templates include both public templates (available to all users) and organization-specific templates (custom templates you've built). ## List All Templates Get a list of all available templates: ```python theme={null} from hopx_ai import Sandbox # List all templates templates = Sandbox.list_templates() print(f"Found {len(templates)} templates:") for template in templates: print(f" - {template.name}: {template.display_name}") if template.description: print(f" {template.description}") ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // List all templates const templates = await Sandbox.listTemplates(); console.log(`Found ${templates.length} templates:`); for (const template of templates) { console.log(` - ${template.name}: ${template.displayName}`); if (template.description) { console.log(` ${template.description}`); } } ``` ## Filter by Category Filter templates by category: ```python theme={null} from hopx_ai import Sandbox # Filter by category dev_templates = Sandbox.list_templates(category="development") print(f"Development templates: {len(dev_templates)}") infra_templates = Sandbox.list_templates(category="infrastructure") print(f"Infrastructure templates: {len(infra_templates)}") os_templates = Sandbox.list_templates(category="operating-system") print(f"OS templates: {len(os_templates)}") ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // Filter by category const devTemplates = await Sandbox.listTemplates({ category: 'development' }); console.log(`Development templates: ${devTemplates.length}`); const infraTemplates = await Sandbox.listTemplates({ category: 'infrastructure' }); console.log(`Infrastructure templates: ${infraTemplates.length}`); const osTemplates = await Sandbox.listTemplates({ category: 'operating-system' }); console.log(`OS templates: ${osTemplates.length}`); ``` ## Filter by Language Filter templates by programming language: ```python theme={null} from hopx_ai import Sandbox # Filter by language python_templates = Sandbox.list_templates(language="python") print(f"Python templates: {len(python_templates)}") for t in python_templates: print(f" - {t.name}: {t.display_name}") nodejs_templates = Sandbox.list_templates(language="nodejs") print(f"\nNode.js templates: {len(nodejs_templates)}") for t in nodejs_templates: print(f" - {t.name}: {t.display_name}") ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // Filter by language const pythonTemplates = await Sandbox.listTemplates({ language: 'python' }); console.log(`Python templates: ${pythonTemplates.length}`); for (const t of pythonTemplates) { console.log(` - ${t.name}: ${t.displayName}`); } const nodejsTemplates = await Sandbox.listTemplates({ language: 'nodejs' }); console.log(`\nNode.js templates: ${nodejsTemplates.length}`); for (const t of nodejsTemplates) { console.log(` - ${t.name}: ${t.displayName}`); } ``` ## Template Information Access template details from the list: ```python theme={null} from hopx_ai import Sandbox templates = Sandbox.list_templates() for template in templates: print(f"\n{template.display_name} ({template.name})") print(f" Category: {template.category}") print(f" Language: {template.language or 'N/A'}") if template.default_resources: res = template.default_resources print(f" Resources: {res.vcpu} vCPU, {res.memory_mb}MB RAM, {res.disk_gb}GB disk") if template.features: print(f" Features: {', '.join(template.features)}") print(f" Status: {template.status}") ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const templates = await Sandbox.listTemplates(); for (const template of templates) { console.log(`\n${template.displayName} (${template.name})`); console.log(` Category: ${template.category}`); console.log(` Language: ${template.language || 'N/A'}`); if (template.defaultResources) { const res = template.defaultResources; console.log(` Resources: ${res.vcpu} vCPU, ${res.memoryMb}MB RAM, ${res.diskGb}GB disk`); } if (template.features) { console.log(` Features: ${template.features.join(', ')}`); } console.log(` Status: ${template.status}`); } ``` ## Find Template by Name Search for a specific template: ```python theme={null} from hopx_ai import Sandbox # List all and find by name templates = Sandbox.list_templates() # Find specific template code_interpreter = next( (t for t in templates if t.name == "code-interpreter"), None ) if code_interpreter: print(f"Found: {code_interpreter.display_name}") print(f"Description: {code_interpreter.description}") else: print("Template not found") ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // List all and find by name const templates = await Sandbox.listTemplates(); // Find specific template const codeInterpreter = templates.find(t => t.name === 'code-interpreter'); if (codeInterpreter) { console.log(`Found: ${codeInterpreter.displayName}`); console.log(`Description: ${codeInterpreter.description}`); } else { console.log('Template not found'); } ``` ## Complete Example Here's a complete example showing template discovery: ```python theme={null} from hopx_ai import Sandbox print("🔍 Discovering Templates\n") # List all templates all_templates = Sandbox.list_templates() print(f"Total templates: {len(all_templates)}\n") # Group by category categories = {} for template in all_templates: cat = template.category or "uncategorized" if cat not in categories: categories[cat] = [] categories[cat].append(template) # Display by category for category, templates in categories.items(): print(f"📁 {category.title()} ({len(templates)} templates)") for template in templates: print(f" • {template.display_name}") if template.default_resources: res = template.default_resources print(f" {res.vcpu}vCPU, {res.memory_mb}MB RAM") print() # Find Python templates python_templates = Sandbox.list_templates(language="python") print(f"🐍 Python Templates: {len(python_templates)}") for t in python_templates[:5]: # Show first 5 print(f" - {t.name}: {t.display_name}") # Find a specific template code_interpreter = next( (t for t in all_templates if t.name == "code-interpreter"), None ) if code_interpreter: print(f"\n✅ Found code-interpreter:") print(f" {code_interpreter.description}") if code_interpreter.default_resources: res = code_interpreter.default_resources print(f" Resources: {res.vcpu} vCPU, {res.memory_mb}MB RAM") ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; console.log('🔍 Discovering Templates\n'); // List all templates const allTemplates = await Sandbox.listTemplates(); console.log(`Total templates: ${allTemplates.length}\n`); // Group by category const categories = {}; for (const template of allTemplates) { const cat = template.category || 'uncategorized'; if (!categories[cat]) { categories[cat] = []; } categories[cat].push(template); } // Display by category for (const [category, templates] of Object.entries(categories)) { console.log(`📁 ${category.charAt(0).toUpperCase() + category.slice(1)} (${templates.length} templates)`); for (const template of templates) { console.log(` • ${template.displayName}`); if (template.defaultResources) { const res = template.defaultResources; console.log(` ${res.vcpu}vCPU, ${res.memoryMb}MB RAM`); } } console.log(); } // Find Python templates const pythonTemplates = await Sandbox.listTemplates({ language: 'python' }); console.log(`🐍 Python Templates: ${pythonTemplates.length}`); for (const t of pythonTemplates.slice(0, 5)) { // Show first 5 console.log(` - ${t.name}: ${t.displayName}`); } // Find a specific template const codeInterpreter = allTemplates.find(t => t.name === 'code-interpreter'); if (codeInterpreter) { console.log(`\n✅ Found code-interpreter:`); console.log(` ${codeInterpreter.description}`); if (codeInterpreter.defaultResources) { const res = codeInterpreter.defaultResources; console.log(` Resources: ${res.vcpu} vCPU, ${res.memoryMb}MB RAM`); } } ``` ## Best Practices Always list templates first to discover available options before creating sandboxes. Use category and language filters to narrow down templates relevant to your needs. Review default resources (vCPU, memory, disk) to ensure they meet your requirements. Check template status (active, building, etc.) before using templates. Use template names (not IDs) when creating sandboxes for better readability. ## Related * **[Getting Template Details](/core-concepts/templates/getting-details)** - Get detailed template information * **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Create sandboxes from templates * **SDK**: [Sandbox.list\_templates()](/sdk/python/sandbox#list_templates) - Python SDK method * **API**: [GET /v1/templates](/api/control-plane/list-templates) - Control Plane API endpoint * [CLI Template Commands](/cli/commands/template) - Template management from CLI ## Next Steps * Learn about [Getting Template Details](/core-concepts/templates/getting-details) for complete template information * Explore [Building Templates](/core-concepts/templates/building) to create custom templates * Review [Template Configuration](/core-concepts/templates/configuration) for advanced setup # WebSocket Terminal Source: https://docs.hopx.ai/core-concepts/terminal/websocket Connect to an interactive terminal via WebSocket for real-time command execution in HopX sandboxes. Access interactive shell sessions, execute commands in real-time, and stream terminal output. Perfect for interactive development, debugging, and system administration. Includes Python and JavaScript SDK examples and WebSocket API endpoints. The WebSocket terminal provides interactive, real-time access to a PTY (pseudo-terminal) in your sandbox. This enables you to run interactive commands, monitor output in real-time, and handle terminal-specific features like resizing. ## Prerequisites Before you begin, make sure you have: * **Active sandbox** - A running sandbox (see [Creating Sandboxes](/core-concepts/sandboxes/creating)) * **WebSocket library** - For Python: `pip install websockets` (for JavaScript, WebSocket is built-in) * **Understanding of async/await** - Familiarity with asynchronous programming patterns * **Terminal access** - Basic understanding of terminal/command-line operations ## Overview The WebSocket terminal is ideal for: * Interactive command-line tools and REPLs * Real-time monitoring of long-running processes * Terminal applications that require PTY support * Building terminal UIs or dashboards * Debugging and troubleshooting The WebSocket terminal requires the `websockets` library for Python. Install it with: `pip install websockets` ## Connecting to Terminal Connect to the terminal using the `terminal` resource: ```python theme={null} from hopx_ai import Sandbox import asyncio async def connect_terminal(): sandbox = Sandbox.create(template="code-interpreter") # Connect to terminal async with await sandbox.terminal.connect() as ws: # Terminal is ready for input pass # Clean up sandbox.kill() asyncio.run(connect_terminal()) ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Connect to terminal const ws = await sandbox.terminal.connect(); // Terminal is ready for input // ... use terminal ... await sandbox.kill(); ``` ## Sending Input Send commands and input to the terminal: ```python theme={null} async def send_commands(): sandbox = Sandbox.create(template="code-interpreter") async with await sandbox.terminal.connect() as ws: # Send a command (include \n to execute) await sandbox.terminal.send_input(ws, "ls -la\n") # Send another command await sandbox.terminal.send_input(ws, "cd /workspace\n") # Send interactive input await sandbox.terminal.send_input(ws, "python3\n") await sandbox.terminal.send_input(ws, "print('Hello')\n") await sandbox.terminal.send_input(ws, "exit()\n") sandbox.kill() asyncio.run(send_commands()) ``` ```javascript theme={null} const sandbox = await Sandbox.create({ template: 'code-interpreter' }); const ws = await sandbox.terminal.connect(); // Send commands sandbox.terminal.sendInput(ws, 'ls -la\n'); sandbox.terminal.sendInput(ws, 'cd /workspace\n'); // Send interactive input sandbox.terminal.sendInput(ws, 'python3\n'); sandbox.terminal.sendInput(ws, "print('Hello')\n"); sandbox.terminal.sendInput(ws, 'exit()\n'); await sandbox.kill(); ``` ## Receiving Output Receive terminal output in real-time using async iteration: ```python theme={null} async def receive_output(): sandbox = Sandbox.create(template="code-interpreter") async with await sandbox.terminal.connect() as ws: # Send command await sandbox.terminal.send_input(ws, "echo 'Hello World'\n") # Receive output async for message in sandbox.terminal.iter_output(ws): if message['type'] == 'output': print(message['data'], end='') elif message['type'] == 'exit': print(f"\nProcess exited with code: {message['code']}") break sandbox.kill() asyncio.run(receive_output()) ``` ```javascript theme={null} const sandbox = await Sandbox.create({ template: 'code-interpreter' }); const ws = await sandbox.terminal.connect(); // Send command sandbox.terminal.sendInput(ws, "echo 'Hello World'\n"); // Receive output for await (const message of sandbox.terminal.output(ws)) { if (message.type === 'output') { process.stdout.write(message.data); } else if (message.type === 'exit') { console.log(`\nProcess exited with code: ${message.code}`); break; } } await sandbox.kill(); ``` ## Resizing Terminal Resize the terminal window to match your display: ```python theme={null} async def resize_terminal(): sandbox = Sandbox.create(template="code-interpreter") async with await sandbox.terminal.connect() as ws: # Resize to 120 columns, 40 rows await sandbox.terminal.resize(ws, cols=120, rows=40) # Send command that benefits from larger terminal await sandbox.terminal.send_input(ws, "ls -la\n") async for message in sandbox.terminal.iter_output(ws): if message['type'] == 'output': print(message['data'], end='') elif message['type'] == 'exit': break sandbox.kill() asyncio.run(resize_terminal()) ``` ```javascript theme={null} const sandbox = await Sandbox.create({ template: 'code-interpreter' }); const ws = await sandbox.terminal.connect(); // Resize terminal sandbox.terminal.resize(ws, 120, 40); // Send command sandbox.terminal.sendInput(ws, 'ls -la\n'); // Receive output for await (const message of sandbox.terminal.output(ws)) { if (message.type === 'output') { process.stdout.write(message.data); } else if (message.type === 'exit') { break; } } await sandbox.kill(); ``` ## Complete Example Here's a complete example that demonstrates interactive terminal usage: ```python theme={null} from hopx_ai import Sandbox import asyncio async def interactive_terminal(): sandbox = Sandbox.create(template="code-interpreter") try: async with await sandbox.terminal.connect() as ws: # Resize terminal await sandbox.terminal.resize(ws, cols=80, rows=24) # Run a series of commands commands = [ "pwd\n", "whoami\n", "uname -a\n", "python3 --version\n" ] for cmd in commands: await sandbox.terminal.send_input(ws, cmd) # Receive output for this command async for message in sandbox.terminal.iter_output(ws): if message['type'] == 'output': print(message['data'], end='') elif message['type'] == 'exit': # Command completed, move to next break print() # Blank line between commands finally: sandbox.kill() asyncio.run(interactive_terminal()) ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; async function interactiveTerminal() { const sandbox = await Sandbox.create({ template: 'code-interpreter' }); try { const ws = await sandbox.terminal.connect(); // Resize terminal sandbox.terminal.resize(ws, 80, 24); // Run a series of commands const commands = [ 'pwd\n', 'whoami\n', 'uname -a\n', 'python3 --version\n' ]; for (const cmd of commands) { sandbox.terminal.sendInput(ws, cmd); // Receive output for this command for await (const message of sandbox.terminal.output(ws)) { if (message.type === 'output') { process.stdout.write(message.data); } else if (message.type === 'exit') { // Command completed, move to next break; } } console.log(); // Blank line between commands } } finally { await sandbox.kill(); } } interactiveTerminal(); ``` ## Message Types The terminal sends different message types: * **`output`**: Terminal output data ```json theme={null} {"type": "output", "data": "command output text"} ``` * **`exit`**: Process exit notification ```json theme={null} {"type": "exit", "code": 0} ``` ## Error Handling Handle connection errors and timeouts: ```python theme={null} import asyncio from hopx_ai import Sandbox async def terminal_with_error_handling(): sandbox = Sandbox.create(template="code-interpreter") try: async with await sandbox.terminal.connect(timeout=30) as ws: await sandbox.terminal.send_input(ws, "invalid-command-that-fails\n") async for message in sandbox.terminal.iter_output(ws): if message['type'] == 'output': print(message['data'], end='') elif message['type'] == 'exit': exit_code = message['code'] if exit_code != 0: print(f"\nCommand failed with exit code: {exit_code}") break except Exception as e: print(f"Terminal error: {e}") finally: sandbox.kill() asyncio.run(terminal_with_error_handling()) ``` ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; async function terminalWithErrorHandling() { const sandbox = await Sandbox.create({ template: 'code-interpreter' }); try { const ws = await sandbox.terminal.connect(); sandbox.terminal.sendInput(ws, 'invalid-command-that-fails\n'); for await (const message of sandbox.terminal.output(ws)) { if (message.type === 'output') { process.stdout.write(message.data); } else if (message.type === 'exit') { const exitCode = message.code; if (exitCode !== 0) { console.log(`\nCommand failed with exit code: ${exitCode}`); } break; } } } catch (error) { console.error(`Terminal error: ${error.message}`); } finally { await sandbox.kill(); } } terminalWithErrorHandling(); ``` ## Best Practices **Use async context managers** in Python to ensure proper WebSocket cleanup. The `async with` statement automatically closes the connection. **Include newline characters** (`\n`) when sending commands to execute them immediately. Without `\n`, the command waits for more input. **Terminal connections are stateful**. Each connection maintains its own shell session. If you need a fresh environment, create a new terminal connection. **Resize the terminal** before running commands that format output based on terminal width (like `ls -la` or `tree`). ## API Reference ### Python SDK * `sandbox.terminal.connect(*, timeout=30)` - Connect to terminal WebSocket * `sandbox.terminal.send_input(ws, data)` - Send input to terminal * `sandbox.terminal.resize(ws, cols, rows)` - Resize terminal window * `sandbox.terminal.iter_output(ws)` - Async iterator for terminal messages ### JavaScript SDK * `sandbox.terminal.connect()` - Connect to terminal WebSocket * `sandbox.terminal.sendInput(ws, data)` - Send input to terminal * `sandbox.terminal.resize(ws, cols, rows)` - Resize terminal window * `sandbox.terminal.output(ws)` - Async iterator for terminal messages ### API Endpoint * **WebSocket**: `/terminal` - Connect to interactive terminal * **Message Types**: `input`, `resize`, `output`, `exit` ## Related * **[Running Commands](/core-concepts/commands/running)** - Execute shell commands synchronously * **[Background Commands](/core-concepts/commands/background)** - Run commands in background * **SDK**: [sandbox.terminal.connect()](/sdk/python/terminal#connect) - Python SDK method * [CLI Terminal](/cli/commands/terminal) - Terminal access from CLI ## Next Steps * Learn about [Running Commands](/core-concepts/commands/running) for synchronous execution * Explore [Background Commands](/core-concepts/commands/background) for non-blocking tasks * Review [Code Execution](/core-concepts/code-execution/synchronous) for programmatic execution # MCP Server Integration Source: https://docs.hopx.ai/guides/integrations/mcp-integration Enable AI assistants to execute code in isolated HopX sandboxes using the Model Context Protocol. Connect Claude, Cursor, and other AI assistants to HopX for secure code execution. Give your AI assistant **superpowers** with secure, isolated code execution through the [Model Context Protocol (MCP)](https://modelcontextprotocol.io). The HopX MCP server enables Claude, Cursor, and other AI assistants to execute Python, JavaScript, Bash, and Go code in blazing-fast (0.1s startup), isolated cloud containers. MCP is a protocol that allows AI assistants to interact with external tools and services. The HopX MCP server provides a standardized way for AI assistants to execute code safely in isolated environments. ## What You'll Learn In this guide, you'll learn how to: * Install the HopX MCP server using `uvx` * Configure MCP server in Cursor, VS Code, Claude Desktop, and other IDEs * Enable AI assistants to execute code in isolated sandboxes * Use different execution modes (isolated, persistent, rich, background) * Set up multi-step workflows and rich output capture * Understand security and best practices for MCP integration ## Prerequisites Before you begin, make sure you have: * **Python 3.14+** installed (required for `uvx`) * **`uvx`** installed (get it from [uv's documentation](https://docs.astral.sh/uv/)) * **HopX API key** from [hopx.ai](https://hopx.ai) * **MCP-compatible IDE** (Cursor, VS Code, Claude Desktop, Windsurf, etc.) * Basic familiarity with your IDE's configuration files ## Quick Start The easiest way to get started: 1. Install the MCP server: `uvx HopX-mcp` 2. Get your API key from [hopx.ai](https://hopx.ai) 3. Configure your IDE with the MCP server 4. Your AI assistant can now execute code safely ## Installation Install the HopX MCP server using `uvx`: ```bash theme={null} uvx hopx-mcp ``` You need Python 3.14+ and `uvx` installed. Get `uvx` from [uv's documentation](https://docs.astral.sh/uv/). ## Get Your API key Sign up at [hopx.ai](https://hopx.ai) to get your free API key. You'll need this to configure the MCP server. ## Configuration After installing with `uvx hopx-mcp`, configure your IDE by adding the MCP server configuration: Add to `.cursor/mcp.json` in your project or workspace: ```json theme={null} { "mcpServers": { "HopX-sandbox": { "command": "uvx", "args": ["hopx-mcp"], "env": { "HOPX_API_KEY": "your-API key-here" } } } } ``` Add to `.vscode/mcp.json` in your workspace: ```json theme={null} { "mcpServers": { "HopX-sandbox": { "command": "uvx", "args": ["hopx-mcp"], "env": { "HOPX_API_KEY": "your-API key-here" } } } } ``` Add to `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS or `%APPDATA%\Claude\claude_desktop_config.json` on Windows: ```json theme={null} { "mcpServers": { "HopX-sandbox": { "command": "uvx", "args": ["hopx-mcp"], "env": { "HOPX_API_KEY": "your-API key-here" } } } } ``` Restart Claude Desktop after making changes. Add to `.windsurf/mcp.json` in your project: ```json theme={null} { "mcpServers": { "HopX-sandbox": { "command": "uvx", "args": ["hopx-mcp"], "env": { "HOPX_API_KEY": "your-API key-here" } } } } ``` For other IDEs (Visual Studio, Cline, Continue.dev, Zed, Codex), use a similar configuration structure. Refer to your IDE's MCP documentation for the exact configuration file location and format. Replace `your-API key-here` with your actual API key from [hopx.ai](https://hopx.ai). ## What This Enables With the HopX MCP server, your AI assistant can: * ✅ **Execute Python, JavaScript, Bash, and Go** in isolated containers * ✅ **Analyze data** with pandas, numpy, matplotlib (pre-installed) * ✅ **Test code snippets** before you use them in production * ✅ **Process data** securely without touching your local system * ✅ **Run system commands** safely in isolated environments * ✅ **Install packages** and test integrations on-the-fly All executions happen in **secure, ephemeral cloud containers** that auto-destroy after use. Your local system stays clean and protected. ## Execution Modes The HopX MCP server provides a unified `execute_code()` function with multiple execution modes: * **`isolated`** (default) - One-shot execution: Creates a new sandbox, executes code, returns output, and auto-destroys. Perfect for quick scripts and data analysis. * **`persistent`** - Execute in an existing sandbox: Use for multi-step workflows where you need to maintain state between executions. * **`rich`** - Execute with rich output capture: Automatically captures matplotlib plots, pandas DataFrames, and other visualizations. * **`background`** - Non-blocking execution: Starts code execution in the background and returns immediately with a process ID. For most use cases, use `mode="isolated"` for quick, one-off code execution. The sandbox is automatically created and destroyed, so you don't need to manage the lifecycle. ## Advanced Usage ### Multi-Step Workflows For workflows that require multiple steps (e.g., installing packages, then running code), create a persistent sandbox: **You:** "Install pandas and analyze this data: \[1, 2, 3, 4, 5]" **Claude:** *Creates a sandbox, then executes multiple commands:* 1. `create_sandbox(template_id="code-interpreter")` - Creates a persistent sandbox 2. `execute_code(sandbox_id="...", code="pip install pandas", mode="persistent")` - Installs package 3. `execute_code(sandbox_id="...", code="import pandas as pd; ...", mode="persistent")` - Runs analysis 4. `delete_sandbox(sandbox_id="...")` - Cleans up ### Rich Output Capture For data visualization, use `mode="rich"` to automatically capture plots and DataFrames: **You:** "Create a plot of \[1, 2, 3, 4, 5]" **Claude:** *Uses rich mode to capture the visualization:* ```python theme={null} result = execute_code( sandbox_id=sandbox_id, code="import matplotlib.pyplot as plt; plt.plot([1,2,3,4,5]); plt.savefig('/tmp/plot.png')", mode="rich" ) # result["rich_outputs"] contains the captured plot ``` ## Related * **[LLM Integration](/guides/integrations/llm-integration)** - Integrate OpenAI, Anthropic, and other LLMs * **[Quickstart Guide](/quickstart)** - Get started with HopX sandboxes * **[Code Execution](/core-concepts/code-execution/synchronous)** - Learn about code execution concepts * **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Understand sandbox creation ## Next Steps Now that you've set up MCP integration, explore more: * **Learn about code execution**: [Synchronous Execution](/core-concepts/code-execution/synchronous) and [Background Execution](/core-concepts/code-execution/background) * **Explore templates**: [Listing Templates](/core-concepts/templates/listing) to find the right environment * **Try rich output capture**: [Rich Output Capture](/core-concepts/code-execution/rich-output) for data visualization * **Integrate with LLMs**: [LLM Integration Guide](/guides/integrations/llm-integration) for direct LLM integration * **Review best practices**: [Cookbooks](/cookbooks/getting-started/first-sandbox) for real-world examples # Welcome to HopX Source: https://docs.hopx.ai/index Get started with HopX - your guide to building with cloud sandboxes. HopX provides instant access to isolated computing environments for executing code, running applications, and processing data. Whether you're building AI applications, running data analysis, testing code, or automating workflows, HopX provides the infrastructure you need. HopX is a cloud sandbox platform that gives you instant access to isolated computing environments that enable you to execute code, run applications, and process data in isolated, secure environments. Whether you're building AI applications, running data analysis, testing code, or automating workflows, HopX provides the infrastructure you need without managing servers or containers. ### Key Capabilities * **Multi-language code execution** - Run Python, JavaScript, Bash, and Go code with full system access * **Rich output capture** - Automatically capture plots, dataframes, and visualizations * **File operations** - Read, write, upload, download, and watch files in your sandbox * **Template system** - Use pre-built templates or create custom environments * **Desktop automation** - Control VNC servers, mouse, keyboard, and capture screenshots * **Process management** - Run background processes, manage execution, and monitor system resources * **Environment management** - Set and manage environment variables securely * **Real-time streaming** - Stream execution output and monitor sandbox status ## Explore the Documentation Complete walkthrough from installation to your first sandbox in under 10 minutes. Comprehensive documentation for Python and JavaScript SDKs with code examples. Command-line interface for managing sandboxes, executing code, and automating workflows. Complete API documentation for the Control Plane and VM Agent APIs. Step-by-step guides for common use cases and integration patterns. ## Core Concepts Learn about the fundamental concepts and capabilities of HopX: Create, manage, and connect to sandbox environments. Execute code synchronously, asynchronously, or in the background. Read, write, and manage files in your sandbox. Use pre-built templates or create custom environments. Control desktop environments with VNC, mouse, and keyboard automation. Run shell commands and manage background processes. ## Related * **[Quickstart Guide](/quickstart)** - Get started in under 2 minutes * **[Python SDK Quickstart](/sdk/python/quickstart)** - Python SDK guide * **[JavaScript SDK Quickstart](/sdk/javascript/quickstart)** - JavaScript SDK guide * **[API Quickstart](/api/quickstart)** - API guide * **[Core Concepts](/core-concepts/sandboxes/creating)** - Learn about sandboxes ## Next Steps * **New to HopX?** Start with our [Quickstart guide](/quickstart) * **Building an integration?** Check out [MCP Integration](/guides/integrations/mcp-integration) * **Need API details?** Explore the [API Reference](/api/introduction) *** # Quickstart Source: https://docs.hopx.ai/quickstart Get started with HopX - your first HopX sandbox running in less than 2 minutes. Complete quickstart guide for creating sandboxes, executing code, and managing resources using Python SDK, JavaScript SDK, CLI, or REST API. Get up and running with HopX; this guide walks you through creating your first sandbox, executing code, and cleaning up. ## What You'll Learn In this quickstart, you'll learn how to: * Install and set up the HopX SDK (Python or JavaScript) or CLI * Create your first sandbox from a pre-built template * Execute code in multiple languages (Python, JavaScript, Bash, Go) * Work with files in sandboxes (read, write, list) * Clean up sandboxes to free resources * Use context managers for automatic cleanup (Python) ## Prerequisites * [HopX API key](https://console.hopx.dev) (get one [here](/api-key) if you don't have it) * Python 3.8+ **or** Node.js 18+ **or** CLI installed * Basic experience with Python, JavaScript, or command line ## Run your first sandbox Choose your preferred method: **Python SDK**, **JavaScript SDK**, or **CLI**. This guide focuses on SDKs. For CLI, see the [CLI Quickstart](/cli/quickstart). Install the HopX SDK for your preferred language, or use the CLI: ```bash theme={null} pip install hopx-ai ``` ```bash theme={null} npm install @hopx-ai/sdk ``` ```bash theme={null} # Quick install curl -fsSL https://hopx.dev/install.sh | sh ``` See [CLI Installation](/cli/installation) for more options. Create a sandbox using a pre-built template. Templates provide pre-configured environments with common tools and packages. ```python theme={null} from hopx_ai import Sandbox from hopx_ai.exceptions import APIError, ResourceLimitError try: # Create a sandbox with the code-interpreter template sandbox = Sandbox.create( template="code-interpreter", api_key="your-api-key-here" # Or set HOPX_API_KEY env var ) print(f"Sandbox created: {sandbox.sandbox_id}") print(f"Status: {sandbox.get_info().status}") except APIError as e: print(f"API error: {e}") except ResourceLimitError as e: print(f"Resource limit exceeded: {e}") ``` **Expected Output:** ``` Sandbox created: sandbox_abc123xyz Status: running ``` You can also use Sandbox.create() without specifying an API key if you set the HOPX\_API\_KEY environment variable. ```typescript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import { APIError, ResourceLimitError } from '@hopx-ai/sdk'; try { // Create a sandbox with the code-interpreter template const sandbox = await Sandbox.create({ template: 'code-interpreter', apiKey: 'your-api-key-here' // Or set HOPX_API_KEY env var }); console.log(`Sandbox created: ${sandbox.sandboxId}`); const info = await sandbox.getInfo(); console.log(`Status: ${info.status}`); } catch (error) { if (error instanceof APIError) { console.error(`API error: ${error.message}`); } else if (error instanceof ResourceLimitError) { console.error(`Resource limit exceeded: ${error.message}`); } else { console.error(`Unexpected error: ${error.message}`); } } ``` **Expected Output:** ``` Sandbox created: sandbox_abc123xyz Status: running ``` You can also use Sandbox.create() without specifying an API key if you set the HOPX\_API\_KEY environment variable. Run code in your sandbox. ```python theme={null} # Execute Python code result = sandbox.run_code(''' import math # Calculate the area of a circle radius = 5 area = math.pi * radius ** 2 print(f"Area of circle with radius {radius}: {area:.2f}") ''', language: 'python') print(result.stdout) # Output: Area of circle with radius 5: 78.54 # Check if execution was successful if result.success: print("✅ Code executed successfully!") else: print(f"❌ Error: {result.stderr}") ``` The run\_code() method automatically captures rich outputs like matplotlib plots and pandas DataFrames. See [Rich Output Capture](/core-concepts/code-execution/rich-output) for more details. ```typescript theme={null} // Execute JavaScript code const result = await sandbox.runCode(` const radius = 5; const area = Math.PI * radius ** 2; console.log(\`Area of circle with radius \${radius}: \${area.toFixed(2)}\`); `, { language: 'javascript' }); console.log(result.stdout); // Output: Area of circle with radius 5: 78.54 // Check if execution was successful if (result.success) { console.log('✅ Code executed successfully!'); } else { console.log(`❌ Error: ${result.stderr}`); } ``` The sandbox will execute code written in any language as long as the template you use provides the necessary dependencies.

See the Getting Template Details page for information on available templates and their environments, alternatively create your own template with the Building Templates guide.
Upload, read, and write files in your sandbox: ```python theme={null} # Write a file sandbox.files.write('/workspace/data.txt', 'Hello, HopX!') # Read the file content = sandbox.files.read('/workspace/data.txt') print(content) # Output: Hello, HopX! # List files in a directory files = sandbox.files.list('/workspace') for file in files: print(f"- {file.name} ({file.size} bytes)") ``` **Expected Output:** ``` Hello, HopX! - data.txt (12 bytes) - script.py (245 bytes) ``` ```typescript theme={null} // Write a file await sandbox.files.write('/workspace/data.txt', 'Hello, HopX!'); // Read the file const content = await sandbox.files.read('/workspace/data.txt'); console.log(content); // Output: Hello, HopX! // List files in a directory const files = await sandbox.files.list('/workspace'); files.forEach(file => { console.log(`- ${file.name} (${file.size} bytes)`); }); ``` **Expected Output:** ``` Hello, HopX! - data.txt (12 bytes) - script.js (189 bytes) ``` Always clean up your sandbox when you're done to free resources: ```python theme={null} # Delete the sandbox sandbox.kill() print("Sandbox deleted") ``` **Expected Output:** ``` Sandbox deleted ``` ```typescript theme={null} // Delete the sandbox await sandbox.kill(); console.log('Sandbox deleted'); ``` **Expected Output:** ``` Sandbox deleted ``` Calling kill() permanently deletes the sandbox and all its data. Make sure you've saved any important files before cleaning up. See [Downloading Files](./core-concepts/filesystem/downloading) for more details.
## Using Context Managers (Python) Python SDK supports context managers for automatic cleanup: ```python theme={null} from hopx_ai import Sandbox # Automatically cleans up when exiting the context with Sandbox.create(template="code-interpreter") as sandbox: result = sandbox.run_code('print("Hello from HopX!")', language='python') print(result.stdout) # Sandbox is automatically deleted when exiting the block ``` **Expected Output:** ``` Hello from HopX! ``` *** ## Complete Example Here's a complete example that brings it all together: ```python theme={null} from hopx_ai import Sandbox # Setup your API key as an env var or inject it here as previously instructed. # Create sandbox sandbox = Sandbox.create(template="code-interpreter") try: # Execute code result = sandbox.run_code(''' import math # Calculate the area of a circle radius = 5 area = math.pi * radius ** 2 print(f"Area of circle with radius {radius}: {area:.2f}") ''', language='python') print("Output:") print(result.stdout) sandbox.run_code('mkdir /workspace/test') # Work with files sandbox.files.write('/workspace/test/result.json', result.stdout) print("\n✅ Result saved to file") # List files in a directory files = sandbox.files.list('/workspace/test') for file in files: print(f"- {file.name} ({file.size} bytes)")\ # Read the file content = sandbox.files.read('/workspace/test/result.json') print(content) finally: # Always clean up sandbox.kill() print("✅ Sandbox cleaned up") ``` ```typescript theme={null} import { Sandbox } from '@hopx-ai/sdk'; async function main() { // Create sandbox const sandbox = await Sandbox.create({ template: 'code-interpreter'}); try { // Execute JavaScript code const result = await sandbox.runCode(` const radius = 5; const area = Math.PI * radius ** 2; console.log(\`Area of circle with radius \${radius}: \${area.toFixed(2)}\`); `, { language: 'javascript' }); console.log('Output:'); console.log(result.stdout); console.log(result.stderr); // Work with files await sandbox.files.write('/workspace/test/result.json', result.stdout); console.log('\n✅ Result saved to file'); // List files in a directory const files = await sandbox.files.list('/workspace/test'); console.log(files); // Read the file const content = await sandbox.files.read('/workspace/test/result.json'); console.log(content); } finally { // Always clean up await sandbox.kill(); console.log('✅ Sandbox cleaned up'); } } main(); ``` ## Related * **[Python SDK Quickstart](/sdk/python/quickstart)** - Detailed Python SDK guide * **[JavaScript SDK Quickstart](/sdk/javascript/quickstart)** - Detailed JavaScript SDK guide * **[CLI Quickstart](/cli/quickstart)** - Command-line interface quickstart * **[API Quickstart](/api/quickstart)** - API-based quickstart * **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Learn more about sandbox creation * **[Code Execution](/core-concepts/code-execution/synchronous)** - Learn about code execution ## Next Steps Now that you've created your first sandbox, explore more: * **Learn about sandbox lifecycle**: [Creating Sandboxes](/core-concepts/sandboxes/creating) * **Execute code in different ways**: [Code Execution](/core-concepts/code-execution/synchronous) * **Work with templates**: [Templates](/core-concepts/templates/listing) * **Integrate with MCP**: [MCP Integration](/guides/integrations/mcp-integration) * **Explore the SDK**: [Python SDK Reference](/sdk/python/introduction) or [JavaScript SDK Reference](/sdk/javascript/introduction) * **Use the CLI**: [CLI Reference](/cli/introduction) - Command-line interface for HopX * **Check supported languages**: [Supported Languages](/supported-languages) For AI agent developers, check out the [MCP Integration guide](/guides/integrations/mcp-integration) to enable AI assistants to execute code safely in sandboxes. # Cache Management Source: https://docs.hopx.ai/sdk/javascript/cache Cache management resource for managing execution result cache in HopX sandboxes using the JavaScript/TypeScript SDK. Complete reference for the Cache class including async methods for viewing cache statistics and clearing execution cache. Includes TypeScript examples for cache optimization. **Version:** 0.1.22\ **Last Verified:** 2025-01-27\ **Package:** `@hopx-ai/sdk` on [npm](https://www.npmjs.com/package/@hopx-ai/sdk) ## Overview The `Cache` resource provides methods for managing the execution result cache in sandboxes. ## Methods ### `stats` Get cache statistics. ```typescript theme={null} async cache.stats(): Promise ``` **Returns:** `Promise` - Cache statistics **Example:** ```typescript theme={null} const stats = await sandbox.cache.stats(); console.log(`Cache hits: ${stats.cache.totalHits}`); console.log(`Cache size: ${stats.cache.size} / ${stats.cache.maxSize}`); ``` *** ### `clear` Clear the execution result cache. ```typescript theme={null} async cache.clear(): Promise ``` This clears all cached execution results. *** ## Related Classes * **[Sandbox](/sdk/javascript/sandbox)** - Main sandbox class * **[Core Concepts: Cache](/core-concepts/cache/statistics)** - Learn about cache management ## See Also * [Sandbox Class](/sdk/javascript/sandbox) - Access cache via `sandbox.cache` * [Cache Statistics](/core-concepts/cache/statistics) - Detailed cache documentation ## Related * **[Python SDK: Cache](/sdk/python/cache)** - Python SDK cache management * **[Cache Statistics](/core-concepts/cache/statistics)** - Learn about cache statistics * **[Clearing Cache](/core-concepts/cache/clearing)** - Clear cache to free memory ## Next Steps * Learn about [Cache Statistics](/core-concepts/cache/statistics) to monitor cache * Review [Clearing Cache](/core-concepts/cache/clearing) to free memory * Explore [Code Execution](/core-concepts/code-execution/synchronous) for cached results * **[CLI System Commands](/cli/commands/system)** - View cache from CLI # Command Execution Source: https://docs.hopx.ai/sdk/javascript/commands Command execution resource for running shell commands in HopX sandboxes using the JavaScript/TypeScript SDK. Complete reference for the Commands class including async methods for running commands synchronously and in the background. Includes TypeScript examples for system administration and automation. **Version:** 0.1.22\ **Last Verified:** 2025-01-27\ **Package:** `@hopx-ai/sdk` on [npm](https://www.npmjs.com/package/@hopx-ai/sdk) ## Overview The `Commands` resource provides shell command execution capabilities for sandboxes. Access it via the `commands` property on a `Sandbox` instance. ## Methods ### `run` Run a shell command. ```typescript theme={null} async commands.run( command: string, options?: CommandOptions ): Promise ``` **Parameters:** * `command` (`string`): Shell command to execute * `options.timeout` (`number`, optional): Command timeout in seconds (default: `30`) * `options.background` (`boolean`, optional): Run in background (default: `false`) * `options.workingDir` (`string`, optional): Working directory (default: `'/workspace'`) * `options.env` (`Record`, optional): Environment variables **Returns:** `Promise` - Command execution result **Example:** ```typescript theme={null} const result = await sandbox.commands.run('ls -la /workspace'); console.log(result.stdout); console.log(`Exit code: ${result.exitCode}`); ``` *** ### `runBackground` Run command in background. ```typescript theme={null} async commands.runBackground( command: string, options?: Omit ): Promise<{ processId: string }> ``` **Returns:** `Promise<{ processId: string }>` - Process ID *** ## Related Classes * **[Sandbox](/sdk/javascript/sandbox)** - Main sandbox class * **[Files](/sdk/javascript/files)** - File operations resource ## See Also * [Core Concepts: Execution](/core-concepts/execution) - Learn about code execution * [Sandbox Class](/sdk/javascript/sandbox) - Access commands via `sandbox.commands` ## Related * **[Python SDK: Commands](/sdk/python/commands)** - Python SDK command execution * **[Running Commands](/core-concepts/commands/running)** - Learn about command execution * **[Background Commands](/core-concepts/commands/background)** - Run commands in background ## Next Steps * Learn about [Running Commands](/core-concepts/commands/running) for synchronous execution * Explore [Background Commands](/core-concepts/commands/background) for non-blocking tasks * Review [Code Execution](/core-concepts/code-execution/synchronous) for programmatic execution * **[CLI Commands](/cli/commands/cmd)** - Execute shell commands from CLI # Desktop Automation Source: https://docs.hopx.ai/sdk/javascript/desktop Desktop automation resource for sandbox GUI interactions, screenshots, and VNC access in HopX using the JavaScript/TypeScript SDK. Complete reference for the Desktop class including async methods for VNC servers, screenshots, mouse and keyboard control, window management, and clipboard operations. Includes TypeScript examples for desktop automation. **Version:** 0.1.22\ **Last Verified:** 2025-01-27\ **Package:** `@hopx-ai/sdk` on [npm](https://www.npmjs.com/package/@hopx-ai/sdk) ## Overview The `Desktop` resource provides desktop automation capabilities for sandboxes with GUI support. Desktop features require a desktop-enabled template. Not all templates support desktop operations. ## Methods ### VNC Methods * `async desktop.startVnc(): Promise` * `async desktop.stopVnc(): Promise` * `async desktop.getVncInfo(): Promise` * `async desktop.getVncUrl(): Promise` ### Mouse Methods * `async desktop.mouseClick(x: number, y: number, options?: MouseClickOptions): Promise` * `async desktop.mouseMove(x: number, y: number): Promise` * `async desktop.mouseDrag(fromX: number, fromY: number, toX: number, toY: number): Promise` * `async desktop.mouseScroll(x: number, y: number, deltaY: number): Promise` ### Keyboard Methods * `async desktop.keyboardType(text: string): Promise` * `async desktop.keyboardPress(key: string): Promise` * `async desktop.keyboardCombination(keys: string[]): Promise` ### Screenshot Methods * `async desktop.screenshot(): Promise` * `async desktop.screenshotRegion(x: number, y: number, width: number, height: number): Promise` *** ## Related Classes * **[Sandbox](/sdk/javascript/sandbox)** - Main sandbox class ## Related * **[Python SDK: Desktop](/sdk/python/desktop)** - Python SDK desktop automation * **[VNC Server](/core-concepts/desktop/vnc-server)** - Learn about VNC access * **[Screenshots](/core-concepts/desktop/screenshots)** - Capture screenshots ## Next Steps * Learn about [VNC Server](/core-concepts/desktop/vnc-server) for remote desktop access * Explore [Screenshots](/core-concepts/desktop/screenshots) for visual verification * Review [Mouse Control](/core-concepts/desktop/mouse-control) and [Keyboard Control](/core-concepts/desktop/keyboard-control) for GUI automation * **[Types](/sdk/javascript/types)** - TypeScript type definitions * **[CLI System Commands](/cli/commands/system)** - System operations from CLI ## See Also * [Core Concepts: Desktop](/core-concepts/desktop) - Learn about desktop automation * [Sandbox Class](/sdk/javascript/sandbox) - Access desktop via `sandbox.desktop` # Environment Variables Source: https://docs.hopx.ai/sdk/javascript/environment-variables Environment variable management resource for configuring sandbox environment in HopX using the JavaScript/TypeScript SDK. Complete reference for the Environment class including async methods for getting, setting, updating, and clearing environment variables. Includes TypeScript examples for configuration management. **Version:** 0.1.22\ **Last Verified:** 2025-01-27\ **Package:** `@hopx-ai/sdk` on [npm](https://www.npmjs.com/package/@hopx-ai/sdk) ## Overview The `EnvironmentVariables` resource (accessed via `sandbox.env`) provides methods for managing environment variables in sandboxes. ## Methods ### `getAll` Get all environment variables. ```typescript theme={null} async env.getAll(): Promise> ``` **Returns:** `Promise>` - Dictionary of all environment variables *** ### `get` Get specific environment variable. ```typescript theme={null} async env.get(key: string): Promise ``` **Returns:** `Promise` - Variable value or `undefined` *** ### `set` Set a single environment variable. ```typescript theme={null} async env.set(key: string, value: string): Promise ``` *** ### `setAll` Replace all environment variables (destructive). ```typescript theme={null} async env.setAll(envVars: Record): Promise> ``` This replaces ALL existing environment variables. Use `update()` to merge instead. *** ### `update` Update environment variables (merge with existing). ```typescript theme={null} async env.update(envVars: Record): Promise> ``` *** ### `delete` Delete a single environment variable. ```typescript theme={null} async env.delete(key: string): Promise ``` *** ## Related Classes * **[Sandbox](/sdk/javascript/sandbox)** - Main sandbox class * **[Commands](/sdk/javascript/commands)** - Command execution resource ## See Also * [Core Concepts: Environment Variables](/core-concepts/environment-variables) - Learn about environment configuration * [Sandbox Class](/sdk/javascript/sandbox) - Access env via `sandbox.env` ## Related * **[Python SDK: Environment Variables](/sdk/python/environment-variables)** - Python SDK environment management * **[Getting Environment Variables](/core-concepts/environment/getting)** - Learn about getting env vars * **[Setting Environment Variables](/core-concepts/environment/setting)** - Learn about setting env vars ## Next Steps * Learn about [Getting Environment Variables](/core-concepts/environment/getting) to read values * Explore [Setting Environment Variables](/core-concepts/environment/setting) to configure environment * Review [Updating Environment Variables](/core-concepts/environment/updating) for batch updates * **[CLI Environment Variables](/cli/commands/env)** - Manage env vars from CLI # Sandbox Error Handling Source: https://docs.hopx.ai/sdk/javascript/errors Error classes and exception handling in the HopX JavaScript/TypeScript SDK. Handle API errors, network errors, agent errors, and validation errors gracefully. Learn about error types, error handling patterns, and best practices for robust error handling in your applications. Includes TypeScript error class reference and handling examples. **Version:** 0.1.22\ **Last Verified:** 2025-01-27\ **Package:** `@hopx-ai/sdk` on [npm](https://www.npmjs.com/package/@hopx-ai/sdk) ## Overview The JavaScript SDK provides a comprehensive error hierarchy for handling different types of errors. All errors inherit from `HopxError`. ## Import ```typescript theme={null} import { HopxError, APIError, AuthenticationError, NotFoundError, ValidationError, RateLimitError, ResourceLimitError, ServerError, NetworkError, TimeoutError } from '@hopx-ai/sdk'; ``` ## Base Error ### `HopxError` Base exception for all HopX SDK errors. **Properties:** * `message` (`string`): Error message * `code` (`string`, optional): Error code * `requestId` (`string`, optional): Request ID for debugging * `statusCode` (`number`, optional): HTTP status code * `details` (`Record`, optional): Additional error details *** ## API Errors ### `APIError` Base class for API request failures. **Inherits from:** `HopxError` *** ### `AuthenticationError` Authentication failed (401). **Inherits from:** `APIError` **When thrown:** * Invalid or missing API key * Expired authentication token *** ### `NotFoundError` Resource not found (404). **Inherits from:** `APIError` **When thrown:** * Sandbox not found * Template not found * File not found *** ### `ValidationError` Request validation failed (400). **Inherits from:** `APIError` **When thrown:** * Invalid parameters * Missing required fields *** ### `RateLimitError` Rate limit exceeded (429). **Inherits from:** `APIError` **Properties:** * `retryAfter` (`number`, optional): Seconds to wait before retrying *** ### `ResourceLimitError` Resource limit exceeded. **Inherits from:** `APIError` **Properties:** * `limit` (`number`): Resource limit * `current` (`number`): Current usage * `available` (`number`): Available resources *** ### `ServerError` Server error (5xx). **Inherits from:** `APIError` *** ## Network Errors ### `NetworkError` Network communication failed. **Inherits from:** `HopxError` *** ### `TimeoutError` Request timed out. **Inherits from:** `NetworkError` *** ## Error Handling Examples ### Example 1: Basic Error Handling ```typescript theme={null} import { Sandbox, HopxError } from '@hopx-ai/sdk'; try { const sandbox = await Sandbox.create({ template: 'code-interpreter' }); const result = await sandbox.runCode("print('Hello')"); } catch (error) { if (error instanceof HopxError) { console.error(`Error: ${error.message}`); if (error.statusCode) { console.error(`Status: ${error.statusCode}`); } } } ``` ### Example 2: Specific Error Handling ```typescript theme={null} import { Sandbox, AuthenticationError, NotFoundError } from '@hopx-ai/sdk'; try { const sandbox = await Sandbox.create({ template: 'code-interpreter' }); } catch (error) { if (error instanceof AuthenticationError) { console.error('Authentication failed. Check your API key.'); } else if (error instanceof NotFoundError) { console.error('Template not found.'); } } ``` *** ## Related Classes * **[Types](/sdk/javascript/types)** - TypeScript type definitions * **[Sandbox](/sdk/javascript/sandbox)** - Sandbox operations that may throw errors ## See Also * [Types](/sdk/javascript/types) - Learn about type definitions * [Core Concepts: Errors](/core-concepts/errors) - Learn about error handling ## Next Steps Now that you understand error handling, explore: * [Error Handling Basics](/cookbooks/getting-started/error-handling) - Practical error handling patterns * [Sandbox Operations](/sdk/javascript/sandbox) - See errors in action * [API Errors](/api/concepts/errors) - Understand API error responses * **[CLI Reference](/cli/introduction)** - Use HopX from the command line * [Troubleshooting](/api/concepts/troubleshooting) - Common issues and solutions # File Operations Source: https://docs.hopx.ai/sdk/javascript/files File operations resource for reading, writing, and managing files in HopX sandboxes using the JavaScript/TypeScript SDK. Complete reference for the Files class including async methods for reading, writing, listing, uploading, downloading, and watching files. Includes TypeScript examples for all file operations. **Version:** 0.1.22\ **Last Verified:** 2025-01-27\ **Package:** `@hopx-ai/sdk` on [npm](https://www.npmjs.com/package/@hopx-ai/sdk) ## Overview The `Files` resource provides file operations for sandboxes. Access it via the `files` property on a `Sandbox` instance. All file operations are async and work with both text and binary files. ## Access ```typescript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); const files = sandbox.files; // Lazy-loaded ``` ## Methods ### `read` Read text file contents. ```typescript theme={null} async files.read(path: string): Promise ``` **Parameters:** * `path` (`string`): File path to read **Returns:** `Promise` - File contents as string **Example:** ```typescript theme={null} const content = await sandbox.files.read('/workspace/script.py'); console.log(content); ``` *** ### `readBytes` Read binary file contents. ```typescript theme={null} async files.readBytes(path: string): Promise ``` **Returns:** `Promise` - File contents as Buffer *** ### `write` Write text file. ```typescript theme={null} async files.write( path: string, content: string, options?: FileWriteOptions ): Promise ``` **Parameters:** * `path` (`string`): File path to write * `content` (`string`): Text content * `options.mode` (`string`, optional): File permissions *** ### `writeBytes` Write binary file. ```typescript theme={null} async files.writeBytes( path: string, content: Buffer, options?: FileWriteOptions ): Promise ``` *** ### `list` List directory contents. ```typescript theme={null} async files.list(path: string): Promise ``` **Returns:** `Promise` - Array of file/directory information objects *** ### `exists` Check if file/directory exists. ```typescript theme={null} async files.exists(path: string): Promise ``` **Returns:** `Promise` - `true` if exists, `false` otherwise *** ### `remove` Remove file or directory. ```typescript theme={null} async files.remove(path: string): Promise ``` *** ### `mkdir` Create directory. ```typescript theme={null} async files.mkdir(path: string): Promise ``` *** ### `download` Download file (alias for `readBytes`). ```typescript theme={null} async files.download(path: string): Promise ``` *** ## Examples ### Example 1: Basic File Operations ```typescript theme={null} import { Sandbox } from '@hopx-ai/sdk'; async function main() { const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Write a file await sandbox.files.write('/workspace/hello.py', "print('Hello, World!')"); // Read it back const content = await sandbox.files.read('/workspace/hello.py'); console.log(content); // Execute it const result = await sandbox.runCode( "exec(open('/workspace/hello.py').read())" ); console.log(result.stdout); await sandbox.kill(); } main(); ``` *** ## Related Classes * **[Sandbox](/sdk/javascript/sandbox)** - Main sandbox class * **[Commands](/sdk/javascript/commands)** - Command execution resource * **[Types](/sdk/javascript/types)** - TypeScript type definitions ## See Also * [Core Concepts: Files](/core-concepts/files) - Learn about file operations * [Sandbox Class](/sdk/javascript/sandbox) - Access files via `sandbox.files` ## Related * **[Python SDK: Files](/sdk/python/files)** - Python SDK file operations * **[Reading Files](/core-concepts/filesystem/reading)** - Learn about reading files * **[Writing Files](/core-concepts/filesystem/writing)** - Learn about writing files ## Next Steps * Learn about [Reading Files](/core-concepts/filesystem/reading) to access file contents * Explore [Writing Files](/core-concepts/filesystem/writing) to create files * Review [Uploading Files](/core-concepts/filesystem/uploading) for local file transfers * **[CLI File Operations](/cli/commands/files)** - Use file operations from CLI # Installation Source: https://docs.hopx.ai/sdk/javascript/installation Install the HopX JavaScript SDK and set up your development environment. Get started with the official JavaScript/TypeScript SDK for HopX, install via npm, configure API keys, and verify installation. Learn system requirements, installation methods, and troubleshooting tips. Includes installation examples for Node.js and browser environments. **SDK Version:** 0.1.21+\ **Last Verified:** 2025-01-27 ## Prerequisites Before installing the HopX JavaScript SDK, ensure you have: * **Node.js 18+** (20+ recommended for LTS support) * **npm, yarn, or pnpm** (package manager) * **HopX API key** - Get yours at [console.hopx.dev](https://console.hopx.dev) ## Install with npm The recommended way to install the HopX JavaScript SDK: ```bash theme={null} npm install @hopx-ai/sdk ``` ## Install with yarn ```bash theme={null} yarn add @hopx-ai/sdk ``` ## Install with pnpm ```bash theme={null} pnpm add @hopx-ai/sdk ``` ## Install Specific Version Install a specific version: ```bash theme={null} npm install @hopx-ai/sdk@0.1.21 ``` ## Install from Source For development or to use the latest unreleased version: ```bash theme={null} git clone https://github.com/hopx-ai/hopx.git cd HopX/javascript npm install npm run build ``` Building from source requires Node.js 18+, TypeScript 5.3+, and build tools. See the [GitHub repository](https://github.com/hopx-ai/HopX) for detailed development setup instructions. ## TypeScript Support TypeScript definitions are included automatically. No additional `@types` package needed. ```typescript theme={null} import { Sandbox, ExecutionResult } from '@hopx-ai/sdk'; const sandbox: Sandbox = await Sandbox.create({ template: 'code-interpreter' }); const result: ExecutionResult = await sandbox.runCode('print("Hello")'); ``` ## Verify Installation Verify the installation: ```bash theme={null} node -e "const { Sandbox } = require('@hopx-ai/sdk'); console.log('SDK installed successfully')" ``` ## Set Up Authentication The SDK requires an API key for authentication. You have three options: ### Option 1: Environment Variable (Recommended) Set the `HOPX_API_KEY` environment variable: ```bash theme={null} # Linux/macOS export HOPX_API_KEY="your-API key-here" # Windows (PowerShell) $env:HOPX_API_KEY="your-API key-here" # Windows (CMD) set HOPX_API_KEY=your-API key-here ``` ### Option 2: Pass API key Directly Pass the API key when creating a sandbox: ```typescript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter', apiKey: 'your-API key-here' }); ``` ### Option 3: Configuration File Create a `.env` file in your project root: ```bash theme={null} # .env HOPX_API_KEY=your-API key-here ``` Then load it in your code (requires `dotenv` package): ```bash theme={null} npm install dotenv ``` ```typescript theme={null} import 'dotenv/config'; import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); ``` Never commit your API key to version control. Always use environment variables or secure secret management for production applications. ## Get Your API key 1. Sign up at [console.hopx.dev](https://console.hopx.dev) 2. Navigate to **Settings** → **API Keys** 3. Create a new API key 4. Copy the key (you'll only see it once) API keys are scoped to your account and have full access to create, manage, and delete sandboxes. Keep them secure. ## Supported Node.js Versions The SDK is tested and supported on: * **Node.js 18.x** - Minimum supported version * **Node.js 20.x** - LTS, recommended for production * **Node.js 22.x** - Latest LTS, fully supported ## Module Systems ### ES Modules (Recommended) ```typescript theme={null} import { Sandbox } from '@hopx-ai/sdk'; const sandbox = await Sandbox.create({ template: 'code-interpreter' }); ``` Ensure your `package.json` has: ```json theme={null} { "type": "module" } ``` ### CommonJS ```javascript theme={null} const { Sandbox } = require('@hopx-ai/sdk'); (async () => { const sandbox = await Sandbox.create({ template: 'code-interpreter' }); })(); ``` ## Dependencies The SDK has minimal dependencies: * `node-fetch` - HTTP client for API calls (Node.js 18+ has native fetch) * `ws` - WebSocket client for streaming * Type definitions included All dependencies are automatically installed with `npm install @hopx-ai/sdk`. ## Browser Support The SDK can be used in browsers with: 1. **CORS Configuration** - Configure your HopX account to allow browser origins 2. **Build Tool** - Use a bundler (webpack, Vite, esbuild) to bundle the SDK 3. **API key Security** - Never expose API keys in client-side code (use a backend proxy) Using the SDK directly in browsers requires CORS configuration and exposes your API key. For production browser applications, use a backend proxy instead. ## Troubleshooting ### Import Errors If you get `Cannot find module '@hopx-ai/sdk'`: 1. Verify Node.js version: `node --version` (should be 18+) 2. Check installation: `npm list @hopx-ai/sdk` 3. Reinstall: `npm install --save @hopx-ai/sdk` ### TypeScript Errors If TypeScript can't find types: 1. Ensure `@hopx-ai/sdk` is in `dependencies` (not `devDependencies`) 2. Restart your TypeScript server/IDE 3. Check `tsconfig.json` includes `node_modules` in type resolution ### Authentication Errors If you get authentication errors: 1. Verify API key is set: `echo $HOPX_API_KEY` (Linux/macOS) or `echo %HOPX_API_KEY%` (Windows) 2. Check API key is valid at [console.hopx.dev](https://console.hopx.dev) 3. Ensure no extra spaces or quotes in the API key ### Network Errors If you encounter network errors: 1. Check internet connection 2. Verify firewall allows outbound HTTPS (port 443) 3. Check if you're behind a corporate proxy (may need proxy configuration) For more troubleshooting help, see the [Troubleshooting Guide](/sdk/javascript/troubleshooting). ## Related * **[JavaScript SDK Quickstart](/sdk/javascript/quickstart)** - Get started with the SDK * **\[API key Management]\(/API key)** - Learn about API key security * **[Sandbox Class Reference](/sdk/javascript/sandbox)** - Complete SDK reference ## Next Steps Once you've successfully installed the SDK: * **[Quickstart Guide](/sdk/javascript/quickstart)** - Create your first sandbox and run code * **[API Reference](/sdk/javascript/sandbox)** - Explore the full SDK API * **[CLI Installation](/cli/installation)** - Install the HopX CLI # Overview Source: https://docs.hopx.ai/sdk/javascript/introduction Official JavaScript/TypeScript SDK for HopX - Create and manage cloud sandboxes in Node.js and browsers. Install the SDK, authenticate with your API key, and start creating sandboxes, executing code, managing files, and automating desktop interactions. Complete reference with async/await examples for all SDK methods and classes. **Version:** 0.1.21+\ **Last Verified:** 2025-01-27\ **Package:** `@hopx-ai/sdk` on [npm](https://www.npmjs.com/package/@hopx-ai/sdk) ## What is the JavaScript SDK? The HopX JavaScript SDK provides a modern, type-safe interface for creating and managing cloud sandboxes from Node.js applications, TypeScript projects, or browser environments. Build AI agents, run untrusted code securely, execute tests in isolation, or process data with rich output capture—all with async/await and full TypeScript support. The SDK is a thin wrapper around the HopX REST API that handles authentication, request formatting, error translation, and response parsing automatically, giving you a better developer experience than working with the raw API. ## Target Audience This SDK is designed for: * **Backend Node.js developers** using Node.js 18+ or 20+ * **TypeScript developers** who want full type safety and IDE autocomplete * **Frontend developers** building browser-based tools (with CORS configuration) * **Full-stack engineers** working with JavaScript/TypeScript ecosystems * **Automation engineers** building Node.js-based workflows ## Supported Runtimes * **Node.js:** 18.x, 20.x, 22.x (LTS versions recommended) * **TypeScript:** 4.5+ (full type definitions included) * **Browsers:** Modern browsers with ES2020+ support (with CORS setup) * **Package Managers:** npm, yarn, pnpm ## When to Use the SDK vs CLI vs Raw API ### Use the JavaScript SDK when: * ✅ You're building Node.js or TypeScript applications * ✅ You want TypeScript type definitions and IDE autocomplete * ✅ You prefer Promise-based async/await patterns * ✅ You need automatic error handling and retries * ✅ You're working with JavaScript objects and JSON * ✅ You want tree-shakeable imports ### Use the CLI when: * ✅ You prefer command-line workflows * ✅ You're scripting or automating from shell * ✅ You want quick one-off operations * ✅ You're working in CI/CD pipelines * ✅ You need interactive terminal sessions ### Use the Raw API when: * ⚠️ You're building in a non-JavaScript language * ⚠️ You need fine-grained control over HTTP requests * ⚠️ You're integrating with existing HTTP client libraries (axios, fetch wrappers) * ⚠️ You need custom retry logic or connection pooling The SDK is a thin wrapper around the HopX REST API. It handles authentication, request formatting, error translation, and response parsing automatically. For most JavaScript/TypeScript use cases, the SDK provides a better developer experience. ## Architecture The SDK is built with: * **TypeScript** - Full type definitions for all APIs * **ES Modules** - Modern import/export syntax * **CommonJS** - Also supports `require()` for compatibility * **Promise-based** - All operations return Promises (async/await friendly) ## Core Capabilities The JavaScript SDK provides: * **Sandbox Management** - Create, connect, list, and delete sandboxes * **Code Execution** - Run Python, JavaScript, Bash, Go, and more * **Rich Outputs** - Capture matplotlib plots, pandas DataFrames, images * **File Operations** - Read, write, list, upload, download files * **Command Execution** - Run shell commands synchronously or in background * **Environment Variables** - Set, get, update, and clear environment variables * **Process Management** - List and manage running processes * **Cache Management** - Monitor and clear execution result cache * **Desktop Automation** - VNC access, mouse/keyboard control (Premium) * **Template Building** - Create custom sandbox environments * **WebSocket Streaming** - Real-time terminal and code execution streaming ## Quick Example ```typescript theme={null} import { Sandbox } from '@hopx-ai/sdk'; // Create a sandbox (~100ms) const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Execute code const result = await sandbox.runCode('print("Hello from HopX!")'); console.log(result.stdout); // "Hello from HopX!\n" // Cleanup await sandbox.kill(); ``` ## Next Steps * **[Installation Guide](/sdk/javascript/installation)** - Install the SDK and set up your environment * **[Quickstart](/sdk/javascript/quickstart)** - Get your first sandbox running in minutes * **[API Reference](/sdk/javascript/sandbox)** - Complete class and method documentation ## Related * [Python SDK](/sdk/python/introduction) - Official Python SDK * [CLI Reference](/cli/introduction) - Command-line interface for HopX * [API Reference](/api/introduction) - Raw REST API documentation * [Core Concepts](/core-concepts/sandboxes/creating) - Learn about sandboxes, execution, and more # Quickstart Source: https://docs.hopx.ai/sdk/javascript/quickstart Get your first sandbox running in minutes with the HopX JavaScript SDK - install, authenticate, execute code, see results. Complete quickstart guide for creating sandboxes, running JavaScript/TypeScript code, managing files, and cleaning up resources. Perfect for developers new to HopX. Includes async/await examples and best practices. **Goal:** Create a sandbox, execute code, and see the output in under 5 minutes.\ **Prerequisites:** Node.js 18+, npm, HopX API key\ **Time:** \~5 minutes This quickstart gets you from zero to your first successful code execution. Follow these steps in order. ## What You'll Learn In this quickstart, you'll learn how to: * Install and verify the JavaScript SDK * Set up API key authentication * Create a sandbox from a template * Execute code in the sandbox using async/await * Access execution results and output * Clean up sandboxes properly ## Step 1: Install the SDK ```bash theme={null} npm install @hopx-ai/sdk ``` ## Step 1.5: Verify Installation Verify the SDK is installed correctly: ```bash theme={null} node -e "const { Sandbox } = require('@hopx-ai/sdk'); console.log('HopX SDK installed successfully')" ``` Expected output: `HopX SDK installed successfully` ## Step 2: Set Your API key Set the `HOPX_API_KEY` environment variable: ```bash theme={null} # Linux/macOS export HOPX_API_KEY="your-API key-here" # Windows (PowerShell) $env:HOPX_API_KEY="your-API key-here" ``` Get your API key from [console.hopx.dev](https://console.hopx.dev) → Settings → API Keys ## Step 3: Create and Run Your First Sandbox Create a file `hello-HopX.js`: ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; async function main() { // Create a sandbox (~100ms) const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Execute code in the sandbox const result = await sandbox.runCode('print("Hello from HopX!")'); // Print the output console.log(result.stdout); // Cleanup - delete the sandbox await sandbox.kill(); } main().catch(console.error); ``` ## Step 4: Run It ```bash theme={null} node hello-HopX.js ``` If using ES modules, ensure your `package.json` has `"type": "module"`, or use `.mjs` extension. ## Expected Output ``` Hello from HopX! ``` 🎉 **Success!** You've created your first sandbox and executed code. The sandbox was automatically cleaned up after execution. ## What Just Happened? 1. **`Sandbox.create()`** - Created a new sandbox from the `code-interpreter` template (Python environment) 2. **`sandbox.runCode()`** - Executed Python code in the sandbox 3. **`result.stdout`** - Retrieved the standard output from code execution 4. **`sandbox.kill()`** - Deleted the sandbox to free resources ## Related * **[API Quickstart](/api/quickstart)** - Get started with the API * **[Python SDK Quickstart](/sdk/python/quickstart)** - Python SDK equivalent * **[Sandbox Class Reference](/sdk/javascript/sandbox)** - Complete SDK reference * **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Learn more about sandbox creation ## Next Steps Now that you have a working setup, explore more: * **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Learn about different templates and options * **[Code Execution](/core-concepts/code-execution/synchronous)** - Run Python, JavaScript, Bash, and more * **[File Operations](/core-concepts/filesystem/reading)** - Read, write, and manage files in sandboxes * **[CLI Quickstart](/cli/quickstart)** - Use HopX from the command line * **[API Reference](/sdk/javascript/sandbox)** - Complete SDK documentation ## Quickstart Variations For more advanced quickstart examples including error handling, environment variables, and TypeScript patterns, see the [Advanced Quickstart Guide](/sdk/javascript/advanced-quickstart) (coming soon). ## Troubleshooting **"API key required" error?** * Verify `HOPX_API_KEY` is set: `echo $HOPX_API_KEY` * Get your key at [console.hopx.dev](https://console.hopx.dev) **"Template not found" error?** * Use `template: 'code-interpreter'` (default Python template) * See [Available Templates](/core-concepts/templates/listing) for options **"Cannot find module" error?** * Run `npm install @hopx-ai/sdk` * Check Node.js version: `node --version` (should be 18+) **Network timeout?** * Check internet connection * Verify firewall allows HTTPS (port 443) For more help, see the [Troubleshooting Guide](/sdk/javascript/troubleshooting). # Template Ready Checks Source: https://docs.hopx.ai/sdk/javascript/ready-checks Utilities for checking template readiness before use in the HopX JavaScript/TypeScript SDK. Verify templates are available and ready before creating sandboxes, check template status, and handle template availability errors. Essential for robust sandbox creation workflows. Includes TypeScript examples and error handling. **Version:** 0.1.22\ **Last Verified:** 2025-01-27\ **Package:** `@hopx-ai/sdk` on [npm](https://www.npmjs.com/package/@hopx-ai/sdk) ## Overview Ready checks are utilities used in template building to verify that a template is ready before it's considered complete. ## Import ```typescript theme={null} import { waitForPort, waitForUrl, waitForFile, waitForProcess, waitForCommand } from '@hopx-ai/sdk'; ``` ## Available Ready Checks ### `waitForPort` Wait for a port to be listening. ```typescript theme={null} waitForPort(port: number, timeout?: number): ReadyCheck ``` *** ### `waitForUrl` Wait for a URL to be accessible. ```typescript theme={null} waitForUrl(url: string, timeout?: number): ReadyCheck ``` *** ### `waitForFile` Wait for a file to exist. ```typescript theme={null} waitForFile(path: string, timeout?: number): ReadyCheck ``` *** ### `waitForProcess` Wait for a process to be running. ```typescript theme={null} waitForProcess(processName: string, timeout?: number): ReadyCheck ``` *** ### `waitForCommand` Wait for a command to succeed. ```typescript theme={null} waitForCommand(command: string, timeout?: number): ReadyCheck ``` *** ## Example ```typescript theme={null} import { Template, waitForPort } from '@hopx-ai/sdk'; const template = new Template() .fromNodeImage('20') .run('npm install express') .expose(3000) .startCmd('node server.js') .readyCheck(waitForPort(3000, 120000)); const result = await template.build(); console.log(`Template ready: ${result.templateId}`); ``` *** ## Related Classes * **[Template Builder](/sdk/javascript/template-builder)** - Use ready checks in templates * **[Sandbox](/sdk/javascript/sandbox)** - Create sandboxes from templates ## See Also * [Template Builder](/sdk/javascript/template-builder) - Learn about building templates * [Core Concepts: Templates](/core-concepts/templates) - Learn about templates ## Next Steps Now that you understand ready checks, explore: * [Template Builder](/sdk/javascript/template-builder) - Use ready checks in template building * [Building Templates](/core-concepts/templates/building) - Learn template building concepts * [Template Configuration](/core-concepts/templates/configuration) - Configure templates * **[CLI Reference](/cli/introduction)** - Use HopX from the command line * [Custom Templates](/cookbooks/advanced/custom-templates) - Build custom templates # Sandbox Source: https://docs.hopx.ai/sdk/javascript/sandbox Main sandbox class for creating and managing cloud sandboxes in JavaScript/TypeScript. Complete reference for the HopX JavaScript SDK Sandbox class including async/await methods for creating sandboxes, executing code, managing files, controlling desktop automation, and monitoring resources. Includes TypeScript examples for all methods. **Version:** 0.1.22\ **Last Verified:** 2025-01-27\ **Package:** `@hopx-ai/sdk` on [npm](https://www.npmjs.com/package/@hopx-ai/sdk) ## Overview The `Sandbox` class is the main entry point for the HopX JavaScript/TypeScript SDK. It provides an async/await interface for creating, managing, and interacting with cloud sandboxes (microVMs). All methods are async and must be called with `await`. The `Sandbox` class handles authentication, request formatting, error translation, and response parsing automatically, giving you a clean, Promise-based API for sandbox management. ## Import ```typescript theme={null} import { Sandbox } from '@hopx-ai/sdk'; ``` Or with CommonJS: ```javascript theme={null} const { Sandbox } = require('@hopx-ai/sdk'); ``` ## Static Methods ### `create` Create a new sandbox from a template. ```typescript theme={null} static async Sandbox.create(options: SandboxCreateOptions): Promise ``` **Parameters:** * `options.template` (`string`, optional): Template name * `options.templateId` (`string`, optional): Template ID (alternative to template) * `options.region` (`string`, optional): Preferred region * `options.timeoutSeconds` (`number`, optional): Auto-kill timeout in seconds * `options.internetAccess` (`boolean`, optional): Enable internet (default: `true`) * `options.envVars` (`Record`, optional): Environment variables * `options.apiKey` (`string`, optional): API key (or use `HOPX_API_KEY` env var) * `options.baseURL` (`string`, optional): API base URL **Returns:** `Promise` - New sandbox instance **Example:** ```typescript theme={null} const sandbox = await Sandbox.create({ template: 'code-interpreter' }); const info = await sandbox.getInfo(); console.log(info.publicHost); ``` **Expected Output:** ``` https://sandbox_abc123xyz.hopx.dev ``` *** ### `connect` Connect to an existing sandbox by ID. ```typescript theme={null} static async Sandbox.connect( sandboxId: string, options?: { apiKey?: string; baseURL?: string } ): Promise ``` **Parameters:** * `sandboxId` (`string`): Existing sandbox ID * `options.apiKey` (`string`, optional): API key * `options.baseURL` (`string`, optional): API base URL **Returns:** `Promise` - Connected sandbox instance If VM is paused, resumes it and refreshes JWT token. If stopped, throws error. **Example:** ```typescript theme={null} const sandbox = await Sandbox.connect('sandbox-abc123'); const info = await sandbox.getInfo(); console.log(`Status: ${info.status}`); ``` **Expected Output:** ``` Status: running ``` *** ### `list` List all sandboxes. ```typescript theme={null} static async Sandbox.list(options?: { apiKey?: string; baseURL?: string; limit?: number; status?: 'running' | 'stopped' | 'paused' | 'creating'; region?: string; }): Promise ``` **Returns:** `Promise` - Array of sandbox information objects **Example:** ```typescript theme={null} const sandboxes = await Sandbox.list({ status: 'running', limit: 50 }); for (const sb of sandboxes) { console.log(`${sb.sandboxId}: ${sb.status}`); } ``` **Expected Output:** ``` sandbox_abc123xyz: running sandbox_def456uvw: running ``` *** ### `listTemplates` List available templates. ```typescript theme={null} static async Sandbox.listTemplates(options?: { category?: string; language?: string; apiKey?: string; baseURL?: string; }): Promise ``` **Returns:** `Promise` - Array of template information objects **Example:** ```typescript theme={null} const templates = await Sandbox.listTemplates({ language: 'python' }); for (const template of templates) { console.log(`${template.name}: ${template.description}`); } ``` **Expected Output:** ``` code-interpreter: Python environment with data science libraries python-basic: Minimal Python 3.11 environment ``` *** ### `getTemplate` Get template details by name. ```typescript theme={null} static async Sandbox.getTemplate( name: string, options?: { apiKey?: string; baseURL?: string } ): Promise ``` **Returns:** `Promise` - Template information object **Example:** ```typescript theme={null} const template = await Sandbox.getTemplate('code-interpreter'); console.log(`Resources: ${template.defaultResources.vcpu} vCPU`); ``` **Expected Output:** ``` Resources: 2 vCPU ``` *** ## Instance Methods ### Lifecycle Methods #### `getInfo` Get current sandbox information. ```typescript theme={null} async sandbox.getInfo(): Promise ``` **Returns:** `Promise` - Sandbox information object *** #### `kill` Destroy the sandbox immediately. ```typescript theme={null} async sandbox.kill(): Promise ``` This action is irreversible. The sandbox and all its data will be permanently deleted. *** #### `start` Start a stopped sandbox. ```typescript theme={null} async sandbox.start(): Promise ``` *** #### `stop` Stop a running sandbox. ```typescript theme={null} async sandbox.stop(): Promise ``` *** #### `pause` Pause a running sandbox. ```typescript theme={null} async sandbox.pause(): Promise ``` *** #### `resume` Resume a paused sandbox. ```typescript theme={null} async sandbox.resume(): Promise ``` *** ### Execution Methods #### `runCode` Execute code synchronously with rich output capture. ```typescript theme={null} async sandbox.runCode( code: string, options?: CodeExecutionOptions ): Promise ``` **Parameters:** * `code` (`string`): Code to execute * `options.language` (`string`, optional): Language (default: `'python'`) * `options.timeout` (`number`, optional): Timeout in seconds (default: `60`) * `options.workingDir` (`string`, optional): Working directory (default: `'/workspace'`) * `options.env` (`Record`, optional): Environment variables **Returns:** `Promise` - Execution result **Example:** ```typescript theme={null} const result = await sandbox.runCode("print('Hello, HopX!')"); console.log(result.stdout); // "Hello, HopX!\n" console.log(result.exitCode); // 0 ``` **Expected Output:** ``` Hello, HopX! 0 ``` *** #### `runCodeAsync` Execute code asynchronously with webhook callback. ```typescript theme={null} async sandbox.runCodeAsync( code: string, options: AsyncExecutionOptions ): Promise ``` **Parameters:** * `code` (`string`): Code to execute * `options.callbackUrl` (`string`): URL to POST results to * `options.language` (`string`, optional): Language * `options.timeout` (`number`, optional): Timeout in seconds * `options.workingDir` (`string`, optional): Working directory * `options.env` (`Record`, optional): Environment variables * `options.callbackHeaders` (`Record`, optional): Callback headers * `options.callbackSignatureSecret` (`string`, optional): Signature secret **Returns:** `Promise` - Response with `executionId` and `status` *** #### `runCodeBackground` Execute code in background and return immediately. ```typescript theme={null} async sandbox.runCodeBackground( code: string, options?: BackgroundExecutionOptions ): Promise ``` **Returns:** `Promise` - Response with `processId` and `executionId` *** #### `runCodeStream` Execute code with real-time output streaming via WebSocket. ```typescript theme={null} async *sandbox.runCodeStream( code: string, options?: CodeExecutionOptions ): AsyncIterableIterator ``` **Returns:** `AsyncIterableIterator` - Async generator of stream messages **Example:** ```typescript theme={null} for await (const message of sandbox.runCodeStream("print('Hello')")) { if (message.type === 'stdout') { console.log(message.data); } } ``` **Expected Output:** ``` Hello ``` *** #### `listProcesses` List all background execution processes. ```typescript theme={null} async sandbox.listProcesses(): Promise ``` **Returns:** `Promise` - Array of process information objects *** #### `killProcess` Kill a background execution process. ```typescript theme={null} async sandbox.killProcess(processId: string): Promise ``` *** ### Information Methods #### `getMetricsSnapshot` Get current system metrics snapshot. ```typescript theme={null} async sandbox.getMetricsSnapshot(): Promise ``` *** #### `getAgentInfo` Get agent information and capabilities. ```typescript theme={null} async sandbox.getAgentInfo(): Promise ``` *** #### `refreshToken` Refresh JWT token for agent authentication. ```typescript theme={null} async sandbox.refreshToken(): Promise ``` *** #### `getToken` Get current JWT token. ```typescript theme={null} async sandbox.getToken(): Promise ``` *** ## Properties ### `files` File operations resource (lazy-loaded). **Type:** `Files` **Example:** ```typescript theme={null} const content = await sandbox.files.read('/workspace/script.py'); await sandbox.files.write('/workspace/data.txt', 'Hello, World!'); ``` **Expected Output:** ``` File written successfully ``` See [Files Resource](/sdk/javascript/files) for complete documentation. *** ### `commands` Command execution resource (lazy-loaded). **Type:** `Commands` **Example:** ```typescript theme={null} const result = await sandbox.commands.run('ls -la /workspace'); console.log(result.stdout); ``` **Expected Output:** ``` total 8 drwxr-xr-x 2 root root 4096 Jan 27 10:30 . drwxr-xr-x 3 root root 4096 Jan 27 10:30 .. -rw-r--r-- 1 root root 42 Jan 27 10:30 data.txt ``` *** ### `env` Environment variables resource (lazy-loaded). **Type:** `EnvironmentVariables` **Example:** ```typescript theme={null} await sandbox.env.set('API_KEY', 'secret123'); const allVars = await sandbox.env.getAll(); ``` **Expected Output:** ``` Environment variable set successfully ``` *** ### `cache` Cache management resource (lazy-loaded). **Type:** `Cache` **Example:** ```typescript theme={null} const stats = await sandbox.cache.stats(); console.log(`Cache size: ${stats.cache.size}`); ``` **Expected Output:** ``` Cache size: 5 ``` *** ### `desktop` Desktop automation resource (lazy-loaded). **Type:** `Desktop` **Example:** ```typescript theme={null} const screenshot = await sandbox.desktop.screenshot(); ``` **Expected Output:** ``` Screenshot captured (PNG bytes) ``` *** ### `terminal` Interactive terminal resource via WebSocket (lazy-loaded). **Type:** `Terminal` *** ### `sandboxId` Read-only sandbox ID. **Type:** `string` (read-only) *** ## Examples ### Example 1: Basic Usage ```typescript theme={null} import { Sandbox } from '@hopx-ai/sdk'; async function main() { const sandbox = await Sandbox.create({ template: 'code-interpreter' }); const result = await sandbox.runCode("print('Hello, HopX!')"); console.log(result.stdout); await sandbox.kill(); } main(); ``` **Expected Output:** ``` Hello, HopX! ``` ### Example 2: File Operations ```typescript theme={null} import { Sandbox } from '@hopx-ai/sdk'; async function main() { const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Write a file await sandbox.files.write('/workspace/script.py', "print('Hello')"); // Execute it const result = await sandbox.runCode( "exec(open('/workspace/script.py').read())" ); console.log(result.stdout); await sandbox.kill(); } ``` **Expected Output:** ``` Hello ``` ### Example 3: Streaming Output ```typescript theme={null} import { Sandbox } from '@hopx-ai/sdk'; async function main() { const sandbox = await Sandbox.create({ template: 'code-interpreter' }); for await (const message of sandbox.runCodeStream( "for i in range(5):\n print(f'Count: {i}')\n import time\n time.sleep(1)" )) { if (message.type === 'stdout') { process.stdout.write(message.data); } } await sandbox.kill(); } ``` **Expected Output:** ``` Count: 0 Count: 1 Count: 2 Count: 3 Count: 4 ``` *** ## Related Classes * **[Files](/sdk/javascript/files)** - File operations resource * **[Commands](/sdk/javascript/commands)** - Command execution resource * **[Environment Variables](/sdk/javascript/environment-variables)** - Environment variable management * **[Types](/sdk/javascript/types)** - TypeScript type definitions ## See Also * [Quickstart Guide](/sdk/javascript/quickstart) - Get started with the SDK * [Installation](/sdk/javascript/installation) - Install and configure the SDK * [Core Concepts](/core-concepts/sandboxes/creating) - Learn about sandboxes ## Next Steps * Learn about [Creating Sandboxes](/core-concepts/sandboxes/creating) with different templates * Explore [Code Execution](/core-concepts/code-execution/synchronous) to run code in sandboxes * Review [File Operations](/sdk/javascript/files) for managing files * Check out [API Reference](/api/vm-agent/overview) for direct API access * **[CLI Sandbox Commands](/cli/commands/sandbox)** - Manage sandboxes from CLI # Template Builder Source: https://docs.hopx.ai/sdk/javascript/template-builder Fluent API for building custom sandbox templates in the HopX JavaScript/TypeScript SDK. Create custom templates from Docker images, configure resources, add build steps, and install dependencies using a fluent builder pattern. Complete reference for TemplateBuilder class with TypeScript examples and template configuration options. **Version:** 0.1.22\ **Last Verified:** 2025-01-27\ **Package:** `@hopx-ai/sdk` on [npm](https://www.npmjs.com/package/@hopx-ai/sdk) ## Overview The `Template` class provides a fluent API for building custom sandbox templates. ## Import ```typescript theme={null} import { Template } from '@hopx-ai/sdk'; ``` ## Methods ### Base Image Methods * `template.fromUbuntuImage(version: string): Template` * `template.fromPythonImage(version: string): Template` * `template.fromNodeImage(version: string): Template` * `template.fromImage(image: string, auth?: AuthConfig): Template` ### Configuration Methods * `template.copy(src: string, dest: string): Template` * `template.run(command: string): Template` * `template.env(key: string, value: string): Template` * `template.expose(port: number): Template` * `template.workdir(path: string): Template` * `template.readyCheck(check: ReadyCheck): Template` * `template.startCmd(command: string): Template` ### Building ```typescript theme={null} async template.build(options?: BuildOptions): Promise ``` **Example:** ```typescript theme={null} const template = new Template() .fromPythonImage('3.11') .run('pip install flask') .expose(5000) .startCmd('python app.py'); const result = await template.build(); console.log(`Template ID: ${result.templateId}`); ``` *** ## Related Classes * **[Ready Checks](/sdk/javascript/ready-checks)** - Ready check utilities * **[Sandbox](/sdk/javascript/sandbox)** - Use templates with `Sandbox.create({ template: ... })` ## See Also * [Ready Checks](/sdk/javascript/ready-checks) - Learn about ready checks * [Core Concepts: Templates](/core-concepts/templates) - Learn about templates ## Next Steps Now that you understand template building, explore: * [Ready Checks](/sdk/javascript/ready-checks) - Add readiness verification * [Building Templates](/core-concepts/templates/building) - Learn template building concepts * [Template Configuration](/core-concepts/templates/configuration) - Configure templates * **[CLI Reference](/cli/introduction)** - Use HopX from the command line * [Custom Templates](/cookbooks/advanced/custom-templates) - Build custom templates # Terminal Access Source: https://docs.hopx.ai/sdk/javascript/terminal Interactive terminal resource for WebSocket-based sandbox terminal access in HopX using the JavaScript/TypeScript SDK. Complete reference for the Terminal class including async methods for connecting to interactive terminals, executing commands in real-time, and streaming terminal output. Includes TypeScript examples for terminal automation. **Version:** 0.1.22\ **Last Verified:** 2025-01-27\ **Package:** `@hopx-ai/sdk` on [npm](https://www.npmjs.com/package/@hopx-ai/sdk) ## Overview The `Terminal` resource provides interactive terminal access via WebSocket. ## Methods ### `connect` Connect to interactive terminal. ```typescript theme={null} async terminal.connect(): Promise ``` **Returns:** `Promise` - WebSocket connection *** ### `sendInput` Send input to terminal. ```typescript theme={null} terminal.sendInput(ws: WebSocket, data: string): void ``` *** ### `resize` Resize terminal. ```typescript theme={null} terminal.resize(ws: WebSocket, cols: number, rows: number): void ``` *** ### `output` Async iterator for terminal output. ```typescript theme={null} async *terminal.output(ws: WebSocket): AsyncIterableIterator ``` **Example:** ```typescript theme={null} const ws = await sandbox.terminal.connect(); sandbox.terminal.sendInput(ws, "echo 'Hello'\n"); for await (const message of sandbox.terminal.output(ws)) { if (message.type === 'stdout') { console.log(message.data); } } ``` *** ## Related Classes * **[Sandbox](/sdk/javascript/sandbox)** - Main sandbox class * **[Types](/sdk/javascript/types)** - TypeScript type definitions ## See Also * [Core Concepts: Terminal](/core-concepts/terminal) - Learn about terminal access * [Sandbox Class](/sdk/javascript/sandbox) - Access terminal via `sandbox.terminal` ## Next Steps Now that you understand terminal access, explore: * [WebSocket Terminal](/core-concepts/terminal/websocket) - Learn terminal concepts * [Sandbox Operations](/sdk/javascript/sandbox) - Use terminal in sandbox workflows * [Running Commands](/core-concepts/commands/running) - Execute commands * **[CLI Reference](/cli/introduction)** - Use HopX from the command line * [Background Commands](/core-concepts/commands/background) - Non-blocking execution # TypeScript Type Definitions Source: https://docs.hopx.ai/sdk/javascript/types TypeScript type definitions for the HopX JavaScript SDK. Complete TypeScript type definitions for sandbox objects, execution results, file metadata, template structures, and all SDK methods. Essential for type-safe development with IntelliSense support. Includes complete type reference and usage examples. **Version:** 0.1.22\ **Last Verified:** 2025-01-27\ **Package:** `@hopx-ai/sdk` on [npm](https://www.npmjs.com/package/@hopx-ai/sdk) ## Overview The JavaScript SDK provides comprehensive TypeScript type definitions for all API responses and objects. ## Core Types ### `SandboxInfo` Sandbox information type. ```typescript theme={null} interface SandboxInfo { sandboxId: string; templateId: string; templateName: string; organizationId: string; nodeId: string; region: string; status: 'running' | 'stopped' | 'paused' | 'creating'; publicHost: string; resources: Resources; startedAt: Date; endAt?: Date; createdAt: Date; } ``` *** ### `TemplateInfo` Template information type. ```typescript theme={null} interface TemplateInfo { id: string; name: string; displayName: string; description: string; category: string; language: string; defaultResources: TemplateResources; // ... more fields } ``` *** ### `ExecutionResult` Result of code execution. ```typescript theme={null} interface ExecutionResult { success: boolean; stdout: string; stderr: string; exitCode: number; executionTime: number; richOutputs: RichOutput[]; } ``` *** ### `CommandResponse` Result of command execution. ```typescript theme={null} interface CommandResponse { stdout: string; stderr: string; exitCode: number; executionTime: number; } ``` *** ### `FileInfo` File or directory information. ```typescript theme={null} interface FileInfo { name: string; path: string; size: number; isDirectory: boolean; permissions: string; modifiedTime: Date; } ``` *** ## Options Types ### `SandboxCreateOptions` Options for creating a sandbox. ```typescript theme={null} interface SandboxCreateOptions { template?: string; templateId?: string; region?: string; timeoutSeconds?: number; internetAccess?: boolean; envVars?: Record; apiKey?: string; baseURL?: string; } ``` *** ### `CodeExecutionOptions` Options for code execution. ```typescript theme={null} interface CodeExecutionOptions { language?: string; timeout?: number; workingDir?: string; env?: Record; } ``` *** ### `CommandOptions` Options for command execution. ```typescript theme={null} interface CommandOptions { timeout?: number; background?: boolean; workingDir?: string; env?: Record; } ``` *** ## Related Classes * **[Errors](/sdk/javascript/errors)** - Error classes and exception handling * **[Sandbox](/sdk/javascript/sandbox)** - Use types with sandbox operations ## See Also * [Errors](/sdk/javascript/errors) - Learn about error handling * [Core Concepts](/core-concepts) - Learn about core concepts ## Next Steps Now that you understand TypeScript types, explore: * [Sandbox Operations](/sdk/javascript/sandbox) - Use types in practice * [Error Handling](/sdk/javascript/errors) - Type-safe error handling * [Quickstart Guide](/sdk/javascript/quickstart) - Get started with the SDK * **[CLI Reference](/cli/introduction)** - Use HopX from the command line * [TypeScript Documentation](https://www.typescriptlang.org/docs/) - Learn more about TypeScript # AsyncSandbox Source: https://docs.hopx.ai/sdk/python/async-sandbox Asynchronous sandbox class for async/await workflows in Python. Use AsyncSandbox for non-blocking operations, concurrent sandbox management, and async/await patterns. Complete reference for all async methods including creating sandboxes, executing code, and managing resources asynchronously. Includes async/await examples and best practices. **Version:** 0.3.0\ **Last Verified:** 2025-01-27\ **Package:** `hopx-ai` on [PyPI](https://pypi.org/project/hopx-ai/) ## Overview The `AsyncSandbox` class provides an asynchronous interface for creating and managing cloud sandboxes. Use this class when building async Python applications (FastAPI, aiohttp, etc.) or when you need to manage multiple sandboxes concurrently. All methods in `AsyncSandbox` are async and must be called with `await`. The class supports async context managers for automatic cleanup. ### When to Use AsyncSandbox vs Sandbox * **Use `AsyncSandbox`** when: * Building async Python applications (FastAPI, aiohttp, etc.) * You need to manage multiple sandboxes concurrently * You want non-blocking operations * You're already using async/await in your codebase * **Use `Sandbox`** when: * Building synchronous Python applications * Writing scripts or simple automation * You prefer blocking operations ## Import ```python theme={null} from hopx_ai import AsyncSandbox ``` ## Class Methods ### `create` Create a new sandbox from a template (async). ```python theme={null} await AsyncSandbox.create( template=None, *, template_id=None, region=None, timeout_seconds=None, internet_access=None, env_vars=None, api_key=None, base_url='https://api.hopx.dev' ) -> AsyncSandbox ``` **Parameters:** Same as `Sandbox.create()` **Returns:** `AsyncSandbox` - New sandbox instance **Example:** ```python theme={null} sandbox = await AsyncSandbox.create(template="code-interpreter") info = await sandbox.get_info() print(info.public_host) ``` **Expected Output:** ``` https://sandbox_abc123xyz.hopx.dev ``` *** ### `connect` Connect to an existing sandbox by ID (async). ```python theme={null} await AsyncSandbox.connect( sandbox_id, *, api_key=None, base_url='https://api.hopx.dev' ) -> AsyncSandbox ``` **Example:** ```python theme={null} sandbox = await AsyncSandbox.connect("sandbox-abc123") ``` **Expected Output:** ``` Connected to sandbox-abc123 ``` *** ### `list` List all sandboxes (async). ```python theme={null} await AsyncSandbox.list( *, status=None, region=None, limit=100, api_key=None, base_url='https://api.hopx.dev' ) -> List[AsyncSandbox] ``` **Example:** ```python theme={null} sandboxes = await AsyncSandbox.list(status="running") for sb in sandboxes: info = await sb.get_info() print(f"{info.sandbox_id}: {info.status}") ``` **Expected Output:** ``` sandbox_abc123xyz: running sandbox_def456uvw: running ``` *** ### `iter` Lazy async iterator for sandboxes. ```python theme={null} async for sandbox in AsyncSandbox.iter(status="running"): info = await sandbox.get_info() print(f"{info.sandbox_id}") ``` **Expected Output:** ``` sandbox_abc123xyz sandbox_def456uvw ``` *** ## Instance Methods ### Lifecycle Methods All lifecycle methods are async versions of `Sandbox` methods: * `await sandbox.get_info() -> SandboxInfo` * `await sandbox.start() -> None` * `await sandbox.stop() -> None` * `await sandbox.pause() -> None` * `await sandbox.resume() -> None` * `await sandbox.kill() -> None` ### Execution Methods #### `run_code` Execute code with rich output capture (async). ```python theme={null} await sandbox.run_code( code, *, language='python', timeout_seconds=60, env=None, working_dir='/workspace' ) -> ExecutionResult ``` **Example:** ```python theme={null} result = await sandbox.run_code("print('Hello, HopX!')") print(result.stdout) ``` **Expected Output:** ``` Hello, HopX! ``` *** #### `run_code_stream` Stream code execution output (async generator). ```python theme={null} async for message in sandbox.run_code_stream( code, *, language='python', timeout_seconds=60 ): print(message) ``` **Expected Output:** ``` {'type': 'stdout', 'data': 'Hello\n'} {'type': 'stderr', 'data': ''} {'type': 'done', 'exit_code': 0} ``` *** #### `list_processes` List running processes in sandbox (async). ```python theme={null} await sandbox.list_processes() -> List[Dict[str, Any]] ``` **Expected Output:** ``` [{'process_id': 'proc_abc123', 'status': 'running', ...}] ``` *** #### `kill_process` Kill a process by ID (async). ```python theme={null} await sandbox.kill_process(process_id) -> Dict[str, Any] ``` **Expected Output:** ``` Process killed successfully ``` *** ### Utility Methods * `await sandbox.get_metrics_snapshot() -> Dict[str, Any]` * `await sandbox.refresh_token() -> None` * `await sandbox.set_timeout(seconds) -> None` *** ## Properties All resource properties are async versions: * `sandbox.files` → `AsyncFiles` * `sandbox.commands` → `AsyncCommands` * `sandbox.env` → `AsyncEnvironmentVariables` * `sandbox.cache` → `AsyncCache` * `sandbox.terminal` → `AsyncTerminal` *** ## Async Context Manager The `AsyncSandbox` class supports async context manager protocol. **Example:** ```python theme={null} async with AsyncSandbox.create(template="code-interpreter") as sandbox: result = await sandbox.run_code("print('Hello')") print(result.stdout) # Automatically calls await sandbox.kill() when exiting ``` **Expected Output:** ``` Hello ``` *** ## Examples ### Example 1: Basic Async Usage ```python theme={null} import asyncio from hopx_ai import AsyncSandbox async def main(): sandbox = await AsyncSandbox.create(template="code-interpreter") result = await sandbox.run_code("print('Hello, HopX!')") print(result.stdout) await sandbox.kill() asyncio.run(main()) ``` **Expected Output:** ``` Hello, HopX! ``` ### Example 2: Using Async Context Manager ```python theme={null} import asyncio from hopx_ai import AsyncSandbox async def main(): async with AsyncSandbox.create(template="code-interpreter") as sandbox: result = await sandbox.run_code("import sys; print(sys.version)") print(result.stdout) asyncio.run(main()) ``` **Expected Output:** ``` 3.11.5 (main, Jan 27 2025, 10:30:00) [GCC 11.2.0] ``` ### Example 3: Concurrent Sandboxes ```python theme={null} import asyncio from hopx_ai import AsyncSandbox async def run_in_sandbox(template): async with AsyncSandbox.create(template=template) as sandbox: result = await sandbox.run_code("print('Hello from', template)") return result.stdout async def main(): templates = ["code-interpreter", "nodejs", "go"] results = await asyncio.gather(*[run_in_sandbox(t) for t in templates]) for r in results: print(r) asyncio.run(main()) ``` **Expected Output:** ``` Hello from code-interpreter Hello from nodejs Hello from go ``` ### Example 4: Streaming Output ```python theme={null} import asyncio from hopx_ai import AsyncSandbox async def main(): sandbox = await AsyncSandbox.create(template="code-interpreter") async for message in sandbox.run_code_stream( "for i in range(5):\n print(f'Count: {i}')\n import time\n time.sleep(1)" ): if message.get('type') == 'stdout': print(message.get('data', ''), end='') await sandbox.kill() asyncio.run(main()) ``` **Expected Output:** ``` Count: 0 Count: 1 Count: 2 Count: 3 Count: 4 ``` *** ## Related Classes * **[Sandbox](/sdk/python/sandbox)** - Synchronous version of AsyncSandbox * **[AsyncFiles](/sdk/python/files)** - Async file operations (accessed via `sandbox.files`) * **[AsyncCommands](/sdk/python/commands)** - Async command execution * **[AsyncEnvironmentVariables](/sdk/python/environment-variables)** - Async environment variable management ## See Also * [Quickstart Guide](/sdk/python/quickstart) - Get started with the SDK * [Sandbox Class](/sdk/python/sandbox) - Synchronous sandbox class * [Core Concepts](/core-concepts/sandboxes/creating) - Learn about sandboxes ## Next Steps * Learn about [Synchronous Sandbox](/sdk/python/sandbox) if you prefer blocking operations * Explore [Code Execution](/core-concepts/code-execution/synchronous) concepts * Review [File Operations](/sdk/python/files) for async file management * **[CLI Reference](/cli/introduction)** - Use HopX from the command line * Check out [API Reference](/api/vm-agent/overview) for direct API access # Cache Management Source: https://docs.hopx.ai/sdk/python/cache Cache management resource for managing execution result cache in HopX sandboxes using the Python SDK. Complete reference for the Cache class including methods for viewing cache statistics and clearing execution cache. Includes code examples for cache optimization and performance tuning. **Version:** 0.3.0\ **Last Verified:** 2025-01-27\ **Package:** `hopx-ai` on [PyPI](https://pypi.org/project/hopx-ai/) ## Overview The `Cache` resource provides methods for managing the execution result cache in sandboxes. The cache stores execution results to improve performance for repeated code executions. Use this resource to view cache statistics and clear the cache when needed. ## Access ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") cache = sandbox.cache # Lazy-loaded ``` ## Methods ### `stats` Get cache statistics. ```python theme={null} cache.stats(*, timeout=None) -> Dict[str, Any] ``` **Returns:** `Dict[str, Any]` - Cache statistics dictionary with: * `cache.total_hits` (`int`): Total cache hits * `cache.size` (`int`): Current cache size * `cache.max_size` (`int`): Maximum cache size * `cache.ttl` (`int`): Time-to-live in seconds * `timestamp` (`str`): Timestamp of the statistics **Example:** ```python theme={null} stats = sandbox.cache.stats() cache_data = stats['cache'] print(f"Cache hits: {cache_data['total_hits']}") print(f"Cache size: {cache_data['size']} / {cache_data['max_size']}") ``` *** ### `clear` Clear the execution result cache. ```python theme={null} cache.clear(*, timeout=None) -> Dict[str, Any] ``` **Returns:** `Dict[str, Any]` - Confirmation message This clears all cached execution results. Subsequent executions will not benefit from cached results until cache is repopulated. **Example:** ```python theme={null} # Check cache size before clearing stats_before = sandbox.cache.stats() print(f"Cache size before: {stats_before['cache']['size']}") # Clear cache sandbox.cache.clear() # Check cache size after clearing stats_after = sandbox.cache.stats() print(f"Cache size after: {stats_after['cache']['size']}") ``` **See Also:** * [API: Clear Cache](/api/vm-agent/clear-cache) *** ## Examples ### Example 1: Viewing Cache Statistics ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Get cache statistics stats = sandbox.cache.stats() cache_data = stats['cache'] print(f"Total cache hits: {cache_data['total_hits']}") print(f"Current size: {cache_data['size']}") print(f"Max size: {cache_data['max_size']}") print(f"TTL: {cache_data['ttl']} seconds") sandbox.kill() ``` ### Example 2: Clearing Cache ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Execute code (may be cached) result1 = sandbox.run_code("print('Hello')") # Clear cache sandbox.cache.clear() print("Cache cleared") # Execute again (not cached) result2 = sandbox.run_code("print('Hello')") sandbox.kill() ``` ### Example 3: Monitoring Cache Usage ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Check initial cache state initial_stats = sandbox.cache.stats() print(f"Initial cache size: {initial_stats['cache']['size']}") # Run multiple executions for i in range(5): sandbox.run_code(f"print('Execution {i}')") # Check cache after executions final_stats = sandbox.cache.stats() print(f"Final cache size: {final_stats['cache']['size']}") print(f"Cache hits: {final_stats['cache']['total_hits']}") sandbox.kill() ``` *** ## Related Classes * **[Sandbox](/sdk/python/sandbox)** - Main sandbox class * **[Core Concepts: Cache](/core-concepts/cache/statistics)** - Learn about cache management ## See Also * [Sandbox Class](/sdk/python/sandbox) - Access cache via `sandbox.cache` * [Cache Statistics](/core-concepts/cache/statistics) - Detailed cache documentation ## Related * **[Code Execution](/core-concepts/code-execution/synchronous)** - Execution results are cached * **[API: Cache Management](/api/vm-agent/get-cache-stats)** - VM Agent API endpoints ## Next Steps * Learn about [Code Execution](/core-concepts/code-execution/synchronous) to see cached results * Review [Cache Statistics](/core-concepts/cache/statistics) for detailed cache information * **[CLI Cache](/cli/commands/system)** - View cache statistics from CLI # Command Execution Source: https://docs.hopx.ai/sdk/python/commands Command execution resource for running shell commands in HopX sandboxes using the Python SDK. Complete reference for the Commands class including methods for running commands synchronously and in the background. Includes code examples for system administration, package installation, and automation tasks. **Version:** 0.3.0\ **Last Verified:** 2025-01-27\ **Package:** `hopx-ai` on [PyPI](https://pypi.org/project/hopx-ai/) ## Overview The `Commands` resource provides shell command execution capabilities for sandboxes. Access it via the `commands` property on a `Sandbox` instance. Use this resource when you need to run shell commands, install packages, or execute system utilities. The `Commands` resource is lazy-loaded and provides synchronous command execution. ## Access ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") commands = sandbox.commands # Lazy-loaded ``` ## Methods ### `run` Run a shell command. ```python theme={null} commands.run( command, *, timeout=30, background=False, env=None, working_dir='/workspace' ) -> CommandResult ``` **Parameters:** * `command` (`str`): Shell command to execute * `timeout` (`int`, optional): Command timeout in seconds (default: `30`) * `background` (`bool`, optional): Run in background (default: `False`) * `env` (`Dict[str, str]`, optional): Environment variables for command * `working_dir` (`str`, optional): Working directory (default: `'/workspace'`) **Returns:** `CommandResult` - Command execution result with `stdout`, `stderr`, `exit_code`, and `execution_time` **Raises:** * `CommandExecutionError`: Command execution failed * `TimeoutError`: Command timed out **Example:** ```python theme={null} result = sandbox.commands.run("ls -la /workspace") print(result.stdout) print(f"Exit code: {result.exit_code}") ``` **See Also:** * [API: Run Command](/api/vm-agent/run-command) *** ## CommandResult Model The `run()` method returns a `CommandResult` object with: * `stdout` (`str`): Standard output * `stderr` (`str`): Standard error * `exit_code` (`int`): Exit code (0 = success) * `execution_time` (`float`): Execution time in seconds * `success` (`bool`): Convenience property (`exit_code == 0`) *** ## Examples ### Example 1: Basic Command Execution ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Run a simple command result = sandbox.commands.run("echo 'Hello, World!'") print(result.stdout) # "Hello, World!\n" print(f"Success: {result.success}") sandbox.kill() ``` ### Example 2: Install Packages ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Install a package result = sandbox.commands.run("pip install requests") if result.success: print("Package installed successfully") else: print(f"Installation failed: {result.stderr}") sandbox.kill() ``` ### Example 3: Command with Environment Variables ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Run command with custom environment result = sandbox.commands.run( "echo $MY_VAR", env={"MY_VAR": "Hello from env"} ) print(result.stdout) sandbox.kill() ``` ### Example 4: Working Directory ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Create directory sandbox.files.mkdir("/workspace/my_project") # Run command in specific directory result = sandbox.commands.run( "pwd", working_dir="/workspace/my_project" ) print(result.stdout) # "/workspace/my_project\n" sandbox.kill() ``` ### Example 5: Long-Running Commands ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Run command with longer timeout result = sandbox.commands.run( "sleep 10 && echo 'Done'", timeout=60 ) print(result.stdout) sandbox.kill() ``` *** ## Related Classes * **[Sandbox](/sdk/python/sandbox)** - Main sandbox class * **[Files](/sdk/python/files)** - File operations resource * **[Models](/sdk/python/models)** - Data models including `CommandResult` ## See Also * [Core Concepts: Execution](/core-concepts/execution) - Learn about code execution * [Sandbox Class](/sdk/python/sandbox) - Access commands via `sandbox.commands` ## Related * **[Running Commands](/core-concepts/commands/running)** - Learn about command execution * **[Background Commands](/core-concepts/commands/background)** - Run commands in background * **[API: Command Execution](/api/vm-agent/run-command)** - VM Agent API endpoints ## Next Steps * Learn about [Running Commands](/core-concepts/commands/running) for synchronous execution * Explore [Background Commands](/core-concepts/commands/background) for non-blocking tasks * Review [Code Execution](/core-concepts/code-execution/synchronous) for programmatic execution * **[CLI Commands](/cli/commands/cmd)** - Execute shell commands from the command line # Desktop Automation Source: https://docs.hopx.ai/sdk/python/desktop Desktop automation resource for sandbox GUI interactions, screenshots, and VNC access in HopX using the Python SDK. Complete reference for the Desktop class including methods for VNC servers, screenshots, mouse and keyboard control, window management, and clipboard operations. Includes code examples for desktop automation. **Version:** 0.3.0\ **Last Verified:** 2025-01-27\ **Package:** `hopx-ai` on [PyPI](https://pypi.org/project/hopx-ai/) ## Overview The `Desktop` resource provides desktop automation capabilities for sandboxes with GUI support. Use this resource for GUI automation, taking screenshots, controlling mouse/keyboard, managing windows, and accessing VNC. Desktop features require a desktop-enabled template. Not all templates support desktop operations. ## Access ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="desktop-template") desktop = sandbox.desktop # Lazy-loaded ``` ## VNC Methods ### `start_vnc` Start VNC server. ```python theme={null} desktop.start_vnc(display=1, password=None) -> VNCInfo ``` **Parameters:** * `display` (`int`, optional): Display number (default: `1`) * `password` (`str`, optional): VNC password **Returns:** `VNCInfo` - VNC server information with `url`, `port`, `password` **Example:** ```python theme={null} vnc = sandbox.desktop.start_vnc(password="mypassword") print(f"VNC URL: {vnc.url}") ``` **Expected Output:** ``` VNC URL: https://vnc-sandbox_abc123xyz.hopx.dev ``` *** ### `stop_vnc` Stop VNC server. ```python theme={null} desktop.stop_vnc() -> None ``` **Expected Output:** ``` VNC server stopped successfully ``` *** ### `get_vnc_status` Get VNC server status. ```python theme={null} desktop.get_vnc_status() -> VNCInfo ``` **Expected Output:** ``` VNC server is running on port 5901 ``` *** ### `get_vnc_url` Get VNC URL (convenience method). ```python theme={null} desktop.get_vnc_url() -> str ``` **Expected Output:** ``` https://vnc-sandbox_abc123xyz.hopx.dev ``` *** ## Mouse Methods ### `click` Click at position. ```python theme={null} desktop.click(x, y, button='left', clicks=1) -> None ``` **Parameters:** * `x` (`int`): X coordinate * `y` (`int`): Y coordinate * `button` (`str`, optional): Mouse button (`'left'`, `'right'`, `'middle'`) (default: `'left'`) * `clicks` (`int`, optional): Number of clicks (default: `1`) **Expected Output:** ``` Mouse clicked at (x, y) ``` *** ### `move` Move mouse cursor to position. ```python theme={null} desktop.move(x, y) -> None ``` **Expected Output:** ``` Mouse moved to (x, y) ``` *** ### `drag` Drag from one position to another. ```python theme={null} desktop.drag(from_x, from_y, to_x, to_y, button='left') -> None ``` **Expected Output:** ``` Drag completed from (from_x, from_y) to (to_x, to_y) ``` *** ### `scroll` Scroll mouse wheel. ```python theme={null} desktop.scroll(amount, direction='down') -> None ``` **Parameters:** * `amount` (`int`): Scroll amount * `direction` (`str`, optional): `'up'` or `'down'` (default: `'down'`) **Expected Output:** ``` Scrolled {amount} units {direction} ``` *** ## Keyboard Methods ### `type` Type text. ```python theme={null} desktop.type(text, delay_ms=10) -> None ``` **Parameters:** * `text` (`str`): Text to type * `delay_ms` (`int`, optional): Delay between keystrokes in milliseconds (default: `10`) **Expected Output:** ``` Text typed: {text} ``` *** ### `press` Press a key. ```python theme={null} desktop.press(key) -> None ``` **Parameters:** * `key` (`str`): Key name (e.g., `'Enter'`, `'Escape'`, `'Tab'`) **Expected Output:** ``` Key pressed: {key} ``` *** ### `combination` Press key combination. ```python theme={null} desktop.combination(modifiers, key) -> None ``` **Parameters:** * `modifiers` (`List[str]`): Modifier keys (e.g., `['Ctrl', 'Alt']`) * `key` (`str`): Key to press **Example:** ```python theme={null} desktop.combination(['Ctrl', 'C'], 'c') # Ctrl+C ``` **Expected Output:** ``` Key combination executed: Ctrl+C ``` *** ## Clipboard Methods ### `set_clipboard` Set clipboard content. ```python theme={null} desktop.set_clipboard(text) -> None ``` **Expected Output:** ``` Clipboard set successfully ``` ### `get_clipboard` Get clipboard content. ```python theme={null} desktop.get_clipboard() -> str ``` **Expected Output:** ``` Clipboard content retrieved ``` ## Screenshot Methods ### `screenshot` Capture full screen screenshot. ```python theme={null} desktop.screenshot() -> bytes ``` **Returns:** `bytes` - Screenshot image as PNG bytes **Example:** ```python theme={null} screenshot = sandbox.desktop.screenshot() with open("screenshot.png", "wb") as f: f.write(screenshot) ``` **Expected Output:** ``` Screenshot saved to screenshot.png (PNG bytes) ``` *** ### `screenshot_region` Capture screenshot of specific region. ```python theme={null} desktop.screenshot_region(x, y, width, height) -> bytes ``` **Parameters:** * `x` (`int`): X coordinate of top-left corner * `y` (`int`): Y coordinate of top-left corner * `width` (`int`): Region width * `height` (`int`): Region height **Expected Output:** ``` Screenshot captured (PNG bytes, {width}x{height} region) ``` *** ## Window Methods ### `get_windows` Get list of all windows. ```python theme={null} desktop.get_windows() -> List[WindowInfo] ``` **Returns:** `List[WindowInfo]` - List of window information objects **Expected Output:** ``` [WindowInfo(id='window_1', title='Application', ...), WindowInfo(id='window_2', ...)] ``` *** ### `focus_window` Focus (activate) window. ```python theme={null} desktop.focus_window(window_id) -> None ``` **Expected Output:** ``` Window focused successfully ``` *** ### `close_window` Close window. ```python theme={null} desktop.close_window(window_id) -> None ``` **Expected Output:** ``` Window closed successfully ``` *** ## Examples ### Example 1: Taking Screenshots ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="desktop-template") # Take full screen screenshot screenshot = sandbox.desktop.screenshot() with open("fullscreen.png", "wb") as f: f.write(screenshot) # Take region screenshot region = sandbox.desktop.screenshot_region(0, 0, 800, 600) with open("region.png", "wb") as f: f.write(region) sandbox.kill() ``` **Expected Output:** ``` Screenshots saved: fullscreen.png, region.png ``` ### Example 2: Mouse and Keyboard Automation ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="desktop-template") # Click at position sandbox.desktop.click(100, 200) # Type text sandbox.desktop.type("Hello, World!") # Press Enter sandbox.desktop.press("Enter") # Drag and drop sandbox.desktop.drag(100, 100, 300, 300) sandbox.kill() ``` **Expected Output:** ``` Mouse clicked at (100, 200) Text typed: Hello, World! Enter key pressed Drag completed from (100, 100) to (300, 300) ``` *** ## Related Classes * **[Sandbox](/sdk/python/sandbox)** - Main sandbox class * **[Models](/sdk/python/models)** - Data models including `VNCInfo`, `WindowInfo` ## See Also * [Core Concepts: Desktop](/core-concepts/desktop) - Learn about desktop automation * [Sandbox Class](/sdk/python/sandbox) - Access desktop via `sandbox.desktop` ## Related * **[Desktop Automation](/core-concepts/desktop/vnc-server)** - Learn about desktop automation * **[Sandbox Class](/sdk/python/sandbox)** - Access desktop via `sandbox.desktop` ## Next Steps * Learn about [VNC Server](/core-concepts/desktop/vnc-server) for remote desktop access * Explore [Screenshots](/core-concepts/desktop/screenshots) for visual verification * Review [Mouse Control](/core-concepts/desktop/mouse-control) and [Keyboard Control](/core-concepts/desktop/keyboard-control) for GUI automation * **[CLI System Commands](/cli/commands/system)** - System operations from CLI # Environment Variables Source: https://docs.hopx.ai/sdk/python/environment-variables Environment variable management resource for configuring sandbox environment in HopX using the Python SDK. Complete reference for the Environment class including methods for getting, setting, updating, and clearing environment variables. Includes code examples for configuration management and environment setup. **Version:** 0.3.0\ **Last Verified:** 2025-01-27\ **Package:** `hopx-ai` on [PyPI](https://pypi.org/project/hopx-ai/) ## Overview The `EnvironmentVariables` resource (accessed via `sandbox.env`) provides methods for managing environment variables in sandboxes. Use this resource to set, get, update, and delete environment variables that are available to all code execution and commands. Environment variables set through this resource persist for the lifetime of the sandbox and are available to all executions. ## Access ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") env = sandbox.env # Lazy-loaded ``` ## Methods ### `get_all` Get all environment variables. ```python theme={null} env.get_all(*, timeout=None) -> Dict[str, str] ``` **Returns:** `Dict[str, str]` - Dictionary of all environment variables **Example:** ```python theme={null} all_vars = sandbox.env.get_all() for key, value in all_vars.items(): print(f"{key}={value}") ``` **Expected Output:** ``` PATH=/usr/local/bin:/usr/bin:/bin HOME=/root LANG=en_US.UTF-8 ``` **See Also:** * [API: Get Environment Variables](/api/vm-agent/get-env) *** ### `get` Get a specific environment variable value. ```python theme={null} env.get(key, default=None) -> Optional[str] ``` **Parameters:** * `key` (`str`): Environment variable name * `default` (`str`, optional): Default value if not found **Returns:** `Optional[str]` - Variable value or default **Example:** ```python theme={null} api_key = sandbox.env.get("API_KEY", "not-set") print(f"API key: {api_key}") ``` **Expected Output:** ``` API key: not-set ``` **See Also:** * [API: Get Environment Variables](/api/vm-agent/get-env) *** ### `set` Set a single environment variable. ```python theme={null} env.set(key, value, *, timeout=None) -> Dict[str, str] ``` **Parameters:** * `key` (`str`): Environment variable name * `value` (`str`): Variable value * `timeout` (`int`, optional): Request timeout **Returns:** `Dict[str, str]` - Updated dictionary of all environment variables **Example:** ```python theme={null} sandbox.env.set("API_KEY", "secret123") all_vars = sandbox.env.get_all() print(all_vars["API_KEY"]) # "secret123" ``` **Expected Output:** ``` secret123 ``` **See Also:** * [API: Set Environment Variables](/api/vm-agent/set-env) *** ### `set_all` Set/replace all environment variables (destructive). ```python theme={null} env.set_all(env_vars, *, timeout=None) -> Dict[str, str] ``` **Parameters:** * `env_vars` (`Dict[str, str]`): Dictionary of environment variables * `timeout` (`int`, optional): Request timeout **Returns:** `Dict[str, str]` - Updated dictionary of all environment variables This replaces ALL existing environment variables. Use `update()` to merge instead. **Example:** ```python theme={null} sandbox.env.set_all({ "API_KEY": "secret123", "DEBUG": "true", "ENV": "production" }) ``` **Expected Output:** ``` All environment variables replaced successfully ``` *** ### `update` Update specific environment variables (merge with existing). ```python theme={null} env.update(env_vars, *, timeout=None) -> Dict[str, str] ``` **Parameters:** * `env_vars` (`Dict[str, str]`): Dictionary of environment variables to update * `timeout` (`int`, optional): Request timeout **Returns:** `Dict[str, str]` - Updated dictionary of all environment variables **Example:** ```python theme={null} # Merge new variables with existing sandbox.env.update({ "NEW_VAR": "value", "API_KEY": "updated-secret" }) ``` **Expected Output:** ``` Environment variables updated successfully ``` **See Also:** * [API: Update Environment Variables](/api/vm-agent/update-env) *** ### `delete` Delete a specific environment variable. ```python theme={null} env.delete(key, *, timeout=None) -> None ``` **Parameters:** * `key` (`str`): Environment variable name to delete * `timeout` (`int`, optional): Request timeout **Example:** ```python theme={null} sandbox.env.delete("OLD_VAR") ``` **Expected Output:** ``` Environment variable deleted successfully ``` *** ## Examples ### Example 1: Basic Environment Variable Management ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Set environment variables sandbox.env.set("API_KEY", "secret123") sandbox.env.set("DEBUG", "true") # Get a variable api_key = sandbox.env.get("API_KEY") print(f"API key: {api_key}") # Get all variables all_vars = sandbox.env.get_all() print(f"Total variables: {len(all_vars)}") sandbox.kill() ``` **Expected Output:** ``` API key: secret123 Total variables: 5 ``` ### Example 2: Setting Variables at Creation ```python theme={null} from hopx_ai import Sandbox # Set environment variables when creating sandbox sandbox = Sandbox.create( template="code-interpreter", env_vars={ "API_KEY": "secret123", "DEBUG": "true", "ENV": "development" } ) # Verify they're set result = sandbox.run_code("import os; print(os.getenv('API_KEY'))") print(result.stdout) sandbox.kill() ``` **Expected Output:** ``` secret123 ``` ### Example 3: Updating Variables ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Set initial variables sandbox.env.set_all({ "VAR1": "value1", "VAR2": "value2" }) # Update specific variables (merge) sandbox.env.update({ "VAR2": "updated-value2", "VAR3": "value3" }) # VAR1 still exists, VAR2 updated, VAR3 added all_vars = sandbox.env.get_all() print(all_vars) sandbox.kill() ``` **Expected Output:** ``` {'VAR1': 'value1', 'VAR2': 'updated-value2', 'VAR3': 'value3', 'PATH': '/usr/local/bin:/usr/bin:/bin', 'HOME': '/root'} ``` ### Example 4: Using Variables in Code Execution ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Set environment variable sandbox.env.set("SECRET", "my-secret-key") # Use it in code execution result = sandbox.run_code( "import os; print(os.getenv('SECRET'))" ) print(result.stdout) # "my-secret-key\n" sandbox.kill() ``` **Expected Output:** ``` my-secret-key ``` ### Example 5: Using Variables in Commands ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Set environment variable sandbox.env.set("MY_VAR", "Hello from env") # Use it in command result = sandbox.commands.run("echo $MY_VAR") print(result.stdout) # "Hello from env\n" sandbox.kill() ``` **Expected Output:** ``` Hello from env ``` *** ## Related Classes * **[Sandbox](/sdk/python/sandbox)** - Main sandbox class * **[Commands](/sdk/python/commands)** - Command execution resource * **[Files](/sdk/python/files)** - File operations resource ## See Also * [Core Concepts: Environment Variables](/core-concepts/environment-variables) - Learn about environment configuration * [Sandbox Class](/sdk/python/sandbox) - Access env via `sandbox.env` ## Related * **[Getting Environment Variables](/core-concepts/environment/getting)** - Learn about getting env vars * **[Setting Environment Variables](/core-concepts/environment/setting)** - Learn about setting env vars * **[Updating Environment Variables](/core-concepts/environment/updating)** - Batch update env vars * **API**: [GET /env](/api/vm-agent/get-env) - VM Agent API endpoint ## Next Steps * Learn about [Getting Environment Variables](/core-concepts/environment/getting) to read values * Explore [Setting Environment Variables](/core-concepts/environment/setting) to configure environment * Review [Updating Environment Variables](/core-concepts/environment/updating) for batch updates * **[CLI Environment Variables](/cli/commands/env)** - Manage environment variables from the command line ## Related * **[Getting Environment Variables](/core-concepts/environment/getting)** - Learn about retrieving variables * **[Setting Environment Variables](/core-concepts/environment/setting)** - Learn about setting variables * **[Updating Environment Variables](/core-concepts/environment/updating)** - Learn about updating variables * **[API: Environment Variables](/api/vm-agent/get-env)** - VM Agent API endpoints # Sandbox Error Handling Source: https://docs.hopx.ai/sdk/python/errors Error classes and exception handling in the HopX Python SDK. Handle API errors, network errors, agent errors, and validation errors gracefully. Learn about error types, error handling patterns, and best practices for robust error handling in your applications. Includes error class reference and handling examples. **Version:** 0.3.0\ **Last Verified:** 2025-01-27\ **Package:** `hopx-ai` on [PyPI](https://pypi.org/project/hopx-ai/) ## Overview The Python SDK provides a comprehensive error hierarchy for handling different types of errors. All errors inherit from `HopxError` and provide detailed error information. ## Import ```python theme={null} from hopx_ai import ( HopxError, APIError, AuthenticationError, NotFoundError, ValidationError, RateLimitError, ResourceLimitError, ServerError, NetworkError, TimeoutError, AgentError, FileNotFoundError, FileOperationError, CodeExecutionError, CommandExecutionError, DesktopNotAvailableError ) ``` ## Base Error ### `HopxError` Base exception for all HopX SDK errors. **Fields:** * `message` (`str`): Error message * `code` (`str`, optional): Error code * `request_id` (`str`, optional): Request ID for debugging * `status_code` (`int`, optional): HTTP status code * `details` (`Dict[str, Any]`, optional): Additional error details **Example:** ```python theme={null} try: sandbox = Sandbox.create(template="invalid-template") except HopxError as e: print(f"Error: {e.message}") print(f"Code: {e.code}") ``` **Expected Output:** ``` Error: Template not found Code: TEMPLATE_NOT_FOUND ``` *** ## API Errors ### `APIError` Base class for API request failures. **Inherits from:** `HopxError` **Fields:** * `status_code` (`int`): HTTP status code *** ### `AuthenticationError` Authentication failed (401). **Inherits from:** `APIError` **When raised:** * Invalid or missing API key * Expired authentication token **Example:** ```python theme={null} try: sandbox = Sandbox.create(template="code-interpreter", api_key="invalid") except AuthenticationError: print("Invalid API key") ``` **Expected Output:** ``` Invalid API key ``` *** ### `NotFoundError` Resource not found (404). **Inherits from:** `APIError` **When raised:** * Sandbox not found * Template not found * File not found **Example:** ```python theme={null} try: sandbox = Sandbox.connect("non-existent-id") except NotFoundError: print("Sandbox not found") ``` **Expected Output:** ``` Sandbox not found ``` *** ### `ValidationError` Request validation failed (400). **Inherits from:** `APIError` **Fields:** * `field` (`str`, optional): Field that failed validation **When raised:** * Invalid parameters * Missing required fields * Invalid data format **Example:** ```python theme={null} try: sandbox = Sandbox.create(template="", template_id="") except ValidationError as e: print(f"Validation failed: {e.message}") if e.field: print(f"Field: {e.field}") ``` **Expected Output:** ``` Validation failed: Either template or template_id must be provided Field: template ``` *** ### `RateLimitError` Rate limit exceeded (429). **Inherits from:** `APIError` **Fields:** * `retry_after` (`int`, optional): Seconds to wait before retrying **When raised:** * Too many requests in a time period **Example:** ```python theme={null} try: sandbox = Sandbox.create(template="code-interpreter") except RateLimitError as e: print(f"Rate limited. Retry after {e.retry_after} seconds") ``` **Expected Output:** ``` Rate limited. Retry after 60 seconds ``` *** ### `ResourceLimitError` Resource limit exceeded. **Inherits from:** `APIError` **Fields:** * `limit` (`int`): Resource limit * `current` (`int`): Current usage * `available` (`int`): Available resources * `upgrade_url` (`str`, optional): URL to upgrade plan **When raised:** * Exceeded sandbox quota * Insufficient resources **Example:** ```python theme={null} try: sandbox = Sandbox.create(template="code-interpreter") except ResourceLimitError as e: print(f"Limit exceeded: {e.current}/{e.limit}") if e.upgrade_url: print(f"Upgrade at: {e.upgrade_url}") ``` **Expected Output:** ``` Limit exceeded: 10/10 Upgrade at: https://console.hopx.dev/upgrade ``` *** ### `ServerError` Server error (5xx). **Inherits from:** `APIError` **When raised:** * Internal server error * Service unavailable *** ## Network Errors ### `NetworkError` Network communication failed. **Inherits from:** `HopxError` **When raised:** * Connection errors * DNS resolution failures *** ### `TimeoutError` Request timed out. **Inherits from:** `NetworkError` **When raised:** * Request exceeded timeout * Operation took too long **Example:** ```python theme={null} try: result = sandbox.run_code("import time; time.sleep(300)", timeout=60) except TimeoutError: print("Execution timed out") ``` **Expected Output:** ``` Execution timed out ``` *** ## Agent Errors ### `AgentError` Base error for agent operations. **Inherits from:** `HopxError` *** ### `FileNotFoundError` File or directory not found in sandbox. **Inherits from:** `AgentError` **Fields:** * `path` (`str`): Path that was not found **Example:** ```python theme={null} try: content = sandbox.files.read("/nonexistent/file.txt") except FileNotFoundError as e: print(f"File not found: {e.path}") ``` **Expected Output:** ``` File not found: /nonexistent/file.txt ``` *** ### `FileOperationError` File operation failed. **Inherits from:** `AgentError` **Fields:** * `operation` (`str`): Operation that failed **Example:** ```python theme={null} try: sandbox.files.write("/readonly/file.txt", "content") except FileOperationError as e: print(f"File operation failed: {e.operation}") ``` **Expected Output:** ``` File operation failed: write ``` *** ### `CodeExecutionError` Code execution failed. **Inherits from:** `AgentError` **Fields:** * `language` (`str`): Language that failed **Example:** ```python theme={null} try: result = sandbox.run_code("invalid syntax here", language="python") except CodeExecutionError as e: print(f"Code execution failed: {e.message}") ``` **Expected Output:** ``` Code execution failed: SyntaxError: invalid syntax ``` *** ### `CommandExecutionError` Command execution failed. **Inherits from:** `AgentError` **Fields:** * `command` (`str`): Command that failed **Example:** ```python theme={null} try: result = sandbox.commands.run("nonexistent-command") except CommandExecutionError as e: print(f"Command failed: {e.command}") ``` **Expected Output:** ``` Command failed: nonexistent-command ``` *** ### `DesktopNotAvailableError` Desktop automation not available in this sandbox. **Inherits from:** `AgentError` **Fields:** * `missing_dependencies` (`List[str]`): Missing dependencies * `docs_url` (`str`, optional): Documentation URL * `install_command` (`str`, optional): Installation command **Example:** ```python theme={null} try: screenshot = sandbox.desktop.screenshot() except DesktopNotAvailableError as e: print(f"Desktop not available: {e.message}") if e.install_command: print(f"Install with: {e.install_command}") ``` **Expected Output:** ``` Desktop not available: Desktop automation requires desktop-enabled template Install with: Use template with desktop support ``` *** ## Error Handling Examples ### Example 1: Basic Error Handling ```python theme={null} from hopx_ai import Sandbox, HopxError try: sandbox = Sandbox.create(template="code-interpreter") result = sandbox.run_code("print('Hello')") except HopxError as e: print(f"Error: {e.message}") if hasattr(e, 'status_code'): print(f"Status: {e.status_code}") ``` **Expected Output:** ``` Hello ``` ### Example 2: Specific Error Handling ```python theme={null} from hopx_ai import Sandbox, AuthenticationError, NotFoundError, ValidationError try: sandbox = Sandbox.create(template="code-interpreter") except AuthenticationError: print("Authentication failed. Check your API key.") except NotFoundError: print("Template not found.") except ValidationError as e: print(f"Invalid request: {e.message}") ``` **Expected Output:** ``` Sandbox created successfully ``` ### Example 3: Retry on Rate Limit ```python theme={null} from hopx_ai import Sandbox, RateLimitError import time def create_sandbox_with_retry(): max_retries = 3 for attempt in range(max_retries): try: return Sandbox.create(template="code-interpreter") except RateLimitError as e: if attempt < max_retries - 1: wait_time = e.retry_after or 60 print(f"Rate limited. Waiting {wait_time} seconds...") time.sleep(wait_time) else: raise ``` **Expected Output:** ``` Sandbox created successfully (after retry if needed) ``` *** ## Related Classes * **[Models](/sdk/python/models)** - Data models * **[Sandbox](/sdk/python/sandbox)** - Sandbox operations that may raise errors ## See Also * [Models](/sdk/python/models) - Learn about data models * [Core Concepts: Errors](/core-concepts/errors) - Learn about error handling ## Next Steps Now that you understand error handling, explore: * [Error Handling Basics](/cookbooks/getting-started/error-handling) - Practical error handling patterns * [Sandbox Operations](/sdk/python/sandbox) - See errors in action * [API Errors](/api/concepts/errors) - Understand API error responses * **[CLI Reference](/cli/introduction)** - Use HopX from the command line * [Troubleshooting](/api/concepts/troubleshooting) - Common issues and solutions # File Operations Source: https://docs.hopx.ai/sdk/python/files File operations resource for reading, writing, and managing files in HopX sandboxes using the Python SDK. Complete reference for the Files class including methods for reading, writing, listing, uploading, downloading, and watching files. Includes code examples for all file operations and error handling. **Version:** 0.3.0\ **Last Verified:** 2025-01-27\ **Package:** `hopx-ai` on [PyPI](https://pypi.org/project/hopx-ai/) ## Overview The `Files` resource provides file operations for sandboxes. Access it via the `files` property on a `Sandbox` instance. All file operations are synchronous and work with both text and binary files. The `Files` resource is lazy-loaded, meaning it's only initialized when first accessed. ## Access ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") files = sandbox.files # Lazy-loaded ``` ## Methods ### `read` Read text file contents. ```python theme={null} files.read(path, *, timeout=None) -> str ``` **Parameters:** * `path` (`str`): File path to read * `timeout` (`int`, optional): Request timeout in seconds **Returns:** `str` - File contents as string **Raises:** * `FileNotFoundError`: File does not exist * `FileOperationError`: Read operation failed **Example:** ```python theme={null} content = sandbox.files.read("/workspace/script.py") print(content) ``` **Expected Output:** ``` print('Hello, World!') ``` **See Also:** * [API: Read File](/api/vm-agent/read-file) *** ### `read_bytes` Read binary file contents. ```python theme={null} files.read_bytes(path, *, timeout=None) -> bytes ``` **Parameters:** * `path` (`str`): File path to read * `timeout` (`int`, optional): Request timeout **Returns:** `bytes` - File contents as bytes **Example:** ```python theme={null} image_data = sandbox.files.read_bytes("/workspace/image.png") with open("local_image.png", "wb") as f: f.write(image_data) ``` *** ### `write` Write text file contents. ```python theme={null} files.write(path, content, mode='0644', *, timeout=None) -> None ``` **Parameters:** * `path` (`str`): File path to write * `content` (`str`): Text content to write * `mode` (`str`, optional): File permissions (default: `'0644'`) * `timeout` (`int`, optional): Request timeout **Raises:** * `FileOperationError`: Write operation failed **Example:** ```python theme={null} sandbox.files.write("/workspace/hello.txt", "Hello, World!") ``` **Expected Output:** ``` File written successfully ``` **See Also:** * [API: Write File](/api/vm-agent/write-file) *** ### `write_bytes` Write binary file contents. ```python theme={null} files.write_bytes(path, content, mode='0644', *, timeout=None) -> None ``` **Parameters:** * `path` (`str`): File path to write * `content` (`bytes`): Binary content to write * `mode` (`str`, optional): File permissions * `timeout` (`int`, optional): Request timeout **Example:** ```python theme={null} with open("local_file.bin", "rb") as f: data = f.read() sandbox.files.write_bytes("/workspace/remote_file.bin", data) ``` *** ### `list` List directory contents. ```python theme={null} files.list(path='/workspace', *, timeout=None) -> List[FileInfo] ``` **Parameters:** * `path` (`str`, optional): Directory path (default: `'/workspace'`) * `timeout` (`int`, optional): Request timeout **Returns:** `List[FileInfo]` - List of file/directory information objects **Example:** ```python theme={null} items = sandbox.files.list("/workspace") for item in items: if item.is_directory: print(f"Directory: {item.name}") else: print(f"File: {item.name} ({item.size} bytes)") ``` **Expected Output:** ``` File: hello.txt (13 bytes) Directory: my_project File: script.py (42 bytes) ``` **See Also:** * [API: List Files](/api/vm-agent/list-files) *** ### `exists` Check if file or directory exists. ```python theme={null} files.exists(path, *, timeout=None) -> bool ``` **Parameters:** * `path` (`str`): File or directory path * `timeout` (`int`, optional): Request timeout **Returns:** `bool` - `True` if exists, `False` otherwise **Example:** ```python theme={null} if sandbox.files.exists("/workspace/config.json"): content = sandbox.files.read("/workspace/config.json") ``` **Expected Output:** ``` File exists, content read successfully ``` **See Also:** * [API: File Exists](/api/vm-agent/file-exists) *** ### `remove` Delete file or directory. ```python theme={null} files.remove(path, *, timeout=None) -> None ``` **Parameters:** * `path` (`str`): File or directory path to delete * `timeout` (`int`, optional): Request timeout **Raises:** * `FileNotFoundError`: Path does not exist * `FileOperationError`: Delete operation failed This operation is irreversible. Directories are deleted recursively. **Example:** ```python theme={null} sandbox.files.remove("/workspace/temp_file.txt") ``` **Expected Output:** ``` File removed successfully ``` **See Also:** * [API: Remove File](/api/vm-agent/remove-file) *** ### `mkdir` Create directory. ```python theme={null} files.mkdir(path, *, timeout=None) -> None ``` **Parameters:** * `path` (`str`): Directory path to create * `timeout` (`int`, optional): Request timeout **Raises:** * `FileOperationError`: Directory creation failed **Example:** ```python theme={null} sandbox.files.mkdir("/workspace/my_project") sandbox.files.write("/workspace/my_project/main.py", "print('Hello')") ``` **Expected Output:** ``` Directory created successfully File written successfully ``` *** ### `upload` Upload file from local filesystem to sandbox. ```python theme={null} files.upload(local_path, remote_path, *, timeout=None) -> None ``` **Parameters:** * `local_path` (`str`): Local file path * `remote_path` (`str`): Remote file path in sandbox * `timeout` (`int`, optional): Request timeout **Example:** ```python theme={null} sandbox.files.upload("./local_script.py", "/workspace/script.py") ``` **Expected Output:** ``` File uploaded successfully ``` *** ### `download` Download file from sandbox to local filesystem. ```python theme={null} files.download(remote_path, local_path, *, timeout=None) -> None ``` **Parameters:** * `remote_path` (`str`): Remote file path in sandbox * `local_path` (`str`): Local file path * `timeout` (`int`, optional): Request timeout **Example:** ```python theme={null} sandbox.files.download("/workspace/output.txt", "./local_output.txt") ``` **Expected Output:** ``` File downloaded successfully ``` *** ## Examples ### Example 1: Basic File Operations ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Write a file sandbox.files.write("/workspace/hello.py", "print('Hello, World!')") # Read it back content = sandbox.files.read("/workspace/hello.py") print(content) # Execute it result = sandbox.run_code("exec(open('/workspace/hello.py').read())") print(result.stdout) sandbox.kill() ``` **Expected Output:** ``` print('Hello, World!') Hello, World! ``` ### Example 2: Working with Directories ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Create directory structure sandbox.files.mkdir("/workspace/my_project") sandbox.files.mkdir("/workspace/my_project/src") # Write files sandbox.files.write("/workspace/my_project/src/main.py", "print('Main')") sandbox.files.write("/workspace/my_project/README.md", "# My Project") # List directory items = sandbox.files.list("/workspace/my_project") for item in items: print(f"{item.name}: {'dir' if item.is_directory else 'file'}") sandbox.kill() ``` **Expected Output:** ``` src: dir README.md: file ``` ### Example 3: File Upload/Download ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Upload local file sandbox.files.upload("./local_script.py", "/workspace/remote_script.py") # Process it in sandbox result = sandbox.run_code("exec(open('/workspace/remote_script.py').read())") # Download result sandbox.files.write("/workspace/output.txt", result.stdout) sandbox.files.download("/workspace/output.txt", "./local_output.txt") sandbox.kill() ``` ### Example 4: Binary File Operations ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Read binary file image_data = sandbox.files.read_bytes("/workspace/image.png") # Process it (example: get size) size = len(image_data) print(f"Image size: {size} bytes") # Write binary data sandbox.files.write_bytes("/workspace/copy.png", image_data) sandbox.kill() ``` *** ## FileInfo Model The `list()` method returns `FileInfo` objects with the following properties: * `name` (`str`): File or directory name * `path` (`str`): Full path * `size` (`int`): Size in bytes * `is_directory` (`bool`): Whether it's a directory * `permissions` (`str`): File permissions * `modified_time` (`datetime`): Last modification time * `is_file` (`bool`): Convenience property (opposite of `is_directory`) * `size_kb` (`float`): Size in kilobytes * `size_mb` (`float`): Size in megabytes *** ## Related Classes * **[Sandbox](/sdk/python/sandbox)** - Main sandbox class * **[Commands](/sdk/python/commands)** - Command execution resource * **[Models](/sdk/python/models)** - Data models including `FileInfo` ## See Also * [Core Concepts: Files](/core-concepts/files) - Learn about file operations * [Sandbox Class](/sdk/python/sandbox) - Access files via `sandbox.files` ## Related * **[Reading Files](/core-concepts/filesystem/reading)** - Learn about reading files * **[Writing Files](/core-concepts/filesystem/writing)** - Learn about writing files * **[Listing Files](/core-concepts/filesystem/listing)** - List directory contents * **[API: File Operations](/api/vm-agent/read-file)** - VM Agent API endpoints ## Next Steps * Learn about [Reading Files](/core-concepts/filesystem/reading) to access file contents * Explore [Writing Files](/core-concepts/filesystem/writing) to create files * Review [Uploading Files](/core-concepts/filesystem/uploading) for local file transfers * **[CLI File Operations](/cli/commands/files)** - Use file operations from the command line # Installation Source: https://docs.hopx.ai/sdk/python/installation Install the HopX Python SDK and set up your development environment. Get started with the official Python SDK for HopX, install via pip, configure API keys, and verify installation. Learn system requirements, installation methods, and troubleshooting tips. Includes installation examples for different Python versions and environments. **SDK Version:** 0.3.0\ **Last Verified:** 2025-01-27 ## Prerequisites Before installing the HopX Python SDK, ensure you have: * **Python 3.8+** (CPython recommended) * **pip** (Python package installer) * **HopX API key** - Get yours at [console.hopx.dev](https://console.hopx.dev) ## Install from PyPI The recommended way to install the HopX Python SDK: ```bash theme={null} pip install hopx-ai ``` ## Install Specific Version Install a specific version: ```bash theme={null} pip install hopx-ai==0.3.0 ``` ## Install from Source For development or to use the latest unreleased version: ```bash theme={null} git clone https://github.com/hopx-ai/hopx.git cd HopX/python pip install -e . ``` ## Verify Installation Verify the installation: ```bash theme={null} python -c "import hopx_ai; print(hopx_ai.__version__)" ``` Expected output: `0.3.0` ## Set Up Authentication The SDK requires an API key for authentication. You have three options: ### Option 1: Environment Variable (Recommended) Set the `HOPX_API_KEY` environment variable: ```bash theme={null} # Linux/macOS export HOPX_API_KEY="your-API key-here" # Windows (PowerShell) $env:HOPX_API_KEY="your-API key-here" # Windows (CMD) set HOPX_API_KEY=your-API key-here ``` ### Option 2: Pass API key Directly Pass the API key when creating a sandbox: ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create( template="code-interpreter", api_key="your-API key-here" ) ``` ### Option 3: Configuration File Create a `.env` file in your project root: ```bash theme={null} # .env HOPX_API_KEY=your-API key-here ``` Then load it in your Python code: ```python theme={null} from dotenv import load_dotenv import os from hopx_ai import Sandbox load_dotenv() sandbox = Sandbox.create(template="code-interpreter") ``` Never commit your API key to version control. Always use environment variables or secure secret management for production applications. ## Get Your API key 1. Sign up at [console.hopx.dev](https://console.hopx.dev) 2. Navigate to **Settings** → **API Keys** 3. Create a new API key 4. Copy the key (you'll only see it once) API keys are scoped to your account and have full access to create, manage, and delete sandboxes. Keep them secure. ## Supported Python Versions The SDK is tested and supported on: * **Python 3.8** - Minimum supported version * **Python 3.9** - Recommended for best compatibility * **Python 3.10** - Recommended for new projects * **Python 3.11** - Recommended for new projects * **Python 3.12** - Latest, fully supported ## Package Managers ### pip ```bash theme={null} pip install hopx-ai ``` ### poetry ```bash theme={null} poetry add hopx-ai ``` ### pipenv ```bash theme={null} pipenv install hopx-ai ``` ### conda ```bash theme={null} conda install -c conda-forge hopx-ai ``` ## Dependencies The SDK has minimal dependencies: * `requests` - HTTP client for API calls * `websocket-client` - WebSocket support for streaming * `typing-extensions` - Type hints for Python \< 3.10 All dependencies are automatically installed with `pip install hopx-ai`. ## Troubleshooting ### Import Errors If you get `ModuleNotFoundError: No module named 'hopx_ai'`: 1. Verify Python version: `python --version` (should be 3.8+) 2. Check installation: `pip list | grep hopx-ai` 3. Reinstall: `pip install --upgrade hopx-ai` ### Authentication Errors If you get authentication errors: 1. Verify API key is set: `echo $HOPX_API_KEY` (Linux/macOS) or `echo %HOPX_API_KEY%` (Windows) 2. Check API key is valid at [console.hopx.dev](https://console.hopx.dev) 3. Ensure no extra spaces or quotes in the API key ### Network Errors If you encounter network errors: 1. Check internet connection 2. Verify firewall allows outbound HTTPS (port 443) 3. Check if you're behind a corporate proxy (may need proxy configuration) For more troubleshooting help, see the [Troubleshooting Guide](/sdk/python/troubleshooting). ## Related * **[Python SDK Quickstart](/sdk/python/quickstart)** - Get started with the SDK * **\[API key Management]\(/API key)** - Learn about API key security * **[Sandbox Class Reference](/sdk/python/sandbox)** - Complete SDK reference ## Next Steps Once you've successfully installed the SDK: * **[Quickstart Guide](/sdk/python/quickstart)** - Create your first sandbox and run code * **[CLI Installation](/cli/installation)** - Install the HopX CLI as an alternative * **[API Reference](/sdk/python/sandbox)** - Explore the full SDK API # Overview Source: https://docs.hopx.ai/sdk/python/introduction Official Python SDK for HopX - Create and manage cloud sandboxes in Python. Install the SDK, authenticate with your API key, and start creating sandboxes, executing code, managing files, and automating desktop interactions. Complete reference with code examples for all SDK methods and classes. **Version:** 0.3.0\ **Last Verified:** 2025-01-27\ **Package:** `hopx-ai` on [PyPI](https://pypi.org/project/hopx-ai/) ## What is the Python SDK? The HopX Python SDK provides a simple, powerful interface for creating and managing cloud sandboxes directly from your Python applications. Build AI agents, run untrusted code securely, execute tests in isolation, or process data with rich output capture—all with a clean, Pythonic API. The SDK is a thin wrapper around the HopX REST API that handles authentication, request formatting, error translation, and response parsing automatically, giving you a better developer experience than working with the raw API. ## Target Audience This SDK is designed for: * **Backend Python developers** using Python 3.8+ (CPython recommended) * **Data scientists** working with Jupyter notebooks, pandas, matplotlib * **AI/ML engineers** building agents that need secure code execution * **DevOps engineers** creating isolated testing environments * **Automation engineers** building workflows that require sandboxed execution ## Supported Runtimes * **Python:** 3.8, 3.9, 3.10, 3.11, 3.12 (CPython) * **Operating Systems:** Linux, macOS, Windows * **Package Managers:** pip, poetry, pipenv, conda ## When to Use the SDK vs CLI vs Raw API ### Use the Python SDK when: * ✅ You're building Python applications * ✅ You want type hints and IDE autocomplete * ✅ You prefer Pythonic error handling and exceptions * ✅ You need async/await support (`AsyncSandbox`) * ✅ You want automatic resource management (context managers) * ✅ You're working with Python data structures (dicts, lists, models) ### Use the CLI when: * ✅ You prefer command-line workflows * ✅ You're scripting or automating from shell * ✅ You want quick one-off operations * ✅ You're working in CI/CD pipelines * ✅ You need interactive terminal sessions ### Use the Raw API when: * ⚠️ You're building in a non-Python language * ⚠️ You need fine-grained control over HTTP requests * ⚠️ You're integrating with existing HTTP client libraries * ⚠️ You need custom retry logic or connection pooling The SDK is a thin wrapper around the HopX REST API. It handles authentication, request formatting, error translation, and response parsing automatically. For most Python use cases, the SDK provides a better developer experience. ## Architecture The SDK consists of two main classes: * **`Sandbox`** - Synchronous sandbox client (blocking operations) * **`AsyncSandbox`** - Asynchronous sandbox client (async/await) Both classes provide the same functionality, with `AsyncSandbox` optimized for concurrent operations and async frameworks. ## Core Capabilities The Python SDK provides: * **Sandbox Management** - Create, connect, list, and delete sandboxes * **Code Execution** - Run Python, JavaScript, Bash, Go, and more * **Rich Outputs** - Capture matplotlib plots, pandas DataFrames, images * **File Operations** - Read, write, list, upload, download files * **Command Execution** - Run shell commands synchronously or in background * **Environment Variables** - Set, get, update, and clear environment variables * **Process Management** - List and manage running processes * **Cache Management** - Monitor and clear execution result cache * **Desktop Automation** - VNC access, mouse/keyboard control (Premium) * **Template Building** - Create custom sandbox environments * **WebSocket Streaming** - Real-time terminal and code execution streaming ## Quick Example ```python theme={null} from hopx_ai import Sandbox # Create a sandbox (~100ms) sandbox = Sandbox.create(template="code-interpreter") # Execute code result = sandbox.run_code('print("Hello from HopX!")') print(result.stdout) # "Hello from HopX!\n" # Cleanup sandbox.kill() ``` ## Next Steps * **[Installation Guide](/sdk/python/installation)** - Install the SDK and set up your environment * **[Quickstart](/sdk/python/quickstart)** - Get your first sandbox running in minutes * **[API Reference](/sdk/python/sandbox)** - Complete class and method documentation ## Related * [JavaScript SDK](/sdk/javascript/introduction) - Official JavaScript/TypeScript SDK * [CLI Reference](/cli/introduction) - Command-line interface for HopX * [API Reference](/api/introduction) - Raw REST API documentation * [Core Concepts](/core-concepts/sandboxes/creating) - Learn about sandboxes, execution, and more # Sandbox Data Models Source: https://docs.hopx.ai/sdk/python/models Data models and type definitions for the HopX Python SDK. Understand sandbox objects, execution results, file metadata, template structures, and other data models used throughout the SDK. Essential for working with SDK responses and building type-safe applications. Includes complete model reference and field descriptions. **Version:** 0.3.0\ **Last Verified:** 2025-01-27\ **Package:** `hopx-ai` on [PyPI](https://pypi.org/project/hopx-ai/) ## Overview The Python SDK provides data models for all API responses and objects. These models provide type safety, convenience methods, and clear documentation of data structures. ## Import ```python theme={null} from hopx_ai import ( SandboxInfo, Template as SandboxTemplate, ExecutionResult, CommandResult, FileInfo, RichOutput, VNCInfo, WindowInfo, RecordingInfo, DisplayInfo ) ``` ## Core Models ### `SandboxInfo` Sandbox information model. **Fields:** * `sandbox_id` (`str`): Unique sandbox identifier * `template_id` (`str`): Template ID used to create sandbox * `template_name` (`str`): Template name * `organization_id` (`str`): Organization ID * `node_id` (`str`): Node ID * `region` (`str`): Deployment region * `status` (`str`): Sandbox status (`"running"`, `"stopped"`, `"paused"`, `"creating"`) * `public_host` (`str`): Public hostname * `resources` (`Resources`): Resource specifications * `started_at` (`datetime`): Start timestamp * `end_at` (`datetime`, optional): End timestamp * `created_at` (`datetime`): Creation timestamp **Example:** ```python theme={null} info = sandbox.get_info() print(f"ID: {info.sandbox_id}") print(f"Status: {info.status}") print(f"Host: {info.public_host}") ``` *** ### `Template` Template information model. **Fields:** * `id` (`str`): Template ID * `name` (`str`): Template name * `display_name` (`str`): Display name * `description` (`str`): Template description * `category` (`str`): Template category * `language` (`str`): Primary language * `icon` (`str`, optional): Icon URL * `default_resources` (`TemplateResources`): Default resource specifications * `min_resources` (`TemplateResources`): Minimum resources * `max_resources` (`TemplateResources`): Maximum resources * `features` (`List[str]`): Available features * `tags` (`List[str]`): Template tags * `popularity_score` (`float`): Popularity score * `docs_url` (`str`, optional): Documentation URL * `is_active` (`bool`): Whether template is active * `status` (`str`): Template status **Example:** ```python theme={null} template = Sandbox.get_template("code-interpreter") print(f"Name: {template.name}") print(f"Resources: {template.default_resources.vcpu} vCPU") ``` *** ### `ExecutionResult` Result of code execution. **Fields:** * `success` (`bool`): Whether execution succeeded * `stdout` (`str`): Standard output * `stderr` (`str`): Standard error * `exit_code` (`int`): Exit code (0 = success) * `execution_time` (`float`): Execution time in seconds * `rich_outputs` (`List[RichOutput]`): Rich outputs (plots, DataFrames, etc.) **Properties:** * `rich_count` (`int`): Number of rich outputs **Example:** ```python theme={null} result = sandbox.run_code("print('Hello')") print(result.stdout) print(f"Success: {result.success}") print(f"Rich outputs: {result.rich_count}") ``` *** ### `CommandResult` Result of command execution. **Fields:** * `stdout` (`str`): Standard output * `stderr` (`str`): Standard error * `exit_code` (`int`): Exit code * `execution_time` (`float`): Execution time in seconds **Properties:** * `success` (`bool`): Whether command succeeded (`exit_code == 0`) **Example:** ```python theme={null} result = sandbox.commands.run("ls -la") print(result.stdout) print(f"Success: {result.success}") ``` *** ### `FileInfo` File or directory information. **Fields:** * `name` (`str`): File or directory name * `path` (`str`): Full path * `size` (`int`): Size in bytes * `is_directory` (`bool`): Whether it's a directory * `permissions` (`str`): File permissions * `modified_time` (`datetime`): Last modification time **Properties:** * `is_file` (`bool`): Whether it's a file * `is_dir` (`bool`): Whether it's a directory * `size_kb` (`float`): Size in kilobytes * `size_mb` (`float`): Size in megabytes **Example:** ```python theme={null} items = sandbox.files.list("/workspace") for item in items: if item.is_directory: print(f"Directory: {item.name}") else: print(f"File: {item.name} ({item.size_kb:.2f} KB)") ``` *** ### `RichOutput` Rich output from code execution (plots, DataFrames, etc.). **Fields:** * `type` (`str`): Output type (`"plot"`, `"dataframe"`, `"html"`, etc.) * `data` (`str` or `bytes`): Output data * `metadata` (`Dict[str, Any]`): Additional metadata * `timestamp` (`datetime`): Output timestamp **Example:** ```python theme={null} result = sandbox.run_code("import matplotlib.pyplot as plt; plt.plot([1,2,3]); plt.savefig('/tmp/plot.png')") for output in result.rich_outputs: if output.type == "plot": print(f"Plot generated at {output.timestamp}") ``` *** ## Desktop Models ### `VNCInfo` VNC server information. **Fields:** * `running` (`bool`): Whether VNC is running * `display` (`int`): Display number * `port` (`int`): VNC port * `url` (`str`): VNC URL * `password` (`str`): VNC password *** ### `WindowInfo` Window information. **Fields:** * `id` (`str`): Window ID * `title` (`str`): Window title * `x` (`int`): X coordinate * `y` (`int`): Y coordinate * `width` (`int`): Window width * `height` (`int`): Window height * `desktop` (`int`): Desktop number * `pid` (`int`): Process ID *** ### `RecordingInfo` Screen recording information. **Fields:** * `recording_id` (`str`): Recording ID * `status` (`str`): Recording status * `fps` (`int`): Frames per second * `format` (`str`): Video format * `duration` (`float`): Duration in seconds * `file_size` (`int`): File size in bytes **Properties:** * `is_recording` (`bool`): Whether recording is active * `is_ready` (`bool`): Whether recording is ready *** ### `DisplayInfo` Display information. **Fields:** * `width` (`int`): Display width * `height` (`int`): Display height * `depth` (`int`): Color depth **Properties:** * `resolution` (`Tuple[int, int]`): Resolution tuple *** ## Resource Models ### `Resources` Resource specifications. **Fields:** * `vcpu` (`int`): Number of vCPUs * `memory_mb` (`int`): Memory in megabytes * `disk_mb` (`int`): Disk space in megabytes *** ### `TemplateResources` Template resource specifications. **Fields:** * `vcpu` (`int`): Number of vCPUs * `memory_mb` (`int`): Memory in megabytes * `disk_gb` (`int`): Disk space in gigabytes *** ## Related Classes * **[Errors](/sdk/python/errors)** - Error classes and exception handling * **[Sandbox](/sdk/python/sandbox)** - Use models with sandbox operations ## See Also * [Errors](/sdk/python/errors) - Learn about error handling * [Core Concepts](/core-concepts) - Learn about core concepts ## Next Steps Now that you understand data models, explore: * [Sandbox Operations](/sdk/python/sandbox) - Use models in practice * [Error Handling](/sdk/python/errors) - Type-safe error handling * [Quickstart Guide](/sdk/python/quickstart) - Get started with the SDK * **[CLI Reference](/cli/introduction)** - Use HopX from the command line * [Python Type Hints](https://docs.python.org/3/library/typing.html) - Learn more about type hints # Quickstart Source: https://docs.hopx.ai/sdk/python/quickstart Get your first sandbox running in minutes with the HopX Python SDK - install, authenticate, execute code, see results. Complete quickstart guide for creating sandboxes, running Python code, managing files, and cleaning up resources. Perfect for developers new to HopX. Includes step-by-step examples and best practices. **Goal:** Create a sandbox, execute code, and see the output in under 5 minutes.\ **Prerequisites:** Python 3.8+, pip, HopX API key\ **Time:** \~5 minutes This quickstart gets you from zero to your first successful code execution. Follow these steps in order. ## What You'll Learn In this quickstart, you'll learn how to: * Install and verify the Python SDK * Set up API key authentication * Create a sandbox from a template * Execute Python code in the sandbox * Access execution results and output * Clean up sandboxes properly ## Step 1: Install the SDK ```bash theme={null} pip install hopx-ai ``` ## Step 1.5: Verify Installation Verify the SDK is installed correctly: ```bash theme={null} python -c "import hopx_ai; print(f'HopX SDK {hopx_ai.__version__} installed successfully')" ``` Expected output: `HopX SDK 0.3.0 installed successfully` ## Step 2: Set Your API key Set the `HOPX_API_KEY` environment variable: ```bash theme={null} # Linux/macOS export HOPX_API_KEY="your-api-key-here" # Windows (PowerShell) $env:HOPX_API_KEY="your-api-key-here" ``` Get your API key from [console.hopx.dev](https://console.hopx.dev) → Settings → API Keys ## Step 3: Create and Run Your First Sandbox Create a file `hello_hopx.py`: ```python theme={null} from hopx_ai import Sandbox # Create a sandbox (~100ms) sandbox = Sandbox.create(template="code-interpreter") # Execute code in the sandbox result = sandbox.run_code('print("Hello from HopX!")') # Print the output print(result.stdout) ``` **Expected Output:** ``` Hello from HopX! ``` # Cleanup - delete the sandbox sandbox.kill() ```` ## Step 4: Run It ```bash python hello_hopx.py ```` ## Expected Output ``` Hello from HopX! ``` 🎉 **Success!** You've created your first sandbox and executed code. The sandbox was automatically cleaned up after execution. ## What Just Happened? 1. **`Sandbox.create()`** - Created a new sandbox from the `code-interpreter` template (Python environment) 2. **`sandbox.run_code()`** - Executed Python code in the sandbox 3. **`result.stdout`** - Retrieved the standard output from code execution 4. **`sandbox.kill()`** - Deleted the sandbox to free resources ## Related * **[API Quickstart](/api/quickstart)** - Get started with the API * **[Sandbox Class Reference](/sdk/python/sandbox)** - Complete SDK reference * **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Learn more about sandbox creation * **[Code Execution](/core-concepts/code-execution/synchronous)** - Understand code execution ## Next Steps Now that you have a working setup, explore more: * **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Learn about different templates and options * **[Code Execution](/core-concepts/code-execution/synchronous)** - Run Python, JavaScript, Bash, and more * **[File Operations](/core-concepts/filesystem/reading)** - Read, write, and manage files in sandboxes * **[CLI Quickstart](/cli/quickstart)** - Use HopX from the command line * **[API Reference](/sdk/python/sandbox)** - Complete SDK documentation ## Quickstart Variations For more advanced quickstart examples including async/await, error handling, and context managers, see the [Advanced Quickstart Guide](/sdk/python/advanced-quickstart) (coming soon). ## Troubleshooting **"API key required" error?** * Verify `HOPX_API_KEY` is set: `echo $HOPX_API_KEY` * Get your key at [console.hopx.dev](https://console.hopx.dev) **"Template not found" error?** * Use `template="code-interpreter"` (default Python template) * See [Available Templates](/core-concepts/templates/listing) for options **Network timeout?** * Check internet connection * Verify firewall allows HTTPS (port 443) For more help, see the [Troubleshooting Guide](/sdk/python/troubleshooting). # Template Ready Checks Source: https://docs.hopx.ai/sdk/python/ready-checks Utilities for checking template readiness before use in the HopX Python SDK. Verify templates are available and ready before creating sandboxes, check template status, and handle template availability errors. Essential for robust sandbox creation workflows. Includes code examples and error handling. **Version:** 0.3.0\ **Last Verified:** 2025-01-27\ **Package:** `hopx-ai` on [PyPI](https://pypi.org/project/hopx-ai/) ## Overview Ready checks are utilities used in template building to verify that a template is ready before it's considered complete. Use ready checks to ensure services are running, files exist, or commands succeed before the template is marked as ready. ## Import ```python theme={null} from hopx_ai.template import ( wait_for_port, wait_for_url, wait_for_file, wait_for_process, wait_for_command ) ``` ## Available Ready Checks ### `wait_for_port` Wait for a port to be listening. ```python theme={null} wait_for_port(port, timeout=60) -> ReadyCheck ``` **Parameters:** * `port` (`int`): Port number to check * `timeout` (`int`, optional): Timeout in seconds (default: `60`) **Example:** ```python theme={null} from hopx_ai.template import Template, wait_for_port template = ( Template() .from_node_image("20") .expose(3000) .start_cmd("node server.js") .ready_check(wait_for_port(3000)) ) ``` *** ### `wait_for_url` Wait for a URL to be accessible. ```python theme={null} wait_for_url(url, timeout=60) -> ReadyCheck ``` **Parameters:** * `url` (`str`): URL to check * `timeout` (`int`, optional): Timeout in seconds **Example:** ```python theme={null} from hopx_ai.template import Template, wait_for_url template = ( Template() .from_python_image("3.11") .start_cmd("python app.py") .ready_check(wait_for_url("http://localhost:5000/health")) ) ``` *** ### `wait_for_file` Wait for a file to exist. ```python theme={null} wait_for_file(path, timeout=60) -> ReadyCheck ``` **Parameters:** * `path` (`str`): File path to check * `timeout` (`int`, optional): Timeout in seconds **Example:** ```python theme={null} from hopx_ai.template import Template, wait_for_file template = ( Template() .from_python_image("3.11") .run("python setup.py") .ready_check(wait_for_file("/app/ready.flag")) ) ``` *** ### `wait_for_process` Wait for a process to be running. ```python theme={null} wait_for_process(process_name, timeout=60) -> ReadyCheck ``` **Parameters:** * `process_name` (`str`): Process name to check * `timeout` (`int`, optional): Timeout in seconds **Example:** ```python theme={null} from hopx_ai.template import Template, wait_for_process template = ( Template() .from_python_image("3.11") .start_cmd("python worker.py") .ready_check(wait_for_process("worker.py")) ) ``` *** ### `wait_for_command` Wait for a command to succeed. ```python theme={null} wait_for_command(command, timeout=60) -> ReadyCheck ``` **Parameters:** * `command` (`str`): Command to execute * `timeout` (`int`, optional): Timeout in seconds **Example:** ```python theme={null} from hopx_ai.template import Template, wait_for_command template = ( Template() .from_python_image("3.11") .run("pip install -r requirements.txt") .ready_check(wait_for_command("python -c 'import requests'")) ) ``` *** ## Examples ### Example 1: Port Ready Check ```python theme={null} from hopx_ai.template import Template, wait_for_port import asyncio async def main(): template = ( Template() .from_node_image("20") .run("npm install express") .copy("./server.js", "/app/server.js") .expose(3000) .start_cmd("node /app/server.js") .ready_check(wait_for_port(3000, timeout=120)) ) result = await template.build() print(f"Template ready: {result.template_id}") asyncio.run(main()) ``` ### Example 2: URL Ready Check ```python theme={null} from hopx_ai.template import Template, wait_for_url import asyncio async def main(): template = ( Template() .from_python_image("3.11") .run("pip install flask") .copy("./app.py", "/app/app.py") .expose(5000) .start_cmd("python /app/app.py") .ready_check(wait_for_url("http://localhost:5000/health", timeout=90)) ) result = await template.build() print(f"Template ready: {result.template_id}") asyncio.run(main()) ``` *** ## Related Classes * **[Template Builder](/sdk/python/template-builder)** - Use ready checks in templates * **[Sandbox](/sdk/python/sandbox)** - Create sandboxes from templates ## See Also * [Template Builder](/sdk/python/template-builder) - Learn about building templates * [Core Concepts: Templates](/core-concepts/templates) - Learn about templates ## Next Steps Now that you understand ready checks, explore: * [Template Builder](/sdk/python/template-builder) - Use ready checks in template building * [Building Templates](/core-concepts/templates/building) - Learn template building concepts * [Template Configuration](/core-concepts/templates/configuration) - Configure templates * **[CLI Reference](/cli/introduction)** - Use HopX from the command line * [Custom Templates](/cookbooks/advanced/custom-templates) - Build custom templates # Sandbox Source: https://docs.hopx.ai/sdk/python/sandbox Main synchronous sandbox class for creating and managing cloud sandboxes in Python. Complete reference for the HopX Python SDK Sandbox class including methods for creating sandboxes, executing code, managing files, controlling desktop automation, and monitoring resources. Includes code examples for all methods. **Version:** 0.3.0\ **Last Verified:** 2025-01-27\ **Package:** `hopx-ai` on [PyPI](https://pypi.org/project/hopx-ai/) ## Overview The `Sandbox` class is the main entry point for the HopX Python SDK. It provides a synchronous interface for creating, managing, and interacting with cloud sandboxes (microVMs). Use this class when you're building synchronous Python applications or scripts. The `Sandbox` class handles authentication, request formatting, error translation, and response parsing automatically, giving you a clean, Pythonic API for sandbox management. ### When to Use Sandbox vs AsyncSandbox * **Use `Sandbox`** when: * Building synchronous Python applications * Writing scripts or simple automation * You prefer blocking operations * You don't need async/await patterns * **Use `AsyncSandbox`** when: * Building async Python applications (FastAPI, aiohttp, etc.) * You need to manage multiple sandboxes concurrently * You want non-blocking operations * You're already using async/await in your codebase ## Import ```python theme={null} from hopx_ai import Sandbox ``` ## Class Methods ### `create` Create a new sandbox from a template. ```python theme={null} Sandbox.create( template=None, *, template_id=None, region=None, timeout_seconds=None, internet_access=None, env_vars=None, api_key=None, base_url='https://api.hopx.dev' ) -> Sandbox ``` **Parameters:** * `template` (`str`, optional): Template name (e.g., `"code-interpreter"`) * `template_id` (`str`, optional): Template ID (alternative to template name) * `region` (`str`, optional): Preferred region (auto-selected if not specified) * `timeout_seconds` (`int`, optional): Auto-kill timeout in seconds (default: no timeout) * `internet_access` (`bool`, optional): Enable internet access (default: `True`) * `env_vars` (`Dict[str, str]`, optional): Environment variables to set in the sandbox * `api_key` (`str`, optional): API key (or use `HOPX_API_KEY` env var) * `base_url` (`str`, optional): API base URL (default: production) **Returns:** `Sandbox` - New sandbox instance **Raises:** * `ValidationError`: Invalid parameters * `ResourceLimitError`: Insufficient resources * `APIError`: API request failed **Example:** ```python theme={null} # Create from template name sandbox = Sandbox.create(template="code-interpreter") print(sandbox.get_info().public_host) # Create with timeout and environment variables sandbox = Sandbox.create( template="code-interpreter", timeout_seconds=300, env_vars={"DEBUG": "true", "API_KEY": "secret"} ) ``` **Expected Output:** ``` https://sandbox_abc123xyz.hopx.dev ``` **See Also:** * [API: Create Sandbox](/api/control-plane/create-sandbox) *** ### `connect` Connect to an existing sandbox by ID. ```python theme={null} Sandbox.connect( sandbox_id, *, api_key=None, base_url='https://api.hopx.dev' ) -> Sandbox ``` **Parameters:** * `sandbox_id` (`str`): Existing sandbox ID * `api_key` (`str`, optional): API key (or use `HOPX_API_KEY` env var) * `base_url` (`str`, optional): API base URL **Returns:** `Sandbox` - Connected sandbox instance **Raises:** * `NotFoundError`: Sandbox not found * `APIError`: API request failed **Example:** ```python theme={null} sandbox = Sandbox.connect("sandbox-abc123") info = sandbox.get_info() print(f"Status: {info.status}") ``` **Expected Output:** ``` Status: running ``` **See Also:** * [API: Get Sandbox](/api/control-plane/get-sandbox) *** ### `list` List all sandboxes (loads all into memory). ```python theme={null} Sandbox.list( *, status=None, region=None, limit=100, api_key=None, base_url='https://api.hopx.dev' ) -> List[Sandbox] ``` **Parameters:** * `status` (`str`, optional): Filter by status (`"running"`, `"stopped"`, `"paused"`, `"creating"`) * `region` (`str`, optional): Filter by region * `limit` (`int`, optional): Maximum number of sandboxes to return (default: `100`) * `api_key` (`str`, optional): API key * `base_url` (`str`, optional): API base URL **Returns:** `List[Sandbox]` - List of sandbox instances **Example:** ```python theme={null} # List all running sandboxes running = Sandbox.list(status="running") for sb in running: print(f"{sb.sandbox_id}: {sb.get_info().status}") # List sandboxes in specific region sandboxes = Sandbox.list(region="us-east", limit=50) ``` **Expected Output:** ``` sandbox_abc123xyz: running sandbox_def456uvw: running sandbox_ghi789rst: paused ``` **See Also:** * [API: List Sandboxes](/api/control-plane/list-sandboxes) *** ### `iter` Lazy iterator for sandboxes (memory-efficient). ```python theme={null} Sandbox.iter( *, status=None, region=None, api_key=None, base_url='https://api.hopx.dev' ) -> Iterator[Sandbox] ``` **Parameters:** * `status` (`str`, optional): Filter by status * `region` (`str`, optional): Filter by region * `api_key` (`str`, optional): API key * `base_url` (`str`, optional): API base URL **Returns:** `Iterator[Sandbox]` - Iterator of sandbox instances **Example:** ```python theme={null} # Iterate over all sandboxes (memory-efficient) for sandbox in Sandbox.iter(status="running"): info = sandbox.get_info() print(f"{info.sandbox_id}: {info.status}") ``` **Expected Output:** ``` sandbox_abc123xyz: running sandbox_def456uvw: running ``` **See Also:** * [API: List Sandboxes](/api/control-plane/list-sandboxes) *** ### `list_templates` List available templates. ```python theme={null} Sandbox.list_templates( *, category=None, language=None, api_key=None, base_url='https://api.hopx.dev' ) -> List[Template] ``` **Parameters:** * `category` (`str`, optional): Filter by category * `language` (`str`, optional): Filter by language * `api_key` (`str`, optional): API key * `base_url` (`str`, optional): API base URL **Returns:** `List[Template]` - List of template objects **Example:** ```python theme={null} # List all Python templates python_templates = Sandbox.list_templates(language="python") for template in python_templates: print(f"{template.name}: {template.description}") ``` **Expected Output:** ``` code-interpreter: Python environment with data science libraries python-basic: Minimal Python 3.11 environment ``` **See Also:** * [API: List Templates](/api/control-plane/list-templates) *** ### `get_template` Get template details by name. ```python theme={null} Sandbox.get_template( name, *, api_key=None, base_url='https://api.hopx.dev' ) -> Template ``` **Parameters:** * `name` (`str`): Template name * `api_key` (`str`, optional): API key * `base_url` (`str`, optional): API base URL **Returns:** `Template` - Template object with details **Raises:** * `NotFoundError`: Template not found **Example:** ```python theme={null} template = Sandbox.get_template("code-interpreter") print(f"Resources: {template.resources.vcpu} vCPU, {template.resources.memory_mb}MB RAM") ``` **Expected Output:** ``` Resources: 2 vCPU, 4096MB RAM ``` **See Also:** * [API: Get Template](/api/control-plane/get-template) *** ### `health_check` Check API health status (does not require authentication). ```python theme={null} Sandbox.health_check( *, base_url='https://api.hopx.dev' ) -> Dict[str, Any] ``` **Parameters:** * `base_url` (`str`, optional): API base URL **Returns:** `Dict[str, Any]` - Health status information **Example:** ```python theme={null} health = Sandbox.health_check() print(f"API Status: {health.get('status')}") ``` **Expected Output:** ``` API Status: healthy ``` *** ## Instance Methods ### Lifecycle Methods #### `get_info` Get current sandbox information. ```python theme={null} sandbox.get_info() -> SandboxInfo ``` **Returns:** `SandboxInfo` - Sandbox information object **Example:** ```python theme={null} info = sandbox.get_info() print(f"ID: {info.sandbox_id}") print(f"Status: {info.status}") print(f"Host: {info.public_host}") ``` **Expected Output:** ``` ID: sandbox_abc123xyz Status: running Host: https://sandbox_abc123xyz.hopx.dev ``` **See Also:** * [API: Get Sandbox](/api/control-plane/get-sandbox) *** #### `start` Start a stopped sandbox. ```python theme={null} sandbox.start() -> None ``` **Raises:** * `APIError`: Failed to start sandbox **Example:** ```python theme={null} sandbox.start() print("Sandbox started") ``` **Expected Output:** ``` Sandbox started ``` **See Also:** * [API: Start Sandbox](/api/control-plane/start-sandbox) *** #### `stop` Stop the sandbox. ```python theme={null} sandbox.stop() -> None ``` **Example:** ```python theme={null} sandbox.stop() print("Sandbox stopped") ``` **Expected Output:** ``` Sandbox stopped ``` **See Also:** * [API: Stop Sandbox](/api/control-plane/stop-sandbox) *** #### `pause` Pause the sandbox. ```python theme={null} sandbox.pause() -> None ``` **Example:** ```python theme={null} sandbox.pause() print("Sandbox paused") ``` **Expected Output:** ``` Sandbox paused ``` **See Also:** * [API: Pause Sandbox](/api/control-plane/pause-sandbox) *** #### `resume` Resume a paused sandbox. ```python theme={null} sandbox.resume() -> None ``` **Example:** ```python theme={null} sandbox.resume() print("Sandbox resumed") ``` **Expected Output:** ``` Sandbox resumed ``` **See Also:** * [API: Resume Sandbox](/api/control-plane/resume-sandbox) *** #### `kill` Destroy the sandbox immediately. ```python theme={null} sandbox.kill() -> None ``` This action is irreversible. The sandbox and all its data will be permanently deleted. **Example:** ```python theme={null} sandbox.kill() print("Sandbox destroyed") ``` **Expected Output:** ``` Sandbox destroyed ``` **See Also:** * [API: Delete Sandbox](/api/control-plane/delete-sandbox) *** ### Execution Methods #### `run_code` Execute code with rich output capture. ```python theme={null} sandbox.run_code( code, *, language='python', timeout=60, env=None, working_dir='/workspace' ) -> ExecutionResult ``` **Parameters:** * `code` (`str`): Code to execute * `language` (`str`, optional): Language (`"python"`, `"javascript"`, `"bash"`, `"go"`) (default: `"python"`) * `timeout` (`int`, optional): Execution timeout in seconds (default: `60`) * `env` (`Dict[str, str]`, optional): Environment variables for execution * `working_dir` (`str`, optional): Working directory (default: `"/workspace"`) **Returns:** `ExecutionResult` - Execution result with `stdout`, `stderr`, `exit_code`, and `rich_outputs` **Example:** ```python theme={null} result = sandbox.run_code("print('Hello, HopX!')") print(result.stdout) # "Hello, HopX!\n" print(result.exit_code) # 0 ``` **Expected Output:** ``` Hello, HopX! 0 ``` **See Also:** * [API: Execute Code](/api/vm-agent/execute) *** #### `run_code_background` Execute code in background and return immediately. ```python theme={null} sandbox.run_code_background( code, *, language='python', timeout=300, env=None, working_dir='/workspace', name=None ) -> Dict[str, Any] ``` **Parameters:** * `code` (`str`): Code to execute * `language` (`str`, optional): Language (default: `"python"`) * `timeout` (`int`, optional): Max execution time in seconds (default: `300`) * `env` (`Dict[str, str]`, optional): Environment variables * `working_dir` (`str`, optional): Working directory * `name` (`str`, optional): Process name for identification **Returns:** `Dict[str, Any]` - Dict with `process_id`, `execution_id`, and `status` **Example:** ```python theme={null} proc = sandbox.run_code_background( "import time; time.sleep(300); print('Done')", name="long-task" ) print(f"Process ID: {proc['process_id']}") # Check status later processes = sandbox.list_processes() ``` **Expected Output:** ``` Process ID: proc-abc123xyz ``` **See Also:** * [API: Execute Code (Background)](/api/vm-agent/execute-background) *** #### `list_processes` List all background execution processes. ```python theme={null} sandbox.list_processes() -> List[Dict[str, Any]] ``` **Returns:** `List[Dict[str, Any]]` - List of process dictionaries **Example:** ```python theme={null} processes = sandbox.list_processes() for proc in processes: print(f"{proc['process_id']}: {proc['status']}") ``` **Expected Output:** ``` proc_abc123: running proc_def456: completed ``` **See Also:** * [API: List Processes](/api/vm-agent/list-processes) *** #### `kill_process` Kill a background execution process. ```python theme={null} sandbox.kill_process(process_id) -> Dict[str, Any] ``` **Parameters:** * `process_id` (`str`): Process ID from `run_code_background()` or `list_processes()` **Returns:** `Dict[str, Any]` - Confirmation message **Example:** ```python theme={null} sandbox.kill_process("proc-abc123") ``` **Expected Output:** ``` Process killed successfully ``` **See Also:** * [API: Kill Process](/api/vm-agent/kill-process) *** ### Information Methods #### `get_agent_metrics` Get real-time agent metrics. ```python theme={null} sandbox.get_agent_metrics() -> Dict[str, Any] ``` **Returns:** `Dict[str, Any]` - Metrics dictionary with `total_executions`, `active_executions`, `error_count`, etc. **Example:** ```python theme={null} metrics = sandbox.get_agent_metrics() print(f"Total executions: {metrics['total_executions']}") print(f"Active: {metrics['active_executions']}") ``` **Expected Output:** ``` Total executions: 42 Active: 2 ``` **See Also:** * [API: Get System Metrics](/api/vm-agent/get-system-metrics) *** #### `get_agent_info` Get VM agent information (version, OS, architecture, endpoints, features). ```python theme={null} sandbox.get_agent_info() -> Dict[str, Any] ``` **Returns:** `Dict[str, Any]` - Agent information dictionary Requires Agent v3.1.0+. Uses GET /info endpoint. **Example:** ```python theme={null} info = sandbox.get_agent_info() print(f"Agent version: {info['version']}") print(f"OS: {info['os']}") ``` **Expected Output:** ``` Agent version: 3.1.0 OS: linux ``` *** #### `get_preview_url` Get preview URL for accessing a service running on a specific port. ```python theme={null} sandbox.get_preview_url(port=7777) -> str ``` **Parameters:** * `port` (`int`, optional): Port number (default: `7777`) **Returns:** `str` - Preview URL HopX automatically exposes all ports. Use this to get the public URL for any port. **Example:** ```python theme={null} # Start a web server sandbox.run_code("python -m http.server 8000", background=True) # Get preview URL url = sandbox.get_preview_url(port=8000) print(f"Access at: {url}") ``` **Expected Output:** ``` Access at: https://8000-sandbox_abc123xyz.hopx.dev ``` *** #### `get_metrics_snapshot` Get current system metrics snapshot. ```python theme={null} sandbox.get_metrics_snapshot() -> Dict[str, Any] ``` **Returns:** `Dict[str, Any]` - System metrics dictionary **Example:** ```python theme={null} metrics = sandbox.get_metrics_snapshot() print(f"CPU: {metrics.get('cpu_percent')}%") print(f"Memory: {metrics.get('memory_percent')}%") ``` **Expected Output:** ``` CPU: 15.3% Memory: 42.1% ``` *** ### Utility Methods #### `set_timeout` Extend sandbox timeout. ```python theme={null} sandbox.set_timeout(seconds) -> None ``` **Parameters:** * `seconds` (`int`): New timeout in seconds **Example:** ```python theme={null} sandbox.set_timeout(3600) # Extend to 1 hour ``` **See Also:** * [API: Set Sandbox Timeout](/api/control-plane/set-timeout) *** #### `refresh_token` Refresh JWT token for agent authentication. ```python theme={null} sandbox.refresh_token() -> None ``` **Example:** ```python theme={null} sandbox.refresh_token() ``` **Expected Output:** ``` Token refreshed successfully ``` *** #### `get_token` Get current JWT token. ```python theme={null} sandbox.get_token() -> str ``` **Returns:** `str` - JWT token string **Example:** ```python theme={null} token = sandbox.get_token() print(f"Token: {token[:20]}...") ``` **Expected Output:** ``` Token: eyJhbGciOiJIUzI1NiIs... ``` *** ## Properties ### `files` File operations resource (lazy-loaded). **Type:** `Files` **Example:** ```python theme={null} # Read a file content = sandbox.files.read("/workspace/script.py") # Write a file sandbox.files.write("/workspace/data.txt", "Hello, World!") ``` **Expected Output:** ``` File written successfully ``` See [Files Resource](/sdk/python/files) for complete documentation. *** ### `commands` Command execution resource (lazy-loaded). **Type:** `Commands` **Example:** ```python theme={null} result = sandbox.commands.run("ls -la /workspace") print(result.stdout) ``` **Expected Output:** ``` total 8 drwxr-xr-x 2 root root 4096 Jan 27 10:30 . drwxr-xr-x 3 root root 4096 Jan 27 10:30 .. -rw-r--r-- 1 root root 42 Jan 27 10:30 data.txt ``` See [Commands Resource](/sdk/python/commands) for complete documentation. *** ### `env` Environment variables resource (lazy-loaded). **Type:** `EnvironmentVariables` **Example:** ```python theme={null} # Set environment variable sandbox.env.set("API_KEY", "secret123") # Get all environment variables all_vars = sandbox.env.get_all() ``` **Expected Output:** ``` Environment variable set successfully ``` See [Environment Variables Resource](/sdk/python/environment-variables) for complete documentation. *** ### `desktop` Desktop automation resource (lazy-loaded). **Type:** `Desktop` **Example:** ```python theme={null} # Take a screenshot screenshot = sandbox.desktop.screenshot() # Click at position sandbox.desktop.click(100, 200) ``` **Expected Output:** ``` Screenshot captured (PNG bytes) Click executed at (100, 200) ``` See [Desktop Resource](/sdk/python/desktop) for complete documentation. *** ### `cache` Cache management resource (lazy-loaded). **Type:** `Cache` **Example:** ```python theme={null} # Get cache statistics stats = sandbox.cache.stats() print(f"Cache size: {stats['cache']['size']}") # Clear cache sandbox.cache.clear() ``` **Expected Output:** ``` Cache size: 5 Cache cleared successfully ``` See [Cache Resource](/sdk/python/cache) for complete documentation. *** ### `terminal` Interactive terminal resource via WebSocket (lazy-loaded). **Type:** `Terminal` Requires `websockets` library: `pip install websockets` **Example:** ```python theme={null} import asyncio async def use_terminal(): ws = await sandbox.terminal.connect() await sandbox.terminal.send_input(ws, "echo 'Hello'\n") # ... handle output await ws.close() asyncio.run(use_terminal()) ``` **Expected Output:** ``` Terminal connected Hello Terminal closed ``` See [Terminal Resource](/sdk/python/terminal) for complete documentation. *** ### `agent_url` Get the sandbox agent URL (port 7777) - convenience property. **Type:** `str` (read-only) **Example:** ```python theme={null} url = sandbox.agent_url print(f"Agent URL: {url}") ``` **Expected Output:** ``` Agent URL: https://sandbox_abc123xyz.hopx.dev ``` *** ## Context Manager The `Sandbox` class supports context manager protocol for automatic cleanup. **Example:** ```python theme={null} # Automatically calls kill() when exiting context with Sandbox.create(template="code-interpreter") as sandbox: result = sandbox.run_code("print('Hello')") print(result.stdout) # Sandbox is automatically destroyed here ``` **Expected Output:** ``` Hello ``` *** ## Examples ### Example 1: Basic Usage ```python theme={null} from hopx_ai import Sandbox # Create sandbox sandbox = Sandbox.create(template="code-interpreter") # Execute code result = sandbox.run_code("print('Hello, HopX!')") print(result.stdout) # Cleanup sandbox.kill() ``` **Expected Output:** ``` Hello, HopX! ``` ### Example 2: Using Context Manager ```python theme={null} from hopx_ai import Sandbox with Sandbox.create(template="code-interpreter") as sandbox: # Work with sandbox result = sandbox.run_code("import sys; print(sys.version)") print(result.stdout) # Automatically cleaned up ``` **Expected Output:** ``` 3.11.5 (main, Jan 27 2025, 10:30:00) [GCC 11.2.0] ``` ### Example 3: File Operations ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Write a file sandbox.files.write("/workspace/script.py", "print('Hello')") # Execute it result = sandbox.run_code("exec(open('/workspace/script.py').read())") print(result.stdout) sandbox.kill() ``` **Expected Output:** ``` Hello ``` ### Example 4: Background Execution ```python theme={null} from hopx_ai import Sandbox import time sandbox = Sandbox.create(template="code-interpreter") # Start long-running task proc = sandbox.run_code_background( "import time; time.sleep(60); print('Done')", name="long-task" ) # Do other work time.sleep(5) # Check status processes = sandbox.list_processes() for p in processes: if p['process_id'] == proc['process_id']: print(f"Status: {p['status']}") sandbox.kill() ``` **Expected Output:** ``` Status: running ``` *** ## Related Classes * **[AsyncSandbox](/sdk/python/async-sandbox)** - Async version of Sandbox for async/await workflows * **[Files](/sdk/python/files)** - File operations resource * **[Commands](/sdk/python/commands)** - Command execution resource * **[Environment Variables](/sdk/python/environment-variables)** - Environment variable management * **[Desktop](/sdk/python/desktop)** - Desktop automation resource * **[Cache](/sdk/python/cache)** - Cache management resource * **[Terminal](/sdk/python/terminal)** - Interactive terminal resource ## See Also * [Quickstart Guide](/sdk/python/quickstart) - Get started with the SDK * [Installation](/sdk/python/installation) - Install and configure the SDK * [Core Concepts](/core-concepts/sandboxes/creating) - Learn about sandboxes ## Next Steps * Learn about [AsyncSandbox](/sdk/python/async-sandbox) for async/await workflows * Explore [Creating Sandboxes](/core-concepts/sandboxes/creating) with different templates * Review [Code Execution](/core-concepts/code-execution/synchronous) to run code in sandboxes * Check out [File Operations](/sdk/python/files) for managing files * See [API Reference](/api/control-plane/create-sandbox) for direct API access * **[CLI Reference](/cli/introduction)** - Use HopX from the command line * [API Reference](/api/introduction) - Raw REST API documentation # Template Builder Source: https://docs.hopx.ai/sdk/python/template-builder Fluent API for building custom sandbox templates in the HopX Python SDK. Create custom templates from Docker images, configure resources, add build steps, and install dependencies using a fluent builder pattern. Complete reference for TemplateBuilder class with code examples and template configuration options. **Version:** 0.3.0\ **Last Verified:** 2025-01-27\ **Package:** `hopx-ai` on [PyPI](https://pypi.org/project/hopx-ai/) ## Overview The `Template` class provides a fluent API for building custom sandbox templates. Use this to create reusable templates with specific configurations, dependencies, and ready checks. Templates are built from base images and can include file copies, command execution, environment variables, port exposure, and ready checks. ## Import ```python theme={null} from hopx_ai.template import Template ``` ## Base Image Methods ### `from_ubuntu_image` Start from Ubuntu base image. ```python theme={null} Template.from_ubuntu_image(version) -> Template ``` **Parameters:** * `version` (`str`): Ubuntu version (e.g., `"22.04"`) **Returns:** `Template` - Template instance (fluent API) **Expected Output:** ``` Template instance ready for configuration ``` *** ### `from_python_image` Start from Python base image. ```python theme={null} Template.from_python_image(version) -> Template ``` **Parameters:** * `version` (`str`): Python version (e.g., `"3.11"`) **Expected Output:** ``` Template instance ready for configuration ``` *** ### `from_node_image` Start from Node.js base image. ```python theme={null} Template.from_node_image(version) -> Template ``` **Parameters:** * `version` (`str`): Node.js version (e.g., `"20"`) **Expected Output:** ``` Template instance ready for configuration ``` *** ### `from_image` Start from any Docker image. ```python theme={null} Template.from_image(image, auth=None) -> Template ``` **Parameters:** * `image` (`str`): Docker image name * `auth` (`Dict`, optional): Authentication credentials **Expected Output:** ``` Template instance ready for configuration ``` *** ## Configuration Methods ### `copy` Copy files to the template. ```python theme={null} Template.copy(src, dest, options=None) -> Template ``` **Parameters:** * `src` (`str`): Source path * `dest` (`str`): Destination path * `options` (`Dict`, optional): Copy options **Expected Output:** ``` Template instance (fluent API) ``` *** ### `run` Run command in template. ```python theme={null} Template.run(command) -> Template ``` **Parameters:** * `command` (`str`): Command to execute **Expected Output:** ``` Template instance (fluent API) ``` **Example:** ```python theme={null} Template.from_python_image("3.11").run("pip install requests") ``` *** ### `env` Set environment variable. ```python theme={null} Template.env(key, value) -> Template ``` **Parameters:** * `key` (`str`): Environment variable name * `value` (`str`): Environment variable value **Expected Output:** ``` Template instance (fluent API) ``` *** ### `expose` Expose port. ```python theme={null} Template.expose(port) -> Template ``` **Parameters:** * `port` (`int`): Port number to expose **Expected Output:** ``` Template instance (fluent API) ``` *** ### `workdir` Set working directory. ```python theme={null} Template.workdir(path) -> Template ``` **Parameters:** * `path` (`str`): Working directory path **Expected Output:** ``` Template instance (fluent API) ``` *** ### `ready_check` Set ready check. ```python theme={null} Template.ready_check(check) -> Template ``` **Parameters:** * `check` (ReadyCheck): Ready check object **Expected Output:** ``` Template instance (fluent API) ``` See [Ready Checks](/sdk/python/ready-checks) for available ready checks. *** ### `start_cmd` Set start command. ```python theme={null} Template.start_cmd(command) -> Template ``` **Parameters:** * `command` (`str`): Start command **Expected Output:** ``` Template instance (fluent API) ``` *** ## Building ### `build` Build the template. ```python theme={null} await Template.build(options=None) -> BuildResult ``` **Parameters:** * `options` (`Dict`, optional): Build options **Returns:** `BuildResult` - Build result with template ID and status **Example:** ```python theme={null} import asyncio async def build_template(): template = ( Template .from_python_image("3.11") .run("pip install flask") .expose(5000) .start_cmd("python app.py") ) result = await template.build() print(f"Template ID: {result.template_id}") asyncio.run(build_template()) ``` **Expected Output:** ``` Template ID: template_abc123xyz ``` *** ## Examples ### Example 1: Simple Python Template ```python theme={null} from hopx_ai.template import Template import asyncio async def main(): template = ( Template .from_python_image("3.11") .run("pip install requests pandas") .env("PYTHONUNBUFFERED", "1") ) result = await template.build() print(f"Built template: {result.template_id}") asyncio.run(main()) ``` **Expected Output:** ``` Built template: template_abc123xyz ``` ### Example 2: Web Server Template ```python theme={null} from hopx_ai.template import Template, wait_for_port import asyncio async def main(): template = ( Template .from_node_image("20") .run("npm install express") .copy("./app.js", "/app/app.js") .expose(3000) .start_cmd("node /app/app.js") .ready_check(wait_for_port(3000)) ) result = await template.build() print(f"Web server template: {result.template_id}") asyncio.run(main()) ``` **Expected Output:** ``` Web server template: template_abc123xyz ``` *** ## Related Classes * **[Ready Checks](/sdk/python/ready-checks)** - Ready check utilities * **[Sandbox](/sdk/python/sandbox)** - Use templates with `Sandbox.create(template=...)` ## See Also * [Ready Checks](/sdk/python/ready-checks) - Learn about ready checks * [Core Concepts: Templates](/core-concepts/templates) - Learn about templates ## Next Steps Now that you understand template building, explore: * [Ready Checks](/sdk/python/ready-checks) - Add readiness verification * [Building Templates](/core-concepts/templates/building) - Learn template building concepts * [Template Configuration](/core-concepts/templates/configuration) - Configure templates * **[CLI Reference](/cli/introduction)** - Use HopX from the command line * [Custom Templates](/cookbooks/advanced/custom-templates) - Build custom templates # Terminal Access Source: https://docs.hopx.ai/sdk/python/terminal Interactive terminal resource for WebSocket-based sandbox terminal access in HopX using the Python SDK. Complete reference for the Terminal class including methods for connecting to interactive terminals, executing commands in real-time, and streaming terminal output. Includes code examples for terminal automation. **Version:** 0.3.0\ **Last Verified:** 2025-01-27\ **Package:** `hopx-ai` on [PyPI](https://pypi.org/project/hopx-ai/) ## Overview The `Terminal` resource provides interactive terminal access via WebSocket. Use this resource when you need interactive shell access, real-time terminal output, or terminal resizing capabilities. Requires `websockets` library: `pip install websockets` ## Access ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") terminal = sandbox.terminal # Lazy-loaded ``` ## Methods ### `connect` Connect to interactive terminal. ```python theme={null} async terminal.connect(*, timeout=30) -> WebSocketClientProtocol ``` **Parameters:** * `timeout` (`int`, optional): Connection timeout in seconds (default: `30`) **Returns:** `WebSocketClientProtocol` - WebSocket connection object **Example:** ```python theme={null} import asyncio async def use_terminal(): ws = await sandbox.terminal.connect() # Use terminal... await ws.close() asyncio.run(use_terminal()) ``` *** ### `send_input` Send input to terminal. ```python theme={null} async terminal.send_input(ws, data) -> None ``` **Parameters:** * `ws` (`WebSocketClientProtocol`): WebSocket connection * `data` (`str` or `bytes`): Input data to send **Example:** ```python theme={null} await sandbox.terminal.send_input(ws, "echo 'Hello'\n") ``` *** ### `resize` Resize terminal window. ```python theme={null} async terminal.resize(ws, cols, rows) -> None ``` **Parameters:** * `ws` (`WebSocketClientProtocol`): WebSocket connection * `cols` (`int`): Number of columns * `rows` (`int`): Number of rows **Example:** ```python theme={null} await sandbox.terminal.resize(ws, 80, 24) ``` *** ### `iter_output` Iterate over terminal output messages. ```python theme={null} async terminal.iter_output(ws) -> AsyncIterator[Dict[str, Any]] ``` **Parameters:** * `ws` (`WebSocketClientProtocol`): WebSocket connection **Returns:** `AsyncIterator[Dict[str, Any]]` - Iterator of message dictionaries **Example:** ```python theme={null} async for message in sandbox.terminal.iter_output(ws): if message.get('type') == 'stdout': print(message.get('data', ''), end='') ``` *** ## Examples ### Example 1: Basic Terminal Usage ```python theme={null} import asyncio from hopx_ai import Sandbox async def main(): sandbox = Sandbox.create(template="code-interpreter") # Connect to terminal ws = await sandbox.terminal.connect() # Send command await sandbox.terminal.send_input(ws, "echo 'Hello, Terminal!'\n") # Read output async for message in sandbox.terminal.iter_output(ws): if message.get('type') == 'stdout': print(message.get('data', ''), end='') break # Exit after first output await ws.close() sandbox.kill() asyncio.run(main()) ``` ### Example 2: Interactive Terminal Session ```python theme={null} import asyncio from hopx_ai import Sandbox async def main(): sandbox = Sandbox.create(template="code-interpreter") ws = await sandbox.terminal.connect() # Resize terminal await sandbox.terminal.resize(ws, 120, 40) # Send multiple commands commands = [ "pwd\n", "ls -la\n", "echo 'Done'\n" ] for cmd in commands: await sandbox.terminal.send_input(ws, cmd) # Read output async for message in sandbox.terminal.iter_output(ws): if message.get('type') == 'stdout': print(message.get('data', ''), end='') elif message.get('type') == 'done': break await ws.close() sandbox.kill() asyncio.run(main()) ``` *** ## Related Classes * **[Sandbox](/sdk/python/sandbox)** - Main sandbox class * **[Core Concepts: Terminal](/core-concepts/terminal)** - Learn about terminal access ## See Also * [Sandbox Class](/sdk/python/sandbox) - Access terminal via `sandbox.terminal` * [Terminal Documentation](/core-concepts/terminal) - Detailed terminal documentation ## Related * **[WebSocket Terminal](/core-concepts/terminal/websocket)** - Learn about terminal access * **[Running Commands](/core-concepts/commands/running)** - Execute shell commands synchronously * **[Sandbox Class](/sdk/python/sandbox)** - Access terminal via `sandbox.terminal` ## Next Steps * Learn about [WebSocket Terminal](/core-concepts/terminal/websocket) for interactive terminal access * Explore [Running Commands](/core-concepts/commands/running) for synchronous command execution * Review [Background Commands](/core-concepts/commands/background) for non-blocking execution * **[CLI Terminal](/cli/commands/terminal)** - Access terminal from CLI # Supported Languages Source: https://docs.hopx.ai/supported-languages Programming languages supported by HopX sandboxes and their specific features. Learn about Python, JavaScript, Bash, Go, and other languages available in HopX sandbox environments. HopX sandboxes support multiple programming languages for code execution. Each language has specific features, pre-installed packages, and capabilities. ## Overview HopX currently supports the following languages: * **Python** - Full-featured Python environment with data science libraries * **JavaScript/Node.js** - Modern JavaScript runtime with npm support * **Bash** - Shell scripting and command execution * **Go** - Go programming language runtime Language support depends on the template you use. The `code-interpreter` template includes Python, JavaScript, and Bash. Other templates may support different language combinations. ## Python Python is the most feature-rich language in HopX sandboxes, with extensive pre-installed packages for data science, web development, and automation. ### Version * **Python 3.11+** (varies by template) ### Pre-installed Packages Common packages available in most Python templates: * **Data Science**: `pandas`, `numpy`, `matplotlib`, `scipy`, `scikit-learn` * **Web**: `requests`, `httpx`, `flask`, `fastapi` * **Utilities**: `beautifulsoup4`, `ipykernel`, `jupyter-client` * **System**: `git`, `curl`, `wget`, `vim`, `nano` ### Features * ✅ **Rich Output Capture**: Automatically captures matplotlib plots, pandas DataFrames, and other visualizations * ✅ **IPython Kernel**: Interactive Python execution with Jupyter kernel support * ✅ **Package Installation**: Install additional packages with `pip` * ✅ **File Operations**: Full filesystem access for reading/writing files * ✅ **Environment Variables**: Access via `os.getenv()` or `os.environ` ### Example ```python theme={null} from hopx_ai import Sandbox from hopx_ai.exceptions import APIError, ResourceLimitError try: sandbox = Sandbox.create(template="code-interpreter") # Execute Python code result = sandbox.run_code(""" import pandas as pd import matplotlib.pyplot as plt data = {'x': [1, 2, 3, 4], 'y': [1, 4, 9, 16]} df = pd.DataFrame(data) print(df.describe()) plt.plot(df['x'], df['y']) plt.savefig('/tmp/plot.png') """, language="python") print(result.stdout) # Rich outputs (plots, DataFrames) are automatically captured sandbox.kill() except APIError as e: print(f"API error: {e}") except ResourceLimitError as e: print(f"Resource limit exceeded: {e}") except Exception as e: print(f"Unexpected error: {e}") ``` **Expected Output:** ``` x y count 4.000000 4.000000 mean 2.500000 7.500000 std 1.290994 6.454972 min 1.000000 1.000000 25% 1.750000 3.250000 50% 2.500000 6.500000 75% 3.250000 11.750000 max 4.000000 16.000000 ``` Rich outputs (plots, DataFrames) are automatically captured in `result.rich_outputs`. ## JavaScript/Node.js JavaScript execution runs in a Node.js environment with access to npm packages and modern JavaScript features. ### Version * **Node.js 18+** (varies by template) ### Pre-installed Packages * **Runtime**: Node.js with npm * **Kernel**: iJavaScript kernel for interactive execution * **System Tools**: Standard Unix utilities ### Features * ✅ **npm Support**: Install packages with `npm install` * ✅ **ES Modules**: Support for modern ES6+ syntax * ✅ **Rich Output**: Can generate HTML, JSON, and text outputs * ✅ **Async/Await**: Full support for asynchronous operations * ✅ **File System**: Access to Node.js `fs` module ### Example ```javascript theme={null} import { Sandbox } from '@hopx-ai/sdk'; import { APIError, ResourceLimitError } from '@hopx-ai/sdk'; try { const sandbox = await Sandbox.create({ template: 'code-interpreter' }); // Execute JavaScript code const result = await sandbox.runCode(` const fs = require('fs'); const data = { message: 'Hello from Node.js!', timestamp: Date.now() }; console.log(JSON.stringify(data, null, 2)); // Write to file fs.writeFileSync('/tmp/output.json', JSON.stringify(data)); `, { language: 'javascript' }); console.log(result.stdout); await sandbox.kill(); } catch (error) { if (error instanceof APIError) { console.error(`API error: ${error.message}`); } else if (error instanceof ResourceLimitError) { console.error(`Resource limit exceeded: ${error.message}`); } else { console.error(`Unexpected error: ${error.message}`); } } ``` **Expected Output:** ```json theme={null} { "message": "Hello from Node.js!", "timestamp": 1706284800000 } ``` ### JavaScript-Specific Features The JavaScript SDK includes some unique features: * **IPython Kernel Support**: `sandbox.runIpython()` method for interactive JavaScript execution * **TypeScript Types**: Full TypeScript support with type definitions * **Async Generators**: WebSocket streaming uses async generators (`for await...of`) ## Bash Bash provides shell scripting capabilities for system administration, automation, and command execution. ### Features * ✅ **Shell Commands**: Execute any shell command or script * ✅ **Pipelines**: Support for command pipelines and redirection * ✅ **Environment Variables**: Access via `$VARIABLE_NAME` syntax * ✅ **File Operations**: Standard Unix file operations (cp, mv, rm, etc.) * ✅ **Process Management**: Background processes, job control ### Example ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Execute bash commands result = sandbox.run_code(""" #!/bin/bash echo "Current directory: $(pwd)" echo "User: $(whoami)" echo "Date: $(date)" # List files ls -la /workspace # Process data echo "1,2,3,4,5" | tr ',' '\\n' | awk '{sum+=$1} END {print "Sum:", sum}' """, language="bash") print(result.stdout) ``` **Expected Output:** ``` Current directory: /workspace User: root Date: Mon Jan 27 10:30:00 UTC 2025 total 8 drwxr-xr-x 2 root root 4096 Jan 27 10:30 . drwxr-xr-x 3 root root 4096 Jan 27 10:30 .. -rw-r--r-- 1 root root 42 Jan 27 10:30 data.txt Sum: 15 ``` ### Common Use Cases * Installing system packages with `apt-get` or `yum` * Running build scripts and automation tasks * Processing text files with `grep`, `sed`, `awk` * Managing files and directories * Running system diagnostics ## Go Go (Golang) support enables compilation and execution of Go programs in sandboxes. ### Version * **Go 1.21+** (varies by template) ### Features * ✅ **Compilation**: Compile Go programs with `go build` * ✅ **Standard Library**: Full access to Go standard library * ✅ **Modules**: Support for Go modules and dependency management * ✅ **Concurrency**: Full support for goroutines and channels * ✅ **Cross-compilation**: Can compile for different platforms ### Example ```python theme={null} from hopx_ai import Sandbox sandbox = Sandbox.create(template="code-interpreter") # Execute Go code result = sandbox.run_code(""" package main import ( "fmt" "time" ) func main() { fmt.Println("Hello from Go!") fmt.Printf("Current time: %s\\n", time.Now().Format(time.RFC3339)) // Simple goroutine example go func() { time.Sleep(1 * time.Second) fmt.Println("Goroutine completed!") }() time.Sleep(2 * time.Second) } """, language="go") print(result.stdout) ``` **Expected Output:** ``` Hello from Go! Current time: 2025-01-27T10:30:00Z # Actual timestamp will vary Goroutine completed! ``` The timestamp in the output will be the actual execution time, not a fixed value. The format follows RFC3339 (e.g., `2025-01-27T10:30:00Z`). ## Language-Specific Considerations ### Execution Timeouts Default timeouts vary by language and execution mode: * **Synchronous execution**: 30-60 seconds (configurable) * **Background execution**: Up to 300 seconds (5 minutes) * **Async execution**: Up to 3600 seconds (1 hour) with webhooks ### Memory and Resources * Each sandbox has allocated CPU, memory, and disk resources * Resource limits are defined by the template * Monitor resource usage to avoid hitting limits ### Package Installation ```python theme={null} # Install packages during execution sandbox.run_code(""" import subprocess subprocess.run(['pip', 'install', 'package-name'], check=True) """, language="python") ``` Or use commands: ```python theme={null} sandbox.commands.run("pip install package-name") ``` ```javascript theme={null} // Install packages during execution await sandbox.runCode(` const { execSync } = require('child_process'); execSync('npm install package-name', { stdio: 'inherit' }); `, { language: 'javascript' }); ``` Or use commands: ```javascript theme={null} await sandbox.commands.run('npm install package-name'); ``` ```python theme={null} sandbox.run_code(""" apt-get update && apt-get install -y package-name """, language="bash") ``` ### Environment Variables All languages can access environment variables set in the sandbox: ```python theme={null} import os value = os.getenv('MY_VAR', 'default') ``` ```javascript theme={null} const value = process.env.MY_VAR || 'default'; ``` ```bash theme={null} value=${MY_VAR:-default} ``` ```go theme={null} import "os" value := os.Getenv("MY_VAR") if value == "" { value = "default" } ``` ## Choosing the Right Language Use **Python** for data analysis, machine learning, and visualization. Pre-installed packages like pandas, numpy, and matplotlib make it ideal for data work. Use **JavaScript** for Node.js applications, API development, and web scraping. Full npm support enables rapid development. Use **Bash** for system administration, file processing, and automation scripts. Perfect for DevOps tasks. Use **Go** for concurrent programs, network services, and performance-critical applications. Excellent for building APIs and microservices. ## Language Support by Template Different templates support different languages. Check template details to see which languages are available: ```python theme={null} from hopx_ai import Sandbox # List available templates templates = Sandbox.list_templates() for template in templates: print(f"{template.name}: {template.language or 'Multiple'}") ``` **Expected Output:** ``` code-interpreter: Multiple python-basic: Python node-basic: JavaScript ubuntu-base: Multiple ``` The actual templates and their languages may vary. Use `Sandbox.list_templates()` to see available templates in your account. ## Related * **[Code Execution](/core-concepts/code-execution/synchronous)** - Execute code in different languages * **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Create sandboxes with language support * **[Listing Templates](/core-concepts/templates/listing)** - Find templates with language support * **[Quickstart Guide](/quickstart)** - Get started with code execution ## Next Steps * Follow the [Quickstart Guide](/quickstart) to execute your first code * Learn about [Code Execution](/core-concepts/code-execution/synchronous) features * Explore [Rich Output Capture](/core-concepts/code-execution/rich-output) for data visualization