Skip to main content
Version: v2.0

How to Upgrade

This guide walks you through upgrading your self-hosted Agenta instance and applying any necessary database schema migrations. Choose the section that matches your deployment method.

Understanding Agenta Versioning​

Agenta follows semantic versioning with new releases every week. Stay updated by:

Upgrading an open source instance to the multi-organization release

The multi-organization release flips OSS from invite-only to open signup. If your instance is reachable beyond a trusted network, set AGENTA_ACCESS_ALLOWED_OWNER_EMAILS (and optionally AGENTA_ACCESS_ALLOWED_DOMAINS) before upgrading. See Migrate to Multi-Organization OSS.

Upgrading to 0.121.0​

This release removes a set of environment variables and a Helm key, makes the mobile app (/m) part of every deployment, and changes three API behaviors. Read each subsection that matches your deployment. The standard upgrade process below still applies.

Removed environment variables​

The variables below no longer exist. Agenta ignores them, and the behavior in the right column is always on. If your env file, Helm values or Railway variables set one of them, delete it. The change affects you only if you had set one to false; at its default each one already behaved as described.

VariableBehavior that is now always on
AGENTA_MOBILE_GATEA phone that opens a desktop route is redirected to /m. A user with Developer Mode off (in Settings > Preferences) is also sent to /m for the pages that exist there.
AGENTA_MOBILE_REVERSE_GATEA desktop browser may open /m. It is not sent back to /w.
AGENTA_MOBILE_ENABLEDThe web-mobile service runs on every deployment. See The mobile app always ships.
AGENTA_SESSIONS_QUEUEAgent messages go through the durable session queue. A message sent while a turn runs is queued instead of refused.
AGENTA_SESSIONS_STEERA message sent while a turn runs can be delivered into that turn.
AGENTA_SESSIONS_DURABLE_APPROVALSApproval requests are stored in the database. Answering one through the API needs an Idempotency-Key header (see API behavior changes).
AGENTA_SESSIONS_DURABLE_STOPStop is stored as a durable command and delivered to the runner.
AGENTA_RECORDS_DURABLEThe runner retries a failed session record write.
AGENTA_RECORDS_SMART_TRUNCATIONA session record that is too large is truncated with its structure kept, instead of losing its body.
AGENTA_SESSIONS_RECONSTRUCTThe runner rebuilds the conversation history of a turn from the stored session records.
NEXT_PUBLIC_SESSIONS_LAST_MESSAGE_ONLYThe web app sends only the newest message of each turn. The runner rebuilds the rest (see the previous row).
NEXT_PUBLIC_AGENT_CHAT_SLICEThe streaming agent chat page is used.
NEXT_PUBLIC_AGENT_TEMPLATE_BUILDERChoosing an agent template opens the playground with the template loaded.
NEXT_PUBLIC_AGENT_PLAYGROUND_ONBOARDINGAgent onboarding runs inside the playground.
NEXT_PUBLIC_AGENT_FILE_UPLOADSFile attachments in the agent chat and uploads in the file drive are shown. They need the durable object store.
NEXT_PUBLIC_AGENT_CONNECT_STEPCreating an agent from the start page first asks the user to connect the accounts the agent needs.
AGENTA_WORKFLOWS_ORDERED_OPERATIONS_ENABLEDWorkflow commits accept ordered operations. A commit that leaves the configuration unchanged creates no new revision.

The runner rebuilds history from the records that the records loop of worker-streams stores. If you run worker-streams with an explicit AGENTA_WORKER_STREAMS list, make sure one instance includes records, or agents lose the earlier turns of a conversation.

The mobile app always ships​

The mobile web app is served at /m and has no off switch. The web app redirects phones to it, so /m must be reachable on every deployment.

Docker Compose​

The web-mobile service starts with the stack. run.sh --no-mobile is removed, and run.sh stops with Unknown parameter if a script still passes it. Do not scale web-mobile to zero: phones would be redirected to a route with nothing behind it.

If you run your own reverse proxy instead of the bundled Traefik or nginx, route /m and every path under /m/ to the web-mobile service on port 3000, before the catch-all route to web.

Helm​

