github NousResearch/hermes-agent v2026.9.11
Hermes Agent v0.21.2 (v2026.9.11)

2 hours ago

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.db every 5 seconds; the dashboard opened a writable handle on startup; cron's lifecycle guard did a raw open() on a live database (which cancels the gateway's POSIX locks — the classic "how to corrupt SQLite" recipe); doctor --fix would checkpoint under a live holder. All four are gone: hosted rooms live in shared-state.db, the dashboard opens read-only first, the guard goes through the tracked connection registry, and doctor --fix refuses 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 a close() racing an append_message both produced a sticky DeletedWalGenerationError on a perfectly good store; the read pool was handed out under an unconfirmed journal mode; a transient disk I/O error on WSL2 killed get_session on 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, .recover output 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 1e30 epoch used to crash the whole listing; malformed marker JSON crashed json_extract; more than 999 ids crashed bulk delete/prune. One coerce_epoch() helper on every reader (bad rows render ? with a WARNING naming the session), a json_valid guard, 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.db under a HERMES_HOME override race; session_search by 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 hermes process 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/<profile>/ 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 CLI, admission CI, docs and dashboard (#69446); Desktop gets one Plugins page owning agent + desktop plugins, install, catalog and per-commit pinning (#107212, #107314, #107321); Radio ships as an opt-in SDK plugin (#107072).

Nous free tier and guided first launch

Free inference and connectors out of the box with one command to sign in (#105258, #105260), /login from a chat (#105261), connector tools (Gmail, Linear, Notion, ...) searchable through tool_search (#106842), and a guided first launch behind HERMES_GUEST_ONBOARDING=1 (#107697, #107958, #107985, #108211).

🐛 Notable Bug Fixes

Gateway & platforms

  • A bare display: key in config.yaml no longer crashes every gateway turn (#106305); a queued-lane final refused by the platform is recorded and redelivered (#106316); a stalled WebSocket send no longer blocks every later event (#106581); the first turn no longer waits on the Python toolchain probe (#106556).
  • Telegram bots must @mention when bots_require_mention is on, breaking bot-to-bot loops (#106534); Matrix renders LaTeX (#106515); Signal renders markdown tables (#106538); WhatsApp replies to view-once messages keep their quote (#106541); media-only replies report SUCCESS everywhere (#106557).

Providers & routing

  • /model and auxiliary auto never bill a provider you didn't select (#107366); never auto-switch to a provider you have no credentials for (#107281); Bedrock Claude/Converse/Mantle models survive /model, fallback and restore (#107621, #107658); Bedrock Guardrails enforced (#107815).
  • Codex: patch-budget image 400 shrinks and retries (#106525); unentitled primary + fallback no longer oscillate (#106549); Azure Foundry replayed-reasoning rejection classified and pruned (#106718 @erosika). MCP OAuth refresh no longer erases the refresh token (#106185). Anthropic clients send exactly one credential (#107978).
  • DeepSeek V4.1 Flash on Nous Portal and OpenRouter pickers (#107489); GPT Image 2.5 via OpenAI and FAL (#105988); Opus 5 / Fable 5.1 on the native Anthropic picker (#106636 @xxxigm).

Agent loop & compression

  • One blocked periodic callback no longer stalls lease refresh (#106308); a mid-turn /steer is persisted as its own user row (#106317, #106344); local-inference memory-ceiling rejections back off instead of compressing history (#106307); context-overflow after partial streaming ends the turn (#106567); length continuation stops when the prompt filled the window (#106571); compression no longer times out silently on aux retries (#106866); model_thresholds keys can be provider-scoped (#108061).
  • Surface switch (Desktop↔TUI) no longer rebuilds the system prompt and busts the prompt cache (#105844); CLI keeps the api_content sidecar so the cache survives an early persist (#105842).

CLI, TUI & Desktop

  • hermes -z --resume continues the session (#106313); Shift+letter and Cmd+Shift+Z work on extended-key terminals (#90674 @francip, #105493); browser_exec timeout kills the whole process tree (#106589); update checks poll the GitHub API once a day instead of git-fetching every 30 min (#107648); hermes update names the real cause and can't hang on a stalled fetch (#108053).
  • Desktop: UI language survives the update relaunch (#106476), expired OAuth grants get a one-click re-sign-in (#106965), HUD mode shows the transcript again and always gives the window back (#107491, #107423), the backend exits when its Desktop parent dies (#107977), Windows updates stop reporting false failures (#106175, #107183), WSLg renders on the Windows GPU (#106528), Telegram quick setup with QR ported from the dashboard (#107242), and ~60 more Desktop fixes largely from @OutThisLife and @kshitijk4poor.

Cron & Kanban

  • An off-tick "run now" no longer cancels the next scheduled run (#106306); a killed manual run no longer blocks the next one for 5 minutes (#106733); a one-shot changed to recurring keeps firing (#106532); unpinned jobs run on their creation-snapshot model (#106499); --clone-all no longer copies cron jobs (#106478); kanban promote refuses undone parents (#106550); kanban_request_review rejects unknown reviewer profiles (#106547).

Tools & memory

  • A stdio MCP server dying mid-call no longer replays the tool call (#106546); 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 tools sharing one word (#106676); remote NOPASSWD sudo no longer prompts (#107939); RSS and Reddit reading no longer activate by default (#105873).

Housekeeping

  • config.yaml backups live in one bounded backups/config/ dir (#106388); hermes backup keeps the newest 3 zips (#106455); hermes setup --reset backs up the real config (#106453); debug share retention shrunk to 1 day on the dpaste fallback (#106531).

👥 Contributors

Thank you to the 140 contributors whose commits, co-author trailers, and salvaged PRs landed in this window.

state.db campaign — salvaged PR authors: @RikETS, @JoaoMarcos44, @Halldrix, @TaoMasterCoder, @chelsealong, @ca-shrimp, @gaoanze888, @nikkoxgonzales, @QDung210, @fangliquanflq, @Sahilvishnaliya, @kshitijk4poor, @jonpol01, @HexLab98, @Sora-bluesky, @Xipong, @efe-arv, @liuhao1024, @mssteuer, @Mi55ed, @SulthanZahran1, @Finn763, @nftpoetrist, @jangomango76, @leegunwoo98, @ggoldani.

state.db campaign — issue reporters (the forensics in these threads were often better than the fixes): @thedigitalcarpenterdad, @Rroven, @aoeman84, @StephanRosin, @rubensandrade-sketch, @wanliqin, @chenzheshushi-commits, @CarlosReyesPena, @revazone, @reservassai-art, @Cuttingwater, @soroush5, @e-shizz, @shobhit-87labs, @shivanathd, @hoelzl, @i8ei, @Ace-Kelly, @YinsenWANG, @zbabiarz, @Sravanjangam, @0gl20shk0sbt36, @RChina, @bronder, @ccwssy, @bottenbenny, and @Hitman117890 whose Discord report kicked the campaign off.

Everyone in the window (alphabetical): @0genlab, @0xalydev, @100yenadmin, @1052326311, @686f6c61, @69k4xmdfm2-blip, @abundantbeing, @Adolanium, @Ahmett101, @albert748, @AlexxRussell, @alt-glitch, @auroracapital, @austinpickett, @babatorik, @Bartok9, @benbarclay, @bennybuoy, @brian717, @briandevans, @buihongduc132, @ca-shrimp, @cervantesh, @Cesar-Azeredo, @ChanPark03, @chelsealong, @ckomma, @ClintonEmok, @crazyief, @ctaylor86, @dalzio, @DavidMetcalfe, @Drexuxux, @edosulai, @efe-arv, @emozilla, @ericmaddox, @erosika, @ethernet8023, @everm1nd, @FalconOrtiz, @fangliquanflq, @Finn763, @FirmamentalSpring, @francip, @g3org3yo, @gaoanze888, @ggoldani, @Halldrix, @haydster7, @hbizi, @helix4u, @HexLab98, @huklaa, @IAvecilla, @infinitycrew39, @jahfaliabdulrahman-dev, @jangomango76, @JoaoMarcos44, @jonpol01, @jwilson411, @KeyArgo, @kokhlo, @KoNit-K, @kshitijk4poor, @kyssta-exe, @leegunwoo98, @lesterlxt, @liuhao1024, @Mabolla, @manuelschipper, @MaxFreedomPollard, @mearls0501, @mengyuyuan, @Mi55ed, @MiseHinoha, @mjshorty, @mkrb84, @moisesvalero, @moken627-hub, @mssteuer, @nateEc, @nftpoetrist, @nickseelert, @nikkoxgonzales, @notwitcheer, @onuraycicek, @outdog-hwh, @OutThisLife, @philmossman, @phuongvm, @pierrenode, @portavales, @PRATHAMESH75, @QDung210, @rewbs, @RikETS, @romanovzky, @ryantuc, @Sahilvishnaliya, @salch-cred, @sgarrand, @shannonsands, @simpolism, @Solitud1nem, @somewheresy, @Sora-bluesky, @sprmn24, @squevo, @StellarisW, @Stoltemberg, @SulthanZahran1, @Svector-anu, @szicely, @TaoMasterCoder, @teknium1, @ten82e, @thedavidweng, @tkaufmann, @Totoro-qaq, @Tranquil-Flow, @tuancookiez-hub, @TurgutKural, @ugoenyioha, @unsupportedpastels, @victor-kyriazakos, @webtecnica, @wliu-dev, @wukangcheng1994, @Xipong, @Xixiartemis, @xkam7ar, @xxxigm, @yavarb, @yoniebans, @Youssef, @yoyodine-industries, @yuanchenglu, @YuhGuan, @Zeus-Deus.

Also: Youssef.

Updating

  • Existing install: hermes update
  • Fresh install: curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
  • Managed deployments should update through their deployment tooling using the new tag.
  • If your state.db was already damaged by 0.21.0/0.21.1: run hermes doctor first; it now names structural vs index damage correctly and points at hermes sessions recover --inspect-only (profile-pinned) when a rebuild isn't enough.

Full Changelog: v2026.9.7...v2026.9.11

Don't miss a new hermes-agent release

NewReleases is sending notifications on new releases.