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
### Problem or Use Case When working in a project that has skills installed via `npx skills experimental_install` (Vercel Labs' [agent skills CLI](https://github.com/vercel-labs/skills)), those skills land in `.claude/skills/` within the repo. These skills contain project-specific best practices (e.g., Langfuse instrumentation patterns, code review guideline
## What does this PR do? Adds four macOS MCP servers to the `optional-mcps/` catalog so Hermes users can install them with `hermes mcp install <name>`: - **apple-mail** — read, search, send, reply, forward, and organize Apple Mail - **apple-notes** — create, search, read, update, and organize Apple Notes - **apple-numbers** — read, write, search, and format
## Summary - add opt-in `send_message(trigger_agent=True)` active handoff result plumbing while keeping passive sends as the default - add Kanban `notify-subscribe --trigger-agent` persistence and gateway notifier support - actively wake the originating gateway agent for gateway-created Kanban task terminal ACKs - preserve Kanban origin ACK edges for CLI/scr
# Bug: `auth_middleware` rejects the desktop `/api/ws?token=...` upgrade with HTTP 401 ## Affected version hermes-agent `0.20.0` (install stamp `fa83af3f9a42`, main, local install). Reproduced on macOS arm64. ## Symptom The Electron desktop app fails to boot in a loop: ``` Local Hermes backend is HTTP-reachable but the WebSocket (/api/ws) rejected the sessio
Closes #54354 ## What Problem This Solves When a cold-start terminal tool call arrives before the config bridge has run, stale env vars (TERMINAL_ENV=local, TERMINAL_DOCKER_IMAGE=old-image) can cause the terminal to silently run on the host instead of in the configured Docker container. This is a sandbox escape: the user thinks code runs in Docker but it act
## Summary - consolidate the focused group-ingress classifier from #73465 while preserving its original authorship - enforce WhatsApp group policy before inbound media extraction - couple the access decision to the media-download callback so rejected groups cannot call `downloadMediaMessage()` or write media locally - pass the adapter's effective DM/group po
## Summary Hermes Agent supports multiple messaging platforms (CLI, Telegram, Discord, etc.) through the gateway architecture. Each platform maintains isolated session stores, meaning an agent handling Telegram messages has no knowledge of conversations the user had via CLI, and vice versa. This feature request proposes a mechanism to share conversation cont
## Bug Description The `terminal` tool has no path validation for protected system files. An agent can bypass the SOUL.md write-protection rules (which block `write_file`/`patch` on protected paths) by executing shell commands like `sed -i "" "s/old/new/" ~/.hermes/SOUL.md`. ## Steps to Reproduce 1. SOUL.md lists protected files: SOUL.md, AGENTS.md, config.y
## Summary Define a coherent lifecycle-event catalog and hook-acceptance standard, then triage the entire pending observer-hook PR cluster against it in one pass — instead of merging (or letting rot) a dozen unrelated one-off `VALID_HOOKS` additions. Output: a documented taxonomy + a batch salvage/disposition of the queued hook PRs. Part of the plugin-interf
Automated freshness probe failed. **Status:** `degraded` **Detail:** Index is 29.8h old (limit 26h) The Skills Hub at /docs/skills depends on `/docs/api/skills-index.json`. The unified index is rebuilt by `.github/workflows/skills-index.yml` (cron 6/18 UTC) and `.github/workflows/deploy-site.yml` (on every push affecting website/skills). If this issue keeps
## What does this PR do? Routes Google Chat's profile-scoped service-account and platform env reads through `agent.secret_scope.get_secret()` so multiplex gateways do not pick up credentials or routing config from another profile's process environment. This is a sibling hardening follow-up to #56680 (Vertex `GOOGLE_APPLICATION_CREDENTIALS` isolation) and the
## Current upstream state - Current published head: `0fdc254cb1cd50eeec62871267c3e6dae4ea2ad6` - Base `main`: `6564f319a647b47de391cab2f608660323804a2b` - Server-side `update-branch --rebase`: already up-to-date - Current GitHub state: `MERGEABLE / BLOCKED`; no checks reported and no review is attached to this head. ## Follow-up update Started from the exact
## Summary - Validate provider-reported final or canonical URLs before returning web content across Firecrawl, Tavily, Exa, and Parallel. - Fail closed for malformed, private, internal, and unresolved final destinations while suppressing unsafe provider metadata and content. - Preserve safe public results and leave Oxylabs behavior unchanged. ## Verification
## Bug Description `DaemonThreadPoolExecutor._adjust_thread_count()` references `self._initializer` and `self._initargs`, which no longer exist in Python 3.14. This breaks **all** concurrent features: `delegate_task`, async delegation, skills hub fan-out, and memory sync. ``` Error during OpenAI-compatible API call: 'DaemonThreadPoolExecutor' object has no a
## What does this PR do? The ACP edit-approval guard promises that sensitive files (`.env`, `.ssh`, `.git`, `id_rsa`, `id_ed25519`) always prompt the user, even when a session runs under an autonomous policy (`session` / `workspace_session`). It did not hold for symlinks. `should_auto_approve_edit` resolves the path with `Path(...).resolve()` for the workspa
## Summary Rebased and repaired the cron external-memory fix on current `main`. ## Behavior - Cron keeps the built-in `memory` tool and local `MEMORY.md`/`USER.md` surface disabled. - A job explicitly configured with the raw `memory` toolset receives only external-provider tools (for example `hindsight_recall`, `hindsight_retain`, and `hindsight_reflect`). -
## Summary - Sanitize `LogRecord.msg` and `LogRecord.args` in Hermes' global record factory using the existing `agent.redact.redact_sensitive_text` path. - Walk string values inside tuple/list/dict logging args while leaving numeric values intact for `%d` and similar formatting. - Add plain `logging.Formatter` coverage for non-Hermes handlers attached to non
## What does this PR do? Prevents turn-scoped `load_hermes_dotenv()` calls from copying a routed profile's credentials into process-global `os.environ` while a multiplex profile scope is active. The root cause was that `load_hermes_dotenv()` always reached `_load_dotenv_with_fallback(..., override=True)`, even when the active Hermes home came from a routed m
## What does this PR do? `hermes model` → a named `custom_providers` entry lands in `_model_flow_named_custom` (`hermes_cli/model_setup_flows.py:1505`), which resolves the provider's credential and immediately probes the endpoint with it: `fetch_api_models(api_key, base_url, **fetch_kwargs)`. Both of the shapes it resolves that credential from were read scop
## Problem The gateway, CLI, and TUI gateway `type: exec` quick_commands all silently dropped user arguments. Any slash command wrapping a CLI tool would fail to receive the query. **Root cause:** `exec_cmd` was used directly without appending user arguments. The alias type handler already forwarded args, but all three exec dispatch paths were missing the sa
## Summary - bound the generic custom-provider `/models` probes at 4 MiB - preserve the existing `/models` -> `/v1/models` fallback sequence for oversized or malformed responses - keep the current credential-safe opener and also clamp bodies discarded by `urllib` while following redirects, so an intermediate 3xx response cannot bypass the final-response cap
## What does this PR do? `resolve_nous_access_token()` and `resolve_nous_runtime_credentials()` are twin allowlist checks on the same stored/network-sourced `portal_base_url` field (both `hermes_cli/auth.py`) — both POST the user's `refresh_token` bearer to this URL on refresh, so both must reject a poisoned value before using it. A same-day fix to `resolve_
## What does this PR do? `browser_cdp(..., frame_id=...)` had two private-page / SSRF gaps on the OOPIF path: (1) a non-dict `params` value skipped the clear validation error and could let the guard fail open, and (2) even with valid params, the guard only checked the top-level page URL before supervisor dispatch, so a public parent could embed a private OOP
# Auxiliary title_generation fails on DeepSeek: HTTP 400 "This response_format type is unavailable now" ## Summary When `auxiliary.title_generation` is configured with `provider: auto` (or explicitly routed to DeepSeek as the main model), the auxiliary title generation task fails with an HTTP 400 error from the DeepSeek API: ``` This response_format type is
## Summary Plugin updates now use a staged review transaction instead of modifying an enabled plugin in place. - Copy the installed Git plugin into a private quarantine directory and fast-forward only the staged copy. - Validate the manifest and exact old/new commits, compute a deterministic staged-content hash, inventory changed files, and run the existing
## What does this PR do? Closes a critical remote-code-execution hole in the trajectory compressor. `CompressionConfig.trust_remote_code` defaulted to `True`, and that value was passed straight into `AutoTokenizer.from_pretrained(..., trust_remote_code=...)`. HuggingFace honors that flag by importing and running arbitrary Python shipped in the tokenizer repo
## What does this PR do? `hermes update` was pruning root-level Node dependencies (e.g. `agent-browser`) on every run. This PR originally tried to fix that by juggling install order between the root and ui-tui/web workspace installs; that approach didn't hold up under review. The old two-pass shape (`npm ci --workspaces=false` then `npm ci --workspace ui-tui
## Summary This PR rescopes the classic CLI quick-command hardening to the execution-safety boundary tracked by #46056. - Runs `quick_commands.<name>.type = exec` through a bounded `Popen` wrapper. - Closes stdin, preserves `TERMINAL_CWD` and the sanitized environment, caps stdout/stderr, terminates the process tree on timeout, hides Windows console windows,
## Summary Implements the **native extract provider** concept first discussed in issue #19198 — a zero-dependency local HTTP fetcher with readability-lxml main-content extraction. No API keys required. ## What it does - **New plugin** `plugins/web/native` — HTTP GET via `httpx`, content extraction via `readability-lxml`, markdown conversion via `html2text`.
Fixes #55041. ## Summary - stream inbound Matrix `mxc://` media through `MATRIX_MAX_MEDIA_BYTES` instead of calling `mautrix.download_media()`'s unbounded `response.read()` path - reject oversized MXC media as soon as the streamed response crosses the cap, without forwarding the HTTP fallback downstream - keep the old `download_media()` path only for test/f
## Summary Fixes #55147. Gateway `/memory` and `/skills` can be allowlisted for non-admin slash users so they can review pending writes, but `approval on|off` mutates global `memory.write_approval` / `skills.write_approval` in `config.yaml`. This patch adds a shared gateway-side subcommand guard: - `/memory approval` and `/skills approval` with no value stil
# Sanitized Kanban REST API for external control planes ## Summary Adds a narrow, authenticated, safe-by-default REST API over the existing Hermes Kanban store, mounted at `/api/plugins/kanban`. It gives external control planes a stable integration boundary for creating, routing, inspecting, and managing Kanban tasks — without reading raw SQLite state, touch
## What does this PR do? `#52387` fixed Block-Kit-only `@mention` detection for the one carrier Slack's WYSIWYG composer produces — a `rich_text` tree with a structured `user` element. Two other carriers were still dropped, so a bot that *explicitly* `@`-mentions the gateway stayed invisible to the `allow_bots: mentions` gate and to `is_mentioned` routing: 1
## What does this PR do? Adds an optional, disabled-by-default LLM cleanup pass after gateway speech-to-text and its configured STT fallback. The implementation is deliberately small and fail-open: it makes one explicit provider/model call, accepts a non-empty structured result only above the configured confidence threshold, and otherwise keeps the raw trans
## The bug `_MEDIA_DELIVERY_DENIED_PREFIXES` is POSIX-only, and the entries **don't degrade gracefully**. `Path("/etc").resolve()` becomes `C:\etc` on the current drive — which doesn't exist. So on Windows every entry in that tuple is inert and the default-mode denylist is effectively empty. Measured against unmodified `main` on Windows: ``` /etc -> C:\etc e
## Summary The Hermes desktop (Electron) client pins the Renderer and GPU helper processes at 50–90% CPU even when idle (no active generation, no user input). The macOS battery/ power menu reports Hermes as the highest energy consumer and the machine gets noticeably hot. Quitting and reopening the app does NOT resolve it — the spin returns within seconds of
## Summary On Windows (Hermes 0.20.0, desktop app), **every desktop-app restart force-kills the running messaging gateway and never relaunches it**. WeChat (iLink), QQ bot and Telegram go completely silent until the gateway is manually restarted. This is a regression: before this version, the old gateway survived desktop restarts (reparented), so messaging s
## Summary - stream existing Teams attachment downloads through the shared inbound-media size limiter - follow redirects manually so every target is SSRF-validated and every intermediate response is closed without reading its body - cap declared, lengthless, and decoded compressed final bodies before aggregation Fixes #55061. ## Why this boundary - This PR o
## What does this PR do? Adds **JetBrains Junie** as a native coding-agent provider (`junie-acp`), driven over the **Agent Client Protocol** using the `agent-client-protocol` SDK (already vendored as the `[acp]` extra). Hermes spawns `junie --acp=true` and talks to it as an ACP *client*, exposing Junie through the standard chat surface so it can be selected
## Summary Introduces a generic `auth_type="none"` capability on `ProviderProfile` so a model-provider plugin can declare that its HTTP endpoints require **no credentials and no `Authorization` header**. Core invariant, asserted by `tests/providers/test_noauth_provider_flag.py`: - a `none` provider resolves **without a secret** (`api_key == ""`, source `"no-
Part of the [Webhook Revolution campaign](https://github.com/NousResearch/hermes-agent/issues/84834). Task 9. Closes #47451, #80327. ## Explicit, mode-bound signature verification Replaces header-driven scheme inference in `gateway/platforms/webhook_auth.py` with a verifier registry keyed by `signature_mode`: `github`, `gitlab`, `svix`, `generic_v2`, `generi
## What does this PR do? Adds an opt-in browser-extension controller lane so Hermes can route existing `browser_*` tools to the exact authenticated browser session that opened the conversation. The implementation has two layers: 1. A transport-neutral broker with principal/profile/session/controller/browser-profile/transport scoping, one-shot WebSocket ticke