The webMobile.enabled key is removed, and the web-mobile Deployment always renders. webMobile.enabled: false in a values file now fails schema validation, so helm upgrade stops. webMobile.enabled: true is accepted and does nothing. Delete the key from your values file before you upgrade.

Railway​

bootstrap.sh now always creates the web-mobile service, and AGENTA_RAILWAY_WITH_MOBILE is ignored. An environment bootstrapped without mobile has no web-mobile service, and configure.sh stops with Service 'web-mobile' is missing. Both deploy-from-images.sh and upgrade.sh run configure.sh, so both stop.

Re-run the bootstrap script first, against the same project and environment as the deployment. It is idempotent and only adds what is missing. The project and environment default to the staging environment of agenta-oss-railway, and the new service gets AGENTA_WEB_MOBILE_IMAGE (default latest), so set all three:

export RAILWAY_PROJECT_NAME="agenta-oss"
export RAILWAY_ENVIRONMENT_NAME="production"
export AGENTA_WEB_MOBILE_IMAGE="ghcr.io/agenta-ai/agenta-web-mobile:v0.121.0"

./hosting/railway/oss/scripts/bootstrap.sh

Then deploy with deploy-from-images.sh, with every image at the same tag. It redeploys web-mobile only when AGENTA_WEB_MOBILE_IMAGE is set. upgrade.sh builds from source and does not deploy web-mobile at all.

export AGENTA_API_IMAGE="ghcr.io/agenta-ai/agenta-api:v0.121.0"
export AGENTA_WEB_IMAGE="ghcr.io/agenta-ai/agenta-web:v0.121.0"
export AGENTA_SERVICES_IMAGE="ghcr.io/agenta-ai/agenta-services:v0.121.0"
export AGENTA_RUNNER_IMAGE="ghcr.io/agenta-ai/agenta-runner:v0.121.0"

./hosting/railway/oss/scripts/deploy-from-images.sh

Channels​

Channels connect an agent to Slack or Telegram. They need no feature flag on the server. Six environment variables are optional and turn on the hosted integrations, where users connect without creating their own Slack app or Telegram bot:

VariableHosted integration
SLACK_CLIENT_ID, SLACK_CLIENT_SECRET, SLACK_SIGNING_SECRETThe hosted Slack app install. It stays off until all three are set.
TELEGRAM_HOSTED_BOT_TOKEN, TELEGRAM_HOSTED_BOT_USERNAME, TELEGRAM_HOSTED_WEBHOOK_SECRETThe shared Telegram bot. It stays off until all three are set. See Set up the hosted Telegram bot.

Without them, users can still connect their own Slack app or Telegram bot. The variables and where to set them are listed in Channels.

Channel replies are sent by the sessions loop of worker-streams. Run that loop in exactly one worker-streams replica. With two or more, a progress update can overwrite a final reply, and a Telegram reply can arrive twice. The Helm chart and the Compose files run one replica by default. On Helm, a rolling update briefly runs the old and the new pod together. To avoid that overlap, set workerStreams.strategy.type: Recreate; worker-streams then stops for a few seconds during each upgrade.

If you run the workers with explicit selectors, add the two new loops: sessions to one AGENTA_WORKER_STREAMS list and channels-inbox to one AGENTA_WORKER_QUEUES list. An empty selector already runs every loop.

On Enterprise Edition, the default roles include the new permissions view_channels, edit_channels and run_channels. If you replace the role catalog with AGENTA_ACCESS_ROLES, add them to your roles, or members without them get 403 on Channels.

API behavior changes​

  • An app-only reference to an archived app returns 410. An invoke that names an archived application by its id alone, with no variant or revision reference and no inline configuration, now fails with status 410 and a status.type ending in #v0:references:archived. Before, it ran. Unarchive the application, or point the caller at a live one. Invokes that name a variant or revision, or carry an inline configuration, still run on an archived application, as before; see #7110.
  • Answering an interaction needs an Idempotency-Key header. POST /api/sessions/interactions/{interaction_id}/respond returns 422 without the header and 202 with a continuation body on success. See Invoke an agent.
  • Posting to the Agenta channel needs the run_channels permission. On Enterprise Edition, an API key whose owner has the viewer or annotator role can no longer post to the Agenta channel of an agent.

Upgrading to 0.119.0​

This section applies if your projects use MCP servers, or if you plan to add one. Skip it otherwise, and follow the standard upgrade process below.

