fix(gateway): gateway sessions lack activity watchdog - agent loop stalls silently with no detection and notification - #72424
Closed
fangliquanflq wants to merge 22 commits into
Closed
Conversation
Stamp sessions.last_activity_at from AIAgent._touch_activity (rate-limited) so hermes sessions list and hermes status observe API/tool/compaction progress while a gateway turn is still writing no message rows (NousResearch#72016).
Prefer max(last_activity_at, latest message) for session last_active so a rate-limited mid-turn heartbeat cannot rank a session behind newer message timestamps in listings, status, and idle archive.
…t_active Document that last_active is max(heartbeat, message time), and separate the status last-activity test from the preceding class with PEP8 spacing.
Clarify that archive_stale_sessions ages on max(last_activity_at, latest message), matching the shared last_active SQL helper.
…ale activity When a busy gateway session has a queued follow-up and the agent activity clock is idle past agent.session_stall_timeout (default 300s), warn once and notify the user to try /new. Does not kill the turn.
…hdog Remove the unused pending-inbound helper and lock overflow-queue plus multiplex profile-adapter delivery with regression tests.
Hung summary models could stall the conversation loop with no host-level inactivity budget. Mirror gateway hygiene: idle progress extends the wait, a total ceiling bounds trickle streams, and a cancelled commit fence skips compaction without dropping messages.
Use a daemon executor so cancelled hung workers cannot block process exit, propagate parent ContextVars into the compression worker, and record the existing timeout cooldown ladder so the next turn does not re-burn the full idle budget.
…meout Resolve the timeout fallback prompt lazily so empty prompt-cache rebuilds do not raise before compression starts. Offload compress_context via a module-shared DaemonThreadPoolExecutor with gateway-style idle/ceiling waits and fence cancel, and fix the zh-Hans session-hygiene wording.
Use a small shared pool (max_workers=4) instead of asyncio fan-out sizing. Compression is rare and heavy, and fence-cancelled workers may still be winding down.
Extend the shared session activity observation contract so durable SessionDB heartbeats carry description/provenance alongside the timestamp, matching in-memory get_activity_summary for NousResearch#72039 consumers.
Keep gateway cache turn resets on the ts/desc/provenance triple, and drop the TypeError persist fallback that could silently omit description/provenance.
Keep last_activity_at for idle/watchdog continuity, but wipe description/provenance in memory and SessionDB so idle sessions do not keep advertising the last mid-turn stamp.
…y-session-stall-watchdog Make the session stall watchdog PR depend on mid-turn activity tracking.
…chdog Use AIAgent.get_activity_summary() / agent.session_activity as the only progress source for pending-inbound stall notify. Drop turn-start and pending-event clocks so NousResearch#72079 stays composable with NousResearch#72039.
Hold the stall latch across activity observation gaps, and latch only after a successful user notification so transient send failures retry.
Inspect adapter.send() success before latching so SendResult(success=False) retries on the next watcher tick instead of silently dropping the warning.
13 tasks
…ctivity-tracking Resolved hermes_state.py search_sessions docstring conflict: keep freshest-of last_active semantics from this branch and workspace_key docs from main.
…on-activity-provenance
…mpression-activity-provenance
… provenance Stamp compaction heartbeats, host timeouts, and cooldown/abort blocks onto the shared activity observation source so gateway stall consumers can distinguish actively compacting from stalled.
…at clobber Stop detached compression heartbeats from overwriting host/hygiene timeout or cooldown stamps, while still allowing a new compression episode start() to republish agent.compression.
fangliquanflq
added a commit
to fangliquanflq/hermes-agent
that referenced
this pull request
Jul 31, 2026
…out (NousResearch#72424) Three mechanisms to detect and notify when gateway sessions stall silently: 1. Mid-turn activity heartbeats stamped to SessionDB so hermes sessions list and hermes status show progress during long turns without new message rows. 2. Stall watchdog: when a busy session has pending inbound and the shared activity clock is idle past agent.session_stall_timeout (default 300), log a WARNING and notify the user once to try /new. Notify-only; does not kill the turn. 3. Compaction timeout: fenceless compress_context callers get a progress-aware host budget (compression.context_timeout_seconds default 120 idle, compression.context_total_ceiling_seconds default 600 ceiling). On timeout, cancel via commit fence, skip compaction without dropping messages, and continue the turn. Closes NousResearch#72016 (slices 1-3; slice 4 cumulative SSE stream-retry deadline remains a follow-up). Cherry-picked from PR NousResearch#72424 by @fangliquanflq.
fangliquanflq
pushed a commit
to fangliquanflq/hermes-agent
that referenced
this pull request
Jul 31, 2026
Three code-reuse fixes applied during salvage: 1. Reuse _relative_time from hermes_cli/main.py instead of duplicating the relative-time formatting logic in hermes_cli/status.py. 2. Extract _stamp_hygiene_compression_provenance helper in gateway/run.py to deduplicate the two nearly-identical try/except blocks that stamp compression timeout/abort provenance in the hygiene path. 3. Add ContextCompressor.record_timeout_failure() method and use it from the in-agent compress_context timeout callback instead of re-implementing the (60, 300, 900) cooldown ladder inline. The existing summary-LLM exception handler already has this ladder — now both paths share one method.
teknium1
pushed a commit
that referenced
this pull request
Aug 1, 2026
…out (#72424) Three mechanisms to detect and notify when gateway sessions stall silently: 1. Mid-turn activity heartbeats stamped to SessionDB so hermes sessions list and hermes status show progress during long turns without new message rows. 2. Stall watchdog: when a busy session has pending inbound and the shared activity clock is idle past agent.session_stall_timeout (default 300), log a WARNING and notify the user once to try /new. Notify-only; does not kill the turn. 3. Compaction timeout: fenceless compress_context callers get a progress-aware host budget (compression.context_timeout_seconds default 120 idle, compression.context_total_ceiling_seconds default 600 ceiling). On timeout, cancel via commit fence, skip compaction without dropping messages, and continue the turn. Closes #72016 (slices 1-3; slice 4 cumulative SSE stream-retry deadline remains a follow-up). Cherry-picked from PR #72424 by @fangliquanflq.
teknium1
pushed a commit
that referenced
this pull request
Aug 1, 2026
Three code-reuse fixes applied during salvage: 1. Reuse _relative_time from hermes_cli/main.py instead of duplicating the relative-time formatting logic in hermes_cli/status.py. 2. Extract _stamp_hygiene_compression_provenance helper in gateway/run.py to deduplicate the two nearly-identical try/except blocks that stamp compression timeout/abort provenance in the hygiene path. 3. Add ContextCompressor.record_timeout_failure() method and use it from the in-agent compress_context timeout callback instead of re-implementing the (60, 300, 900) cooldown ladder inline. The existing summary-LLM exception handler already has this ladder — now both paths share one method.
teknium1
pushed a commit
that referenced
this pull request
Aug 2, 2026
…out (#72424) Three mechanisms to detect and notify when gateway sessions stall silently: 1. Mid-turn activity heartbeats stamped to SessionDB so hermes sessions list and hermes status show progress during long turns without new message rows. 2. Stall watchdog: when a busy session has pending inbound and the shared activity clock is idle past agent.session_stall_timeout (default 300), log a WARNING and notify the user once to try /new. Notify-only; does not kill the turn. 3. Compaction timeout: fenceless compress_context callers get a progress-aware host budget (compression.context_timeout_seconds default 120 idle, compression.context_total_ceiling_seconds default 600 ceiling). On timeout, cancel via commit fence, skip compaction without dropping messages, and continue the turn. Closes #72016 (slices 1-3; slice 4 cumulative SSE stream-retry deadline remains a follow-up). Cherry-picked from PR #72424 by @fangliquanflq.
teknium1
pushed a commit
that referenced
this pull request
Aug 2, 2026
Three code-reuse fixes applied during salvage: 1. Reuse _relative_time from hermes_cli/main.py instead of duplicating the relative-time formatting logic in hermes_cli/status.py. 2. Extract _stamp_hygiene_compression_provenance helper in gateway/run.py to deduplicate the two nearly-identical try/except blocks that stamp compression timeout/abort provenance in the hygiene path. 3. Add ContextCompressor.record_timeout_failure() method and use it from the in-agent compress_context timeout callback instead of re-implementing the (60, 300, 900) cooldown ladder inline. The existing summary-LLM exception handler already has this ladder — now both paths share one method.
teknium1
pushed a commit
that referenced
this pull request
Aug 2, 2026
…out (#72424) Three mechanisms to detect and notify when gateway sessions stall silently: 1. Mid-turn activity heartbeats stamped to SessionDB so hermes sessions list and hermes status show progress during long turns without new message rows. 2. Stall watchdog: when a busy session has pending inbound and the shared activity clock is idle past agent.session_stall_timeout (default 300), log a WARNING and notify the user once to try /new. Notify-only; does not kill the turn. 3. Compaction timeout: fenceless compress_context callers get a progress-aware host budget (compression.context_timeout_seconds default 120 idle, compression.context_total_ceiling_seconds default 600 ceiling). On timeout, cancel via commit fence, skip compaction without dropping messages, and continue the turn. Closes #72016 (slices 1-3; slice 4 cumulative SSE stream-retry deadline remains a follow-up). Cherry-picked from PR #72424 by @fangliquanflq.
teknium1
pushed a commit
that referenced
this pull request
Aug 2, 2026
Three code-reuse fixes applied during salvage: 1. Reuse _relative_time from hermes_cli/main.py instead of duplicating the relative-time formatting logic in hermes_cli/status.py. 2. Extract _stamp_hygiene_compression_provenance helper in gateway/run.py to deduplicate the two nearly-identical try/except blocks that stamp compression timeout/abort provenance in the hygiene path. 3. Add ContextCompressor.record_timeout_failure() method and use it from the in-agent compress_context timeout callback instead of re-implementing the (60, 300, 900) cooldown ladder inline. The existing summary-LLM exception handler already has this ladder — now both paths share one method.
kenyonxu
added a commit
to kenyonxu/hermes-agent
that referenced
this pull request
Aug 3, 2026
Conflicts resolved: - .gitignore: merged both sets of rules - hermes_state.py: kept our shared SessionDB + reader pool + _init_schema cache, took upstream's journal_mode resolver (supports database.journal_mode config), kept _IMPORT_DEFAULT_DB_PATH - tests/gateway/test_channel_directory.py: took upstream - tests/gateway/test_delivery_ledger.py: took upstream - tests/test_hermes_state.py: took upstream (our TestSharedWriterSessionDB and TestReadOnlyPool classes lost again — will restore in follow-up) Key upstream changes in this merge: - Session activity watchdog + stall notify (NousResearch#72424) - Single-row routing UPSERT fast path (50c4afe) - Sub-second busy budget for activity writes (92c7369) - Sophisticated journal_mode resolver with database.journal_mode config - VACUUM throttle (bd856a0) - Read-only connection close on FTS probe failure (e38055a) 7 FTS/PK tests fail (upstream schema migration differences, not our changes). 63 gateway/cron tests pass.
This was referenced Aug 3, 2026
Closed
gabrielcosi
pushed a commit
to gabrielcosi/home-ops
that referenced
this pull request
Aug 5, 2026
….7.30 ➔ v2026.8.3) (#253)
This PR contains the following updates:
| Package | Update | Change |
|---|---|---|
| [ghcr.io/gabrielcosi/hermes-agent](https://github.com/NousResearch/hermes-agent) | minor | `v2026.7.30` → `v2026.8.3` |
---
### Release Notes
<details>
<summary>NousResearch/hermes-agent (ghcr.io/gabrielcosi/hermes-agent)</summary>
### [`v2026.8.3`](https://github.com/NousResearch/hermes-agent/releases/tag/v2026.8.3): Hermes Agent v0.20.0 (2026.8.3)
[Compare Source](https://github.com/NousResearch/hermes-agent/compare/v2026.7.30...v2026.8.3)
##### Hermes Agent v0.20.0 (v2026.8.3)
**Release Date:** August 3, 2026
**Since v0.19.0:** \~3,650 commits · \~1,400 merged PRs · \~5,200 files changed · \~559,000 insertions · \~405,000 deletions · **\~1,200 issues closed** · 650+ contributors
> **The Herald Release.** Hermes is the herald of the gods, and this release makes him one in earnest: he **speaks** (real-time conversational voice with streaming TTS, barge-in, on-device wake words, and hands-free control across the CLI, desktop, and every audio-capable gateway platform), he **carries word to other agents** (A2A v1.0), he **announces events to your systems** (signed outbound webhooks), and he **cites his sources** (grounded research with verifiable citations and fact-checking). Around that spine: the desktop app became a platform (artifacts with live preview, a plugin SDK, quick-entry from anywhere, multiple windows), the CLI got a wave of power commands (`!` shell mode, `/init`, `/diff`, `/context`, `/focus`), compression got smarter and gentler, and the tools themselves now recover from their own failures instead of making the model guess. This release rolls up everything from the v0.19.1 infrastructure patch tag — that window is fully documented here.
***
##### ✨ Highlights
- **Talk to Hermes — streaming, conversational voice with barge-in** — Voice mode used to mean: speak, wait for the whole reply to generate, then listen to one long audio file. Now Hermes speaks clause-by-clause as the response streams, you can interrupt it mid-sentence by just talking (it stops, listens, and the model is told you cut in), and busy-aware silence detection means it doesn't talk over you. This works in CLI voice mode, on the desktop, and through gateway adapters. Talking to Hermes finally feels like a conversation, not a voicemail exchange. ([#​69511](https://github.com/NousResearch/hermes-agent/pull/69511), [#​73862](https://github.com/NousResearch/hermes-agent/pull/73862), [#​74223](https://github.com/NousResearch/hermes-agent/pull/74223), [#​74000](https://github.com/NousResearch/hermes-agent/pull/74000), [#​69602](https://github.com/NousResearch/hermes-agent/pull/69602) — [@​teknium1](https://github.com/teknium1), [@​OutThisLife](https://github.com/OutThisLife))
- **Wake words and hands-free control** — Say your own open-vocabulary wake phrase ("hey Hermes", or anything you pick) and Hermes starts listening — detection runs on-device, so no audio leaves your machine while it waits. Multi-profile voice routing means different wake words can reach different profiles, and saying "stop" ends the voice chat on every surface without touching the keyboard. Your terminal is now something you can talk to from across the room. ([#​70509](https://github.com/NousResearch/hermes-agent/pull/70509), [#​73106](https://github.com/NousResearch/hermes-agent/pull/73106), [#​73933](https://github.com/NousResearch/hermes-agent/pull/73933) — [@​teknium1](https://github.com/teknium1))
- **Voice on every platform** — Send a voice note to Hermes on WhatsApp, Feishu, DingTalk, LINE, QQ, Photon, or Weixin and it's transcribed and answered; auto-TTS replies are delivered platform-aware (opus where platforms want opus, captions attached correctly). STT is now fully configurable — its own `hermes tools` category, GUI toggles, dashboard dropdowns, unified language resolution so transcripts stop coming back in the wrong language, and OpenAI's gpt-transcribe support. One unified spoken-text preprocessor cleans markdown, code, and URLs out of speech across all TTS providers. ([#​73515](https://github.com/NousResearch/hermes-agent/pull/73515), [#​73508](https://github.com/NousResearch/hermes-agent/pull/73508), [#​73910](https://github.com/NousResearch/hermes-agent/pull/73910), [#​73513](https://github.com/NousResearch/hermes-agent/pull/73513), [#​73067](https://github.com/NousResearch/hermes-agent/pull/73067) — [@​teknium1](https://github.com/teknium1))
- **Research you can trust — grounded citations with fact-checking** — The new `grounded-citations` skill makes Hermes produce research where every claim is backed by a verifiable source: quotes are matched against the actual page text (not hallucinated), citations link to the exact evidence, and a fact-checking mode turns the same machinery on any document or claim you hand it — it tells you what checks out, what doesn't, and what couldn't be verified. If you use Hermes for research, this is the difference between "sounds right" and "provably sourced." ([#​71698](https://github.com/NousResearch/hermes-agent/pull/71698), [#​77104](https://github.com/NousResearch/hermes-agent/pull/77104) — [@​teknium1](https://github.com/teknium1))
- **Outbound webhooks — Hermes pushes events to your systems** — Until now, integrating with Hermes meant polling or listening on a platform. Now Hermes pushes **signed lifecycle events** (session activity, turn completions, tool events) to any HTTP endpoint you register — with HMAC signatures so your receiver can verify authenticity. Wire Hermes into your CI, your home automation, your dashboards, or any service that speaks HTTP, with no polling loop. ([#​69406](https://github.com/NousResearch/hermes-agent/pull/69406) — [@​teknium1](https://github.com/teknium1))
- **The desktop app becomes a platform — artifacts, plugin SDK, quick entry** — Hermes desktop now renders **artifacts**: versioned cards with sandboxed live preview in a right-rail viewer, so generated HTML/apps run safely next to the chat. A real **plugin SDK** landed with Kanban as its founding plugin, `ctx.download` for handing users files, floating pane placement, and multiple GUI windows. A global-hotkey **quick-entry window** captures a thought into any session from anywhere in your OS. The desktop stopped being a chat client and started being a workbench. ([#​72345](https://github.com/NousResearch/hermes-agent/pull/72345), [#​61173](https://github.com/NousResearch/hermes-agent/pull/61173), [#​74413](https://github.com/NousResearch/hermes-agent/pull/74413), [#​72315](https://github.com/NousResearch/hermes-agent/pull/72315), [#​68259](https://github.com/NousResearch/hermes-agent/pull/68259), [#​73143](https://github.com/NousResearch/hermes-agent/pull/73143) — [@​OutThisLife](https://github.com/OutThisLife), [@​teknium1](https://github.com/teknium1))
- **Hermes speaks Agent-to-Agent — A2A v1.0** — A new bundled plugin implements the Agent-to-Agent protocol, so Hermes can discover, talk to, and be driven by other A2A-compatible agents. This closes issue [#​514](https://github.com/NousResearch/hermes-agent/issues/514) — one of the oldest open feature requests in the repo. If you're building multi-agent systems with heterogeneous stacks, Hermes now has a standard wire protocol for joining them. ([#​77109](https://github.com/NousResearch/hermes-agent/pull/77109) — [@​teknium1](https://github.com/teknium1))
- **CLI power-user wave** — `!command` runs a shell command instantly without spending a model turn. `/init` scans your project and generates (or updates) an `AGENTS.md`. `/diff` shows staged/all/session changes from any surface, `/context` breaks down exactly what's filling your context window, `/focus` gives you a reduced-output view with hidden-line recovery, and Ctrl+S stashes a half-written prompt into a browsable panel. Plus `hermes import-agent` migrates your Claude Code or Codex CLI setup into Hermes in one command. ([#​72257](https://github.com/NousResearch/hermes-agent/pull/72257), [#​72178](https://github.com/NousResearch/hermes-agent/pull/72178), [#​72240](https://github.com/NousResearch/hermes-agent/pull/72240), [#​72242](https://github.com/NousResearch/hermes-agent/pull/72242), [#​72302](https://github.com/NousResearch/hermes-agent/pull/72302), [#​72262](https://github.com/NousResearch/hermes-agent/pull/72262), [#​72190](https://github.com/NousResearch/hermes-agent/pull/72190) — [@​teknium1](https://github.com/teknium1), several salvaging long-standing community PRs)
- **Correct the agent mid-turn — redirects** — If Hermes is heading the wrong way, you no longer have to `/stop` and re-explain. Type a correction while it works and the active turn is redirected: work in flight is preserved, the original prompt is kept, and the agent course-corrects with your new guidance. Paired with double-ESC draft discard and a composer undo stack, steering feels like editing, not restarting. ([#​63104](https://github.com/NousResearch/hermes-agent/pull/63104), [#​72339](https://github.com/NousResearch/hermes-agent/pull/72339), [#​74736](https://github.com/NousResearch/hermes-agent/pull/74736) — [@​OutThisLife](https://github.com/OutThisLife))
- **Tools that fix themselves** — A sweep of self-recovery upgrades means the agent wastes far fewer turns on tool friction: truncated terminal output spills to a file the agent can read back, `patch` detects already-applied edits and diagnoses whitespace mismatches, `write_file` verifies content on disk, searches that match nothing probe for near-misses and recover, and common failure classes come back with actionable hints. The default tool-calling iteration limit also jumped 90 → 500 — long autonomous runs stopped hitting an artificial wall. ([#​77041](https://github.com/NousResearch/hermes-agent/pull/77041), [#​76998](https://github.com/NousResearch/hermes-agent/pull/76998), [#​77024](https://github.com/NousResearch/hermes-agent/pull/77024), [#​77055](https://github.com/NousResearch/hermes-agent/pull/77055), [#​77011](https://github.com/NousResearch/hermes-agent/pull/77011), [#​76992](https://github.com/NousResearch/hermes-agent/pull/76992), [#​72176](https://github.com/NousResearch/hermes-agent/pull/72176) — [@​teknium1](https://github.com/teknium1))
- **Compression that respects your conversation** — Context compression got a deep overhaul: proactive tool-result pruning for large-window models, per-turn micro-compaction that amortizes the cost instead of one giant pause, a guaranteed N-user-message tail so recent conversation always survives, progress-aware timeouts that stop punishing slow summary models, and ghost-skill defense so a pruned skill can never silently haunt a session. Thresholds are now configurable per-model and in absolute tokens. Long sessions stay coherent and stop stalling. ([#​70254](https://github.com/NousResearch/hermes-agent/pull/70254), [#​75345](https://github.com/NousResearch/hermes-agent/pull/75345), [#​70250](https://github.com/NousResearch/hermes-agent/pull/70250), [#​71508](https://github.com/NousResearch/hermes-agent/pull/71508), [#​70275](https://github.com/NousResearch/hermes-agent/pull/70275) — [@​teknium1](https://github.com/teknium1), [@​kshitijk4poor](https://github.com/kshitijk4poor), salvaging multiple community PRs)
- **Smart approvals grow up** — `hermes approvals suggest` mines your approval history into allowlist proposals, operators can customize the smart-approval policy, a consecutive-denial circuit breaker stops a misbehaving loop cold, and desktop pairing approvals are profile-correct with a proper surface to answer them from. Plus a new approval gate for docker/podman daemon-redirect commands. Less clicking "approve", without giving an inch of control. ([#​72259](https://github.com/NousResearch/hermes-agent/pull/72259), [#​72186](https://github.com/NousResearch/hermes-agent/pull/72186), [#​72203](https://github.com/NousResearch/hermes-agent/pull/72203), [#​74446](https://github.com/NousResearch/hermes-agent/pull/74446), [#​71092](https://github.com/NousResearch/hermes-agent/pull/71092) — [@​teknium1](https://github.com/teknium1), [@​OutThisLife](https://github.com/OutThisLife))
- **Faster everywhere, again** — Prompt caching now covers tool schemas on native Anthropic without history loss. `hermes -w` cold start dropped \~14s → \~1.8s, `hermes update` no-ops got 2–6s faster, heavy SDKs lazy-load off the import path, config reads stopped deep-copying (54× faster on the telemetry gate), and the desktop shipped a second 60fps wave — streaming cost independent of transcript length, drag at 60fps with five streaming tabs, idle CPU near zero in the background. ([#​76032](https://github.com/NousResearch/hermes-agent/pull/76032), [#​71637](https://github.com/NousResearch/hermes-agent/pull/71637), [#​74218](https://github.com/NousResearch/hermes-agent/pull/74218), [#​74204](https://github.com/NousResearch/hermes-agent/pull/74204), [#​71835](https://github.com/NousResearch/hermes-agent/pull/71835), [#​72346](https://github.com/NousResearch/hermes-agent/pull/72346), [#​75218](https://github.com/NousResearch/hermes-agent/pull/75218) — [@​kshitijk4poor](https://github.com/kshitijk4poor), [@​teknium1](https://github.com/teknium1), [@​OutThisLife](https://github.com/OutThisLife))
- **New places to run and be reached** — Buzz lands as a bundled gateway platform (Block's Nostr-based messenger, with native WebSocket transport and NIP-42 auth), the Vercel AI Gateway provider and Vercel Sandbox terminal backend return modernized, desktop gains an SSH remote-backend connection mode, and the Relay shipped four phases of parity — media, interactive prompts, thread lifecycle, typing indicators — plus HSP personal + org skill sync. ([#​73610](https://github.com/NousResearch/hermes-agent/pull/73610), [#​73761](https://github.com/NousResearch/hermes-agent/pull/73761), [#​74518](https://github.com/NousResearch/hermes-agent/pull/74518), [#​68130](https://github.com/NousResearch/hermes-agent/pull/68130), [#​71300](https://github.com/NousResearch/hermes-agent/pull/71300)–[#​71624](https://github.com/NousResearch/hermes-agent/pull/71624), [#​66730](https://github.com/NousResearch/hermes-agent/pull/66730) — [@​teknium1](https://github.com/teknium1), [@​yoniebans](https://github.com/yoniebans), [@​benbarclay](https://github.com/benbarclay))
***
##### 🎙️ Voice & Speech
##### Conversational voice
- Streaming, conversational TTS with barge-in across all surfaces; clause-by-clause synthesis for CLI voice mode + gateway adapters ([#​69511](https://github.com/NousResearch/hermes-agent/pull/69511), [#​73862](https://github.com/NousResearch/hermes-agent/pull/73862) — [@​OutThisLife](https://github.com/OutThisLife), [@​teknium1](https://github.com/teknium1))
- Voice chat UX polish — busy-aware silence, stop hint, thinking sounds, barge-in fix; full-duplex turn listener (interrupt by voice during generation AND playback) ([#​74000](https://github.com/NousResearch/hermes-agent/pull/74000), [#​74223](https://github.com/NousResearch/hermes-agent/pull/74223) — [@​teknium1](https://github.com/teknium1))
- On-device wake words with open-vocabulary phrases + multi-profile voice routing; say "stop" to end voice chat hands-free on every surface ([#​70509](https://github.com/NousResearch/hermes-agent/pull/70509), [#​73106](https://github.com/NousResearch/hermes-agent/pull/73106), [#​73933](https://github.com/NousResearch/hermes-agent/pull/73933) — [@​teknium1](https://github.com/teknium1))
- The model is told when the user interrupts its spoken reply; desktop speaks the whole turn and idle-flushes held narration ([#​69602](https://github.com/NousResearch/hermes-agent/pull/69602), [#​69936](https://github.com/NousResearch/hermes-agent/pull/69936) — [@​OutThisLife](https://github.com/OutThisLife), [@​teknium1](https://github.com/teknium1))
- 15-item CLI/TUI voice-mode UX and environment fix wave ([#​73520](https://github.com/NousResearch/hermes-agent/pull/73520) — [@​teknium1](https://github.com/teknium1))
##### TTS / STT infrastructure
- Unified spoken-text preprocessing + speed/instructions/provider tool params; unified STT language resolution (fixes the wrong-language transcription class); global `stt.language` defaults to `en` ([#​73513](https://github.com/NousResearch/hermes-agent/pull/73513), [#​73067](https://github.com/NousResearch/hermes-agent/pull/73067), [#​73100](https://github.com/NousResearch/hermes-agent/pull/73100) — [@​teknium1](https://github.com/teknium1))
- Fully configurable STT — `hermes tools` category, GUI toggle/matrix, dashboard dropdowns, setup status; OpenAI gpt-transcribe support ([#​73910](https://github.com/NousResearch/hermes-agent/pull/73910), [#​73853](https://github.com/NousResearch/hermes-agent/pull/73853) — [@​teknium1](https://github.com/teknium1))
- Platform-aware auto-TTS voice delivery (opus platforms, streamed/global gap, captions); inbound voice classification/routing for Feishu, DingTalk, LINE, QQ, Photon, WhatsApp, Weixin ([#​73508](https://github.com/NousResearch/hermes-agent/pull/73508), [#​73515](https://github.com/NousResearch/hermes-agent/pull/73515) — [@​teknium1](https://github.com/teknium1))
- Command TTS/STT provider hardening — idle timeouts, env scrubbing, no-shell, path guards ([#​73514](https://github.com/NousResearch/hermes-agent/pull/73514) — [@​teknium1](https://github.com/teknium1))
- Sync per-sentence TTS synthesis pipelined with playback — the next sentence renders while the current one speaks ([#​77355](https://github.com/NousResearch/hermes-agent/pull/77355) — [@​kshitijk4poor](https://github.com/kshitijk4poor))
- Discord voice PCM streams to ffmpeg stdin instead of a temp file ([#​76970](https://github.com/NousResearch/hermes-agent/pull/76970) — [@​kshitijk4poor](https://github.com/kshitijk4poor))
##### 🏗️ Core Agent & Architecture
##### Compression & context
- Proactive tool-result pruning for large-window models; per-turn micro-compaction; N-user tail guarantee (`compression.min_tail_user_messages`); bounded summarizer input with head+tail retention ([#​70254](https://github.com/NousResearch/hermes-agent/pull/70254), [#​75345](https://github.com/NousResearch/hermes-agent/pull/75345), [#​70250](https://github.com/NousResearch/hermes-agent/pull/70250), [#​70249](https://github.com/NousResearch/hermes-agent/pull/70249) — [@​teknium1](https://github.com/teknium1), [@​kshitijk4poor](https://github.com/kshitijk4poor))
- Ghost-skill defense — `[SKILL_PRUNED]` markers, protected prune, deterministic survival; progress-aware timeouts; lock-contended compression soft-defers instead of exhausting ([#​70275](https://github.com/NousResearch/hermes-agent/pull/70275), [#​71508](https://github.com/NousResearch/hermes-agent/pull/71508), [#​70285](https://github.com/NousResearch/hermes-agent/pull/70285) — [@​teknium1](https://github.com/teknium1))
- Per-model threshold overrides; absolute token threshold (`compression.threshold_tokens`); opt-in idle-triggered compaction; opt-in progress notices; structured local logging for compression attempts ([#​69339](https://github.com/NousResearch/hermes-agent/pull/69339), [#​69335](https://github.com/NousResearch/hermes-agent/pull/69335), [#​69360](https://github.com/NousResearch/hermes-agent/pull/69360), [#​70457](https://github.com/NousResearch/hermes-agent/pull/70457), [#​69338](https://github.com/NousResearch/hermes-agent/pull/69338) — [@​teknium1](https://github.com/teknium1))
- Context-engine ABC grows `select_context()` + `on_turn_complete()` verbs (salvage of [@​chaos-xxl](https://github.com/chaos-xxl)'s RFC work); engines can suppress or customize compaction status ([#​70458](https://github.com/NousResearch/hermes-agent/pull/70458), [#​69859](https://github.com/NousResearch/hermes-agent/pull/69859) — [@​teknium1](https://github.com/teknium1))
- Strict redaction applied at every compaction text boundary ([#​69294](https://github.com/NousResearch/hermes-agent/pull/69294) — [@​teknium1](https://github.com/teknium1))
##### Prompt caching & hot-path performance
- Tool schemas cached on native Anthropic without history loss + consolidated cache-plan internals ([#​76032](https://github.com/NousResearch/hermes-agent/pull/76032), [#​76067](https://github.com/NousResearch/hermes-agent/pull/76067) — [@​kshitijk4poor](https://github.com/kshitijk4poor))
- DeepSeek prompt caching on OpenCode gateways; per-API-call token accounting off the turn thread; OpenAI wire client reused across sequential LLM calls; send-path tool-call canonicalization memoized ([#​75886](https://github.com/NousResearch/hermes-agent/pull/75886), [#​73359](https://github.com/NousResearch/hermes-agent/pull/73359), [#​73375](https://github.com/NousResearch/hermes-agent/pull/73375), [#​76880](https://github.com/NousResearch/hermes-agent/pull/76880) — [@​teknium1](https://github.com/teknium1), [@​kshitijk4poor](https://github.com/kshitijk4poor))
- Readonly config loader at 29 call sites (28× cheaper reads); per-turn config deepcopies killed (telemetry gate 54×); one raw config.yaml parse per process; inter-tool delay removed ([#​74322](https://github.com/NousResearch/hermes-agent/pull/74322), [#​74211](https://github.com/NousResearch/hermes-agent/pull/74211), [#​74228](https://github.com/NousResearch/hermes-agent/pull/74228), [#​64172](https://github.com/NousResearch/hermes-agent/pull/64172) — [@​teknium1](https://github.com/teknium1), [@​Soju06](https://github.com/Soju06))
- Lazy heavy-SDK imports (−8-10% import cost on top of the mcp/tool-discovery diet); streaming hot loop drops per-chunk repr() (\~3× cheaper accounting); cursor/memo optimizations for per-iteration history walks ([#​74204](https://github.com/NousResearch/hermes-agent/pull/74204), [#​74194](https://github.com/NousResearch/hermes-agent/pull/74194), [#​74221](https://github.com/NousResearch/hermes-agent/pull/74221), [#​74231](https://github.com/NousResearch/hermes-agent/pull/74231) — [@​teknium1](https://github.com/teknium1))
- Cold-start \~14s GIL stall during backend init mitigated; turn flush batched into one SQLite transaction; provider-capability-gated prompt cache keys (implied for api.openai.com) ([#​77814](https://github.com/NousResearch/hermes-agent/pull/77814), [#​77619](https://github.com/NousResearch/hermes-agent/pull/77619), [#​77609](https://github.com/NousResearch/hermes-agent/pull/77609) — [@​kshitijk4poor](https://github.com/kshitijk4poor))
- AIAgent hot-path salvage — prompt-cache copy, reasoning-timeout precompute, lazy compressor init ([#​57229](https://github.com/NousResearch/hermes-agent/pull/57229) — [@​kshitijk4poor](https://github.com/kshitijk4poor))
##### Approvals & the agent loop
- `hermes approvals suggest` mines approval history into allowlist proposals; operator-customizable `approvals.smart_policy`; consecutive-denial circuit breaker; cross-surface approvals mode command ([#​72259](https://github.com/NousResearch/hermes-agent/pull/72259), [#​72186](https://github.com/NousResearch/hermes-agent/pull/72186), [#​72203](https://github.com/NousResearch/hermes-agent/pull/72203), [#​63517](https://github.com/NousResearch/hermes-agent/pull/63517) — [@​teknium1](https://github.com/teknium1))
- Docker/podman daemon-redirect commands require approval; session-wide runaway-loop caps for web\_search + delegate\_task (Claude Code-inspired) ([#​71092](https://github.com/NousResearch/hermes-agent/pull/71092), [#​66600](https://github.com/NousResearch/hermes-agent/pull/66600) — [@​teknium1](https://github.com/teknium1))
- Mid-turn redirects — user corrections steer the active turn, preserving in-flight work and the original prompt ([#​63104](https://github.com/NousResearch/hermes-agent/pull/63104), [#​72339](https://github.com/NousResearch/hermes-agent/pull/72339) — [@​OutThisLife](https://github.com/OutThisLife))
- Delegation: structured timeout/stall metadata + live per-child status in `/agents`; subagents can use `execute_code`; redacted child tool history exposed in `subagent_stop`; public subagent lifecycle API for plugins ([#​72300](https://github.com/NousResearch/hermes-agent/pull/72300), [#​69325](https://github.com/NousResearch/hermes-agent/pull/69325), [#​72403](https://github.com/NousResearch/hermes-agent/pull/72403), [#​72501](https://github.com/NousResearch/hermes-agent/pull/72501) — [@​teknium1](https://github.com/teknium1))
- Single-owner refactors for backend identity + failure-scoped skips, empty-content wire repair, call\_id/reasoning sanitization, model-switch parsing ([#​72505](https://github.com/NousResearch/hermes-agent/pull/72505), [#​73071](https://github.com/NousResearch/hermes-agent/pull/73071), [#​74319](https://github.com/NousResearch/hermes-agent/pull/74319), [#​74229](https://github.com/NousResearch/hermes-agent/pull/74229) — [@​teknium1](https://github.com/teknium1))
- Labeled reasoning excerpt surfaced at the empty-response terminal; tool\_search probe-validates blind tool\_call args ([#​65144](https://github.com/NousResearch/hermes-agent/pull/65144), [#​59267](https://github.com/NousResearch/hermes-agent/pull/59267) — [@​teknium1](https://github.com/teknium1))
##### Tool self-recovery wave
- Terminal: recoverable truncation (full output spilled + pre-truncation size), cwd echoed when a command changes directory, output-pattern failure hints ([#​77041](https://github.com/NousResearch/hermes-agent/pull/77041), [#​77004](https://github.com/NousResearch/hermes-agent/pull/77004), [#​76992](https://github.com/NousResearch/hermes-agent/pull/76992) — [@​teknium1](https://github.com/teknium1))
- Patch: already-applied edits return success no-op, whitespace-visualized no-match diagnosis, ambiguous-match locations listed ([#​76998](https://github.com/NousResearch/hermes-agent/pull/76998), [#​77024](https://github.com/NousResearch/hermes-agent/pull/77024), [#​77001](https://github.com/NousResearch/hermes-agent/pull/77001) — [@​teknium1](https://github.com/teknium1))
- Search: zero-match probes + multi-path recovery, auto-multiline for newline patterns; read\_file default limit 500 → 2000 lines; negative-result cache for read/search misses; write\_file verifies on-disk content ([#​77011](https://github.com/NousResearch/hermes-agent/pull/77011), [#​77102](https://github.com/NousResearch/hermes-agent/pull/77102), [#​76996](https://github.com/NousResearch/hermes-agent/pull/76996), [#​76945](https://github.com/NousResearch/hermes-agent/pull/76945), [#​77055](https://github.com/NousResearch/hermes-agent/pull/77055) — [@​teknium1](https://github.com/teknium1), [@​kshitijk4poor](https://github.com/kshitijk4poor))
- execute\_code recovery hints; skill\_view dedup stub for unchanged re-reads; terminal/execute\_code schema prose trimmed \~40%; tiered tool disclosure scales with catalog size; default iteration limit 90 → 500 ([#​77106](https://github.com/NousResearch/hermes-agent/pull/77106), [#​77095](https://github.com/NousResearch/hermes-agent/pull/77095), [#​77023](https://github.com/NousResearch/hermes-agent/pull/77023), [#​67034](https://github.com/NousResearch/hermes-agent/pull/67034), [#​72176](https://github.com/NousResearch/hermes-agent/pull/72176) — [@​teknium1](https://github.com/teknium1))
##### Providers & models
- Vercel AI Gateway provider + Vercel Sandbox terminal backend return, modernized (SDK 0.7.2, telemetry off) ([#​74518](https://github.com/NousResearch/hermes-agent/pull/74518) — [@​teknium1](https://github.com/teknium1))
- Gemini 3.1 Pro + 3.6 Flash in catalogs; Gemini salvage cluster (3.6-flash aux default, Vertex catalog, direct cost tracking); claude-opus-5 in OpenRouter + Nous Portal; deepseek-v4-flash-0731 ([#​73479](https://github.com/NousResearch/hermes-agent/pull/73479), [#​73516](https://github.com/NousResearch/hermes-agent/pull/73516), [#​70946](https://github.com/NousResearch/hermes-agent/pull/70946), [#​75501](https://github.com/NousResearch/hermes-agent/pull/75501) — [@​teknium1](https://github.com/teknium1))
- Bedrock Converse API prompt caching (cachePoint) ([#​70231](https://github.com/NousResearch/hermes-agent/pull/70231) — [@​JoaoMarcos44](https://github.com/JoaoMarcos44))
- OpenAI data-residency endpoints get declared transport + correct catalog; provider-aware API-server request routing; backend-acknowledged session model lock; Nous sticky routing via top-level session\_id ([#​74958](https://github.com/NousResearch/hermes-agent/pull/74958), [#​70853](https://github.com/NousResearch/hermes-agent/pull/70853), [#​70950](https://github.com/NousResearch/hermes-agent/pull/70950), [#​69253](https://github.com/NousResearch/hermes-agent/pull/69253) — [@​victor-kyriazakos](https://github.com/victor-kyriazakos), [@​teknium1](https://github.com/teknium1))
- Model picker: curated defaults + collapsible providers + select-all; stale caches served instantly with background refresh; custom-endpoint probe capped at 1.5s; honcho OAuth device-code login ([#​73172](https://github.com/NousResearch/hermes-agent/pull/73172), [#​76430](https://github.com/NousResearch/hermes-agent/pull/76430), [#​76922](https://github.com/NousResearch/hermes-agent/pull/76922), [#​61608](https://github.com/NousResearch/hermes-agent/pull/61608) — [@​OutThisLife](https://github.com/OutThisLife), [@​teknium1](https://github.com/teknium1), [@​kshitijk4poor](https://github.com/kshitijk4poor), [@​akattelu](https://github.com/akattelu))
- ACP: named custom providers in the model selector; authenticated cross-provider model choices; non-blocking startup via background MCP discovery ([#​70082](https://github.com/NousResearch/hermes-agent/pull/70082), [#​70404](https://github.com/NousResearch/hermes-agent/pull/70404), [#​75985](https://github.com/NousResearch/hermes-agent/pull/75985) — [@​israellot](https://github.com/israellot), [@​amanning3390](https://github.com/amanning3390), [@​kshitijk4poor](https://github.com/kshitijk4poor))
##### Secrets & config
- Command-helper secret source (composes with all vaults); one-command token rotation + actionable startup errors; opt-in encrypted break-glass cache for Bitwarden; vault-injected keys scoped per profile home; orchestrator preserve\_existing + profile aliasing ([#​69266](https://github.com/NousResearch/hermes-agent/pull/69266), [#​68605](https://github.com/NousResearch/hermes-agent/pull/68605), [#​69251](https://github.com/NousResearch/hermes-agent/pull/69251), [#​69250](https://github.com/NousResearch/hermes-agent/pull/69250), [#​69058](https://github.com/NousResearch/hermes-agent/pull/69058) — [@​teknium1](https://github.com/teknium1))
- `${env:VAR}` SecretRef parity between config.yaml and MCP config; secret-source env vars reach stdio MCP servers ([#​69267](https://github.com/NousResearch/hermes-agent/pull/69267), [#​69053](https://github.com/NousResearch/hermes-agent/pull/69053) — [@​teknium1](https://github.com/teknium1))
- Canonical config loaders for behavioral reads; table-driven config migration registry; DEFAULT\_CONFIG extracted to config\_defaults.py; auto-migration support floor at v12 ([#​74237](https://github.com/NousResearch/hermes-agent/pull/74237), [#​74200](https://github.com/NousResearch/hermes-agent/pull/74200), [#​74182](https://github.com/NousResearch/hermes-agent/pull/74182), [#​74433](https://github.com/NousResearch/hermes-agent/pull/74433) — [@​teknium1](https://github.com/teknium1))
##### 🌐 Gateway, Relay & Fleet
- Session activity heartbeats, stall watchdog, and bounded compression waits — re-landed hardened after an in-window revert cycle (originally [#​72424](https://github.com/NousResearch/hermes-agent/issues/72424) by [@​fangliquanflq](https://github.com/fangliquanflq)) ([#​76354](https://github.com/NousResearch/hermes-agent/pull/76354) — [@​teknium1](https://github.com/teknium1))
- SessionState consolidation (19 session-keyed dicts → one turn/conversation/persistent-scoped object); TurnContext/TurnRunner seam extraction; declarative busy\_policy on CommandDef ([#​74289](https://github.com/NousResearch/hermes-agent/pull/74289), [#​74353](https://github.com/NousResearch/hermes-agent/pull/74353), [#​74197](https://github.com/NousResearch/hermes-agent/pull/74197) — [@​teknium1](https://github.com/teknium1))
- Relay parity waves: Phase 1 (supported\_ops discovery, identity fields, /handoff aliasing), Phase 2 media, Phase 3 interactive prompts, Phase 4 thread lifecycle; egress typing indicators ([#​71300](https://github.com/NousResearch/hermes-agent/pull/71300), [#​71363](https://github.com/NousResearch/hermes-agent/pull/71363), [#​71404](https://github.com/NousResearch/hermes-agent/pull/71404), [#​71624](https://github.com/NousResearch/hermes-agent/pull/71624), [#​69721](https://github.com/NousResearch/hermes-agent/pull/69721) — [@​benbarclay](https://github.com/benbarclay))
- HSP skill sync: personal client (M1) + org-skills client (M2) + org-skill namespace with token-gated discovery ([#​66730](https://github.com/NousResearch/hermes-agent/pull/66730), [#​70024](https://github.com/NousResearch/hermes-agent/pull/70024), [#​70459](https://github.com/NousResearch/hermes-agent/pull/70459) — [@​benbarclay](https://github.com/benbarclay))
- Buzz (Block/Nostr) platform adapter with native WebSocket inbound transport + NIP-42 auth ([#​73610](https://github.com/NousResearch/hermes-agent/pull/73610), [#​73761](https://github.com/NousResearch/hermes-agent/pull/73761) — [@​teknium1](https://github.com/teknium1))
- Photon: native polls, effects, clarify-as-poll, rich links (4-PR salvage) ([#​73614](https://github.com/NousResearch/hermes-agent/pull/73614) — [@​teknium1](https://github.com/teknium1))
- Slack: native Block Kit clarify buttons; opt-in reaction triggers; outbound payload sanitization; thread-context lifecycle fixes ([#​69318](https://github.com/NousResearch/hermes-agent/pull/69318), [#​70195](https://github.com/NousResearch/hermes-agent/pull/70195), [#​69317](https://github.com/NousResearch/hermes-agent/pull/69317), [#​69320](https://github.com/NousResearch/hermes-agent/pull/69320) — [@​teknium1](https://github.com/teknium1))
- Discord auto-thread sessions keyed on prospective\_thread\_id; reply references built from ids (no fetch\_message); WhatsApp configurable inbound read receipts ([#​76513](https://github.com/NousResearch/hermes-agent/pull/76513), [#​76875](https://github.com/NousResearch/hermes-agent/pull/76875), [#​73322](https://github.com/NousResearch/hermes-agent/pull/73322) — [@​benbarclay](https://github.com/benbarclay), [@​kshitijk4poor](https://github.com/kshitijk4poor))
- Kanban wakes resume the creator's DM/thread session; kanban/delegate wake-ups reach api\_server sessions; per-task model + thinking-depth from the board ([#​72191](https://github.com/NousResearch/hermes-agent/pull/72191), [#​70171](https://github.com/NousResearch/hermes-agent/pull/70171), [#​69876](https://github.com/NousResearch/hermes-agent/pull/69876), [#​76417](https://github.com/NousResearch/hermes-agent/pull/76417) — [@​teknium1](https://github.com/teknium1), [@​OutThisLife](https://github.com/OutThisLife))
- Relay: Discord tool-progress routed into the auto-thread instead of the parent channel ([#​77830](https://github.com/NousResearch/hermes-agent/pull/77830) — [@​benbarclay](https://github.com/benbarclay))
- Outbound webhooks — push signed lifecycle events to external endpoints; simplex channel enumeration in `hermes send --list` ([#​69406](https://github.com/NousResearch/hermes-agent/pull/69406), [#​77110](https://github.com/NousResearch/hermes-agent/pull/77110) — [@​teknium1](https://github.com/teknium1))
##### 🖥️ Hermes Desktop App
##### The platform wave
- **Artifacts** — versioned cards, sandboxed live preview, right-rail viewer ([#​72345](https://github.com/NousResearch/hermes-agent/pull/72345) — [@​teknium1](https://github.com/teknium1))
- **Plugin SDK** — Kanban as the founding desktop plugin; `ctx.download` hands the user a file; widget-app SDK (apps as state+reducer+render) with three reference apps; widget-grid layout engine + background-aware theme engine ([#​61173](https://github.com/NousResearch/hermes-agent/pull/61173), [#​74413](https://github.com/NousResearch/hermes-agent/pull/74413), [#​68306](https://github.com/NousResearch/hermes-agent/pull/68306), [#​20379](https://github.com/NousResearch/hermes-agent/pull/20379) — [@​OutThisLife](https://github.com/OutThisLife))
- Quick-entry window (global hotkey → any session); multiple GUI windows; floating pane placement; pane toggles anywhere + hidden header; ⌘O open-folder-as-project ([#​72315](https://github.com/NousResearch/hermes-agent/pull/72315), [#​68259](https://github.com/NousResearch/hermes-agent/pull/68259), [#​73143](https://github.com/NousResearch/hermes-agent/pull/73143), [#​75848](https://github.com/NousResearch/hermes-agent/pull/75848), [#​74623](https://github.com/NousResearch/hermes-agent/pull/74623) — [@​teknium1](https://github.com/teknium1), [@​OutThisLife](https://github.com/OutThisLife))
- SSH remote-backend connection mode; event-driven live sync replaces always-on polls; remote profile routing/sessions/pool lifecycle repaired ([#​68130](https://github.com/NousResearch/hermes-agent/pull/68130), [#​73673](https://github.com/NousResearch/hermes-agent/pull/73673), [#​72835](https://github.com/NousResearch/hermes-agent/pull/72835) — [@​yoniebans](https://github.com/yoniebans), [@​OutThisLife](https://github.com/OutThisLife))
- Let the agent drive the shell (preview pane + pane focus) AND inspect the desktop app it's developing; find-in-page (Ctrl+F); GUI terminal copy/paste + font picker ([#​69519](https://github.com/NousResearch/hermes-agent/pull/69519), [#​73121](https://github.com/NousResearch/hermes-agent/pull/73121), [#​72235](https://github.com/NousResearch/hermes-agent/pull/72235), [#​73705](https://github.com/NousResearch/hermes-agent/pull/73705), [#​76395](https://github.com/NousResearch/hermes-agent/pull/76395) — [@​OutThisLife](https://github.com/OutThisLife), [@​teknium1](https://github.com/teknium1))
##### Composer & UX
- Attach files/folders/links via picker; composer chips for @​ paths and pasted links; composer undo stack; double-ESC discards draft; double-Enter sends the queued turn; type-to-focus ([#​74668](https://github.com/NousResearch/hermes-agent/pull/74668), [#​73110](https://github.com/NousResearch/hermes-agent/pull/73110), [#​72201](https://github.com/NousResearch/hermes-agent/pull/72201), [#​72288](https://github.com/NousResearch/hermes-agent/pull/72288), [#​74736](https://github.com/NousResearch/hermes-agent/pull/74736), [#​73101](https://github.com/NousResearch/hermes-agent/pull/73101), [#​68918](https://github.com/NousResearch/hermes-agent/pull/68918) — [@​OutThisLife](https://github.com/OutThisLife))
- 2-keypress model switching (⌘⇧M); YOLO in ⌘K with live toggle state; keyboard-first pickers; keyboard navigation for clarify choices; server-owned pins that follow you between apps ([#​74545](https://github.com/NousResearch/hermes-agent/pull/74545), [#​74674](https://github.com/NousResearch/hermes-agent/pull/74674), [#​74602](https://github.com/NousResearch/hermes-agent/pull/74602), [#​69799](https://github.com/NousResearch/hermes-agent/pull/69799), [#​74234](https://github.com/NousResearch/hermes-agent/pull/74234) — [@​OutThisLife](https://github.com/OutThisLife))
- Grouped, live-ticking tool-activity line; improved tool call detail views; [@​session](https://github.com/session) links resolve to clickable titles; brand icons on known-domain links; iMessage-style emoji reactions (opt-in, two-way); double-click to heart ([#​72893](https://github.com/NousResearch/hermes-agent/pull/72893), [#​69868](https://github.com/NousResearch/hermes-agent/pull/69868), [#​71162](https://github.com/NousResearch/hermes-agent/pull/71162), [#​73047](https://github.com/NousResearch/hermes-agent/pull/73047), [#​74533](https://github.com/NousResearch/hermes-agent/pull/74533), [#​74644](https://github.com/NousResearch/hermes-agent/pull/74644) — [@​OutThisLife](https://github.com/OutThisLife), [@​teknium1](https://github.com/teknium1))
- Sidebar date dividers + pinned section + opt-in stale-session auto-archive; sessions stop lying about running state; credit-usage toasts; configurable attachment size limit; Cron Blueprints + Webhooks pages; searchable timezone picker ([#​70822](https://github.com/NousResearch/hermes-agent/pull/70822), [#​72303](https://github.com/NousResearch/hermes-agent/pull/72303), [#​69828](https://github.com/NousResearch/hermes-agent/pull/69828), [#​73221](https://github.com/NousResearch/hermes-agent/pull/73221), [#​70066](https://github.com/NousResearch/hermes-agent/pull/70066), [#​69687](https://github.com/NousResearch/hermes-agent/pull/69687), [#​73505](https://github.com/NousResearch/hermes-agent/pull/73505) — [@​OutThisLife](https://github.com/OutThisLife), [@​austinpickett](https://github.com/austinpickett), [@​Adolanium](https://github.com/Adolanium), [@​teknium1](https://github.com/teknium1))
- RFC 8252 native desktop sign-in (system browser + PKCE, no webview cookies); "Connect to existing Hermes" in first-run onboarding; profile-correct pairing approvals with a desktop surface ([#​67920](https://github.com/NousResearch/hermes-agent/pull/67920), [#​70907](https://github.com/NousResearch/hermes-agent/pull/70907), [#​74446](https://github.com/NousResearch/hermes-agent/pull/74446) — [@​benbarclay](https://github.com/benbarclay), [@​OutThisLife](https://github.com/OutThisLife))
- Keep-computer-awake toggle + notch wake indicator; /battery status-bar toggle; UI zoom 90% default preset; status bar hideable ([#​68140](https://github.com/NousResearch/hermes-agent/pull/68140), [#​76396](https://github.com/NousResearch/hermes-agent/pull/76396), [#​68860](https://github.com/NousResearch/hermes-agent/pull/68860), [#​73161](https://github.com/NousResearch/hermes-agent/pull/73161), [#​72960](https://github.com/NousResearch/hermes-agent/pull/72960) — [@​OutThisLife](https://github.com/OutThisLife), [@​teknium1](https://github.com/teknium1))
##### Desktop performance (60fps wave 2)
- Streaming cost independent of transcript length; 60fps on real sessions (reflow-gated pins, adaptive flush); drag at 60fps with five streaming tabs; multitab streaming made fast ([#​71835](https://github.com/NousResearch/hermes-agent/pull/71835), [#​72504](https://github.com/NousResearch/hermes-agent/pull/72504), [#​72346](https://github.com/NousResearch/hermes-agent/pull/72346), [#​71780](https://github.com/NousResearch/hermes-agent/pull/71780) — [@​OutThisLife](https://github.com/OutThisLife))
- Hidden-pane timers paused (agents view, cron sidebar, floating pet), scroll/status loops stopped in busy sessions ([#​77651](https://github.com/NousResearch/hermes-agent/pull/77651) — [@​kshitijk4poor](https://github.com/kshitijk4poor)); idle CPU near zero in the background; sidebar/overlay render churn killed; statusbar + transcript stop re-rendering per token/sash-drag/session-switch; ⌘K opens instantly; renderer cold start keeps shiki/mermaid off the boot path ([#​75218](https://github.com/NousResearch/hermes-agent/pull/75218), [#​73698](https://github.com/NousResearch/hermes-agent/pull/73698), [#​72163](https://github.com/NousResearch/hermes-agent/pull/72163), [#​72245](https://github.com/NousResearch/hermes-agent/pull/72245), [#​72524](https://github.com/NousResearch/hermes-agent/pull/72524), [#​74665](https://github.com/NousResearch/hermes-agent/pull/74665), [#​73024](https://github.com/NousResearch/hermes-agent/pull/73024) — [@​OutThisLife](https://github.com/OutThisLife))
- State diagnostics (render + store churn counters) + a lint rule banning atom-mirrored refs so the stale-read bug class cannot return; Playwright E2E suite with visual regression diffs ([#​71925](https://github.com/NousResearch/hermes-agent/pull/71925), [#​71560](https://github.com/NousResearch/hermes-agent/pull/71560), [#​65805](https://github.com/NousResearch/hermes-agent/pull/65805) — [@​OutThisLife](https://github.com/OutThisLife), [@​teknium1](https://github.com/teknium1), [@​ethernet8023](https://github.com/ethernet8023))
##### 🖥️ CLI, TUI & Dashboard
- `!` shell mode; `/init` AGENTS.md generation; `/diff` (staged/all/session, cross-surface); `/context` breakdown; `/focus` reduced-output view; Ctrl+S prompt stash; persistent `/goal` indicator; multi-select clarify (checkboxes) across CLI/gateway/TUI ([#​72257](https://github.com/NousResearch/hermes-agent/pull/72257), [#​72178](https://github.com/NousResearch/hermes-agent/pull/72178), [#​72240](https://github.com/NousResearch/hermes-agent/pull/72240), [#​72242](https://github.com/NousResearch/hermes-agent/pull/72242), [#​72302](https://github.com/NousResearch/hermes-agent/pull/72302), [#​72262](https://github.com/NousResearch/hermes-agent/pull/72262), [#​72244](https://github.com/NousResearch/hermes-agent/pull/72244), [#​72188](https://github.com/NousResearch/hermes-agent/pull/72188) — [@​teknium1](https://github.com/teknium1), salvaging [@​SHL0MS](https://github.com/SHL0MS), [@​iRonin](https://github.com/iRonin), [@​gigi206](https://github.com/gigi206) + more)
- `hermes import-agent` — one-command migration from Claude Code / Codex CLI setups ([#​72190](https://github.com/NousResearch/hermes-agent/pull/72190) — [@​teknium1](https://github.com/teknium1))
- Per-turn summary line + live token flow in the spinner; cross-surface theme SDK (one skin themes CLI, TUI, and desktop, live) ([#​72246](https://github.com/NousResearch/hermes-agent/pull/72246), [#​68857](https://github.com/NousResearch/hermes-agent/pull/68857) — [@​teknium1](https://github.com/teknium1), [@​OutThisLife](https://github.com/OutThisLife))
- TUI: reach the model picker without wrecking your draft + mid-turn switching; slash menu leads with your most-used skills; attachments live in the composer; Arabic (ar) locale with RTL across desktop/dashboard/agent ([#​74756](https://github.com/NousResearch/hermes-agent/pull/74756), [#​75931](https://github.com/NousResearch/hermes-agent/pull/75931), [#​75210](https://github.com/NousResearch/hermes-agent/pull/75210), [#​70870](https://github.com/NousResearch/hermes-agent/pull/70870) — [@​OutThisLife](https://github.com/OutThisLife))
- `hermes -w` startup \~14s → \~1.8s; global `--version` fast path; banner update-check 6× faster; dashboard lazy-loads routes + GROUP BY session stats; session filtering tabs (Chats/Automation/All) ([#​71637](https://github.com/NousResearch/hermes-agent/pull/71637), [#​62096](https://github.com/NousResearch/hermes-agent/pull/62096), [#​74188](https://github.com/NousResearch/hermes-agent/pull/74188), [#​72294](https://github.com/NousResearch/hermes-agent/pull/72294), [#​73362](https://github.com/NousResearch/hermes-agent/pull/73362), [#​73865](https://github.com/NousResearch/hermes-agent/pull/73865) — [@​teknium1](https://github.com/teknium1), [@​kshitijk4poor](https://github.com/kshitijk4poor))
- Runtime: Node 26 required across installers/heal/upgrade, managed Node/uv resolve before bare PATH, outdated managed trees heal to target major; brew + pip/PyPI wheel channels retired (shell installer / Docker / Nix are the supported channels) ([#​76459](https://github.com/NousResearch/hermes-agent/pull/76459), [#​68217](https://github.com/NousResearch/hermes-agent/pull/68217) — [@​ethernet8023](https://github.com/ethernet8023))
##### 🧩 Skills, Plugins & MCP
- **A2A v1.0** — Agent-to-Agent protocol plugin (closes [#​514](https://github.com/NousResearch/hermes-agent/issues/514)) ([#​77109](https://github.com/NousResearch/hermes-agent/pull/77109) — [@​teknium1](https://github.com/teknium1))
- Curator: surface unmanaged skills + `curator adopt`; skill-description truncation surfaced to authors; grounded-citations skill (+ fact-checking mode); simplify-code v1.1; tldraw-offline scripting skill ([#​71648](https://github.com/NousResearch/hermes-agent/pull/71648), [#​70519](https://github.com/NousResearch/hermes-agent/pull/70519), [#​71698](https://github.com/NousResearch/hermes-agent/pull/71698), [#​77104](https://github.com/NousResearch/hermes-agent/pull/77104), [#​70440](https://github.com/NousResearch/hermes-agent/pull/70440), [#​66896](https://github.com/NousResearch/hermes-agent/pull/66896) — [@​teknium1](https://github.com/teknium1))
- Office skills bundled: docx, xlsx, pdf + refreshed powerpoint; skills-tree debloat continues (yuanbao, segment-anything, jupyter, heartmula, audiocraft → optional-skills; claude-marketplace source removed; hub restructure absorbing themes/desktop-plugins/tui-widgets) ([#​68595](https://github.com/NousResearch/hermes-agent/pull/68595), [#​70452](https://github.com/NousResearch/hermes-agent/pull/70452)–[#​70456](https://github.com/NousResearch/hermes-agent/pull/70456), [#​73903](https://github.com/NousResearch/hermes-agent/pull/73903) — [@​teknium1](https://github.com/teknium1))
- MCP: Comfy Cloud catalog entry with curated 20-tool default; hidden-whitespace warnings in MCP config; pinecone-research optional skill ([#​66112](https://github.com/NousResearch/hermes-agent/pull/66112), [#​75736](https://github.com/NousResearch/hermes-agent/pull/75736), [#​70512](https://github.com/NousResearch/hermes-agent/pull/70512) — [@​teknium1](https://github.com/teknium1))
- MCP lazy server startup from a fingerprint-keyed on-disk tool-schema cache — configured servers no longer all boot at session start (design from [#​56832](https://github.com/NousResearch/hermes-agent/issues/56832)) ([#​77511](https://github.com/NousResearch/hermes-agent/pull/77511) — [@​kshitijk4poor](https://github.com/kshitijk4poor))
- NeMo Relay observability integration — re-landed after an in-window revert, on stable NeMo Relay 0.6 ([#​67607](https://github.com/NousResearch/hermes-agent/pull/67607) — [@​afourniernv](https://github.com/afourniernv))
- Gateway health & diagnostics OTLP export ([#​64536](https://github.com/NousResearch/hermes-agent/pull/64536) — [@​victor-kyriazakos](https://github.com/victor-kyriazakos))
##### 🔒 Security & Reliability
- Iron-proxy credential-injection egress firewall re-landed ([#​70848](https://github.com/NousResearch/hermes-agent/pull/70848) — [@​teknium1](https://github.com/teknium1))
- DNS-pinned SSRF-safe fetches + Slack CDN allowlist; strict redaction at compaction boundaries; ReDoS eliminated in config-key redaction patterns; prose words embedding a secret keyword no longer masked ([#​70193](https://github.com/NousResearch/hermes-agent/pull/70193), [#​69294](https://github.com/NousResearch/hermes-agent/pull/69294), [#​76083](https://github.com/NousResearch/hermes-agent/pull/76083), [#​67776](https://github.com/NousResearch/hermes-agent/pull/67776) — [@​teknium1](https://github.com/teknium1))
- Tier-3 credential reads scoped (FAL/XAI/VERCEL/DAYTONA/GITHUB presence checks etc.); CVE dependency pins refreshed (cryptography, starlette, python-multipart); hindsight env file 0600; /model moved off the gateway event loop ([#​75888](https://github.com/NousResearch/hermes-agent/pull/75888), [#​72362](https://github.com/NousResearch/hermes-agent/pull/72362) — [@​teknium1](https://github.com/teknium1))
- Windows hardening wave: text-mode subprocess decode bug class closed repo-wide, console flashes hidden across daemons/env probes/LSP/installer paths, residual encoding gaps (MCP stdio, gateway update I/O, STT/TTS, desktop spawn) ([#​70875](https://github.com/NousResearch/hermes-agent/pull/70875), [#​70205](https://github.com/NousResearch/hermes-agent/pull/70205), [#​70264](https://github.com/NousResearch/hermes-agent/pull/70264), [#​71014](https://github.com/NousResearch/hermes-agent/pull/71014) — [@​teknium1](https://github.com/teknium1), salvaging several community PRs)
- State/session integrity: four session-state fixes (safe close tracking, flush-cursor class fix, row-retry, usage-PK healer); compact v23 FTS layout + `hermes sessions optimize` + CJK-bigram FTS; read-path split with per-thread read-only connections ([#​75883](https://github.com/NousResearch/hermes-agent/pull/75883), [#​65798](https://github.com/NousResearch/hermes-agent/pull/65798), [#​69423](https://github.com/NousResearch/hermes-agent/pull/69423), [#​73344](https://github.com/NousResearch/hermes-agent/pull/73344) — [@​teknium1](https://github.com/teknium1), [@​kshitijk4poor](https://github.com/kshitijk4poor))
- OpenViking memory-provider hardening — fail closed on blocked endpoints, server verification before credentials are sent, config.yaml-first settings ([#​77747](https://github.com/NousResearch/hermes-agent/pull/77747) — [@​kshitijk4poor](https://github.com/kshitijk4poor))
- Credential pool: reset-aware primary restore (stay on fallback until the rate-limit window resets) + deferred-refresh locking fixes; FTS UPDATE triggers narrowed with fail-closed CJK migration ([#​77631](https://github.com/NousResearch/hermes-agent/pull/77631), [#​77628](https://github.com/NousResearch/hermes-agent/pull/77628) — [@​kshitijk4poor](https://github.com/kshitijk4poor))
- Config-driven memory allocator trim with telemetry; holographic memory vectors stored float32; loop-invariant HRR encodes hoisted ([#​76905](https://github.com/NousResearch/hermes-agent/pull/76905), [#​76917](https://github.com/NousResearch/hermes-agent/pull/76917), [#​76881](https://github.com/NousResearch/hermes-agent/pull/76881) — [@​kshitijk4poor](https://github.com/kshitijk4poor))
##### 🐛 Notable Bug Fixes
- Voice: full-duplex interruption during generation AND playback; whole-turn desktop speech; auto-TTS delivery gaps ([#​74223](https://github.com/NousResearch/hermes-agent/pull/74223), [#​69936](https://github.com/NousResearch/hermes-agent/pull/69936), [#​73508](https://github.com/NousResearch/hermes-agent/pull/73508) — [@​teknium1](https://github.com/teknium1))
- Desktop: Stop parks the queue instead of firing the next queued prompt; branch-in-new-chat restart loss; false remote-gateway reauthentication; cross-session composer leaks ([#​68725](https://github.com/NousResearch/hermes-agent/pull/68725), [#​71960](https://github.com/NousResearch/hermes-agent/pull/71960), [#​68250](https://github.com/NousResearch/hermes-agent/pull/68250), [#​70986](https://github.com/NousResearch/hermes-agent/pull/70986) — [@​SHL0MS](https://github.com/SHL0MS), [@​alelpoan](https://github.com/alelpoan), [@​helix4u](https://github.com/helix4u), [@​OutThisLife](https://github.com/OutThisLife))
- Gateway: session lists scoped before limiting; relay-backed home delivery after restart; timeline display events persisted ([#​65509](https://github.com/NousResearch/hermes-agent/pull/65509), [#​70102](https://github.com/NousResearch/hermes-agent/pull/70102), [#​69771](https://github.com/NousResearch/hermes-agent/pull/69771) — [@​GodsBoy](https://github.com/GodsBoy), [@​victor-kyriazakos](https://github.com/victor-kyriazakos), [@​ethernet8023](https://github.com/ethernet8023))
- Agent: context-length fallback logging + batch trajectory durability; Codex OAuth context windows revalidated against the live catalog ([#​76027](https://github.com/NousResearch/hermes-agent/pull/76027), [#​68554](https://github.com/NousResearch/hermes-agent/pull/68554) — [@​kshitijk4poor](https://github.com/kshitijk4poor), [@​teknium1](https://github.com/teknium1))
- ...plus roughly 770 more `fix:` PRs across every subsystem this window.
##### 👥 Contributors
**647 contributors** shipped this release (commit authors, co-authors, and salvaged-PR credits).
##### Core
[@​teknium1](https://github.com/teknium1), [@​OutThisLife](https://github.com/OutThisLife) (desktop, voice, perf), [@​kshitijk4poor](https://github.com/kshitijk4poor) (perf, caching, salvage), [@​ethernet8023](https://github.com/ethernet8023) (runtime, E2E, desktop), [@​benbarclay](https://github.com/benbarclay) (relay, HSP, auth)
##### All Contributors (alphabetical)
[@​02356abc](https://github.com/02356abc), [@​0301chris](https://github.com/0301chris), [@​0xAlcibiades](https://github.com/0xAlcibiades), [@​0xDevNinja](https://github.com/0xDevNinja), [@​0xLeathery](https://github.com/0xLeathery), [@​0xprincess](https://github.com/0xprincess), [@​0xr00tf3rr3t](https://github.com/0xr00tf3rr3t), [@​100yenadmin](https://github.com/100yenadmin),
[@​2001Y](https://github.com/2001Y), [@​3ssiri](https://github.com/3ssiri), [@​55nx954gn6-debug](https://github.com/55nx954gn6-debug), [@​686f6c61](https://github.com/686f6c61), [@​87degrees](https://github.com/87degrees), [@​aaronlab](https://github.com/aaronlab), [@​abundantbeing](https://github.com/abundantbeing), [@​Adolanium](https://github.com/Adolanium),
[@​adriansotomora](https://github.com/adriansotomora), [@​adurham](https://github.com/adurham), [@​afourniernv](https://github.com/afourniernv), [@​afurm](https://github.com/afurm), [@​AgenticSpark](https://github.com/AgenticSpark), [@​ahmadashfq](https://github.com/ahmadashfq), [@​AhmetArif0](https://github.com/AhmetArif0), [@​ai-ag2026](https://github.com/ai-ag2026),
[@​AIalliAI](https://github.com/AIalliAI), [@​aider4ryder](https://github.com/aider4ryder), [@​airclear](https://github.com/airclear), [@​ajzrva-sys](https://github.com/ajzrva-sys), [@​akattelu](https://github.com/akattelu), [@​AKAZIK-py](https://github.com/AKAZIK-py), [@​akb4q](https://github.com/akb4q), [@​akshan-main](https://github.com/akshan-main), [@​AlanBurningsuit](https://github.com/AlanBurningsuit),
[@​alelpoan](https://github.com/alelpoan), [@​AlexFucuson9](https://github.com/AlexFucuson9), [@​AlexxRussell](https://github.com/AlexxRussell), [@​AllardQuek](https://github.com/AllardQuek), [@​alt-glitch](https://github.com/alt-glitch), [@​aman-merchant](https://github.com/aman-merchant), [@​amanning3390](https://github.com/amanning3390), [@​amathxbt](https://github.com/amathxbt),
[@​aml1973](https://github.com/aml1973), [@​amoreno16003](https://github.com/amoreno16003), [@​AndrewMoryakov](https://github.com/AndrewMoryakov), [@​andrexibiza](https://github.com/andrexibiza), [@​andynguyendk](https://github.com/andynguyendk), [@​andyylin](https://github.com/andyylin), [@​aneym](https://github.com/aneym), [@​angelos](https://github.com/angelos),
[@​aniruddhaadak80](https://github.com/aniruddhaadak80), [@​AnnasMazhar](https://github.com/AnnasMazhar), [@​annguyenNous](https://github.com/annguyenNous), [@​anoopmehendale-cue](https://github.com/anoopmehendale-cue), [@​AnthonyFrancis](https://github.com/AnthonyFrancis), [@​arcabotai](https://github.com/arcabotai), [@​ArcherQAQ](https://github.com/ArcherQAQ),
[@​Ares4Tech](https://github.com/Ares4Tech), [@​arimu1](https://github.com/arimu1), [@​arnoldfrancisca](https://github.com/arnoldfrancisca), [@​asimons81](https://github.com/asimons81), [@​asorry75](https://github.com/asorry75), [@​AtakanGs](https://github.com/AtakanGs), [@​ATran28](https://github.com/ATran28), [@​austinpickett](https://github.com/austinpickett),
[@​Automata-intelligentsia](https://github.com/Automata-intelligentsia), [@​awain7](https://github.com/awain7), [@​aweiker](https://github.com/aweiker), [@​aydnOktay](https://github.com/aydnOktay), [@​ayushere](https://github.com/ayushere), [@​b](https://github.com/b), [@​baau](https://github.com/baau), [@​baauzi](https://github.com/baauzi), [@​baenregod](https://github.com/baenregod),
[@​bakhtiersizhaev](https://github.com/bakhtiersizhaev), [@​Baophan00](https://github.com/Baophan00), [@​baoyu0](https://github.com/baoyu0), [@​Bartok9](https://github.com/Bartok9), [@​basilalshukaili](https://github.com/basilalshukaili), [@​BB-light](https://github.com/BB-light), [@​bbopen](https://github.com/bbopen), [@​Beandon13](https://github.com/Beandon13),
[@​beardedeagle](https://github.com/beardedeagle), [@​bedirhancode](https://github.com/bedirhancode), [@​benbarclay](https://github.com/benbarclay), [@​benegessarit](https://github.com/benegessarit), [@​benjamin2026-dot](https://github.com/benjamin2026-dot), [@​bennybuoy](https://github.com/bennybuoy), [@​BenSheridanEdwards](https://github.com/BenSheridanEdwards),
[@​BKStock](https://github.com/BKStock), [@​BlackishGreen33](https://github.com/BlackishGreen33), [@​bnikanjam](https://github.com/bnikanjam), [@​bounce12340](https://github.com/bounce12340), [@​Bounty13](https://github.com/Bounty13), [@​bpross](https://github.com/bpross), [@​briandevans](https://github.com/briandevans), [@​bricelb](https://github.com/bricelb), [@​brunopirz](https://github.com/brunopirz),
[@​bryanneva](https://github.com/bryanneva), [@​byshubham](https://github.com/byshubham), [@​camaleonidas](https://github.com/camaleonidas), [@​canorionen](https://github.com/canorionen), [@​carbongotfound](https://github.com/carbongotfound), [@​carljborg](https://github.com/carljborg), [@​carlotestor](https://github.com/carlotestor), [@​carrion256](https://github.com/carrion256),
[@​caseyanthony](https://github.com/caseyanthony), [@​cat-thats-fat](https://github.com/cat-thats-fat), [@​Cdddo](https://github.com/Cdddo), [@​ceverson70](https://github.com/ceverson70), [@​chancelu](https://github.com/chancelu), [@​chaos-xxl](https://github.com/chaos-xxl), [@​CharlesMcquade](https://github.com/CharlesMcquade), [@​chazmaniandinkle](https://github.com/chazmaniandinkle),
[@​chefboyrdave21](https://github.com/chefboyrdave21), [@​chelsealong](https://github.com/chelsealong), [@​Christopher-Schulze](https://github.com/Chr…
pull Bot
pushed a commit
to ai-starklabs/hermes-agent
that referenced
this pull request
Aug 7, 2026
After `hermes update`, the desktop sidebar showed "No sessions yet" until the user's first message. NousResearch#72424 added sessions.last_activity_at, which list_sessions_rich now selects — but column adds only land through _reconcile_columns() in the writable _init_schema, and read-only opens skip that by design. Every sidebar read path opens state.db read-only, so each poll raised "no such column: s.last_activity_at" until the first prompt's lazy session-row persist forced a writable open and reconciled. A heal for exactly this class already existed (_open_session_db_for_profile probes the read-only handle and does a one-time writable reopen on staleness), but its probe was a hand-written four-column list that never learned last_activity_at — it went stale three days after shipping. And the batched sidebar route (/api/profiles/sessions/sidebar) bypassed the helper entirely, swallowing per-profile failures into an errors array the desktop never surfaces, so the incident produced an empty sidebar with clean logs. The fix removes the maintenance burden instead of paying it once more: - hermes_state_schema.schema_read_probe_statements() derives one `SELECT <every declared column> FROM <table> LIMIT 0` per table from SCHEMA_SQL via the existing _parse_schema_columns() — the same source of truth the writable reconciler diffs against, so any future ADD COLUMN is probed with no list to update. Column references are table-qualified: an unqualified double-quoted identifier that fails to resolve silently degrades to a string literal (SQLite's double-quoted-string misfeature) and would make the probe pass on exactly the store it exists to catch. - web_server splits the heal into a path-level _open_session_db_at_path (semantics unchanged) so the cross-profile session routes can share it; both profiles.py loops and _count_status_active_sessions (the remaining raw read-only sibling) now open through it. The heal stays a helper rather than a SessionDB classmethod on purpose: escalation-to-writable must remain an explicit caller decision — update_cmd.py opens read-only mid-update and must never write. - Exhaustion guard: if the writable heal SUCCEEDS and the re-probe still fails (a schema problem ADD COLUMN cannot express), the store is marked exhausted — warn once, skip the probe, serve reads probe-less — instead of re-running the full writable init on every poll against a possibly live DB. A FAILED writable open (transient lock) is deliberately not recorded, so the next poll retries the heal. - The per-profile swallow sites in profiles.py now also log a deduplicated warning, so a persistent read failure is loud in errors.log even though the response errors array stays invisible to the sidebar. Tests: probe/SCHEMA_SQL coverage invariants (tests/test_schema_read_probe.py), last_activity_at added to the /api/sessions heal parametrize, a sidebar-route heal test reproducing the shipped symptom (errors == [] and the session returned against a store missing the column), and an exhaustion test pinning exactly one writable open. The sidebar and last_activity_at tests fail on main.
POWERFULMOVES
pushed a commit
to POWERFULMOVES/PMOVES-hermes-agent
that referenced
this pull request
Aug 10, 2026
After `hermes update`, the desktop sidebar showed "No sessions yet" until the user's first message. NousResearch#72424 added sessions.last_activity_at, which list_sessions_rich now selects — but column adds only land through _reconcile_columns() in the writable _init_schema, and read-only opens skip that by design. Every sidebar read path opens state.db read-only, so each poll raised "no such column: s.last_activity_at" until the first prompt's lazy session-row persist forced a writable open and reconciled. A heal for exactly this class already existed (_open_session_db_for_profile probes the read-only handle and does a one-time writable reopen on staleness), but its probe was a hand-written four-column list that never learned last_activity_at — it went stale three days after shipping. And the batched sidebar route (/api/profiles/sessions/sidebar) bypassed the helper entirely, swallowing per-profile failures into an errors array the desktop never surfaces, so the incident produced an empty sidebar with clean logs. The fix removes the maintenance burden instead of paying it once more: - hermes_state_schema.schema_read_probe_statements() derives one `SELECT <every declared column> FROM <table> LIMIT 0` per table from SCHEMA_SQL via the existing _parse_schema_columns() — the same source of truth the writable reconciler diffs against, so any future ADD COLUMN is probed with no list to update. Column references are table-qualified: an unqualified double-quoted identifier that fails to resolve silently degrades to a string literal (SQLite's double-quoted-string misfeature) and would make the probe pass on exactly the store it exists to catch. - web_server splits the heal into a path-level _open_session_db_at_path (semantics unchanged) so the cross-profile session routes can share it; both profiles.py loops and _count_status_active_sessions (the remaining raw read-only sibling) now open through it. The heal stays a helper rather than a SessionDB classmethod on purpose: escalation-to-writable must remain an explicit caller decision — update_cmd.py opens read-only mid-update and must never write. - Exhaustion guard: if the writable heal SUCCEEDS and the re-probe still fails (a schema problem ADD COLUMN cannot express), the store is marked exhausted — warn once, skip the probe, serve reads probe-less — instead of re-running the full writable init on every poll against a possibly live DB. A FAILED writable open (transient lock) is deliberately not recorded, so the next poll retries the heal. - The per-profile swallow sites in profiles.py now also log a deduplicated warning, so a persistent read failure is loud in errors.log even though the response errors array stays invisible to the sidebar. Tests: probe/SCHEMA_SQL coverage invariants (tests/test_schema_read_probe.py), last_activity_at added to the /api/sessions heal parametrize, a sidebar-route heal test reproducing the shipped symptom (errors == [] and the session returned against a store missing the column), and an exhaustion test pinning exactly one writable open. The sidebar and last_activity_at tests fail on main.
randlee
pushed a commit
to randlee/hermes-agent
that referenced
this pull request
Aug 11, 2026
…out (NousResearch#72424) Three mechanisms to detect and notify when gateway sessions stall silently: 1. Mid-turn activity heartbeats stamped to SessionDB so hermes sessions list and hermes status show progress during long turns without new message rows. 2. Stall watchdog: when a busy session has pending inbound and the shared activity clock is idle past agent.session_stall_timeout (default 300), log a WARNING and notify the user once to try /new. Notify-only; does not kill the turn. 3. Compaction timeout: fenceless compress_context callers get a progress-aware host budget (compression.context_timeout_seconds default 120 idle, compression.context_total_ceiling_seconds default 600 ceiling). On timeout, cancel via commit fence, skip compaction without dropping messages, and continue the turn. Closes NousResearch#72016 (slices 1-3; slice 4 cumulative SSE stream-retry deadline remains a follow-up). Cherry-picked from PR NousResearch#72424 by @fangliquanflq.
randlee
pushed a commit
to randlee/hermes-agent
that referenced
this pull request
Aug 11, 2026
Three code-reuse fixes applied during salvage: 1. Reuse _relative_time from hermes_cli/main.py instead of duplicating the relative-time formatting logic in hermes_cli/status.py. 2. Extract _stamp_hygiene_compression_provenance helper in gateway/run.py to deduplicate the two nearly-identical try/except blocks that stamp compression timeout/abort provenance in the hygiene path. 3. Add ContextCompressor.record_timeout_failure() method and use it from the in-agent compress_context timeout callback instead of re-implementing the (60, 300, 900) cooldown ladder inline. The existing summary-LLM exception handler already has this ladder — now both paths share one method.
randlee
pushed a commit
to randlee/hermes-agent
that referenced
this pull request
Aug 11, 2026
randlee
pushed a commit
to randlee/hermes-agent
that referenced
this pull request
Aug 11, 2026
…fy, compress timeout Reverting NousResearch#72817 (salvage of NousResearch#72424) pending further review. All 4 commits reverted: feat, refactor, chore (contributor map), CI fix.
randlee
pushed a commit
to randlee/hermes-agent
that referenced
this pull request
Aug 11, 2026
…out (NousResearch#72424) Three mechanisms to detect and notify when gateway sessions stall silently: 1. Mid-turn activity heartbeats stamped to SessionDB so hermes sessions list and hermes status show progress during long turns without new message rows. 2. Stall watchdog: when a busy session has pending inbound and the shared activity clock is idle past agent.session_stall_timeout (default 300), log a WARNING and notify the user once to try /new. Notify-only; does not kill the turn. 3. Compaction timeout: fenceless compress_context callers get a progress-aware host budget (compression.context_timeout_seconds default 120 idle, compression.context_total_ceiling_seconds default 600 ceiling). On timeout, cancel via commit fence, skip compaction without dropping messages, and continue the turn. Closes NousResearch#72016 (slices 1-3; slice 4 cumulative SSE stream-retry deadline remains a follow-up). Cherry-picked from PR NousResearch#72424 by @fangliquanflq.
randlee
pushed a commit
to randlee/hermes-agent
that referenced
this pull request
Aug 11, 2026
Three code-reuse fixes applied during salvage: 1. Reuse _relative_time from hermes_cli/main.py instead of duplicating the relative-time formatting logic in hermes_cli/status.py. 2. Extract _stamp_hygiene_compression_provenance helper in gateway/run.py to deduplicate the two nearly-identical try/except blocks that stamp compression timeout/abort provenance in the hygiene path. 3. Add ContextCompressor.record_timeout_failure() method and use it from the in-agent compress_context timeout callback instead of re-implementing the (60, 300, 900) cooldown ladder inline. The existing summary-LLM exception handler already has this ladder — now both paths share one method.
randlee
pushed a commit
to randlee/hermes-agent
that referenced
this pull request
Aug 11, 2026
After `hermes update`, the desktop sidebar showed "No sessions yet" until the user's first message. NousResearch#72424 added sessions.last_activity_at, which list_sessions_rich now selects — but column adds only land through _reconcile_columns() in the writable _init_schema, and read-only opens skip that by design. Every sidebar read path opens state.db read-only, so each poll raised "no such column: s.last_activity_at" until the first prompt's lazy session-row persist forced a writable open and reconciled. A heal for exactly this class already existed (_open_session_db_for_profile probes the read-only handle and does a one-time writable reopen on staleness), but its probe was a hand-written four-column list that never learned last_activity_at — it went stale three days after shipping. And the batched sidebar route (/api/profiles/sessions/sidebar) bypassed the helper entirely, swallowing per-profile failures into an errors array the desktop never surfaces, so the incident produced an empty sidebar with clean logs. The fix removes the maintenance burden instead of paying it once more: - hermes_state_schema.schema_read_probe_statements() derives one `SELECT <every declared column> FROM <table> LIMIT 0` per table from SCHEMA_SQL via the existing _parse_schema_columns() — the same source of truth the writable reconciler diffs against, so any future ADD COLUMN is probed with no list to update. Column references are table-qualified: an unqualified double-quoted identifier that fails to resolve silently degrades to a string literal (SQLite's double-quoted-string misfeature) and would make the probe pass on exactly the store it exists to catch. - web_server splits the heal into a path-level _open_session_db_at_path (semantics unchanged) so the cross-profile session routes can share it; both profiles.py loops and _count_status_active_sessions (the remaining raw read-only sibling) now open through it. The heal stays a helper rather than a SessionDB classmethod on purpose: escalation-to-writable must remain an explicit caller decision — update_cmd.py opens read-only mid-update and must never write. - Exhaustion guard: if the writable heal SUCCEEDS and the re-probe still fails (a schema problem ADD COLUMN cannot express), the store is marked exhausted — warn once, skip the probe, serve reads probe-less — instead of re-running the full writable init on every poll against a possibly live DB. A FAILED writable open (transient lock) is deliberately not recorded, so the next poll retries the heal. - The per-profile swallow sites in profiles.py now also log a deduplicated warning, so a persistent read failure is loud in errors.log even though the response errors array stays invisible to the sidebar. Tests: probe/SCHEMA_SQL coverage invariants (tests/test_schema_read_probe.py), last_activity_at added to the /api/sessions heal parametrize, a sidebar-route heal test reproducing the shipped symptom (errors == [] and the session returned against a store missing the column), and an exhaustion test pinning exactly one writable open. The sidebar and last_activity_at tests fail on main.
33hodl
pushed a commit
to 33hodl/hermes-agent
that referenced
this pull request
Aug 12, 2026
…out (NousResearch#72424) Three mechanisms to detect and notify when gateway sessions stall silently: 1. Mid-turn activity heartbeats stamped to SessionDB so hermes sessions list and hermes status show progress during long turns without new message rows. 2. Stall watchdog: when a busy session has pending inbound and the shared activity clock is idle past agent.session_stall_timeout (default 300), log a WARNING and notify the user once to try /new. Notify-only; does not kill the turn. 3. Compaction timeout: fenceless compress_context callers get a progress-aware host budget (compression.context_timeout_seconds default 120 idle, compression.context_total_ceiling_seconds default 600 ceiling). On timeout, cancel via commit fence, skip compaction without dropping messages, and continue the turn. Closes NousResearch#72016 (slices 1-3; slice 4 cumulative SSE stream-retry deadline remains a follow-up). Cherry-picked from PR NousResearch#72424 by @fangliquanflq.
33hodl
pushed a commit
to 33hodl/hermes-agent
that referenced
this pull request
Aug 12, 2026
Three code-reuse fixes applied during salvage: 1. Reuse _relative_time from hermes_cli/main.py instead of duplicating the relative-time formatting logic in hermes_cli/status.py. 2. Extract _stamp_hygiene_compression_provenance helper in gateway/run.py to deduplicate the two nearly-identical try/except blocks that stamp compression timeout/abort provenance in the hygiene path. 3. Add ContextCompressor.record_timeout_failure() method and use it from the in-agent compress_context timeout callback instead of re-implementing the (60, 300, 900) cooldown ladder inline. The existing summary-LLM exception handler already has this ladder — now both paths share one method.
33hodl
pushed a commit
to 33hodl/hermes-agent
that referenced
this pull request
Aug 12, 2026
33hodl
pushed a commit
to 33hodl/hermes-agent
that referenced
this pull request
Aug 12, 2026
…fy, compress timeout Reverting NousResearch#72817 (salvage of NousResearch#72424) pending further review. All 4 commits reverted: feat, refactor, chore (contributor map), CI fix.
33hodl
pushed a commit
to 33hodl/hermes-agent
that referenced
this pull request
Aug 12, 2026
…out (NousResearch#72424) Three mechanisms to detect and notify when gateway sessions stall silently: 1. Mid-turn activity heartbeats stamped to SessionDB so hermes sessions list and hermes status show progress during long turns without new message rows. 2. Stall watchdog: when a busy session has pending inbound and the shared activity clock is idle past agent.session_stall_timeout (default 300), log a WARNING and notify the user once to try /new. Notify-only; does not kill the turn. 3. Compaction timeout: fenceless compress_context callers get a progress-aware host budget (compression.context_timeout_seconds default 120 idle, compression.context_total_ceiling_seconds default 600 ceiling). On timeout, cancel via commit fence, skip compaction without dropping messages, and continue the turn. Closes NousResearch#72016 (slices 1-3; slice 4 cumulative SSE stream-retry deadline remains a follow-up). Cherry-picked from PR NousResearch#72424 by @fangliquanflq.
33hodl
pushed a commit
to 33hodl/hermes-agent
that referenced
this pull request
Aug 12, 2026
Three code-reuse fixes applied during salvage: 1. Reuse _relative_time from hermes_cli/main.py instead of duplicating the relative-time formatting logic in hermes_cli/status.py. 2. Extract _stamp_hygiene_compression_provenance helper in gateway/run.py to deduplicate the two nearly-identical try/except blocks that stamp compression timeout/abort provenance in the hygiene path. 3. Add ContextCompressor.record_timeout_failure() method and use it from the in-agent compress_context timeout callback instead of re-implementing the (60, 300, 900) cooldown ladder inline. The existing summary-LLM exception handler already has this ladder — now both paths share one method.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Closes three of the four slices in #72016 so gateway/CLI sessions stop going silent when the agent loop stops making progress:
Gateway session activity tracking (P1) - Mid-turn heartbeats stamp
last_activity_at(plus bounded description/provenance) on API, tool, and compaction transitions.hermes sessions listandhermes statusobserve progress even while a turn is still writing no message rows. Listings/status/archive usemax(last_activity_at, latest message).Session stall watchdog (P1) - When a busy session has pending inbound and the shared activity clock is idle past
agent.session_stall_timeout(default 300;0disables), log a WARNING and notify the user once to try/new. Notify-only; does not kill the turn.Compaction timeout (P2) - Fenceless
compress_contextcallers get a progress-aware host budget (compression.context_timeout_secondsdefault 120 idle,compression.context_total_ceiling_secondsdefault 600 ceiling). On timeout, cancel via commit fence, skip compaction without dropping messages, and continue the turn.Compression transitions publish through the same activity provenance so stall consumers can tell "actively compacting" from "stalled". Does not include #72016 item 4 (cumulative SSE stream-retry deadline); that remains a follow-up.
Activity tracking details
AIAgent.get_activity_summary()/agent.session_activityand durable SessionDB heartbeats (ts/description/provenance)._touch_activityon API/tool/compaction start/end; turn end clears description/provenance while keepinglast_activity_atfor idle/watchdog continuity.start()can still republishagent.compression.Stall watchdog details
SendResult(success=False)retries next tick).gateway/shutdown_watchdog.pyandgateway/delivery_ledger.py.Compaction timeout details
_compress_contextonto a module-sharedDaemonThreadPoolExecutor(max_workers=4); poll with gateway-style idle/ceiling waits; cancel viaCompressionCommitFence.commit_fence(gateway hygiene) are not double-wrapped.Related Issue
Fixes #72016
Type of Change
Changes Made
agent/session_activity.py/run_agent.py/hermes_state.py/hermes_cli/status.py- mid-turn activity observation (ts/desc/provenance), freshest-of last_active, CLI status surfacinggateway/session_stall.py/gateway/run.py- pending-inbound stall notify watcher, latch, SendResult-aware sendagent/conversation_compression.py/agent/agent_init.py- daemon-pool progress-aware compaction timeout, fence cancel, compression activity provenancehermes_cli/config.py/cli-config.yaml.example/hermes_cli/dump.py-agent.session_stall_timeout,compression.context_timeout_seconds,compression.context_total_ceiling_secondswebsite/docs/user-guide/configuration.md(+ zh-Hans) - document the new knobstests/agent/test_session_activity.py,tests/run_agent/test_session_activity_persist.py,tests/gateway/test_session_stall_watchdog.py,tests/agent/test_compress_context_progress_timeout.py, plus related config/status/state coverageHow to Test
hermes sessions list/hermes statusadvancelast_activewithout waiting for a new message row; confirm turn end clears activity description/provenance./newnotification after the timeout; confirm a second tick does not spam; confirm activity resume clears the latch for a new episode.Checklist
Code
scripts/run_tests.shon relevant tests and they passDocumentation & Housekeeping
cli-config.yaml.exampleif I added/changed config keysCONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows - N/A