Upgrade
This page covers the upgrade and rollback procedures for a self-hosted XTM One instance. Filigran SaaS instances are upgraded by Filigran.
Procedure
- Read the release notes.
- Apply the update based on your deployment option:
Pre-built images (Option B):
Source-based (Option A):
Migrations run automatically on startup. Wait for /api/health/ready to return 200 before verifying.
Image tags follow the format <major>.<YYMMDD>.<patch> and are listed on Docker Hub.
Deprecated environment variables
Environment variables renamed by a release keep working under their old name for a while, so an upgrade does not silently change what your deployment does. While an old name is in use, XTM One logs a warning naming the replacement. Rename them in your compose files, Helm values and CI secrets before the removal date.
| Old name | New name | Read until | Notes |
|---|---|---|---|
OPENGRC_API_URL |
OPENCRQ_API_URL |
2026-12-31 | Renamed with the OpenGRC -> OpenCRQ product rename. When both are set, OPENCRQ_API_URL wins. See Network reachability. |
Version notes
Code interpreter sandbox workspace
From this release the code interpreter keeps a sandbox workspace per conversation and per assignment run. Nothing has to be done on upgrade: a migration adds two tables (sandbox_workspaces, sandbox_workspace_files), and a cell that worked before works unchanged.
- Storage. No volume to provision: workspace files live in the platform bucket under
sandbox-workspaces/, their manifest in PostgreSQL, so every backend replica and worker sees the same workspaces. Budget the bucket for the workspaces in use (2 GiB at most each by default, usually far less) and, with the local sandbox, the backend pods' temporary directory for the per-process cache (CODE_INTERPRETER_WORKSPACE_CACHE_MB, 2 GiB by default). See Storage sizing. - Clean-up. A sweep runs in the worker every hour (once for the whole install): it deletes the workspaces of archived or deleted conversations and deleted runs, the workspaces unused for
CODE_INTERPRETER_WORKSPACE_IDLE_TTL_HOURS(7 days by default), and objects left under a prefix no workspace owns. Archiving or deleting a conversation from the chat also deletes its workspace at once. - Kernels.
session=trueruns a long-lived kernel: a child process of the backend on the local sandbox, a container of its own on OpenSandbox (kept forCODE_INTERPRETER_KERNEL_IDLE_SECONDS, 15 minutes by default, and found again from any replica). - Packages. Installs stay off until you set
CODE_INTERPRETER_PACKAGE_ALLOWLIST(and, for a mirror,CODE_INTERPRETER_PACKAGE_INDEX_URL). - Graceful stops. During a deployment, a chat turn whose worker is stopping now ends at its next step once less than a minute (or half of
GRACEFUL_TIMEOUT) of the grace is left, its completed tool calls kept for "Continue where you left off". A turn that would have finished within the grace is not affected. - Turning it off.
CODE_INTERPRETER_WORKSPACE_ENABLED=falserestores the stateless code interpreter.
Platform registration token (Docker Compose)
This note applies when PLATFORM_REGISTRATION_TOKEN is not set in your .env, or is set to xtm-default-registration-token: Docker Compose then runs XTM One with that published default, which authenticates nobody. After upgrading such a deployment:
- The OpenCTI, OpenAEV and OpenCRQ platforms already registered keep their heartbeat, but the published default can no longer register a new platform, change the URL of a registered one, rename one or unregister one: a registered platform's URL is trusted to sign XTM One users in, and its name is what the agents bound to it read. Nor does its heartbeat change the intents and business vertical a platform declares (those of an upgraded platform are recorded once you set your own token), or replace a platform's license with anything but its renewal.
- The XTM One license certificate is no longer sent to the connected platforms, so a platform whose Enterprise Edition comes from your XTM One license (a sub-license) cannot prove it. The registration answer says why:
xtm_license_withheld_reason: registration_token_published_default.
To leave the published default:
- Generate a token:
python -c "import secrets; print(secrets.token_urlsafe(32))". - Set it as
PLATFORM_REGISTRATION_TOKENin the.envof XTM One, and set the same value as the registration token of every connected OpenCTI, OpenAEV and OpenCRQ platform. A platform still presenting the old value is refused. - Restart XTM One (
docker compose up -d) and the platforms. - Check the security audit (
Settings→Security, orGET /api/v1/security-audit): the platform registration token finding now readspass. Then review the registered platforms and purge any you do not recognise: earlier releases let anyone holding the published default register one, and changing the token does not end the trust a registration carries. The integration catalog in Settings lists the OpenCTI, OpenAEV and OpenCRQ registrations; the security audit names any registration under another identifier with its id, whichDELETE /api/v1/platform/registrations/{id}/purgeremoves.
Rollback
Warning
Migrations run automatically on startup and may alter the database schema. Once a migration has run, the previous application version may not work against the new schema. Rollback requires restoring the database and object storage from the same pre-upgrade recovery point.
docker compose down- Restore the database from the pre-upgrade backup.
- Restore Silo/S3 to the same recovery point.
- Revert image tags to the previous version.
docker compose up -d