What changed​

Before 0.119.0, an agent's sandbox called an MCP server directly. Since 0.119.0, every MCP call an agent makes goes to the api container, which relays it to the server. The server's credential stays on your deployment instead of travelling into the sandbox. AGENTA_MCP_GATEWAY_ENABLED controls the relay and defaults to true.

Because the api container now makes the call, the relay's own outbound guard decides which MCP servers an agent can reach. That guard is a separate setting from the one that governs webhooks.

Add the new settings to your env file​

An upgrade reuses your existing .env file, which has none of the new lines, so your deployment runs on the code defaults. Those defaults refuse an MCP server that is on a private network or answers over plain HTTP. The env templates shipped with 0.119.0 set them permissively instead, so a fresh install and an upgraded install behave differently until you add the lines yourself.

If an MCP server in one of your projects is on http:// or on a private address, add this to your env file:

# Let the relay call MCP servers on plain HTTP and on private addresses.
# Code default: false. The 0.119.x env templates ship true.
AGENTA_GATEWAYS_INSECURE_EGRESS_ALLOWED=true

A second setting applies only if your own Agenta deployment is reached over plain HTTP at an address that is not loopback, such as an IP address or a LAN name. It governs the hop into Agenta, not the hop out to an MCP server, and without it a gateway-routed run fails with gateway_insecure_endpoint:

# Let gateway credentials travel when your own deployment is reached over plain HTTP
# at a non-loopback address. Code default: false. The 0.119.x env templates ship true.
AGENTA_GATEWAYS_INSECURE_HTTP_ALLOWED=true

On a deployment where people you do not trust can create MCP connections, leave AGENTA_GATEWAYS_INSECURE_EGRESS_ALLOWED at false and name the servers you want reachable with AGENTA_MCP_GATEWAY_HOST_ALLOWLIST instead. Both postures are set out in Use an MCP server on a private network or over plain HTTP.

Containers read the env file at start, so recreate them after editing it:

docker compose -f hosting/docker-compose/oss/docker-compose.gh.yml \
--env-file hosting/docker-compose/oss/.env.oss.gh \
--profile with-web --profile with-traefik up -d

For Helm, set gatewayEgress.insecureAllowed and gatewayEgress.insecureHttpAllowed in your values file. The chart ships both commented out, so an upgrade that touches no values file keeps the code defaults and both guards stay on. The chart renders each key you do set into the containers that read it. See Agenta gateways.

Two more things change for Helm in this release. The chart now implements all five gateway keys, so a key you added under api.extraEnv, services.extraEnv or agentRunner.extraEnv to work around their absence now duplicates the one the chart renders. Remove the extraEnv copy. And the schema now rejects an unknown key under mcpGateway, llmGateway, gatewayEgress or gatewayCredentials, where 0.119.0 accepted and ignored it, so helm upgrade fails on a typo it used to swallow. For the same reason a real key that used to do nothing now takes effect: if you set mcpGateway.enabled: false against 0.119.0 and saw no change, it now turns the MCP gateway off.

Saving an MCP server URL on 0.119.0​

This applies only while you are on 0.119.0. In that version, the check that runs when someone saves a custom MCP server URL reads AGENTA_INSECURE_EGRESS_ALLOWED, the setting that governs webhooks, rather than the gateway setting above. The two production templates, env.oss.gh.example and env.ee.gh.example, set it to false, so on such a deployment a plain-HTTP or literal-private-IP URL is refused with a 400:

endpoint.data.route.base_url is invalid: URL must use https.
endpoint.data.route.base_url is invalid: URL resolves to a blocked IP range.

From 0.119.1, that check follows AGENTA_GATEWAYS_INSECURE_EGRESS_ALLOWED, the same setting the relay uses at call time. Upgrade to 0.119.1 rather than setting AGENTA_INSECURE_EGRESS_ALLOWED=true: that variable has no effect on MCP saves from 0.119.1, and setting it widens what webhooks, workflow hooks, custom model provider endpoints and OIDC issuer probes may reach. If you set it to true on 0.119.0 for this reason alone, set it back after upgrading.

A server that is already saved keeps working. This check runs only when a URL is saved.

Before rolling back below 0.119.0​

