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 i
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 ro
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 atta
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 halluci
## Goal Propagate authenticated webhook event type and immutable delivery identity into configured route scripts so deterministic zero-LLM consumers can verify and persist the same delivery identity that Hermes authenticated. ## Repository `NousResearch/hermes-agent` ## Profile `default` ## Current condition After HMAC validation, `WebhookAdapter._handle_web
## Summary `_manage_thinking_signatures` (`agent/anthropic_adapter.py`) strips **all** thinking blocks from the conversation history for third-party Anthropic-Messages endpoints. MiniMax is explicitly named in the docstring as one of the hosts that "cannot validate them and will reject them outright". Measured against the live endpoint, that premise does not
## Summary The stale-request watchdog for the non-streaming inline path fires, but its abort does NOT actually kill hung TCP sockets. Stalls therefore run far beyond the configured threshold — observed **7137s vs 600s threshold** (11.9x) and 6780s/6562s/4990s/3366s on 2026-08-13 during a DeepSeek API slowdown window. ## Environment - hermes-agent v0.20.0 (20
Bug Description In the desktop app, when the assistant delivers a file via a [File: ](https://github.com/NousResearch/hermes-agent/issues/new?title=%5BDesktop%5D%20MEDIA%20file%20link%20label%20shows%20percent-encoded%20filename%20for%20non-ASCII%20names&labels=bug,comp%2Fdesktop#media:)path, the rendered link label shows the URL-percent-encoded filename ins
## Summary Hermes exposes native session IDs to plugins, but session lifecycle payloads are not consistent enough across CLI, TUI, and Gateway for plugins that must attribute state or writes to the exact logical session. On current `main` (`fa83af3f9a42790730b8966ff67e7d9fb627899f` when reproduced): - CLI `/new` finalizes the old session before minting the n
### Bug Description After updating 0.19.1 → 0.20.0, the Telegram gateway adapter fails to connect. The gateway starts with **no connected platforms** (cron jobs still run), so the bot never answers on Telegram. It retries every few minutes and always fails with `Any cannot be instantiated`. Only the Telegram platform is affected — the dashboard / Desktop con
## Problem `tool_output.max_bytes`, `tool_output.max_lines`, and `tool_output.max_line_length` cap tool output by **size**, not by **relevance**. Every tool result is injected into the agent context as a raw blob up to that cap. That's the wrong axis for a lot of tools. Concrete examples: - **`search_files` / grep-style tools**: a search across a codebase ca
## Bug Description Hermes Desktop violated both session and profile isolation on a local Windows installation. While secondary/compact session windows belonging to two different profiles were active, a prompt intended for Profile A appeared, executed, and was durably stored in the unrelated Profile B session. It appeared twice in Profile B. This was not only
`scripts/install.sh` prints "Installation Complete!" and exits 0 after `install_node_deps` fails, leaving no `node_modules`. ## What happens `install_node_deps` runs `npm install` inside the cloned repo. The failure is caught under a `log_warn` and execution continues; `log_success` then runs unconditionally, `main()` reaches the completion banner, and the s
**Bug: MCP servers page ignores the active profile — shows default profile's servers in any profile** I run Hermes with two profiles (default + a secondary business profile). MCP servers are configured **only** in default (`mcp_servers` in default's config.yaml). The secondary profile has no `mcp_servers` at all — `hermes --profile <name> mcp list` confirms
The sidebar derives the live/working dot from renderer-side turn activity only. Sessions created by other surfaces (CLI, TUI, gateway, cron) that are actively running on the backend appear idle until the renderer sees a turn. Expected: the backend's `active_list` / liveness stamps drive the dot for foreign (agent-created) sessions too. Implementation: #84821
Opening (mounting) a finished session reopens its row (`ended_at` cleared), and the dot-state machine paints it as live even though no message was sent. Expected: resume is read-only; only a real first turn (real activity) reopens/re-lights a finalized session. Implementation: #84847 (stacked on #84821).
Session rows created by one-shot surfaces (cli, acp, cron, subagents) that never close accumulate as open rows with no liveness. Expected: a maintenance pass closes non-chat rows idle for 24h+ (orphan_heal). Implementation: #84846.
The sidebar has no way to mark a session unread or track read-state across restarts. Expected: mark unread/read actions backed by the existing `last_read_at` watermark, surfaced as a persisted unread dot. Implementation: #84822.
remark-math parses prose amounts like `US$ 5M` / `R$ 15.4M` as inline math, corrupting message rendering. Expected: escape currency amounts so the parser leaves them as prose. Implementation: #84183.
The title ladder descends on schema failures but returns unconditionally on empty 200 completions, so a session can end with no title. Expected: descend to the next rung on empty completions too. Implementation: #84137.
A stale inflight-journal fold can re-emit answers that are already in the transcript, showing duplicated messages. Expected: skip folds whose journal state is stale relative to the transcript. Implementation: #84021.
## Title [Bug] `auxiliary.free_only` gate rejects explicitly-requested `:free` models and misreports the skip as a payment/credential error ## Summary When an auxiliary task resolves an OpenRouter client via `resolve_provider_client(provider="openrouter")` with `auxiliary.free_only: true` and the caller passes an **explicit** `:free` model, the `model` argum
## Summary `~/.bashrc` and the other shell rc files are gated by the terminal tool but **not** by the file tools, so `patch`/`write_file` can rewrite them with no prompt. Separately, `touch`, `mkdir` and `ln` are not covered by any `DANGEROUS_PATTERNS` rule, so the `write_file` deny on `~/.ssh/` is trivially reachable around via `terminal`. I know from SECUR
## Bug Report **Version:** Hermes Agent v0.20.0 (2026.8.3), running on Python 3.14.6 (Homebrew) ### Symptom Parallel tool calls fail with: ``` AttributeError: 'DaemonThreadPoolExecutor' object has no attribute '_initializer' ``` This happens when multiple tool calls are dispatched concurrently (e.g. several `web_search` calls in one turn). Single tool calls
### Problem or Use Case Hermes users cannot select SayGM through the provider/profile system today, despite SayGM exposing compatible Chat Completions models and live model discovery. Generic endpoint configuration does not provide curated fallback models, protocol filtering, model output limits, or the required Sol request adjustment. ### Proposed Solution
## Bug Description Hermes Desktop fails to boot with: ``` [hermes] [boot] could not read served dashboard token (Hermes backend): 404: {"error":"Headless backend (hermes serve): web UI disabled — use `hermes dashboard` for the browser UI."} [hermes] [boot] Desktop boot failed: Local Hermes backend is HTTP-reachable but the WebSocket (/api/ws) rejected the se
## Bug Description During `hermes update`, the desktop app rebuild fails because the `get-windows@9.3.0` npm dependency cannot install on Linux. This causes the Electron GUI to be unavailable until the build eventually succeeds (or never, if the conditions persist). The failure chain: 1. `node-pre-gyp` tries to download a prebuilt binary for `get-windows` →
+# Bug Report: Spinner/status line smears vertically instead of updating in-place (v0.20.0, Windows) + +## Description + +After updating from v0.19.0 to v0.20.0, the CLI spinner/status line no longer updates in-place. Each animation frame renders on a new line, filling the terminal with hundreds of repeated status lines instead of a single updating line. + +
### Bug Description The fenced-code protection regex in `plugins/platforms/telegram/adapter.py` (around line 8022, the `_protect_fenced` step before MarkdownV2 escaping) is too permissive: `r'(```(?:[^\n]*\n)?[\s\S]*?```)'` matches **inline** triple backticks anywhere in the text, not just standalone fenced blocks. When a message contains inline `` ``` `` se
# Bug report: cronjob tool create fails when repeat='forever' is passed explicitly ## Summary `cronjob action='create'` raises `TypeError: '<=' not supported between instances of 'str' and 'int'` whenever the `repeat` parameter is explicitly provided as the string `"forever"`, even though the tool's own schema/success responses use that exact string value fo
## Summary Two fixes in one file for the stacked-frame guard on Windows PowerShell: ### 1. _get_terminal_surface_id: HWND augmentation After GetConsoleTitleW returns a title, also call GetConsoleWindow() and append the HWND. Two PowerShell tabs with the same default title ("Windows PowerShell") previously both resolved to "win32-console:Windows PowerShell" a
## Summary The dashboard's managed-files API protects sensitive files (`.env`, `config.yaml`, credential stores) on the **read** side (`list` / `read` / `download`), but the **write** endpoints (`/api/files/upload`, `/api/files/upload-stream`, `/api/files/mkdir`) will happily **overwrite** those same files. `_is_sensitive_path()` explicitly documents this as
# WhatsApp pairing: `hermes whatsapp` wizard writes to a different session dir than the gateway reads, and a 0-byte `creds.json` counts as "paired" **Version:** Hermes Agent v0.19.0 (2026.7.20) · upstream `36e41c09` **Platform:** Linux (s6 container image), `HERMES_HOME=/opt/data`, install root `/opt/hermes` Two independent bugs in the WhatsApp pairing flow.
## Description On a **Windows host** with `terminal.backend: docker`, `vision_analyze` fails for every local image path that routes to the in-container exec-read. The error is 100% reproducible: ``` Error analyzing image: sandbox returned non-image data for '\workspace\research\...\vision_test.png': Only base64 data is allowed ``` Note the **backslashes in t
### Bug Description The Docker container's **s6 boot orchestrator** crash-loops per-profile gateway services when `multiplex_profiles: true` is set via `config.yaml` alone, because the s6 reconciler keys its auto-start decision off the `GATEWAY_MULTIPLEX_PROFILES` **environment variable** rather than the config file the user was told to edit. Setup / repro:
## Bug Setting `provider: ollama-cloud` in `~/.hermes/config.yaml` fails every request with HTTP 404, even though both the native provider profile *and* an explicit `model.base_url` override in config.yaml correctly specify `https://ollama.com/v1`. The actual outbound request silently loses the `/v1` segment and hits `https://ollama.com` (the marketing homep
Hi @DavidMetcalfe. You helped us out on #52954 back in July, the Chrome DevTools blank-profile issue. We've been running `--autoConnect` since and it fixed it for good. Thank you again for that. While running Hermes we ended up building a memory layer that we think fits Hermes' own philosophy, and we'd love your eyes on it. **What it is:** [MAYA Memory Lane]
## Summary After every Hermes auto-update, all profile gateways remain stopped. The sidebar shows a blank list with zero feedback to the user. Recovery requires manually running `gateway start` for each profile via CLI — an impossible task for non-technical users. ## Environment | Item | Value | |------|-------| | **OS** | Windows 10 | | **Hermes Version** |
### Summary A `.drain_request.json` marker that is orphaned **without a machine restart** wedges the gateway in `draining` indefinitely — every inbound message on every platform is bounced with *"⏳ This agent is draining for a maintenance action and isn't accepting new turns right now"* until someone manually removes the marker or the container happens to be
## Bug Description A `kimi-coding` request never returns. The process sends the HTTP request, then blocks **forever** waiting for response headers — no error, no timeout, no fallback. The run has to be killed externally. This is not a slow response: the call is still blocked in `httpcore`'s socket read after 200 s, and the configured per-provider timeout doe
## Problem Hermes core owns directory and entry-point discovery, collision precedence, and module loading. A plugin-side preflight can validate its own source tree and refuse similarly prefixed sibling directories, but it cannot prove which manifest/module the live PluginManager selected. A generic unsafe case is two enabled directory candidates with differe
## Summary `terminal_tool` crashes with `ValueError: embedded null byte` before running the command, when the command string leads the guard to derive a script path containing a NUL byte. The failure happens in the cron lifecycle guard's pre-flight scan, so the command never executes and the tool call returns an error instead of output. ## Impact Hit repeate
## What does this PR do? - `_rpc_server_loop` and `_rpc_poll_loop` dispatched nested tool calls (e.g. `read_file` invoked by `execute_code`) via `handle_function_call` without passing `session_id`. Plugin hooks `on_pre_tool_call` / `on_post_tool_call` therefore saw an empty `session_id` and could not correlate nested calls with the originating turn. - Follow
## What does this PR do? Adds a per-parent-session cap (`delegation.max_children_per_session`, default 10) on the total number of subagent children that `delegate_task` may spawn across all calls in a session. This directly addresses the "Token Incinerator" scenario in #52484, where a runaway parent spawned 44+ subagent sessions in 53 minutes with no throttl
## What does this PR do? Fixes Azure AI Foundry/OpenAI Responses replay failures by preserving reasoning item `id` fields only on Azure Foundry-style endpoints, while keeping the existing OpenAI/Codex behavior that strips those ids from general Responses replay. Based on the original PR #63264 by @LeonSGP43. This version applies the review feedback from @tek
## Problem Two error-handling gaps in the Telegram caption parse retry path: 1. **Caption-fallback failure is invisible to the agent.** When the caption-fallback send fails (the file is gone and the caption text is sent alone), the error is logged via `logger.warning` but never appended to the `warnings` list — the agent never knows it happened. 2. **Voice/a
## What does this PR do? `hermes update` can finish with a clean `✓ Update complete!` and exit 0 while leaving a running gateway on pre-update modules — the next turn then dies with `ImportError: cannot import name 'is_trivial_prompt' from 'agent.memory_provider'`. The cause is the blanket handler around the entire gateway auto-restart phase in `hermes_cli/u
## Summary Remove Hermes-owned runtime contamination while preserving user-owned `PYTHONPATH` semantics. This consolidates and builds on #78917, incorporates the follow-up correctness work from Yiipu/hermes-agent#1, and rebases the complete attributed history onto main at `f4c2c263f0672a4b1485f3071cd5f79cd32d38ab`. ## Rebase onto main at f4c2c263f (#84500 re
## Bug Description Self-hosted Langfuse list view shows many `Hermes turn` rows with **blank Input/Output** while Observation Levels and Latency are still populated. Drilling in shows GENERATION/TOOL observations but **no CHAIN root**. ## Root Cause Langfuse Python SDK **v3** exposes `span.update_trace()`, not `set_trace_io()`. `_finish_trace` called the mis