NousResearch/hermes-agent v2026.9.11
NousResearch/hermes-agent
Captured source
source ↗Hermes Agent v0.21.2 (v2026.9.11)
Repository: NousResearch/hermes-agent
Tag: v2026.9.11
Published: 2026-09-11T19:20:31Z
Prerelease: no
Release notes:
Hermes Agent v0.21.2 (v2026.9.11) — The state.db Patch Release
Release Date: September 11, 2026
> Patch release. v0.21.0 shipped a large rewrite of the session store's connection handling, and for some installs it made state.db fragile: second writers cancelling each other's locks, healthy databases reported as corrupt, one bad row killing sessions list. This release closes that class and rolls up everything else that landed on main in the four days since v0.21.1.
About this release
Measured at commit 04dd80a977f40b05e5b2054111747af07a61886a, the window since v0.21.1 contains 947 non-merge commits across 1,869 changed files (+182,504 / −15,564) and 312 merged PRs. 140 contributors appear in commits, co-author trailers, or salvage credits.
✨ Highlights
state.db reliability campaign (six PRs, 44 issues closed)
If your state.db broke after 0.21.0, this is the release for you. Six PRs fix the root causes rather than the symptoms:
- No more second writers. Profile gateways wrote hosted-room state into the *root*
state.dbevery 5 seconds; the dashboard opened a writable handle on startup; cron's lifecycle guard did a rawopen()on a live database (which cancels the gateway's POSIX locks — the classic "how to corrupt SQLite" recipe);doctor --fixwould checkpoint under a live holder. All four are gone: hosted rooms live inshared-state.db, the dashboard opens read-only first, the guard goes through the tracked connection registry, anddoctor --fixrefuses a checkpoint it can't prove is safe. (#108076 — salvage #103489 @RikETS, #102682 @JoaoMarcos44, #108012 @Halldrix, #105428 @TaoMasterCoder) - Healthy WAL databases stop wedging. OpenZFS
(deleted)dentries and aclose()racing anappend_messageboth produced a stickyDeletedWalGenerationErroron a perfectly good store; the read pool was handed out under an unconfirmed journal mode; a transientdisk I/O erroron WSL2 killedget_sessionon the first attempt; and a "state.db locked" banner was broadcast after the lock had already cleared. (#108082 — salvage #107411 @chelsealong, #105578 @ca-shrimp, #105711 @gaoanze888, #106958 @nikkoxgonzales; co-authored @QDung210, @fangliquanflq, @Sahilvishnaliya) - FTS damage no longer kills your turn. An error scoped to the full-text-search index was classified as whole-file corruption and fail-closed the conversation. It's now
fts_index: search degrades, the index rebuilds later, the transcript store is untouched. Same PR: doctor names structural damage honestly instead of "FTS write corruption", the FTS write probe catches the stale-index shape that passed every check while every write failed,.recoveroutput no longer fails startup on orphan FTS5 shadow tables, header-zeroed databases recover instead of being refused, and the dashboard analytics poller returns a 503 instead of 520K tracebacks a day. (#108130 — salvage #97843 @SulthanZahran1 + #97841 @Finn763, #88604 #56824 #103657 @liuhao1024, #106890 @nftpoetrist, #103321 @jangomango76, #91413 @leegunwoo98, #102808 @TaoMasterCoder) - One corrupt row no longer kills `sessions list`, export, or insights. A TEXT timestamp or a
1e30epoch used to crash the whole listing; malformed marker JSON crashedjson_extract; more than 999 ids crashed bulk delete/prune. Onecoerce_epoch()helper on every reader (bad rows render?with a WARNING naming the session), ajson_validguard, IN-list chunking, and batched export hydration. (#108086 — salvage #106071 @Xipong, #101726 @efe-arv, #94701 @liuhao1024, #102679 @mssteuer, #100658 @Mi55ed) - Sessions never bind to or read another profile's database. The Desktop launch backend could pin itself to the wrong profile's
state.dbunder a HERMES_HOME override race;session_searchby bare ID silently scanned every profile and returned someone else's transcript; recovery guidance pointed at the wrong file; profile delete kept a handle open (WinError 32). (#108074 — salvage #102534 @HexLab98, #106975 @Sora-bluesky) - Opening state.db no longer takes the write lock when nothing needs writing. A one-shot
hermesprocess opening the store behind a busy gateway stalled 4–20 s and then failed with "database is locked". Now 0.01 s. (#108067 — salvage #106751 @kshitijk4poor, #101881 @jonpol01)
Also in the window from the same subsystem: a fresh state.db no longer publishes FTS tables before owning the rebuild lock (#106311), a handle that lost its WAL generation no longer checkpoints stale frames at shutdown (#106315, #106840), a clobbered first page is quarantined with its WAL instead of opened destructively (#106587), WAL setup leaves an unverifiable database untouched (#106568), and quarantined handles refuse VACUUM/FTS optimize (#106343, #106349). Most of these salvaged community diagnoses by @kshitijk4poor.
Multi-profile isolation hardening
A cluster of fixes for installs running several profiles under one gateway (multiplex): secondary-profile bots no longer inherit the default profile's allow-lists (#107616), adapters no longer send credentials to the default profile's host (#107617), stdio MCP servers no longer receive the default profile's vault secrets (#107630), MEDIA: delivery can no longer attach another profile's .env / auth.json / state.db (#107609), Feishu drive callbacks and /p// webhook replies stay on the routed profile (#107620, #107626), and secondary profiles no longer get a sibling's Nous bearer from per-process memos (#107611).
Desktop backend spawn storms are over
Bot Mode used to spawn or dial one backend per profile on launch and on every roster tick, hovering the Bots roster spawned a backend per row, and profile switches could spawn a duplicate primary. (#108069, #108107, #108118, #108134, #107969, #108112 — salvage #102512, #103634, #103399, #107997 and others by @kshitijk4poor)
Password-blind credential vault
The agent can now sign in, pay, and fill addresses from 1Password, Bitwarden, or the local Hermes vault without ever seeing a secret; two-factor codes come from a saved authenticator key or are asked for in the user's UI (#106480, #107585). Private git plugins install with the user's stored credentials (#106981).
Plugin catalog and one Plugins page
A curated, SHA-pinned plugin index with...
Excerpt shown — open the source for the full document.