Migration oss000000030 adds two labels, OAUTH_PROVIDER and OAUTH_GRANT, to the Postgres enum behind the kind column of the secrets table. A version before 0.119.0 does not know those labels, and listing a project's secrets reads every row, so one row of either kind makes the whole list fail with a server error. That takes down the playground's provider key list for the project, not just the MCP screens.

PostgreSQL cannot remove a value from an enum once it is added, and running the migration's own downgrade does not remove it either. A schema rollback alone does not fix this.

If any project completed an MCP OAuth connection while you were on 0.119.0 or later, delete those rows before rolling back:

DELETE FROM secrets WHERE kind IN ('OAUTH_PROVIDER','OAUTH_GRANT');

Through Docker Compose:

docker compose -f hosting/docker-compose/oss/docker-compose.gh.yml \
--env-file hosting/docker-compose/oss/.env.oss.gh exec -T postgres \
psql -U username -d agenta_oss_core \
-c "DELETE FROM secrets WHERE kind IN ('OAUTH_PROVIDER','OAUTH_GRANT');"

Those rows are the stored OAuth registrations and tokens for MCP connections. Deleting them ends those connections. Reconnect each affected MCP server after you upgrade again.

Standard Upgrade Process​

For most upgrades, follow these steps to update your Agenta instance:

1. Pull the Latest Images​

Download the newest version of all Agenta Docker images:

docker compose -f hosting/docker-compose/oss/docker-compose.gh.yml pull

2. Restart Services​

Restart all services with the updated images:

docker compose -f hosting/docker-compose/oss/docker-compose.gh.yml --env-file hosting/docker-compose/oss/.env.oss.gh --profile with-web --profile with-traefik up -d
info

This method will cause a brief downtime while services restart. For production environments, consider the zero-downtime upgrade approach below.

Zero-Downtime Upgrade​

For production environments where uptime is critical, use this approach to upgrade without service interruption.

Prerequisites​

Install docker rollout for rolling updates

Upgrade Steps​

1. Pull Latest Images

docker compose -f hosting/docker-compose/oss/docker-compose.gh.yml pull

2. Apply Database Migrations

Before updating services, apply any database schema changes:

docker exec -e PYTHONPATH=/app -w /app/oss/databases/postgres/migrations/core <api-container-name> alembic -c alembic.ini upgrade head

Replace <api-container-name> with your actual API container name (e.g., agenta-oss-gh-api-1).

3. Rolling Update Services

Update each service individually to maintain availability:

# Update core services one by one
docker rollout -f hosting/docker-compose/oss/docker-compose.gh.yml --env-file hosting/docker-compose/oss/.env.oss.gh api
docker rollout -f hosting/docker-compose/oss/docker-compose.gh.yml --env-file hosting/docker-compose/oss/.env.oss.gh services
docker rollout -f hosting/docker-compose/oss/docker-compose.gh.yml --env-file hosting/docker-compose/oss/.env.oss.gh web
# Background workers run as two consolidated kinds by default:
# worker-streams = records + events + spans
# worker-queues = webhooks + triggers + interactions + evaluations
docker rollout -f hosting/docker-compose/oss/docker-compose.gh.yml --env-file hosting/docker-compose/oss/.env.oss.gh worker-streams
docker rollout -f hosting/docker-compose/oss/docker-compose.gh.yml --env-file hosting/docker-compose/oss/.env.oss.gh worker-queues

Each command will:

  • Scale the service to double the current instances
  • Wait for new containers to be ready
  • Remove old containers once new ones are healthy

Helm Chart Upgrade​

One-time migration from pre-v0.100.3 to v0.100.3

v0.100.3 relocated the Helm chart (from hosting/helm/agenta-oss/ to hosting/kubernetes/helm/), reshaped the values.yaml keys, and renamed many env vars. If you are upgrading across that boundary, follow Migrate to v0.100.3 (Helm chart relocation + config reshape) once, then resume using this section for subsequent upgrades.

If you deployed Agenta on Kubernetes using the Helm chart, upgrade with:

helm upgrade agenta hosting/kubernetes/helm \
--namespace agenta \
-f hosting/kubernetes/oss/.values.oss.yaml

Database migrations run automatically as a post-upgrade hook. Check the migration job status:

