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
## What does this PR do? Fixes an HTTP 400 error from DeepSeek v4 and newer OpenAI providers when `sanitize_api_messages()` produces an empty `tool_calls: []` array after deduplicating all tool_calls in a message. The dedup pass introduced by #58327 removes duplicate `tool_call_id`s to comply with provider requirements. However, when ALL tool_calls in a mess
## Summary Resolve configured API session-key aliases into canonical native-platform identities before agent construction. This lets API-originated turns use the same platform identity, toolset selection, prompt context, and session namespace as the configured Telegram or Discord destination without trusting caller-supplied routing fields. ## Behavior - Load
When the positional `agent` parameter is removed from `agent/agent_runtime_helpers.py::anthropic_prompt_cache_policy`, all call sites that pass `agent` positionally raise at runtime: - `agent/moa_loop.py:247` (positional) - `agent/agent_runtime_helpers.py` (recursive call) - `run_agent.py::_anthropic_prompt_cache_policy` (forwarder) This was traced from a us
## What does this PR do? Adds first-class `agent.text_verbosity` configuration for OpenAI Responses requests. Valid values are `low`, `medium`, and `high`; empty, unset, or malformed values preserve the provider default. The setting is emitted as top-level `text.verbosity` only for supported GPT-5 requests through Codex OAuth or the exact `api.openai.com` ho
Bundles previously-separate Hindsight/memory PRs into a single review surface. Each was independently mergeable; combining them avoids parallel reviews of the same file (`plugins/memory/hindsight/__init__.py`, which most of them touch). ## What's included | Supersedes | Change | Fixes | |---|---|---| | #70278 | **Opt-in synchronous recall** for the current t
## What does this PR do? Slack user names, channel names and bot detection are silently broken on `main`: the agent receives `[U0BCE4NRVKN | Slack user <@U0BCE4NRVKN>]` instead of `[Nikita | Slack user <@U0BCE4NRVKN>]`, every user resolves as a non-bot, and some send paths report success as failure. **Root cause.** `slack_sdk` Web API calls return `SlackResp
## What does this PR do? Fixes two gaps in Buzz channel discovery: 1. When no explicit channel allowlist is configured, startup now lists only channels where the agent is a member. 2. A WebSocket membership event now discovers and subscribes to newly joined ordinary channels, not only new DM conversations. An explicit `BUZZ_CHANNELS` configuration remains a
## What does this PR do? The MiniMax **API-key** overlay advertises `anthropic_messages` but had no `base_url_override`. `get_provider()` therefore kept the models.dev OpenAI-style URL (`https://api.minimax.io/v1`). Worse, `hermes setup` persists that `/v1` URL into `model.base_url`, and the runtime pool path treated it as an explicit override of the registr
## What does this PR do? This fixes lifecycle plugin hooks that received different session transition and workspace payloads depending on whether `/new` ran through the CLI, TUI, or messaging gateway. Without this fix, plugins cannot reliably release old-session resources, initialize the replacement session, or associate model turns with the authoritative ta
## What changed - Add an explicit failed capture result with `ok:false`, `success:false`, `status:"failed"`, a bounded error code/phase/repair hint, and target-presence metadata. - Preserve that contract through addon pre-tool governance blocks instead of returning a generic error string. - Reject half-pairs and invalid native capture targets explicitly; kee
## What does this PR do? Fixes a crash when users select `local_embedded` mode via `hermes memory setup`. The setup wizard tries to install `hindsight-all` but the install can silently fail because `capture_output=True` swallows errors. Since `plugin.yaml` only declares `hindsight-client>=0.4.22` as a dependency, hermes startup validation passes even when `h
## Summary When using Anthropic (and other providers that split `system` out of `messages`), Langfuse **LLM call** generation observations only showed user/assistant turns — the Hermes system prompt (skills, memory, context) was missing from the trace input. This change: - Passes `system_prompt` from `api_kwargs["system"]` (with fallback when the first messa
## Summary `_get_langfuse()` holds a global `_LANGFUSE_CLIENT` variable with no lock protecting the double-check initialization. Two concurrent first callers (e.g. two gateway sessions both triggering a Langfuse hook at the same time) both pass the `_LANGFUSE_CLIENT is not None` guard, both construct a `Langfuse(**kwargs)` client, and the loser's client leak
## Summary The desktop model dropdown no longer makes a model look duplicated when a reasoning effort is set. The effort (and "Fast") now renders as a distinct badge chip beside the model name instead of plain grey text appended to it. Fixes #51833. **Root cause:** in `model-menu-panel.tsx` each row built a single `meta` string (`Fast High`, `Med`, …) and re
## What does this PR do? Update/bootstrap orchestration now respects existing configuration before running heavyweight browser dependency installs or interactive setup stages. ## Related Issue ## Type of Change - [x] 🐛 Bug fix (non-breaking change that fixes an issue) - [ ] ✨ New feature (non-breaking change that adds functionality) - [ ] 🔒 Security fix - [
## What does this PR do? Async delegation records each subagent's full task source (goal, context, role, model) in the completion block that re-enters the parent conversation — but **not the toolsets the child actually held** after parent-intersection and blocked-tool stripping. Because of that, when a delegation goal structurally requires a toolset the chil
## What does this PR do? Fixes Langfuse generation/trace/session cost rollups when Hermes exports cache or other custom cost buckets. The bug was reproduced on unchanged `main` at `d2c81eb681dea1382fbd1ed403f58320d5aef575`; the branch is now rebased onto current `main` at `9baa7d4673ce89f09378daa3660530f8bf142708`. Hermes already computes the right request-l
## Summary This is the focused current-main replacement for the unique safety fix in #26873. `get_model_context_length()` can be called while a runtime/model selection is still empty. Before this guard, an empty or `None` model flowed into provider-prefix normalization and then into cache/probe logic. Return the documented 256K fallback immediately instead.
## What does this PR do? `hermes -z "…" -w` accepts `-w/--worktree` but silently ignores it. One-shot mode had no worktree lifecycle — `run_oneshot` (`hermes_cli/oneshot.py`) never set one up, and both `-z` dispatch sites in `hermes_cli/main.py` forwarded neither the flag nor any isolation. So the agent runs in the caller's cwd and its commits land on the ch
Running gateways could keep cached Honcho managers and SDK clients after construction-frozen settings changed, while active session peers retained prior observation settings. This change: - fingerprints every resolved Honcho setting frozen into the gateway agent/provider/manager; - fingerprints secrets without storing raw key material in cache signatures; -
## Problem `_inherit_notify_subs()` in `hermes_cli/kanban_db.py` copies a parent task's notification subscription to a child via `INSERT … SELECT`, but omits the `chat_type` and `delivery_metadata` columns. Inherited child rows silently lose available routing metadata. This affects all three call paths that route through the helper: `create_task(parents=…)`,
Fixes #74604 The agent can end a turn by emitting a progress narration (e.g. 'I am now compiling the complete answer.') as its final assistant message, producing no deliverable. No bound was reached, nothing errored, and no hook exists to catch this. Work in progress — root cause analysis and fix coming in the next commit.
<!-- native-links:v1 --> Related #77221 #77222 #77223 #77262 ## What changed and why This PR turns Hermes' existing local usage accounting and security controls into first-class desktop surfaces. ### 1. Usage observability (`/usage`) The desktop now provides three distinct Usage decks: - **Overview** — profile/session telemetry from `usage.overview`: session
## What does this PR do? Stops the Desktop sessions sidebar from jumping/flickering while you scroll a long virtualized list. Native scroll anchoring was fighting the virtualizer’s padding updates, and date-divider rows were estimated at the session-row height. Rebased onto current `main` so inbox-style card rows keep the 66px estimate. A naive replay of the
## Problem When the PyPI `utils` package is installed in the same venv (common in the webui Docker setup), `from utils import atomic_write_text` in `cron/jobs.py` and `from utils import atomic_replace` in `cron/suggestions.py` resolve to the PyPI package instead of the local `utils.py`, causing: ``` ImportError: cannot import name 'atomic_write_text' from 'u
## Summary Current main's disconnect drop-guard (#55971) correctly refuses to dispatch buffered Telegram updates into a torn-down session (`_should_drop_delayed_delivery` / `_drop_delayed_deliveries`). The implementation still **destroys** the inbound event: debug-level `return` after `pop()` (or before enqueue) at the text/photo/media-group batch sites, and
## Summary Official card ([docs.x.ai/developers/models/grok-4.6](https://docs.x.ai/developers/models/grok-4.6)): **500,000** context. [#84661](https://github.com/NousResearch/hermes-agent/pull/84661) landed the catalog. `main` already lists native `grok-4.6` on the xAI picker. This PR is **only** the leftover cache guard. Pre-catalog builds resolved `grok-4.
## Problem The desktop Memory & context panel for Hindsight (issue #84572) only declares `cloud` and `local_external` modes, so Hindsight instances configured in `local_embedded` mode display incorrect cloud defaults: - **Mode** shows Cloud (fallback from invalid `local_embedded` value) - **API URL** shows the cloud default (the actual value is silently coer
## What does this PR do? Adds right-click "Add as context" to both message blocks (selected text) and file explorer rows, staging content as composer attachment chips that ride along with the next prompt. **Two surfaces, one architecture:** | Surface | Gesture | Result | |---|---|---| | Message thread (user + assistant) | Select text → right-click → "Add as
## Summary - add a separate `nous-blue-contrast` dashboard preset that preserves Nous Blue chrome while using a navy, high-contrast embedded terminal - add a matching built-in TUI skin with a complete audited dark palette - expose both choices in dashboard configuration and document them - keep the existing `nous-blue` theme unchanged ## Test plan - `scripts
## Summary Desktop's `isDesktopSlashCommand` gate rejected `/learn` because it had no row in `DESKTOP_COMMAND_SPECS`, so it never reached the TUI backend handler that already builds the prompt (`agent/learn_prompt.py::build_learn_prompt`). Add it as an `exec()` spec (`argumentMode: text`), matching the existing backend-executed commands. The desktop dispatch
## Summary Two interlocking cron-delivery bugs on relay-fronted Slack deployments (the gateway runs only the relay platform; a connector owns the Slack app). Reported from a live deployment: `/sethome` was set correctly, yet cron jobs created from Slack delivered into the ephemeral thread that Slack spawns around the creation message — and the explicit-targe
## Summary Kanban notify subscriptions gain explicit delivery modes — `notify`, `notify+wake`, `wake` — and woken turns now land in the creator's REAL session instead of a context-less parallel one. Salvage of #37865 by @verybigdog onto current main (authorship preserved; original commits carried a local placeholder identity, re-attributed to the contributor
## Summary Every open PR's CI is currently red on one shard with: ``` FAILED tests/run_agent/test_primary_runtime_restore.py::TestTryRecoverPrimaryTransport::test_allowed_for_nous_anthropic_messages ValueError: Model has a context window of 32,000 tokens, which is below the minimum 64,000 required by Hermes Agent. ``` (Seen on #85444 slice 7/12, #85452 slice
Fixes #2513. When a custom provider is saved via `hermes model` / `hermes setup` with the context-length prompt left blank, the value stays `None` and the runtime resolution chain (`agent/model_metadata.get_model_context_length`) runs silently later. Users got no feedback about which context window was actually in effect — or whether it was a real detection
## What does this PR do? <!-- Describe the change clearly. What problem does it solve? Why is this approach the right one? --> Two small bugfixes from local-mods: 1. **Dedup context engine tools** — `lcm_grep`/`lcm_describe`/`lcm_expand` were injected without checking `valid_tool_names`. On session restore or context-engine re-init, `get_tool_schemas()` retu
## Summary Fixes stuck typing indicator on Telegram that persists after normal session completion. ## Problem Two independent issues caused Telegram typing to stay visible indefinitely: 1. **Normal completion**: `_keep_typing` is cancelled, but Telegram adapter had no `stop_typing()` implementation — the base class no-op left the typing bubble to expire on i
## Problem When a custom provider is configured with `api_mode: anthropic_messages`, the code in `resolve_provider_client()` unconditionally rewrites the base URL via `_to_openai_base_url()`, converting e.g. `http://host/anthropic` → `http://host/v1`. The Anthropic SDK then appends `/v1/messages` to the base URL, resulting in a request to `/v1/v1/messages` →
## Summary This PR is rebased onto current `upstream/main` (`6f1870cd1`) and narrowed to complement #65632 rather than duplicate it. It adds only the OpenAI-compatible provider extensions that #65632 does not cover: - `stt.openai.prompt_file`: a UTF-8 prompt file read at transcription time, so vocabulary edits take effect without restarting Hermes; - `stt.op
## Summary Three model families gained explicit `DEFAULT_CONTEXT_LENGTHS` entries after some users may have already cached lower (incorrect) values through earlier resolution paths. This PR adds stale-cache guards for each, mirroring the pattern used for Kimi (≤32K), MiniMax-M3 (≤204,800), and Grok-4.3 (≤256K) in prior PRs. ### qwen3.6-plus (1M context) The
## Summary Langfuse assistant-message serialization only reads `message.reasoning`. Reasoning models and adapters can expose reasoning under `reasoning_content` or structured `reasoning_details`, which makes Langfuse traces show `reasoning: None` despite available reasoning data. This PR adds a small reasoning extraction helper and uses it during assistant-m
## Summary Stores per-API-call timing and token counts on the agent so downstream consumers (desktop status bar, gateway runtime footer, CLI status bar) can display real-time tokens-per-second. - **run_agent.py**: Initialize `last_api_duration` / `last_output_tokens` on agent - **agent/conversation_loop.py**: Persist per-call `api_duration` + `output_tokens`
## Summary `local_embedded` imports the top-level `hindsight` module (from the `hindsight-all` package), but `plugin.yaml` only declares `hindsight-client`. Users who configure `local_embedded` by hand — or upgrade from the legacy `"mode": "local"` — never run the setup wizard that installs `hindsight-all`, so long-term memory is **silently disabled** behind
## What does this PR do? Adds comprehensive, network-free unit coverage for the lazy dependency install and binding paths in `tools/lazy_deps.py`. The branch has been reconciled with every newer upstream test in the same file; the final test-only diff retains both upstream coverage and this PR's fallback matrix. ## Related Issue Fixes #36565 ## Type of Chang
Currently, if the agent runs a terminal command (like a unit test runner) that fails, and then successfully modifies files to fix the issue (using `patch` or `write_file`), the terminal failure counts are not reset. After `hard_stop_after.exact_failure` (default: 5) attempts, even with different code patches in between, the guardrail blocks the terminal comm
## What does this PR do? `read_file` / `read_file_raw` in `tools/file_operations.py` stat the target with `wc -c` before reading it. **Any** non-zero exit fell straight through to `_suggest_similar_files()`, which returns `File not found: <path>`. When a client disconnects mid-turn (`SSE client disconnected; interrupted agent task ...`), the interrupt kills
## Summary Langfuse **LLM call** generation observations show conversations without the agent's system prompt (skills, memory, SOUL, tool guidance) for every provider that moves the system prompt out of `messages`: - **Anthropic Messages API** → separate `system` kwarg (`agent/anthropic_adapter.py`), reported in #32175 - **Responses/Codex API** → top-level `
## What does this PR do? The `custom` + `explicit_base_url` branch of `resolve_provider_client()` (in `agent/auxiliary_client.py`) rewrote a trailing `/anthropic` to `/v1` via `_to_openai_base_url()` and then passed that rewritten base to the wrap-decision (`_wrap_if_needed` → `_maybe_wrap_anthropic`) — **even when `api_mode` was `anthropic_messages`**. The
## What does this PR do? `GET /api/config` is an `async def` handler that runs on the asyncio event-loop thread, but it entered `_profile_scope(profile)` — the skills-aware scope that acquires the process-global `_SKILLS_PROFILE_LOCK` **synchronously**. When a worker thread holds that lock (e.g. slow model-option / skills discovery during Desktop setup), the