Hermes v0.21.2: Multi-Profile Isolation Hardening, and No More One Backend Per Profile

You run three profiles of the same bot on one machine: one watches a support channel, one posts a daily digest, one patrols in the background. On Monday you add a fourth, and it simply never appears in the desktop Bots list — the gateway status next to it says stopped, so you restart the whole gateway and interrupt the two instances that were actually working. The question that bothers you more is the other one: do these profiles, sharing one machine, quietly see each other’s credentials, memory and session history?
v0.21.2 answers both. There is no headline feature in this one — the two goals are plain: make every profile on a machine keep its own things, and stop the desktop from opening a backend for each profile.
One gateway process, three sets of bots
First, what a profile actually is: a largely independent Hermes install with its own config, its own credentials, its own memory and session history. So that several profiles on one machine do not each need their own gateway, Hermes ships a multiplexer — a single gateway process hosting the bots of several profiles at once. Sharing that process is exactly the point, and exactly the risk: anything resolved “globally” inside it can leak from one profile into another.
The everyday shape of such an install is one primary profile plus a few secondary ones, sharing a process and part of the runtime state. If you want your machine organised that way, the multi-instance profile guide covers what should be shared and what must stay separate.
v0.21.2 (tag v2026.9.11, released September 11, 2026, officially nicknamed “The state.db Patch Release”) is the patch release that follows v0.21.1, and it is not small: since v0.21.1 it carries 947 non-merge commits, 1,869 changed files (+182,504 / -15,564), 312 merged pull requests from 140 contributors. The full section-by-section list lives on the v0.21.2 release page; below are the parts that have nothing to do with state.db but change how your install behaves day to day.
Seven leak paths, closed in one batch
The thing to fear in a multi-profile install is not a crash but a quiet bleed — one profile’s permissions, secrets or files being used by another, with every screen looking normal. Seven pull requests in this release are aimed at exactly that:
| PR | What crossed the line | Behaviour now |
|---|---|---|
| #107616 | A secondary profile’s bots inherited the default profile’s allow-list; the permission list was resolved across profiles | each profile resolves its own allow-list |
| #107617 | Adapters could send credentials to the default profile’s host | credentials travel with the profile that owns them |
| #107630 | stdio MCP servers were handed the default profile’s vault secrets | stdio MCP servers get only the current profile’s secrets |
| #107609 | MEDIA: delivery could carry another profile’s .env, auth.json or state.db |
delivery is scoped to the profile that started it |
| #107620 / #107626 | Feishu drive callbacks, and webhook replies on a profile-scoped path, could land on another profile | callbacks and replies stay on the routed profile |
| #107611 | A secondary profile could pick up a sibling profile’s Nous bearer token out of in-process memory | tokens are no longer reused across profiles |
#107616 deserves its own sentence. The allow-list is what defines a bot’s permission boundary, and it used to be resolved against the default profile: whatever you had opened up on the primary profile, a secondary profile inherited. For two bots doing unrelated work, that handed the primary profile’s permissions to the other one. The background on this one is in the profile allow-list write-up.
Reading the table as a whole gives you a useful test: anything “process-level shared” — in-process memory, the vault, adapter hosts, delivery channels — has been the weak surface of multi-profile setups. This batch does not patch those one by one; it pins the resolution points back to the profile boundary.
The desktop stops opening a backend per profile
The second block is the desktop’s Bot Mode startup behaviour, and the symptom was very visible. Previously, at startup and on every roster tick, the desktop spawned or dialled a backend for every profile; hovering the mouse over the Bots list spawned a backend for every row; switching profiles could spawn duplicate primary backends. However many profiles you had, that is how many multiples of backend processes you got, and the extras competed for the same gateway.
This release touches both the startup path and the roster rendering path: #108069, #108107, #108118, #108134, #107969, #108112. The practical result is that the scenario above stops happening — adding a profile no longer means restarting the gateway in the middle of the night, and the Bots list no longer grows suspicious “ghost” entries.
The “that makes no sense” fixes
Beyond those two blocks, this release cleans up a set of small behaviours that had been quietly annoying for a long time. None of them is dramatic alone; together they are a wall you walk into every day.
Cron. An off-the-hour “run now” no longer cancels the next scheduled run (#106306); a manual run you killed no longer blocks the following five-minute slot (#106733); a task switched from one-off to recurring keeps firing (#106532); a task without a pinned model runs on the model snapshotted when it was created (#106499); and hermes profile create --clone-all no longer copies cron jobs along (#106478). That last one matters most for multi-profile users, because cloning a profile is usually about reusing configuration — not about running the same scheduled job a second time on the second profile.
Kanban. kanban promote now rejects an unfinished parent task (#106550), and kanban_request_review rejects an unknown reviewer profile (#106547). Both turn “silently accept a bad input” into “refuse it clearly”.
Tools and memory. When a stdio MCP server dies mid-call, the tool call is no longer replayed (#106546) — a replay means a write that may already have executed happens a second time, which makes this a valuable fix. A skills-only background review can no longer delete memory entries (#106310); mem0 memory no longer drops long turns (#106542); tool_search returns nothing rather than five unrelated tools that share one word (#106676); remote NOPASSWD sudo no longer triggers an approval prompt (#107939); and RSS and Reddit reading is no longer on by default (#105873).
Updates and quota. The update check now polls the GitHub API once a day instead of doing a git fetch every 30 minutes (#107648); hermes update states the real reason for a failure and no longer hangs on a stalled fetch (#108053).
Providers and routing. /model and auxiliary auto-routing will not bill a provider you did not select (#107366); Hermes never auto-switches to a provider you have no credentials for (#107281); Bedrock Guardrails take effect (#107815).
Cache. Switching between the desktop and the TUI no longer rebuilds the system prompt, so it no longer breaks the prompt cache (#105844) — a real saving for anyone who hops between the two all day.
What you should do
Upgrading is one command:
hermes update
A few things are worth confirming afterwards:
- If you configured a permission allow-list on a multi-profile machine, each profile now resolves its own (#107616) — check that the secondary profiles’ lists are what you actually want.
- If you relied on
hermes profile create --clone-allto bring cron jobs across, you now need to recreate them by hand (#106478). - If you want to keep using RSS or Reddit as content sources, enable them explicitly; they are off by default now (#105873).
- If a scheduled task has no pinned model, it now runs the model snapshotted at creation time (#106499).
- The update check runs once a day now (#107648) — do not read that as it getting slower; it just stopped fetching every half hour.
One more line on the state.db work, which is not the subject here: v0.21.0 rewrote the session store’s connection handling, which left state.db fragile on some installs, and v0.21.2 closed that class of problem. We covered that separately — details in state.db lock and writer contention.
The takeaway
v0.21.2 is a textbook hardening patch: no feature to show off, with 947 non-merge commits and 312 merged pull requests mostly spent pulling boundaries back in. If you run a single profile, the most visible change is probably that the desktop stops sitting on a pile of ghost backends. If you run several profiles on one machine, the release matters a great deal more: from the permission allow-list, vault secrets and credential hosts down to in-process tokens, seven cross-profile leak paths are closed at once.
Multiple profiles stop being a setup that “works, but you are never quite sure”: each profile keeps its own things, and the desktop opens only the backends it needs. That is what this release actually fixes.