kubectl -n agenta get jobs -l app.kubernetes.io/component=alembic
kubectl -n agenta logs job/agenta-alembic

To pin to a specific version, set the image tags in your values.yaml:

api:
image:
tag: "v0.86.8"
web:
image:
tag: "v0.86.8"
services:
image:
tag: "v0.86.8"

For full details, see the Deploy on Kubernetes guide.

Database Schema Migrations​

PostgreSQL major-version upgrade​

Agenta's Docker Compose and Helm deployments pin PostgreSQL to major version 17. If your existing Docker Compose deployment was created with an older major version, do not upgrade by only changing the image tag while reusing the same Postgres data volume.

PostgreSQL data directories are tied to the major version that created them. A newer major version container cannot start against an older major version data directory. Use a backup and restore flow instead.

Docker Compose​

These commands use the default OSS Compose files from the self-host quick start.

Check the current Postgres version:

docker compose -f hosting/docker-compose/oss/docker-compose.gh.yml --env-file hosting/docker-compose/oss/.env.oss.gh exec postgres \
psql -U username -d postgres -c "SHOW server_version;"

Create a logical backup and confirm the file is not empty:

docker compose -f hosting/docker-compose/oss/docker-compose.gh.yml --env-file hosting/docker-compose/oss/.env.oss.gh exec -T postgres \
pg_dumpall -U username > agenta-postgres-17-backup.sql
ls -lh agenta-postgres-17-backup.sql

Stop the stack:

docker compose -f hosting/docker-compose/oss/docker-compose.gh.yml --env-file hosting/docker-compose/oss/.env.oss.gh down

Find the existing Postgres volume, keep a copy, then remove the original so Compose can create a fresh volume for the new version:

docker volume ls | grep postgres

POSTGRES_VOLUME=<postgres-volume-name>
POSTGRES_VOLUME_BACKUP="${POSTGRES_VOLUME}-pg17-backup"

docker volume create "$POSTGRES_VOLUME_BACKUP"
docker run --rm \
-v "$POSTGRES_VOLUME":/from:ro \
-v "$POSTGRES_VOLUME_BACKUP":/to \
alpine:3 sh -c 'cd /from && cp -a . /to'

docker volume rm "$POSTGRES_VOLUME"

Do not remove the backup volume until the upgrade is verified. Start the new Postgres version and restore the dump:

docker compose -f hosting/docker-compose/oss/docker-compose.gh.yml --env-file hosting/docker-compose/oss/.env.oss.gh up -d postgres

cat agenta-postgres-17-backup.sql | docker compose -f hosting/docker-compose/oss/docker-compose.gh.yml --env-file hosting/docker-compose/oss/.env.oss.gh exec -T postgres \
psql -U username -d postgres

Verify the restore:

docker compose -f hosting/docker-compose/oss/docker-compose.gh.yml --env-file hosting/docker-compose/oss/.env.oss.gh exec postgres \
psql -U username -d postgres -c "SHOW server_version;"

docker compose -f hosting/docker-compose/oss/docker-compose.gh.yml --env-file hosting/docker-compose/oss/.env.oss.gh exec postgres \
psql -U username -d postgres -c "\l"

Start the full stack, then run Agenta migrations if your release requires them:

docker compose -f hosting/docker-compose/oss/docker-compose.gh.yml --env-file hosting/docker-compose/oss/.env.oss.gh --profile with-web --profile with-traefik up -d

docker ps | grep api
docker exec -e PYTHONPATH=/app -w /app/oss/databases/postgres/migrations/core <api-container-name> \
alembic -c alembic.ini upgrade head

Verify the stack:

docker compose -f hosting/docker-compose/oss/docker-compose.gh.yml --env-file hosting/docker-compose/oss/.env.oss.gh ps
docker compose -f hosting/docker-compose/oss/docker-compose.gh.yml --env-file hosting/docker-compose/oss/.env.oss.gh logs --tail=100 api

Open the Agenta web UI and confirm that existing projects, prompts, traces, and evaluations are present before deleting any backup files or backup volumes.

Kubernetes / Helm​

The Helm chart uses the Bitnami PostgreSQL subchart. These commands use the default release and namespace from the Kubernetes guide: agenta.

Check the current Postgres version:

