Skip to main content
Requirements:

How It Works

Custom sandbox images are registered through the Runtime API — a management interface built into OpenHands Enterprise. The process has three steps:
  1. Set an admin password in the install admin UI. This secures the Runtime API so only authorized administrators can register or remove images.
  2. Register images via the API. Use the helper script below to give each image a name and tell OpenHands where to pull it from. OpenHands pulls the image from the registry you specify and keeps a pool of ready sandboxes for it. No restarts or redeployments are needed — new images become available within about a minute.
  3. Users choose their environment. Each registered image appears in the user’s Settings → Application → Default Sandbox dropdown. Users pick their default and all their new conversations start in that environment.

Step 1: Confirm the Admin Password

The Runtime API admin endpoints require an admin password.
The password is auto-generated at install ({{repl RandomString 32}}) and stored in the admin-password Kubernetes secret. The helper script in Step 2 reads it from the pod environment automatically — no action required for a standard installation.To set a memorable password or rotate the generated one:
  1. Open the Admin Console at https://admin.<your-base-domain>:30000.
  2. Navigate to Config → Sandbox Configuration → Runtime API Admin Password.
  3. Enter your new password and click Save config, then Deploy.
The Admin Console updates the secret and rolls out the runtime-api automatically. The password persists across all future Admin Console deploys.
Do not use kubectl patch to set the password. The Admin Console manages the admin-password secret and overwrites it on every deploy, so a patched value is lost the next time you save any config change. Always use the Admin Console field.

Step 2: Save the Helper Script

The runtime-api is exposed externally at https://runtime-api.<your-base-domain>. All API calls go directly to that URL — no cluster shell or kubectl exec needed for day-to-day operations.Save the script below as warm-runtime-configs.sh. On first run it reads credentials from Kubernetes secrets; export them afterward and you can run the script entirely without cluster access.
After the first run, export the discovered values so subsequent runs need no cluster access at all:
Listing authenticates with the regular API key (X-API-Key). Saving and deleting use the admin password via a PBKDF2 challenge-response login that returns a 24-hour JWT. The script handles both flows automatically.

Step 3: Save Your First Configuration

Do not write configurations from scratch. The default configuration contains install-specific values (callback URLs, CA bundles, workspace paths) that sandboxes need to function. Fetch it from the API and use it as your template:
The default v1_current pool keeps running while you add configurations. Derive your custom configuration from the template, changing only the image and pool size, then save it:

Configuration Format

The configuration name comes from the URL path (the save <name> argument), not the body. A source field appears in list responses (file for installer-managed entries, db for API-managed entries) but must not be included in saved configurations. The application uses the image reference as the sandbox spec ID. Give every selectable configuration a distinct image reference; configurations that share an image reference cannot be selected independently.
Set count explicitly. Every warm pod reserves the full sandbox resource envelope (25 Gi of ephemeral storage by default) whether or not it is in use, so the sum of all pool sizes must fit your node capacity. Pools that exceed capacity show up as Pending pods. Start with count: 1 per image and grow the pools that see real traffic.

Step 4: Verify

Confirm your configurations were saved:
The response shows each saved configuration with its name, image, pool size, and source. Within about a minute the pool is ready. Open Settings → Application → Default Sandbox — your image name appears in the dropdown. Select it and start a conversation to confirm it loads in a few seconds rather than 20 or more. If the image does not appear or conversations cold-start, see Troubleshooting below.

Updating and Deleting Configurations

Update by saving the same name again:
Within a minute the reconciler stops the old pods and starts pods on the new image. Delete a configuration to remove its pool:
If the deleted name overrides an installer-managed entry, the underlying installer entry becomes effective again. Confirm with ./warm-runtime-configs.sh list — its source changes from db to file. Keep superseded image tags available in your registry while conversations that used them can still resume: a paused conversation resumes on its original image. Delete old tags only after the conversations that used them are gone (stopped sandboxes are cleaned up after 10 days by default).

After Upgrading OpenHands Enterprise

API-managed configurations are frozen snapshots — upgrades do not touch them. The installer-managed v1_current entry updates automatically unless a database entry with that name overrides it. Each release expects a specific agent-server version and may add or change sandbox environment variables. After every OHE upgrade:
  1. Rebuild your custom images on the release’s new agent-server base version.
  2. Re-export the default template (Step 3) from the refreshed ConfigMap.
  3. Re-derive and save each API-managed custom configuration from the new template.
  4. If you intentionally override v1_current, refresh or delete that override so the new installer-managed entry can take effect.
Skipping this leaves configurations pointing at the previous agent-server version, and new conversations fail with a version mismatch error until the configurations are updated.

Returning an Entry to Installer Management

Delete a same-named database override to restore the installer-managed entry on the next reconciler cycle:
Other API-managed configurations continue running. Delete them individually when you no longer want their pools or images in the application’s selector.

Troubleshooting


API Reference

The endpoints below are served by the runtime-api service. Admin authentication (required for save and delete):
  1. GET /api/admin/challenge returns {challenge, salt, iterations}. Challenges are single-use and expire after 5 minutes.
  2. Compute PBKDF2-HMAC-SHA256(password, salt + challenge, iterations, dklen=32) and hex-encode the result.
  3. POST /api/admin/login with {"challenge": ..., "hash": ...} returns {"token": ...}, a JWT valid for 24 hours.
  4. Send Authorization: Bearer <token> on admin requests.
List configurations (regular API key, not admin):
Returns 200 with the effective configuration set:
source: "file" — installer-managed entry. source: "db" — API-managed entry. On Replicated installs (overlay mode), the list is the full effective set: ConfigMap entries merged with same-named API entries overriding them. On Helm installs without overlay mode, only API-saved entries appear while the database contains any rows. Create or update a configuration (admin):
Returns 200 with the saved configuration. Creates or overwrites; the name in the URL is the identity. Delete a configuration (admin):
Returns 200 with a confirmation message, or 404 if no database configuration has that name. When the deleted name also exists in the installer-managed ConfigMap, that ConfigMap entry becomes effective again.