- OpenHands Enterprise 0.64.0 or later
- Custom images built and pushed as described in Building a Custom Image
How It Works
Custom sandbox images are registered through the Runtime API — a management interface built into OpenHands Enterprise. The process has three steps:-
Set an admin password in the install admin UI. This secures the Runtime
API so only authorized administrators can register or remove images.
On Helm installs, use the
admin-passwordsecret created during installation. - 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.
- 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.- VM Install
- Helm
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:- Open the Admin Console at
https://admin.<your-base-domain>:30000. - Navigate to Config → Sandbox Configuration → Runtime API Admin Password.
- Enter your new password and click Save config, then Deploy.
Enable Overlay Mode (Helm Installs Only)
By default on Helm installs, saving any configuration via the API takes over warm pool management and the installer-managedv1_current default is
ignored. Enable overlay mode so API-saved configurations sit alongside
v1_current rather than replacing it. VM installs have overlay mode enabled
by default and can skip this section.
Merge these settings into the same values.yaml used for the
Kubernetes installation. Keep the
other values for your release:
python3 scripts/warm_runtime_configs.py list — v1_current should appear
with "source": "file".
Step 2: Install the Management CLI
We publish a small Python CLI — theruntime-api-configs plugin — that
wraps the runtime-api admin endpoints. It uses only the Python standard
library and runs from any host that can reach the runtime-api (or from
inside the pod on Helm installs). Install it once with OpenHands
extensions:
Prefer to run everything as raw HTTP calls? The API Reference
section at the bottom of this page documents the endpoints so you can drive
them directly from
curl or any HTTP client. All following steps show the
CLI form because it is shorter and handles the PBKDF2 handshake for you.- VM Install
- Helm
The runtime-api is exposed externally at
That is the full setup. No
https://runtime-api.<your-base-domain>. Export the two env vars the
CLI needs — the URL, and the admin password you confirmed in Step 1:kubectl, no SSH, no cluster access. The
CLI uses the admin password directly for save and delete (via the
PBKDF2 handshake), and for list and template it logs in as admin
and fetches the read-only API key over HTTPS from
/api/admin/api-keys.Prefer to pull the credentials straight from Kubernetes secrets in one
shot? That is the bootstrap subcommand — kept as an optional
convenience for cluster operators and CI, and documented in
Advanced: bootstrap from Kubernetes
at the bottom of this page.For
save and delete, the CLI runs a PBKDF2 challenge-response login
with ADMIN_PASSWORD to obtain a 24-hour JWT and calls the admin routes
as Authorization: Bearer <jwt>. For list and template, it uses that
same admin login to fetch the default read-only API key from
/api/admin/api-keys and sends it as X-API-Key on
/api/warm-runtime-configs. Export API_KEY explicitly if you would
rather skip the extra login round trip on reads. See the plugin’s
SKILL.md
for the full subcommand reference.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. The CLI’stemplate subcommand fetches an
existing configuration, strips the identity fields, and lets you override the
image and pool size in one step.
- VM Install
- Helm
The default Piping directly into
v1_current pool keeps running while you add configurations.
Derive your custom configuration from the template and save it:save works too: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.
Step 4: Verify
Confirm your configurations were saved:Pending replacement means the pool is not ready
for the next conversation.
If the image does not appear or conversations cold-start, see
Troubleshooting below.
Updating and Deleting Configurations
Update by re-deriving from the current default and saving under the same name:python3 scripts/warm_runtime_configs.py 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
Returning an Entry to Installer Management
Delete a same-named database override to restore the installer-managed entry on the next reconciler cycle:Troubleshooting
API Reference
The endpoints below are served by the runtime-api service. Admin authentication (required for save, delete, and — if you skip theX-API-Key header on reads — for GET /api/admin/api-keys):
GET /api/admin/challengereturns{challenge, salt, iterations}. Challenges are single-use and expire after 5 minutes.saltis returned as an ASCII hex string.- Compute
PBKDF2-HMAC-SHA256(password_utf8, (salt_hex + challenge).utf8, iterations, dklen=32)and hex-encode the result. Thesaltvalue returned above goes into PBKDF2 as its ASCII hex string, not decoded to raw bytes first — concatenatesaltandchallengeas strings, then UTF-8 encode. POST /api/admin/loginwith{"challenge": ..., "hash": ...}returns{"token": ...}, a JWT valid for 24 hours.- Send
Authorization: Bearer <token>on admin requests.
/api/warm-runtime-configs without any cluster access):
200 with [{"id": ..., "name": "default", "key_value": "...", ...}, ...].
Use the key_value of the name: "default" entry as your X-API-Key.
List configurations (regular API key, not admin):
200 with the effective configuration set:
source: "file" — installer-managed entry. source: "db" — API-managed
entry. The list is the full effective set: ConfigMap entries merged with
same-named API entries overriding them.
Create or update a configuration (admin):
200 with the saved configuration. Creates or overwrites; the name
in the URL is the identity.
Delete a configuration (admin):
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.
Advanced: bootstrap from Kubernetes
The CLI’sbootstrap subcommand pulls RUNTIME_API_URL, API_KEY, and
ADMIN_PASSWORD from Kubernetes secrets in one step. It is optional — the
HTTPS-only flow in Step 2 is preferred for interactive administration. Use
bootstrap when you have kubectl access anyway and want a single
one-liner for a CI job or an operator runbook.
- VM Install
- Helm
The Replicated embedded k0s cluster stores its kubeconfig at
/var/lib/k0s/pki/admin.conf, which is root-owned. Run under sudo -E
so the CLI’s kubectl calls can read it:bootstrap prints three export lines. After the eval, subsequent
commands run from any host with network access to the ingress — no
further cluster access needed.