kubectl -n agenta exec agenta-postgresql-0 -- \
psql -U agenta -d postgres -c "SHOW server_version;"

Create a logical backup and save the current Helm values:

kubectl -n agenta exec agenta-postgresql-0 -- \
pg_dumpall -U agenta > agenta-postgres-backup.sql

ls -lh agenta-postgres-backup.sql
helm -n agenta get values agenta -o yaml > agenta-values-before-pg18.yaml
kubectl -n agenta get pvc

Create a fresh PostgreSQL data volume for the new major version. The exact storage operation depends on your cluster: use your storage provider's snapshot/restore workflow, restore into a new release, or delete the old bundled PostgreSQL PVC only after you have verified the logical backup. For a disposable local cluster, that last option looks like this:

kubectl -n agenta scale deploy --all --replicas=0
kubectl -n agenta delete statefulset agenta-postgresql --ignore-not-found
kubectl -n agenta delete pvc data-agenta-postgresql-0

Upgrade the chart so bundled PostgreSQL starts with the major-18 image. If you installed with --set values instead of a file, pass the same required secrets and settings again.

helm upgrade agenta hosting/kubernetes/helm \
--namespace agenta \
-f hosting/kubernetes/oss/.values.oss.yaml

Wait for PostgreSQL, restore the dump, and verify the databases:

kubectl -n agenta rollout status statefulset/agenta-postgresql

cat agenta-postgres-backup.sql | kubectl -n agenta exec -i agenta-postgresql-0 -- \
psql -U agenta -d postgres

kubectl -n agenta exec agenta-postgresql-0 -- \
psql -U agenta -d postgres -c "SHOW server_version;"

kubectl -n agenta exec agenta-postgresql-0 -- \
psql -U agenta -d postgres -c "\l"

Run the Helm upgrade again to restart Agenta workloads and run the migration hook, then watch the rollout:

helm upgrade agenta hosting/kubernetes/helm \
--namespace agenta \
-f hosting/kubernetes/oss/.values.oss.yaml

kubectl -n agenta get jobs
kubectl -n agenta get pods -w

Open the Agenta web UI and confirm that existing data is present before deleting the backup file or any old storage snapshots.

If you use an external database, upgrade that database through your provider's supported PostgreSQL major-version process, then run the Agenta upgrade.

When Migrations Are Needed​

Check the release notes to see if a version requires database migrations. Not all updates require schema changes.

Manual Migration Process​

1. Find Your API Container Name

List running containers to identify your API container:

docker ps | grep api

2. Run the Migration Command

Apply all pending migrations:

docker exec -e PYTHONPATH=/app -w /app/oss/databases/postgres/migrations/core <api-container-name> alembic -c alembic.ini upgrade head

Command Breakdown:

  • docker exec: Runs commands inside an existing container
  • -e PYTHONPATH=/app: Sets the Python path for the application
  • -w /app/oss/databases/postgres/migrations/core: Sets the working directory to the migrations folder
  • <api-container-name>: Your actual API container name
  • alembic -c alembic.ini upgrade head: Runs all migrations to the latest version

Verifying Migrations​

After running migrations:

  1. Check Application Health: Access Agenta through your web browser
  2. Verify Data Integrity: Ensure your projects, prompts, and evaluations are intact
  3. Test Core Functions: Try creating a new prompt or running an evaluation
  4. Check Logs: Review container logs for any error messages

Migration Troubleshooting​

If you encounter issues after migration:

  1. Check Migration Status:

    docker exec <api-container-name> alembic -c alembic.ini current
  2. Review Migration History:

    docker exec <api-container-name> alembic -c alembic.ini history
  3. Rollback if Necessary:

    docker exec <api-container-name> alembic -c alembic.ini downgrade -1
  4. Report Issues: Create a GitHub issue with details about the problem

Automatic Migration Configuration​

warning

Use automatic migrations with caution in production environments. Always test migrations on staging environments first.

You can configure Agenta to run migrations automatically during container startup.

Enabling Automatic Migrations​

Add this environment variable to your .env.oss.gh file:

ALEMBIC_AUTO_MIGRATIONS=true

With this setting enabled:

  • Migrations run automatically when the API container starts
  • No manual migration commands are needed
  • Container startup may take longer while migrations run