Upgrading
Upgrade Hubzoid from 0.9.x to 1.0.1 and apply later releases safely, with what changes, the steps, database migrations and the way back.
Hub files need no changes between releases. What changes is the software around them: Hubzoid's own tables, the workflow engine and the chat app. Each upgrades itself at the first start of the new version, so an upgrade is a short maintenance window with a backup taken just before that start.
When to use this
Follow the general procedure for every release. Read the 0.9.x to 1.0.1 section once if your deployment runs a 0.9 release, because 1.0.1 changes security defaults and moves schedules onto the workflow engine. The full list of changes is in the changelog.
The general procedure
- Drain runs
- Stop
- Install
- Back up
- Check
- Start
- Verify
Drain scheduled work
Runs belong to the code that started them. After an upgrade, runs that were queued or interrupted under the old version are cancelled at the next start so they cannot block the queue, and show as CANCELLED. Queued markdown tasks that had not started are queued again under the new code. To avoid losing work, wait until hubzoid schedule status <hub> shows no run PENDING or ENQUEUED, ideally between slots.
Stop everything
Stop the hub, or the gateway and every bridge. Upgrade the whole deployment together. Running an old and a new version side by side against the same databases is not supported.
Install the new version
In the same environment, either bump the pin in your hubs' requirements.txt and reinstall, or upgrade directly:
pip install -U hubzoid # or: pip install -U "hubzoid[postgres]"Back up
hubzoid backup ./my-hub --out pre-upgrade.tar.gzA backup never creates or upgrades a table, so this archive is the deployment exactly as the old version left it. For PostgreSQL, also run pg_dump for each database. See backup and restore.
Check
hubzoid doctor ./my-hubFix every fail. Before the first start, db.operational and db.hub report info or warn because their schemas have not been upgraded yet.
Start
Start as before. At the first start, Hubzoid, the workflow engine and the chat app each upgrade their own tables.
Verify
Sign in as an ordinary user and chat with each agent, download a file an agent makes, open the Console (Agents, each agent's Runs and schedules tab, Activity), and run hubzoid doctor again. If a cancelled scheduled run is still needed, start it with hubzoid schedule run <hub> <name>.
How database upgrades work
Hubzoid versions its own tables with Alembic in two stores, each with its own version table so they never collide with each other, with the chat app's migrations or with the workflow engine's:
| Store | Version table | Holds |
|---|---|---|
| Operational | hz_alembic_operational | Access, identities, audit, workflow catalog and state, usage, tool decisions |
| Hub | hz_alembic_hub | WhatsApp and Telegram conversation history |
Each bridge upgrades both stores before it serves anything. Bridges that start together take a lock first (a PostgreSQL advisory lock, or a file lock next to a SQLite database), so only one runs a migration at a time. Deployments from before versioning are handled by a baseline revision that creates any missing table and verifies the columns of existing ones. A table that does not match is refused rather than silently stamped.
A database already upgraded by a newer Hubzoid is refused, and the bridge stops with a message naming the store. hubzoid doctor reports this as a fail on db.operational or db.hub. The fix is to install that newer version or restore a backup. This is also why going back to an older release always means restoring the backup taken before the upgrade.
From 0.9.x to 1.0.1
1.0.1 changes security defaults, moves markdown schedules onto the workflow engine and versions Hubzoid's tables. Hub files (AGENTS.md, skills, schedule/*.md, workflows/) need no changes.
| Change | What you do |
|---|---|
The public bridge key dev is refused for downloads, and hubzoid doctor fails when BRIDGE_API_KEYS is unset. | Before restarting, set BRIDGE_API_KEYS to a long random value in each hub's .env (openssl rand -hex 32). The gateway hands each hub's key to the chat app at start. A hub with OWUI_NATIVE_MCP=true also needs the new key entered in the chat app's admin settings, under Connections. |
| Download links for files the agent made are signed. Links from earlier versions stop working. | Nothing. The files are still there, so ask the agent for the link again. HUBZOID_ARTIFACT_LINK_TTL adds an optional expiry. |
| Administrators can no longer open or export other people's chats in the chat app. | To allow it, set ENABLE_ADMIN_CHAT_ACCESS=true and ENABLE_ADMIN_EXPORT=true. |
The chat app keeps its own branding unless the hub has files in branding/. | Nothing, unless you relied on the Hubzoid logo there. |
| OpenAI Agents SDK traces are no longer sent to OpenAI. | To keep them, set HUBZOID_OPENAI_TRACING=true. |
Markdown tasks run on the hub's workflow engine. Each hub gets .hubzoid/dbos.db, and runs appear in the Console. | Nothing. Timing, catch-up and commit behaviour are unchanged. Let running tasks finish before you stop the hub. |
| On Python 3.12 the workflow engine needs SQLite 3.42 or newer. | Check deps.sqlite in hubzoid doctor. The Docker image moves to Debian 13 for this reason. |
| Hubzoid's tables are versioned and upgraded at the first start. A database written by a newer Hubzoid is refused. | Take the backup in the procedure above. Going back to 0.9.x means restoring it. |
Tool decisions are stored in the database instead of logs/access-*.jsonl. | Nothing. The old files are imported once and left in place. |
| Usage is recorded per chat turn and workflow model call, with no message content. The Console opens on Agents, with usage totals above the agent cards. | Nothing. Counting starts at the upgrade. |
In code workflows, hub.call_llm is one model call without tools. Earlier it ran the full agent. | Use hub.call_agent where a workflow needs tools. |
Agent calls in code workflows are not retried unless agent_max_attempts is set. Runs left over from older workflow code are cancelled at start. | Drain queued runs before upgrading. |
The public port rejects . and .. path segments and drops client-sent X-Hubzoid-* and X-OpenWebUI-* headers. | Nothing, unless a client relied on sending those. |
Then follow the general procedure: set the bridge keys, stop, pip install -U hubzoid, back up, check, start and verify. At the first start Hubzoid upgrades its tables and imports the old decision logs.
Upgrading a container
Back up, stop the container, build or pull the new image, and start again. With the Compose files, which build hubzoid:local from the checkout by default:
docker compose -f docker/docker-compose.yml exec hubzoid hubzoid backup /hub --out /hub/pre-upgrade.tar.gz
docker compose -f docker/docker-compose.yml down
git checkout v1.0.1
HUB_PATH=$PWD/my-hub docker compose -f docker/docker-compose.yml up -d --buildTo run a published image instead, set HUBZOID_IMAGE=ghcr.io/hubzoid/hubzoid:1.0.1.
The container upgrades its tables at its first start, the same as a native install. See Docker.
Upgrading a gateway
One hubzoid backup of any hub in a gateway covers the gateway's data directory and every hub. Stop the gateway and every bridge before installing, including bridges run as their own services with --no-bridges, and start the gateway before external bridges so they find its manifest.
Moving hubs from chat app groups to managed grants is a separate maintenance window with its own preview, cutover and rollback. Schedule it after the upgrade is verified. See access administration.
Going back
Stop everything. Restore with the new version still installed, because releases before 1.0.1 have no restore command, then reinstall the previous version and start:
hubzoid restore pre-upgrade.tar.gz
pip install "hubzoid==<previous version>"Whatever the restore replaces is kept beside it as <name>.pre-restore-<time>. For PostgreSQL, restore each dump with pg_restore before restoring the archive.
Next steps
Backup and restore
Back up a hub or a whole gateway to one archive while chat keeps working, restore it in place or on a new machine, and include PostgreSQL.
Observability
Watch a Hubzoid deployment through usage and cost in the Console, tool decisions with hubzoid audit, OpenTelemetry traces, logs and health checks.
