Merge commit '6110aed9b' into feat/whatsapp-cloud-api
This commit is contained in:
commit
bfcc9f92b4
3038 changed files with 499128 additions and 63841 deletions
|
|
@ -9,7 +9,7 @@ This guide covers adding a new messaging platform to the Hermes gateway. A platf
|
|||
:::tip
|
||||
There are two ways to add a platform:
|
||||
- **Plugin** (recommended for community/third-party): Drop a plugin directory into `~/.hermes/plugins/` — zero core code changes needed. See [Plugin Path](#plugin-path-recommended) below.
|
||||
- **Built-in**: Modify 20+ files across code, config, and docs. Use the [Built-in Checklist](#step-by-step-checklist) below.
|
||||
- **Built-in**: Modify 20+ files across code, config, and docs. Use the [Built-in Checklist](#step-by-step-checklist-built-in-path) below.
|
||||
:::
|
||||
|
||||
## Architecture Overview
|
||||
|
|
@ -34,11 +34,11 @@ The plugin system lets you add a platform adapter without modifying any core Her
|
|||
|
||||
```
|
||||
~/.hermes/plugins/my-platform/
|
||||
PLUGIN.yaml # Plugin metadata
|
||||
plugin.yaml # Plugin metadata
|
||||
adapter.py # Adapter class + register() entry point
|
||||
```
|
||||
|
||||
### PLUGIN.yaml
|
||||
### plugin.yaml
|
||||
|
||||
Plugin metadata. The `requires_env` and `optional_env` blocks auto-populate `hermes config` UI entries (see [Surfacing Env Vars](#surfacing-env-vars-in-hermes-config) below).
|
||||
|
||||
|
|
|
|||
|
|
@ -116,12 +116,12 @@ When you add a plugin and it calls `register_provider()`, the following wire up
|
|||
8. `hermes setup` wizard delegates to `main.py` automatically
|
||||
9. `provider:model` alias syntax works
|
||||
10. Runtime resolver returns the correct `base_url` and `api_key`
|
||||
11. `HERMES_INFERENCE_PROVIDER` env-var override accepts the provider id
|
||||
11. `--provider <name>` CLI flag accepts the provider id
|
||||
12. Fallback model activation can switch into the provider cleanly
|
||||
|
||||
User plugins at `$HERMES_HOME/plugins/model-providers/<name>/` override bundled plugins of the same name (last-writer-wins in `register_provider()`) — so third parties can monkey-patch or replace any built-in profile without editing the repo.
|
||||
|
||||
See `plugins/model-providers/nvidia/` or `plugins/model-providers/gmi/` as a template, and the full [Model Provider Plugin guide](/docs/developer-guide/model-provider-plugin) for field reference, hook idioms, and end-to-end examples.
|
||||
See `plugins/model-providers/nvidia/` or `plugins/model-providers/gmi/` as a template, and the full [Model Provider Plugin guide](/developer-guide/model-provider-plugin) for field reference, hook idioms, and end-to-end examples.
|
||||
|
||||
## Full path: OAuth and complex providers
|
||||
|
||||
|
|
@ -321,12 +321,12 @@ At minimum, touch the tests that guard provider wiring.
|
|||
|
||||
Common places:
|
||||
|
||||
- `tests/test_runtime_provider_resolution.py`
|
||||
- `tests/test_cli_provider_resolution.py`
|
||||
- `tests/test_cli_model_command.py`
|
||||
- `tests/test_setup_model_selection.py`
|
||||
- `tests/test_provider_parity.py`
|
||||
- `tests/test_run_agent.py`
|
||||
- `tests/hermes_cli/test_runtime_provider_resolution.py`
|
||||
- `tests/cli/test_cli_provider_resolution.py`
|
||||
- `tests/hermes_cli/test_model_switch_custom_providers.py` (and adjacent `tests/hermes_cli/test_model_switch_*.py`)
|
||||
- `tests/hermes_cli/test_setup_model_provider.py`
|
||||
- `tests/run_agent/test_provider_parity.py`
|
||||
- `tests/run_agent/test_run_agent.py`
|
||||
- `tests/test_<provider>_adapter.py` for a native provider
|
||||
|
||||
For docs-only examples, the exact file set may differ. The point is to cover:
|
||||
|
|
@ -342,7 +342,7 @@ Run tests with xdist disabled:
|
|||
|
||||
```bash
|
||||
source venv/bin/activate
|
||||
python -m pytest tests/test_runtime_provider_resolution.py tests/test_cli_provider_resolution.py tests/test_cli_model_command.py tests/test_setup_model_selection.py -n0 -q
|
||||
python -m pytest tests/hermes_cli/test_runtime_provider_resolution.py tests/cli/test_cli_provider_resolution.py tests/hermes_cli/test_setup_model_provider.py tests/run_agent/test_provider_parity.py -n0 -q
|
||||
```
|
||||
|
||||
For deeper changes, run the full suite before pushing:
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ This page is for adding a **built-in Hermes tool** to the repository itself.
|
|||
If you want a personal, project-local, or otherwise custom tool without
|
||||
modifying Hermes core, use the plugin route instead:
|
||||
|
||||
- [Plugins](/docs/user-guide/features/plugins)
|
||||
- [Build a Hermes Plugin](/docs/guides/build-a-hermes-plugin)
|
||||
- [Plugins](/user-guide/features/plugins)
|
||||
- [Build a Hermes Plugin](/guides/build-a-hermes-plugin)
|
||||
|
||||
Default to plugins for most custom tool creation. Only follow this page when
|
||||
you explicitly want to ship a new built-in tool in `tools/` and `toolsets.py`.
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ description: "Detailed walkthrough of AIAgent execution, API modes, tools, callb
|
|||
|
||||
# Agent Loop Internals
|
||||
|
||||
The core orchestration engine is `run_agent.py`'s `AIAgent` class — a large file (15k+ lines) that handles everything from prompt assembly to tool dispatch to provider failover.
|
||||
The core orchestration engine is `run_agent.py`'s `AIAgent` class — a large file that handles everything from prompt assembly to tool dispatch to provider failover.
|
||||
|
||||
## Core Responsibilities
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ This page is the top-level map of Hermes Agent internals. Use it to orient yours
|
|||
▼ ▼
|
||||
┌───────────────────┐ ┌──────────────────────┐
|
||||
│ Session Storage │ │ Tool Backends │
|
||||
│ (SQLite + FTS5) │ │ Terminal (7 backends) │
|
||||
│ (SQLite + FTS5) │ │ Terminal (6 backends) │
|
||||
│ hermes_state.py │ │ Browser (5 backends) │
|
||||
│ gateway/session.py│ │ Web (4 backends) │
|
||||
└───────────────────┘ │ MCP (dynamic) │
|
||||
|
|
@ -130,7 +130,7 @@ hermes-agent/
|
|||
├── skills/ # Bundled skills (always available)
|
||||
├── optional-skills/ # Official optional skills (install explicitly)
|
||||
├── website/ # Docusaurus documentation site
|
||||
└── tests/ # Pytest suite (~3,000+ tests)
|
||||
└── tests/ # Pytest suite (~25,000 tests across ~1,250 files)
|
||||
```
|
||||
|
||||
## Data Flow
|
||||
|
|
@ -197,7 +197,7 @@ The synchronous orchestration engine (`AIAgent` in `run_agent.py`). Handles prov
|
|||
|
||||
Prompt construction and maintenance across the conversation lifecycle:
|
||||
|
||||
- **`prompt_builder.py`** — Assembles the system prompt from: personality (SOUL.md), memory (MEMORY.md, USER.md), skills, context files (AGENTS.md, .hermes.md), tool-use guidance, and model-specific instructions
|
||||
- **`system_prompt.py` + `prompt_builder.py`** — assembles the ordered system-prompt tiers (`stable` → `context` → `volatile`): identity/tool guidance/skills, context files, then memory/profile/timestamp blocks
|
||||
- **`prompt_caching.py`** — Applies Anthropic cache breakpoints for prefix caching
|
||||
- **`context_compressor.py`** — Summarizes middle conversation turns when context exceeds thresholds
|
||||
|
||||
|
|
@ -211,7 +211,7 @@ A shared runtime resolver used by CLI, gateway, cron, ACP, and auxiliary calls.
|
|||
|
||||
### Tool System
|
||||
|
||||
Central tool registry (`tools/registry.py`) with 70+ registered tools across ~28 toolsets. Each tool file self-registers at import time. The registry handles schema collection, dispatch, availability checking, and error wrapping. Terminal tools support 7 backends (local, Docker, SSH, Daytona, Modal, Singularity, Vercel Sandbox).
|
||||
Central tool registry (`tools/registry.py`) with 70+ registered tools across ~28 toolsets. Each tool file self-registers at import time. The registry handles schema collection, dispatch, availability checking, and error wrapping. Terminal tools support 6 backends (local, Docker, SSH, Daytona, Modal, Singularity).
|
||||
|
||||
→ [Tools Runtime](./tools-runtime.md)
|
||||
|
||||
|
|
@ -231,7 +231,7 @@ Long-running process with 20 platform adapters, unified session routing, user au
|
|||
|
||||
Three discovery sources: `~/.hermes/plugins/` (user), `.hermes/plugins/` (project), and pip entry points. Plugins register tools, hooks, and CLI commands through a context API. Two specialized plugin types exist: memory providers (`plugins/memory/`) and context engines (`plugins/context_engine/`). Both are single-select — only one of each can be active at a time, configured via `hermes plugins` or `config.yaml`.
|
||||
|
||||
→ [Plugin Guide](/docs/guides/build-a-hermes-plugin), [Memory Provider Plugin](./memory-provider-plugin.md)
|
||||
→ [Plugin Guide](/guides/build-a-hermes-plugin), [Memory Provider Plugin](./memory-provider-plugin.md)
|
||||
|
||||
### Cron
|
||||
|
||||
|
|
|
|||
|
|
@ -1,57 +1,49 @@
|
|||
# Browser CDP Supervisor — Design
|
||||
---
|
||||
sidebar_position: 18
|
||||
title: "Browser CDP Supervisor"
|
||||
description: "How Hermes detects and responds to native JS dialogs and interacts with cross-origin iframes via a persistent CDP connection."
|
||||
---
|
||||
|
||||
**Status:** Shipped (PR 14540)
|
||||
**Last updated:** 2026-04-23
|
||||
**Author:** @teknium1
|
||||
# Browser CDP Supervisor
|
||||
|
||||
## Problem
|
||||
The CDP supervisor closes two long-standing gaps in Hermes' browser tooling:
|
||||
|
||||
Native JS dialogs (`alert`/`confirm`/`prompt`/`beforeunload`) and iframes are
|
||||
the two biggest gaps in our browser tooling:
|
||||
1. **Native JS dialogs** (`alert`/`confirm`/`prompt`/`beforeunload`) block the
|
||||
page's JS thread. Without supervision, the agent has no way to know a
|
||||
dialog is open — subsequent tool calls hang or throw opaque errors.
|
||||
2. **Cross-origin iframes (OOPIFs)** are invisible to top-level
|
||||
`Runtime.evaluate`. The agent can see iframe nodes in the DOM snapshot but
|
||||
can't click, type, or eval inside them without a CDP session attached to
|
||||
the child target.
|
||||
|
||||
1. **Dialogs block the JS thread.** Any operation on the page stalls until the
|
||||
dialog is handled. Before this work, the agent had no way to know a dialog
|
||||
was open — subsequent tool calls would hang or throw opaque errors.
|
||||
2. **Iframes are invisible.** The agent could see iframe nodes in the DOM
|
||||
snapshot but could not click, type, or eval inside them — especially
|
||||
cross-origin (OOPIF) iframes that live in separate Chromium processes.
|
||||
The supervisor solves both by holding a persistent WebSocket to the backend's
|
||||
CDP endpoint per browser task, surfacing pending dialogs and frame structure
|
||||
into `browser_snapshot`, and exposing a `browser_dialog` tool for explicit
|
||||
responses.
|
||||
|
||||
[PR #12550](https://github.com/NousResearch/hermes-agent/pull/12550) proposed a
|
||||
stateless `browser_dialog` wrapper. That doesn't solve detection — it's a
|
||||
cleaner CDP call for when the agent already knows (via symptoms) that a dialog
|
||||
is open. Closed as superseded.
|
||||
|
||||
## Backend capability matrix (verified live 2026-04-23)
|
||||
|
||||
Using throwaway probe scripts against a data-URL page that fires alerts in the
|
||||
main frame and in a same-origin srcdoc iframe, plus a cross-origin
|
||||
`https://example.com` iframe:
|
||||
## Backend support
|
||||
|
||||
| Backend | Dialog detect | Dialog respond | Frame tree | OOPIF `Runtime.evaluate` via `browser_cdp(frame_id=...)` |
|
||||
|---|---|---|---|---|
|
||||
| Local Chrome (`--remote-debugging-port`) / `/browser connect` | ✓ | ✓ full workflow | ✓ | ✓ |
|
||||
| Browserbase | ✓ (via bridge) | ✓ full workflow (via bridge) | ✓ | ✓ (`document.title = "Example Domain"` verified on real cross-origin iframe) |
|
||||
| Browserbase | ✓ (via bridge) | ✓ full workflow (via bridge) | ✓ | ✓ |
|
||||
| Camofox | ✗ no CDP (REST-only) | ✗ | partial via DOM snapshot | ✗ |
|
||||
|
||||
**How Browserbase respond works.** Browserbase's CDP proxy uses Playwright
|
||||
internally and auto-dismisses native dialogs within ~10ms, so
|
||||
`Page.handleJavaScriptDialog` can't keep up. To work around this, the
|
||||
supervisor injects a bridge script via
|
||||
**Browserbase quirk.** Browserbase's CDP proxy uses Playwright internally and
|
||||
auto-dismisses native dialogs within ~10ms, so `Page.handleJavaScriptDialog`
|
||||
can't keep up. The supervisor injects a bridge script via
|
||||
`Page.addScriptToEvaluateOnNewDocument` that overrides
|
||||
`window.alert`/`confirm`/`prompt` with a synchronous XHR to a magic host
|
||||
(`hermes-dialog-bridge.invalid`). `Fetch.enable` intercepts those XHRs
|
||||
before they touch the network — the dialog becomes a `Fetch.requestPaused`
|
||||
event the supervisor captures, and `respond_to_dialog` fulfills via
|
||||
(`hermes-dialog-bridge.invalid`). `Fetch.enable` intercepts those XHRs before
|
||||
they touch the network — the dialog becomes a `Fetch.requestPaused` event the
|
||||
supervisor captures, and `respond_to_dialog` fulfills via
|
||||
`Fetch.fulfillRequest` with a JSON body the injected script decodes.
|
||||
|
||||
Net result: from the page's perspective, `prompt()` still returns the
|
||||
agent-supplied string. From the agent's perspective, it's the same
|
||||
`browser_dialog(action=...)` API either way. Tested end-to-end against
|
||||
real Browserbase sessions — 4/4 (alert/prompt/confirm-accept/confirm-dismiss)
|
||||
pass including value round-tripping back into page JS.
|
||||
From the page's perspective, `prompt()` still returns the agent-supplied
|
||||
string. From the agent's perspective, it's the same `browser_dialog(action=...)`
|
||||
API either way.
|
||||
|
||||
Camofox stays unsupported for this PR; follow-up upstream issue planned at
|
||||
`jo-inc/camofox-browser` requesting a dialog polling endpoint.
|
||||
Camofox is unsupported — no CDP surface, REST-only.
|
||||
|
||||
## Architecture
|
||||
|
||||
|
|
@ -63,9 +55,10 @@ Holds a persistent WebSocket to the backend's CDP endpoint. Maintains:
|
|||
- **Dialog queue** — `List[PendingDialog]` with `{id, type, message, default_prompt, session_id, opened_at}`
|
||||
- **Frame tree** — `Dict[frame_id, FrameInfo]` with parent relationships, URL, origin, whether cross-origin child session
|
||||
- **Session map** — `Dict[session_id, SessionInfo]` so interaction tools can route to the right attached session for OOPIF operations
|
||||
- **Recent console errors** — ring buffer of the last 50 (for PR 2 diagnostics)
|
||||
- **Recent console errors** — ring buffer of the last 50 for diagnostics
|
||||
|
||||
Subscribes on attach:
|
||||
|
||||
- `Page.enable` — `javascriptDialogOpening`, `frameAttached`, `frameNavigated`, `frameDetached`
|
||||
- `Runtime.enable` — `executionContextCreated`, `consoleAPICalled`, `exceptionThrown`
|
||||
- `Target.setAutoAttach {autoAttach: true, flatten: true}` — surfaces child OOPIF targets; supervisor enables `Page`+`Runtime` on each
|
||||
|
|
@ -76,11 +69,13 @@ frozen snapshot without awaiting.
|
|||
### Lifecycle
|
||||
|
||||
- **Start:** `SupervisorRegistry.get_or_start(task_id, cdp_url)` — called by
|
||||
`browser_navigate`, Browserbase session create, `/browser connect`. Idempotent.
|
||||
`browser_navigate`, Browserbase session create, `/browser connect`.
|
||||
Idempotent.
|
||||
- **Stop:** session teardown or `/browser disconnect`. Cancels the asyncio
|
||||
task, closes the WebSocket, discards state.
|
||||
- **Rebind:** if the CDP URL changes (user reconnects to a new Chrome), stop
|
||||
the old supervisor and start fresh — never reuse state across endpoints.
|
||||
- **Rebind:** if the CDP URL changes (user reconnects to a new Chrome), the
|
||||
old supervisor is stopped and a fresh one started — state is never reused
|
||||
across endpoints.
|
||||
|
||||
### Dialog policy
|
||||
|
||||
|
|
@ -92,14 +87,14 @@ Configurable via `config.yaml` under `browser.dialog_policy`:
|
|||
forever.
|
||||
- `auto_dismiss` — record and dismiss immediately; agent sees it after the
|
||||
fact via `browser_state` inside `browser_snapshot`.
|
||||
- `auto_accept` — record and accept (useful for `beforeunload` where the user
|
||||
wants to navigate away cleanly).
|
||||
- `auto_accept` — record and accept (useful for `beforeunload` where the
|
||||
workflow wants to navigate away cleanly).
|
||||
|
||||
Policy is per-task; no per-dialog overrides in v1.
|
||||
Policy is per-task; no per-dialog overrides.
|
||||
|
||||
## Agent surface (PR 1)
|
||||
## Agent surface
|
||||
|
||||
### One new tool
|
||||
### `browser_dialog` tool
|
||||
|
||||
```
|
||||
browser_dialog(action, prompt_text=None, dialog_id=None)
|
||||
|
|
@ -107,9 +102,9 @@ browser_dialog(action, prompt_text=None, dialog_id=None)
|
|||
|
||||
- `action="accept"` / `"dismiss"` → responds to the specified or sole pending dialog (required)
|
||||
- `prompt_text=...` → text to supply to a `prompt()` dialog
|
||||
- `dialog_id=...` → disambiguate when multiple dialogs queued (rare)
|
||||
- `dialog_id=...` → disambiguate when multiple dialogs are queued (rare)
|
||||
|
||||
Tool is response-only. Agent reads pending dialogs from `browser_snapshot`
|
||||
Tool is response-only. The agent reads pending dialogs from `browser_snapshot`
|
||||
output before calling.
|
||||
|
||||
### `browser_snapshot` extension
|
||||
|
|
@ -137,72 +132,52 @@ is attached:
|
|||
}
|
||||
```
|
||||
|
||||
- **`pending_dialogs`**: dialogs currently blocking the page's JS thread.
|
||||
- **`pending_dialogs`** — dialogs currently blocking the page's JS thread.
|
||||
The agent must call `browser_dialog(action=...)` to respond. Empty on
|
||||
Browserbase because their CDP proxy auto-dismisses within ~10ms.
|
||||
|
||||
- **`recent_dialogs`**: ring buffer of up to 20 recently-closed dialogs with
|
||||
a `closed_by` tag — `"agent"` (we responded), `"auto_policy"` (local
|
||||
- **`recent_dialogs`** — ring buffer of up to 20 recently-closed dialogs with
|
||||
a `closed_by` tag: `"agent"` (we responded), `"auto_policy"` (local
|
||||
auto_dismiss/auto_accept), `"watchdog"` (must_respond timeout hit), or
|
||||
`"remote"` (browser/backend closed it on us, e.g. Browserbase). This is
|
||||
how agents on Browserbase still get visibility into what happened.
|
||||
|
||||
- **`frame_tree`**: frame structure including cross-origin (OOPIF) children.
|
||||
- **`frame_tree`** — frame structure including cross-origin (OOPIF) children.
|
||||
Capped at 30 entries + OOPIF depth 2 to bound snapshot size on ad-heavy
|
||||
pages. `truncated: true` surfaces when limits were hit; agents needing
|
||||
the full tree can use `browser_cdp` with `Page.getFrameTree`.
|
||||
|
||||
No new tool schema surface for any of these — the agent reads the snapshot
|
||||
it already requests.
|
||||
No new tool schema surface for any of these — the agent reads the snapshot it
|
||||
already requests.
|
||||
|
||||
### Availability gating
|
||||
|
||||
Both surfaces gate on `_browser_cdp_check` (supervisor can only run when a CDP
|
||||
endpoint is reachable). On Camofox / no-backend sessions, the dialog tool is
|
||||
hidden and snapshot omits the new fields — no schema bloat.
|
||||
hidden and the snapshot omits the new fields — no schema bloat.
|
||||
|
||||
## Cross-origin iframe interaction
|
||||
|
||||
Extending the dialog-detect work, `browser_cdp(frame_id=...)` routes CDP
|
||||
calls (notably `Runtime.evaluate`) through the supervisor's already-connected
|
||||
WebSocket using the OOPIF's child `sessionId`. Agents pick frame_ids out of
|
||||
`browser_cdp(frame_id=...)` routes CDP calls (notably `Runtime.evaluate`)
|
||||
through the supervisor's already-connected WebSocket using the OOPIF's child
|
||||
`sessionId`. Agents pick frame_ids out of
|
||||
`browser_snapshot.frame_tree.children[]` where `is_oopif=true` and pass them
|
||||
to `browser_cdp`. For same-origin iframes (no dedicated CDP session), the
|
||||
agent uses `contentWindow`/`contentDocument` from a top-level
|
||||
`Runtime.evaluate` instead — supervisor surfaces an error pointing at that
|
||||
`Runtime.evaluate` instead — the supervisor surfaces an error pointing at that
|
||||
fallback when `frame_id` belongs to a non-OOPIF.
|
||||
|
||||
On Browserbase, this is the ONLY reliable path for iframe interaction —
|
||||
On Browserbase, this is the only reliable path for iframe interaction —
|
||||
stateless CDP connections (opened per `browser_cdp` call) hit signed-URL
|
||||
expiry, while the supervisor's long-lived connection keeps a valid session.
|
||||
|
||||
## Camofox (follow-up)
|
||||
|
||||
Issue planned against `jo-inc/camofox-browser` adding:
|
||||
- Playwright `page.on('dialog', handler)` per session
|
||||
- `GET /tabs/:tabId/dialogs` polling endpoint
|
||||
- `POST /tabs/:tabId/dialogs/:id` to accept/dismiss
|
||||
- Frame-tree introspection endpoint
|
||||
|
||||
## Files touched (PR 1)
|
||||
|
||||
### New
|
||||
## File layout
|
||||
|
||||
- `tools/browser_supervisor.py` — `CDPSupervisor`, `SupervisorRegistry`, `PendingDialog`, `FrameInfo`
|
||||
- `tools/browser_dialog_tool.py` — `browser_dialog` tool handler
|
||||
- `tests/tools/test_browser_supervisor.py` — mock CDP WebSocket server + lifecycle/state tests
|
||||
- `website/docs/developer-guide/browser-supervisor.md` — this file
|
||||
|
||||
### Modified
|
||||
|
||||
- `toolsets.py` — register `browser_dialog` in `browser`, `hermes-acp`, `hermes-api-server`, core toolsets (gated on CDP reachability)
|
||||
- `tools/browser_tool.py`
|
||||
- `browser_navigate` start-hook: if CDP URL resolvable, `SupervisorRegistry.get_or_start(task_id, cdp_url)`
|
||||
- `browser_snapshot` (at ~line 1536): merge supervisor state into return payload
|
||||
- `/browser connect` handler: restart supervisor with new endpoint
|
||||
- Session teardown hooks in `_cleanup_browser_session`
|
||||
- `hermes_cli/config.py` — add `browser.dialog_policy` and `browser.dialog_timeout_s` to `DEFAULT_CONFIG`
|
||||
- Docs: `website/docs/user-guide/features/browser.md`, `website/docs/reference/tools-reference.md`, `website/docs/reference/toolsets-reference.md`
|
||||
- `tools/browser_tool.py` — `browser_navigate` start-hook, `browser_snapshot` merge, `/browser connect` reattach, `_cleanup_browser_session` teardown
|
||||
- `toolsets.py` — registers `browser_dialog` in `browser`, `hermes-acp`, `hermes-api-server`, and core toolsets (gated on CDP reachability)
|
||||
- `hermes_cli/config.py` — `browser.dialog_policy` and `browser.dialog_timeout_s` defaults
|
||||
|
||||
## Non-goals
|
||||
|
||||
|
|
@ -214,9 +189,10 @@ Issue planned against `jo-inc/camofox-browser` adding:
|
|||
|
||||
## Testing
|
||||
|
||||
Unit tests use an asyncio mock CDP server that speaks enough of the protocol
|
||||
to exercise all state transitions: attach, enable, navigate, dialog fire,
|
||||
dialog dismiss, frame attach/detach, child target attach, session teardown.
|
||||
Real-backend E2E (Browserbase + local Chromium-family browser) is manual — exercise via
|
||||
`/browser connect` to a live Chromium-family browser and run the dialog/frame
|
||||
test cases described above.
|
||||
Unit tests (`tests/tools/test_browser_supervisor.py`) use an asyncio mock CDP
|
||||
server that speaks enough of the protocol to exercise all state transitions:
|
||||
attach, enable, navigate, dialog fire, dialog dismiss, frame attach/detach,
|
||||
child target attach, session teardown. Real-backend E2E (Browserbase + local
|
||||
Chromium-family browser) is manual — exercise via `/browser connect` to a
|
||||
live Chromium-family browser and run the dialog/frame test cases described
|
||||
above.
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ Plugin engines are **never auto-activated** — the user must explicitly set `co
|
|||
|
||||
Configure via `hermes plugins` → Provider Plugins → Context Engine, or edit `config.yaml` directly.
|
||||
|
||||
For building a context engine plugin, see [Context Engine Plugins](/docs/developer-guide/context-engine-plugin).
|
||||
For building a context engine plugin, see [Context Engine Plugins](/developer-guide/context-engine-plugin).
|
||||
|
||||
## Dual Compression System
|
||||
|
||||
|
|
@ -84,6 +84,7 @@ compression:
|
|||
threshold: 0.50 # Fraction of context window (default: 0.50 = 50%)
|
||||
target_ratio: 0.20 # How much of threshold to keep as tail (default: 0.20)
|
||||
protect_last_n: 20 # Minimum protected tail messages (default: 20)
|
||||
codex_gpt55_autoraise: true # gpt-5.5 on Codex OAuth: raise trigger to 85% (default: true)
|
||||
|
||||
# Summarization model/provider configured under auxiliary:
|
||||
auxiliary:
|
||||
|
|
@ -101,6 +102,22 @@ auxiliary:
|
|||
| `target_ratio` | `0.20` | 0.10-0.80 | Controls tail protection token budget: `threshold_tokens × target_ratio` |
|
||||
| `protect_last_n` | `20` | ≥1 | Minimum number of recent messages always preserved |
|
||||
| `protect_first_n` | `3` | (hardcoded) | System prompt + first exchange always preserved |
|
||||
| `codex_gpt55_autoraise` | `true` | bool | Raise the trigger to 85% for gpt-5.5 on the ChatGPT Codex OAuth route (see below). Set `false` to keep the global `threshold` |
|
||||
|
||||
### Codex gpt-5.5 threshold autoraise
|
||||
|
||||
The ChatGPT Codex OAuth backend hard-caps gpt-5.5 at a **272K** context window
|
||||
(the same slug exposes 1.05M on OpenAI's direct API and OpenRouter, and 400K on
|
||||
GitHub Copilot). At the default 50% trigger, compaction would fire at ~136K —
|
||||
half the window the model can actually use. When the active route is Codex
|
||||
OAuth (`provider: openai-codex`) and the model is gpt-5.5, Hermes raises the
|
||||
trigger to **85%** (~231K) and prints a one-time notice with the opt-out
|
||||
command. Only this exact route is affected; gpt-5.5 on any other provider keeps
|
||||
your global `threshold`. To opt back down to the global value:
|
||||
|
||||
```bash
|
||||
hermes config set compression.codex_gpt55_autoraise false
|
||||
```
|
||||
|
||||
### Computed Values (for a 200K context model at defaults)
|
||||
|
||||
|
|
@ -111,6 +128,17 @@ tail_token_budget = 100,000 × 0.20 = 20,000
|
|||
max_summary_tokens = min(200,000 × 0.05, 12,000) = 10,000
|
||||
```
|
||||
|
||||
:::note Threshold is derived from the MAIN model's context window
|
||||
`threshold_tokens` is always `threshold × context_length`, where `context_length`
|
||||
is the **main agent model's** context window — never the auxiliary/summary
|
||||
model's. On a 262,144-token model at the default `0.50`, the threshold is
|
||||
`262,144 × 0.50 = 131,072`. That number being close to a common "128K context"
|
||||
is a coincidence of the percentage, not a sign that the auxiliary model's window
|
||||
is the trigger. The auxiliary model's context window is a separate concern — see
|
||||
the "Summary model context length" warning below for how it affects whether a
|
||||
summary can be produced, not when compression fires.
|
||||
:::
|
||||
|
||||
|
||||
## Compression Algorithm
|
||||
|
||||
|
|
|
|||
|
|
@ -189,6 +189,6 @@ See `tests/agent/test_context_engine.py` for the full ABC contract test suite.
|
|||
|
||||
## See also
|
||||
|
||||
- [Context Compression and Caching](/docs/developer-guide/context-compression-and-caching) — how the built-in compressor works
|
||||
- [Memory Provider Plugins](/docs/developer-guide/memory-provider-plugin) — analogous single-select plugin system for memory
|
||||
- [Plugins](/docs/user-guide/features/plugins) — general plugin system overview
|
||||
- [Context Compression and Caching](/developer-guide/context-compression-and-caching) — how the built-in compressor works
|
||||
- [Memory Provider Plugins](/developer-guide/memory-provider-plugin) — analogous single-select plugin system for memory
|
||||
- [Plugins](/user-guide/features/plugins) — general plugin system overview
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ We value contributions in this order:
|
|||
|
||||
| Requirement | Notes |
|
||||
|-------------|-------|
|
||||
| **Git** | With `--recurse-submodules` support, and the `git-lfs` extension installed |
|
||||
| **Git** | With the `git-lfs` extension installed |
|
||||
| **Python 3.11+** | uv will install it if missing |
|
||||
| **uv** | Fast Python package manager ([install](https://docs.astral.sh/uv/)) |
|
||||
| **Node.js 20+** | Optional — needed for browser tools and WhatsApp bridge (matches root `package.json` engines) |
|
||||
|
|
@ -41,7 +41,7 @@ We value contributions in this order:
|
|||
### Clone and Install
|
||||
|
||||
```bash
|
||||
git clone --recurse-submodules https://github.com/NousResearch/hermes-agent.git
|
||||
git clone https://github.com/NousResearch/hermes-agent.git
|
||||
cd hermes-agent
|
||||
|
||||
# Create venv with Python 3.11
|
||||
|
|
@ -94,7 +94,7 @@ pytest tests/ -v
|
|||
|
||||
## Cross-Platform Compatibility
|
||||
|
||||
Hermes officially supports **Linux, macOS, WSL2, and native Windows (early beta — via PowerShell install)**. Native Windows uses Git Bash (from [Git for Windows](https://git-scm.com/download/win)) for shell commands. A few features require POSIX kernel primitives and are gated: the dashboard's embedded PTY terminal pane (`/chat` tab) is WSL2-only. The native-Windows path is new and moves fast — if you're doing Windows-heavy dev, expect to hit and fix rough edges.
|
||||
Hermes officially supports **Linux, macOS, WSL2, and native Windows (via PowerShell install)**. Native Windows uses Git Bash (from [Git for Windows](https://git-scm.com/download/win)) for shell commands. A few features require POSIX kernel primitives and are gated: the dashboard's embedded PTY terminal pane (`/chat` tab) is WSL2-only. If you're doing Windows-heavy dev, run the Windows-footgun lint (`scripts/check-windows-footguns.py`) before pushing.
|
||||
|
||||
When contributing code, keep these rules in mind:
|
||||
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ required_environment_variables:
|
|||
The user can skip setup and keep loading the skill. Hermes never exposes the raw secret value to the model. Gateway and messaging sessions show local setup guidance instead of collecting secrets in-band.
|
||||
|
||||
:::tip Sandbox Passthrough
|
||||
When your skill is loaded, any declared `required_environment_variables` that are set are **automatically passed through** to `execute_code` and `terminal` sandboxes — including remote backends like Docker and Modal. Your skill's scripts can access `$TENOR_API_KEY` (or `os.environ["TENOR_API_KEY"]` in Python) without the user needing to configure anything extra. See [Environment Variable Passthrough](/docs/user-guide/security#environment-variable-passthrough) for details.
|
||||
When your skill is loaded, any declared `required_environment_variables` that are set are **automatically passed through** to `execute_code` and `terminal` sandboxes — including remote backends like Docker and Modal. Your skill's scripts can access `$TENOR_API_KEY` (or `os.environ["TENOR_API_KEY"]` in Python) without the user needing to configure anything extra. See [Environment Variable Passthrough](/user-guide/security#environment-variable-passthrough) for details.
|
||||
:::
|
||||
|
||||
Legacy `prerequisites.env_vars` remains supported as a backward-compatible alias.
|
||||
|
|
@ -330,7 +330,7 @@ Bundled skills (in `skills/`) ship with every Hermes install. They should be **b
|
|||
- Document handling, web research, common dev workflows, system administration
|
||||
- Used regularly by a wide range of people
|
||||
|
||||
If your skill is official and useful but not universally needed (e.g., a paid service integration, a heavyweight dependency), put it in **`optional-skills/`** — it ships with the repo, is discoverable via `hermes skills browse` (labeled "official"), and installs with builtin trust.
|
||||
If your skill is official and useful but not universally needed (e.g., a paid service integration, a heavyweight dependency), put it in **`optional-skills/`** — it ships with the repo, is discoverable via `hermes skills browse` (labeled "official"), and installs with built-in trust.
|
||||
|
||||
If your skill is specialized, community-contributed, or niche, it's better suited for a **Skills Hub** — upload it to a registry and share it via `hermes skills install`.
|
||||
|
||||
|
|
@ -363,7 +363,7 @@ All hub-installed skills go through a security scanner that checks for:
|
|||
|
||||
Trust levels:
|
||||
- `builtin` — ships with Hermes (always trusted)
|
||||
- `official` — from `optional-skills/` in the repo (builtin trust, no third-party warning)
|
||||
- `official` — from `optional-skills/` in the repo (built-in trust, no third-party warning)
|
||||
- `trusted` — from openai/skills, anthropics/skills, huggingface/skills
|
||||
- `community` — non-dangerous findings can be overridden with `--force`; `dangerous` verdicts remain blocked
|
||||
|
||||
|
|
|
|||
|
|
@ -223,6 +223,6 @@ hermes cron remove <job_id> # Delete a job
|
|||
|
||||
## Related Docs
|
||||
|
||||
- [Cron Feature Guide](/docs/user-guide/features/cron)
|
||||
- [Cron Feature Guide](/user-guide/features/cron)
|
||||
- [Gateway Internals](./gateway-internals.md)
|
||||
- [Agent Loop Internals](./agent-loop.md)
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ Outgoing deliveries (`gateway/delivery.py`) handle:
|
|||
|
||||
- **Direct reply** — send response back to the originating chat
|
||||
- **Home channel delivery** — route cron job outputs and background results to a configured home channel
|
||||
- **Explicit target delivery** — `send_message` tool specifying `telegram:-1001234567890`, or the [`hermes send` CLI](/docs/guides/pipe-script-output) wrapping the same tool for shell scripts
|
||||
- **Explicit target delivery** — `send_message` tool specifying `telegram:-1001234567890`, or the [`hermes send` CLI](/guides/pipe-script-output) wrapping the same tool for shell scripts
|
||||
- **Cross-platform delivery** — deliver to a different platform than the originating message
|
||||
|
||||
Cron job deliveries are NOT mirrored into gateway session history — they live in their own cron session only. This is a deliberate design choice to avoid message alternation violations.
|
||||
|
|
@ -259,4 +259,4 @@ The gateway runs as a long-lived process, managed via:
|
|||
- [Cron Internals](./cron-internals.md)
|
||||
- [ACP Internals](./acp-internals.md)
|
||||
- [Agent Loop Internals](./agent-loop.md)
|
||||
- [Messaging Gateway (User Guide)](/docs/user-guide/messaging)
|
||||
- [Messaging Gateway (User Guide)](/user-guide/messaging)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ description: "How to build an image-generation backend plugin for Hermes Agent"
|
|||
Image-gen provider plugins register a backend that services every `image_generate` tool call — DALL·E, gpt-image, Grok, Flux, Imagen, Stable Diffusion, fal, Replicate, a local ComfyUI rig, anything. Built-in providers (OpenAI, OpenAI-Codex, xAI) all ship as plugins. You can add a new one, or override a bundled one, by dropping a directory into `plugins/image_gen/<name>/`.
|
||||
|
||||
:::tip
|
||||
Image-gen is one of several **backend plugins** Hermes supports. The others (with more specialized ABCs) are [Memory Provider Plugins](/docs/developer-guide/memory-provider-plugin), [Context Engine Plugins](/docs/developer-guide/context-engine-plugin), and [Model Provider Plugins](/docs/developer-guide/model-provider-plugin). General tool/hook/CLI plugins live in [Build a Hermes Plugin](/docs/guides/build-a-hermes-plugin).
|
||||
Image-gen is one of several **backend plugins** Hermes supports. The others (with more specialized ABCs) are [Memory Provider Plugins](/developer-guide/memory-provider-plugin), [Context Engine Plugins](/developer-guide/context-engine-plugin), and [Model Provider Plugins](/developer-guide/model-provider-plugin). General tool/hook/CLI plugins live in [Build a Hermes Plugin](/guides/build-a-hermes-plugin).
|
||||
:::
|
||||
|
||||
## How discovery works
|
||||
|
|
@ -279,10 +279,10 @@ Or interactively: `hermes tools` → "Image Generation" → select `my-backend`
|
|||
my-backend-imggen = "my_backend_imggen_package"
|
||||
```
|
||||
|
||||
`my_backend_imggen_package` must expose a top-level `register` function. See [Distribute via pip](/docs/guides/build-a-hermes-plugin#distribute-via-pip) in the general plugin guide for the full setup.
|
||||
`my_backend_imggen_package` must expose a top-level `register` function. See [Distribute via pip](/guides/build-a-hermes-plugin#distribute-via-pip) in the general plugin guide for the full setup.
|
||||
|
||||
## Related pages
|
||||
|
||||
- [Image Generation](/docs/user-guide/features/image-generation) — user-facing feature documentation
|
||||
- [Plugins overview](/docs/user-guide/features/plugins) — all plugin types at a glance
|
||||
- [Build a Hermes Plugin](/docs/guides/build-a-hermes-plugin) — general tools/hooks/slash commands guide
|
||||
- [Image Generation](/user-guide/features/image-generation) — user-facing feature documentation
|
||||
- [Plugins overview](/user-guide/features/plugins) — all plugin types at a glance
|
||||
- [Build a Hermes Plugin](/guides/build-a-hermes-plugin) — general tools/hooks/slash commands guide
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ description: "How to build a memory provider plugin for Hermes Agent"
|
|||
Memory provider plugins give Hermes Agent persistent, cross-session knowledge beyond the built-in MEMORY.md and USER.md. This guide covers how to build one.
|
||||
|
||||
:::tip
|
||||
Memory providers are one of two **provider plugin** types. The other is [Context Engine Plugins](/docs/developer-guide/context-engine-plugin), which replace the built-in context compressor. Both follow the same pattern: single-select, config-driven, managed via `hermes plugins`.
|
||||
Memory providers are one of two **provider plugin** types. The other is [Context Engine Plugins](/developer-guide/context-engine-plugin), which replace the built-in context compressor. Both follow the same pattern: single-select, config-driven, managed via `hermes plugins`.
|
||||
:::
|
||||
|
||||
## Directory Structure
|
||||
|
|
@ -61,7 +61,7 @@ class MyMemoryProvider(MemoryProvider):
|
|||
| `is_available()` | Agent init, before activation | **Yes** — no network calls |
|
||||
| `initialize(session_id, **kwargs)` | Agent startup | **Yes** |
|
||||
| `get_tool_schemas()` | After init, for tool injection | **Yes** |
|
||||
| `handle_tool_call(name, args)` | When agent uses your tools | **Yes** (if you have tools) |
|
||||
| `handle_tool_call(tool_name, args, **kwargs)` | When agent uses your tools | **Yes** (if you have tools) |
|
||||
|
||||
### Config
|
||||
|
||||
|
|
@ -75,9 +75,9 @@ class MyMemoryProvider(MemoryProvider):
|
|||
| Method | When Called | Use Case |
|
||||
|--------|-----------|----------|
|
||||
| `system_prompt_block()` | System prompt assembly | Static provider info |
|
||||
| `prefetch(query)` | Before each API call | Return recalled context |
|
||||
| `prefetch(query, *, session_id="")` | Before each API call | Return recalled context |
|
||||
| `queue_prefetch(query)` | After each turn | Pre-warm for next turn |
|
||||
| `sync_turn(user, assistant)` | After each completed turn | Persist conversation |
|
||||
| `sync_turn(user, assistant, *, session_id="")` | After each completed turn | Persist conversation |
|
||||
| `on_session_end(messages)` | Conversation ends | Final extraction/flush |
|
||||
| `on_pre_compress(messages)` | Before context compression | Save insights before discard |
|
||||
| `on_memory_write(action, target, content)` | Built-in memory writes | Mirror to your backend |
|
||||
|
|
@ -154,10 +154,10 @@ hooks:
|
|||
**`sync_turn()` MUST be non-blocking.** If your backend has latency (API calls, LLM processing), run the work in a daemon thread:
|
||||
|
||||
```python
|
||||
def sync_turn(self, user_content, assistant_content):
|
||||
def sync_turn(self, user_content, assistant_content, *, session_id="", messages=None):
|
||||
def _sync():
|
||||
try:
|
||||
self._api.ingest(user_content, assistant_content)
|
||||
self._api.ingest(user_content, assistant_content, session_id=session_id, messages=messages)
|
||||
except Exception as e:
|
||||
logger.warning("Sync failed: %s", e)
|
||||
|
||||
|
|
@ -167,6 +167,16 @@ def sync_turn(self, user_content, assistant_content):
|
|||
self._sync_thread.start()
|
||||
```
|
||||
|
||||
`messages` is optional OpenAI-style conversation context as of the completed
|
||||
turn. When present, it includes user/assistant messages, assistant tool calls,
|
||||
and tool result messages. Providers that do not need raw turn context can omit
|
||||
the `messages` parameter; Hermes will continue calling them with the legacy
|
||||
signature.
|
||||
|
||||
Cloud providers should document what parts of `messages` are sent off-device.
|
||||
Tool calls and tool results may contain file paths, command output, or other
|
||||
workspace data.
|
||||
|
||||
## Profile Isolation
|
||||
|
||||
All storage paths **must** use the `hermes_home` kwarg from `initialize()`, not hardcoded `~/.hermes`:
|
||||
|
|
@ -182,7 +192,7 @@ data_dir = Path("~/.hermes/my-provider").expanduser()
|
|||
|
||||
## Testing
|
||||
|
||||
See `tests/agent/test_memory_plugin_e2e.py` for the complete E2E testing pattern using a real SQLite provider.
|
||||
See `tests/agent/test_memory_provider.py` and adjacent memory tests (`tests/agent/test_memory_session_switch.py`, `tests/agent/test_memory_user_id.py`, `tests/run_agent/test_memory_provider_init.py`) for end-to-end patterns.
|
||||
|
||||
```python
|
||||
from agent.memory_manager import MemoryManager
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ description: "How to build a model provider (inference backend) plugin for Herme
|
|||
Model provider plugins declare an inference backend — an OpenAI-compatible endpoint, an Anthropic Messages server, a Codex-style Responses API, or a Bedrock-native surface — that Hermes can route `AIAgent` calls through. Every built-in provider (OpenRouter, Anthropic, GMI, DeepSeek, Nvidia, …) ships as one of these plugins. Third parties can add their own by dropping a directory under `$HERMES_HOME/plugins/model-providers/` with zero changes to the repo.
|
||||
|
||||
:::tip
|
||||
Model provider plugins are the third kind of **provider plugin**. The others are [Memory Provider Plugins](/docs/developer-guide/memory-provider-plugin) (cross-session knowledge) and [Context Engine Plugins](/docs/developer-guide/context-engine-plugin) (context compression strategies). All three follow the same "drop a directory, declare a profile, no repo edits" pattern.
|
||||
Model provider plugins are the third kind of **provider plugin**. The others are [Memory Provider Plugins](/developer-guide/memory-provider-plugin) (cross-session knowledge) and [Context Engine Plugins](/developer-guide/context-engine-plugin) (context compression strategies). All three follow the same "drop a directory, declare a profile, no repo edits" pattern.
|
||||
:::
|
||||
|
||||
## How discovery works
|
||||
|
|
@ -89,7 +89,7 @@ Full definition in `providers/base.py`. The most useful ones:
|
|||
|
||||
| Field | Type | Purpose |
|
||||
|---|---|---|
|
||||
| `name` | str | Canonical id — matches `--provider` choices and `HERMES_INFERENCE_PROVIDER` |
|
||||
| `name` | str | Canonical id — matches `model.provider` in `config.yaml` and the `--provider` flag |
|
||||
| `aliases` | `tuple[str, ...]` | Alternative names resolved by `get_provider_profile()` (e.g. `grok` → `xai`) |
|
||||
| `api_mode` | str | `chat_completions` \| `codex_responses` \| `anthropic_messages` \| `bedrock_converse` |
|
||||
| `display_name` | str | Human label shown in `hermes model` picker |
|
||||
|
|
@ -131,8 +131,9 @@ class AcmeProfile(ProviderProfile):
|
|||
|
||||
def build_api_kwargs_extras(self, *, reasoning_config=None, **context):
|
||||
"""Returns (extra_body_additions, top_level_kwargs). Needed when some
|
||||
fields go top-level (Kimi's reasoning_effort) and some go in extra_body
|
||||
(OpenRouter's reasoning dict). Default: ({}, {})."""
|
||||
fields go top-level (Kimi's reasoning_effort, OpenRouter's verbosity for
|
||||
adaptive Anthropic models) and some go in extra_body (OpenRouter's
|
||||
reasoning dict). Default: ({}, {})."""
|
||||
return {}, {}
|
||||
|
||||
def fetch_models(self, *, api_key=None, timeout=8.0) -> list[str] | None:
|
||||
|
|
@ -250,18 +251,18 @@ The general `PluginManager` (the thing `hermes plugins` operates on) **sees** mo
|
|||
Like any Hermes plugin, model providers can ship as a pip package. Add an entry point to your `pyproject.toml`:
|
||||
|
||||
```toml
|
||||
[project.entry-points."hermes.plugins"]
|
||||
[project.entry-points."hermes_agent.plugins"]
|
||||
acme-inference = "acme_hermes_plugin:register"
|
||||
```
|
||||
|
||||
…where `acme_hermes_plugin:register` is a function that calls `register_provider(profile)`. The general PluginManager picks up entry-point plugins during `discover_and_load()`. For `kind: model-provider` pip plugins, you still need to declare the kind in your manifest (or rely on the source-text heuristic).
|
||||
|
||||
See [Building a Hermes Plugin](/docs/guides/build-a-hermes-plugin#distribute-via-pip) for the full entry-points setup.
|
||||
See [Building a Hermes Plugin](/guides/build-a-hermes-plugin#distribute-via-pip) for the full entry-points setup.
|
||||
|
||||
## Related pages
|
||||
|
||||
- [Provider Runtime](/docs/developer-guide/provider-runtime) — resolution precedence + where each layer reads the profile
|
||||
- [Adding Providers](/docs/developer-guide/adding-providers) — end-to-end checklist for new inference backends (covers both the fast plugin path and the full CLI/auth integration)
|
||||
- [Memory Provider Plugins](/docs/developer-guide/memory-provider-plugin)
|
||||
- [Context Engine Plugins](/docs/developer-guide/context-engine-plugin)
|
||||
- [Building a Hermes Plugin](/docs/guides/build-a-hermes-plugin) — general plugin authoring
|
||||
- [Provider Runtime](/developer-guide/provider-runtime) — resolution precedence + where each layer reads the profile
|
||||
- [Adding Providers](/developer-guide/adding-providers) — end-to-end checklist for new inference backends (covers both the fast plugin path and the full CLI/auth integration)
|
||||
- [Memory Provider Plugins](/developer-guide/memory-provider-plugin)
|
||||
- [Context Engine Plugins](/developer-guide/context-engine-plugin)
|
||||
- [Building a Hermes Plugin](/guides/build-a-hermes-plugin) — general plugin authoring
|
||||
|
|
|
|||
|
|
@ -462,4 +462,4 @@ own model call — for any reason, structured or not — `ctx.llm`.
|
|||
* [`plugin-llm-example`](https://github.com/NousResearch/hermes-example-plugins/tree/main/plugin-llm-example) — sync structured extraction with image input
|
||||
* [`plugin-llm-async-example`](https://github.com/NousResearch/hermes-example-plugins/tree/main/plugin-llm-async-example) — async with `asyncio.gather()`
|
||||
* Auxiliary client (the engine under the hood): see
|
||||
[Provider Runtime](/docs/developer-guide/provider-runtime).
|
||||
[Provider Runtime](/developer-guide/provider-runtime).
|
||||
|
|
|
|||
|
|
@ -41,7 +41,8 @@ hermes acp --bootstrap # print install snippet for an ACP-capable IDE
|
|||
|
||||
```
|
||||
prompt.submit prompt.background session.steer
|
||||
session.create session.list session.interrupt
|
||||
session.create session.list session.active_list
|
||||
session.activate session.close session.interrupt
|
||||
session.history session.compress session.branch
|
||||
session.title session.usage session.status
|
||||
clarify.respond sudo.respond secret.respond
|
||||
|
|
@ -52,6 +53,8 @@ delegation.status subagent.interrupt spawn_tree.save / list / load
|
|||
terminal.resize clipboard.paste image.attach
|
||||
```
|
||||
|
||||
`session.active_list`, `session.activate`, and `session.close` are the process-local live-session controls used by the TUI session switcher. Use `session.list` / `/resume` for saved transcript discovery; use the active-session methods only for sessions that are currently open in the TUI gateway process.
|
||||
|
||||
### Events streamed back
|
||||
|
||||
`message.delta`, `message.complete`, `tool.start`, `tool.progress`, `tool.complete`, `approval.request`, `clarify.request`, `sudo.request`, `secret.request`, `gateway.ready`, plus session lifecycle and error events.
|
||||
|
|
|
|||
|
|
@ -26,18 +26,18 @@ Primary files:
|
|||
|
||||
## Cached system prompt layers
|
||||
|
||||
The cached system prompt is assembled in roughly this order:
|
||||
The cached system prompt is assembled as three ordered tiers (see `agent/system_prompt.py`):
|
||||
|
||||
1. agent identity — `SOUL.md` from `HERMES_HOME` when available, otherwise falls back to `DEFAULT_AGENT_IDENTITY` in `prompt_builder.py`
|
||||
2. tool-aware behavior guidance
|
||||
3. Honcho static block (when active)
|
||||
4. optional system message
|
||||
5. frozen MEMORY snapshot
|
||||
6. frozen USER profile snapshot
|
||||
7. skills index
|
||||
8. context files (`AGENTS.md`, `.cursorrules`, `.cursor/rules/*.mdc`) — SOUL.md is **not** included here when it was already loaded as the identity in step 1
|
||||
9. timestamp / optional session ID
|
||||
10. platform hint
|
||||
1. **stable** — identity (`SOUL.md` or fallback), tool/model guidance, skills prompt, environment hints, platform hints
|
||||
2. **context** — caller-supplied `system_message` plus project context files (`.hermes.md` / `AGENTS.md` / `CLAUDE.md` / `.cursorrules`)
|
||||
3. **volatile** — built-in memory snapshot (`MEMORY.md`), user profile snapshot (`USER.md`), external memory-provider block, timestamp/session/model/provider line
|
||||
|
||||
The final system prompt is then joined as: `stable` → `context` → `volatile`.
|
||||
|
||||
This ordering matters for precedence discussions:
|
||||
- skills are part of the **stable** tier
|
||||
- memory/profile snapshots are part of the **volatile** tier
|
||||
- both are still in the cached system prompt (they are not injected as ad-hoc mid-turn overlays)
|
||||
|
||||
When `skip_context_files` is set (e.g., subagent delegation), SOUL.md is not loaded and the hardcoded `DEFAULT_AGENT_IDENTITY` is used instead.
|
||||
|
||||
|
|
@ -205,13 +205,15 @@ These are intentionally *not* persisted as part of the cached system prompt:
|
|||
- `ephemeral_system_prompt`
|
||||
- prefill messages
|
||||
- gateway-derived session context overlays
|
||||
- later-turn Honcho recall injected into the current-turn user message
|
||||
- later-turn Honcho/external recall injected into the current-turn user message
|
||||
|
||||
`pre_llm_call` plugin context also lands in this API-call-time path: it is appended to the current turn's **user message**, not written into the cached system prompt. When multiple plugins return context, Hermes concatenates those context blocks (see [Hooks → `pre_llm_call`](../user-guide/features/hooks.md#pre_llm_call)).
|
||||
|
||||
This separation keeps the stable prefix stable for caching.
|
||||
|
||||
## Memory snapshots
|
||||
|
||||
Local memory and user profile data are injected as frozen snapshots at session start. Mid-session writes update disk state but do not mutate the already-built system prompt until a new session or forced rebuild occurs.
|
||||
Local memory and user profile data are captured in the system prompt's **volatile tier**. Mid-session writes update disk state but do not mutate the already-built cached system prompt until a rebuild path runs (new session, or explicit invalidation/rebuild flow such as compression-triggered rebuild).
|
||||
|
||||
## Context files
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ That ordering matters because Hermes treats the saved model/provider choice as t
|
|||
|
||||
Current provider families include (see `plugins/model-providers/` for the complete bundled set):
|
||||
|
||||
- AI Gateway (Vercel)
|
||||
- OpenRouter
|
||||
- Nous Portal
|
||||
- OpenAI Codex
|
||||
|
|
@ -93,18 +92,13 @@ This resolver is the main reason Hermes can share auth/runtime logic between:
|
|||
- ACP editor sessions
|
||||
- auxiliary model tasks
|
||||
|
||||
## AI Gateway
|
||||
## OpenRouter and custom OpenAI-compatible base URLs
|
||||
|
||||
Set `AI_GATEWAY_API_KEY` in `~/.hermes/.env` and run with `--provider ai-gateway`. Hermes fetches available models from the gateway's `/models` endpoint, filtering to language models with tool-use support.
|
||||
|
||||
## OpenRouter, AI Gateway, and custom OpenAI-compatible base URLs
|
||||
|
||||
Hermes contains logic to avoid leaking the wrong API key to a custom endpoint when multiple provider keys exist (e.g. `OPENROUTER_API_KEY`, `AI_GATEWAY_API_KEY`, and `OPENAI_API_KEY`).
|
||||
Hermes contains logic to avoid leaking the wrong API key to a custom endpoint when multiple provider keys exist (e.g. `OPENROUTER_API_KEY` and `OPENAI_API_KEY`).
|
||||
|
||||
Each provider's API key is scoped to its own base URL:
|
||||
|
||||
- `OPENROUTER_API_KEY` is only sent to `openrouter.ai` endpoints
|
||||
- `AI_GATEWAY_API_KEY` is only sent to `ai-gateway.vercel.sh` endpoints
|
||||
- `OPENAI_API_KEY` is used for custom endpoints and as a fallback
|
||||
|
||||
Hermes also distinguishes between:
|
||||
|
|
@ -115,7 +109,7 @@ Hermes also distinguishes between:
|
|||
That distinction is especially important for:
|
||||
|
||||
- local model servers
|
||||
- non-OpenRouter/non-AI Gateway OpenAI-compatible APIs
|
||||
- non-OpenRouter OpenAI-compatible APIs
|
||||
- switching providers without re-running setup
|
||||
- config-saved custom endpoints that should keep working even when `OPENAI_BASE_URL` is not exported in the current shell
|
||||
|
||||
|
|
@ -199,7 +193,11 @@ Cron jobs **do** support fallback: `run_job()` reads `fallback_providers` (or le
|
|||
|
||||
### Test coverage
|
||||
|
||||
See `tests/test_fallback_model.py` for comprehensive tests covering all supported providers, one-shot semantics, and edge cases.
|
||||
Fallback behavior is exercised across several suites:
|
||||
|
||||
- `tests/run_agent/test_fallback_credential_isolation.py` — credential isolation between primary and fallback
|
||||
- `tests/hermes_cli/test_fallback_cmd.py` — the `/fallback` CLI command
|
||||
- `tests/gateway/test_fallback_eviction.py` — gateway eviction of failed providers
|
||||
|
||||
## Related docs
|
||||
|
||||
|
|
|
|||
|
|
@ -213,7 +213,6 @@ The terminal system supports multiple backends:
|
|||
- singularity
|
||||
- modal
|
||||
- daytona
|
||||
- vercel_sandbox
|
||||
|
||||
It also supports:
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ description: "How to build a video-generation backend plugin for Hermes Agent"
|
|||
Video-gen provider plugins register a backend that services every `video_generate` tool call. Built-in providers (xAI, FAL) ship as plugins. Add a new one, or override a bundled one, by dropping a directory into `plugins/video_gen/<name>/`.
|
||||
|
||||
:::tip
|
||||
Video-gen mirrors [Image Generation Provider Plugins](/docs/developer-guide/image-gen-provider-plugin) almost line-for-line — if you've built an image-gen backend, you already know the shape. The main differences: a `capabilities()` method advertising modalities/aspect-ratios/durations, and a routing convention (pass `image_url` to use image-to-video, omit it to use text-to-video — the provider picks the right endpoint internally).
|
||||
Video-gen mirrors [Image Generation Provider Plugins](/developer-guide/image-gen-provider-plugin) almost line-for-line — if you've built an image-gen backend, you already know the shape. The main differences: a `capabilities()` method advertising modalities/aspect-ratios/durations, and a routing convention (pass `image_url` to use image-to-video, omit it to use text-to-video — the provider picks the right endpoint internally).
|
||||
:::
|
||||
|
||||
## The unified surface (one tool, two modalities)
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@ description: "How to build a web-search/extract/crawl backend plugin for Hermes
|
|||
|
||||
# Building a Web Search Provider Plugin
|
||||
|
||||
Web-search provider plugins register a backend that services `web_search`, `web_extract`, and (optionally) deep-crawl tool calls. Built-in providers — Firecrawl, SearXNG, Tavily, Exa, Parallel, Brave Search (free tier), and DDGS — all ship as plugins under `plugins/web/<name>/`. You can add a new one, or override a bundled one, by dropping a directory next to them.
|
||||
Web-search provider plugins register a backend that services `web_search`, `web_extract`, and (optionally) deep-crawl tool calls. Built-in providers — Firecrawl, SearXNG, Tavily, Exa, Parallel, Brave Search (free tier), xAI, and DDGS — all ship as plugins under `plugins/web/<name>/`. You can add a new one, or override a bundled one, by dropping a directory next to them.
|
||||
|
||||
:::tip
|
||||
Web search is one of several **backend plugins** Hermes supports. The others (with their own ABCs) are [Image Generation Provider Plugins](/docs/developer-guide/image-gen-provider-plugin), [Video Generation Provider Plugins](/docs/developer-guide/video-gen-provider-plugin), [Memory Provider Plugins](/docs/developer-guide/memory-provider-plugin), [Context Engine Plugins](/docs/developer-guide/context-engine-plugin), and [Model Provider Plugins](/docs/developer-guide/model-provider-plugin). General tool/hook/CLI plugins live in [Build a Hermes Plugin](/docs/guides/build-a-hermes-plugin).
|
||||
Web search is one of several **backend plugins** Hermes supports. The others (with their own ABCs) are [Image Generation Provider Plugins](/developer-guide/image-gen-provider-plugin), [Video Generation Provider Plugins](/developer-guide/video-gen-provider-plugin), [Memory Provider Plugins](/developer-guide/memory-provider-plugin), [Context Engine Plugins](/developer-guide/context-engine-plugin), and [Model Provider Plugins](/developer-guide/model-provider-plugin). General tool/hook/CLI plugins live in [Build a Hermes Plugin](/guides/build-a-hermes-plugin).
|
||||
:::
|
||||
|
||||
## How discovery works
|
||||
|
|
@ -43,7 +43,7 @@ plugins/web/my-backend/
|
|||
|
||||
## The WebSearchProvider ABC
|
||||
|
||||
Subclass `agent.web_search_provider.WebSearchProvider`. The only required members are `name`, `is_available()`, and whichever of `search()` / `extract()` / `crawl()` you implement.
|
||||
Subclass `agent.web_search_provider.WebSearchProvider`. The only required members are `name`, `is_available()`, and whichever of `search()` / `extract()` you implement. (Deep crawling is not a separate method — it's a mode of `extract()`.)
|
||||
|
||||
```python
|
||||
# plugins/web/my-backend/provider.py
|
||||
|
|
@ -80,9 +80,6 @@ class MyBackendWebSearchProvider(WebSearchProvider):
|
|||
def supports_extract(self) -> bool:
|
||||
return False
|
||||
|
||||
def supports_crawl(self) -> bool:
|
||||
return False
|
||||
|
||||
def search(self, query: str, limit: int = 5) -> Dict[str, Any]:
|
||||
import httpx
|
||||
|
||||
|
|
@ -144,7 +141,7 @@ requires_env:
|
|||
|---|---|
|
||||
| `kind: backend` | Routes the plugin through the backend-loading path |
|
||||
| `provides_web_providers` | List of provider `name`s this plugin registers — used by the loader to advertise the plugin in `hermes tools` even before `register()` runs |
|
||||
| `requires_env` | Interactive credential prompt during `hermes plugins install` (see [Build a Hermes Plugin](/docs/guides/build-a-hermes-plugin#gate-on-environment-variables) for the rich format) |
|
||||
| `requires_env` | Interactive credential prompt during `hermes plugins install` (see [Build a Hermes Plugin](/guides/build-a-hermes-plugin#gate-on-environment-variables) for the rich format) |
|
||||
|
||||
## ABC reference
|
||||
|
||||
|
|
@ -157,12 +154,10 @@ Full contract in `agent/web_search_provider.py`. Methods you may override:
|
|||
| `is_available()` | ✅ | — | Cheap availability gate — env vars, optional deps |
|
||||
| `supports_search()` | — | `True` | Capability flag for `web_search` routing |
|
||||
| `supports_extract()` | — | `False` | Capability flag for `web_extract` routing |
|
||||
| `supports_crawl()` | — | `False` | Capability flag for deep-crawl modes |
|
||||
| `search(query, limit)` | conditional | raises | Required when `supports_search()` returns `True` |
|
||||
| `extract(urls, **kwargs)` | conditional | raises | Required when `supports_extract()` returns `True` |
|
||||
| `crawl(url, **kwargs)` | conditional | raises | Required when `supports_crawl()` returns `True` |
|
||||
|
||||
Providers can advertise multiple capabilities from a single class — Firecrawl, Tavily, Exa, and Parallel all implement all three of search/extract/crawl. Brave Search and DDGS are search-only; SearXNG is search-only with a documented "pair me with an extract provider" workflow.
|
||||
Providers can advertise multiple capabilities from a single class — Firecrawl, Tavily, Exa, and Parallel all implement both search and extract. Brave Search and DDGS are search-only; SearXNG is search-only with a documented "pair me with an extract provider" workflow.
|
||||
|
||||
## Response shape
|
||||
|
||||
|
|
@ -231,14 +226,14 @@ The `web_search` and `web_extract` tools live in `tools/web_tools.py`. At call t
|
|||
1. Read the relevant config key (`web.search_backend` for `web_search`, `web.extract_backend` for `web_extract`)
|
||||
2. Ask the registry for the provider with that `name`
|
||||
3. Check `is_available()` and the matching `supports_*()` flag
|
||||
4. Dispatch to `search()` / `extract()` / `crawl()`, awaiting if the method is a coroutine
|
||||
4. Dispatch to `search()` / `extract()` (deep crawl runs as a mode inside `extract()`), awaiting if the method is a coroutine
|
||||
5. JSON-serialize the response envelope and hand it back to the LLM
|
||||
|
||||
Errors surface as the tool result; the LLM decides how to explain them. If no provider is registered (or every available one fails the capability gate), the tool returns a helpful error pointing at `hermes tools`.
|
||||
|
||||
## Lazy-installing optional dependencies
|
||||
|
||||
If your provider wraps a third-party SDK (like DDGS does with the `ddgs` package), don't `import` it at module top level. Use `tools.lazy_deps.ensure(...)` inside `is_available()` or `search()` — Hermes will install the package on first use, gated by `security.allow_lazy_installs`. See [Build a Hermes Plugin → Lazy-install](/docs/guides/build-a-hermes-plugin#lazy-install-optional-python-dependencies) for the security model.
|
||||
If your provider wraps a third-party SDK (like DDGS does with the `ddgs` package), don't `import` it at module top level. Use `tools.lazy_deps.ensure(...)` inside `is_available()` or `search()` — Hermes will install the package on first use, gated by `security.allow_lazy_installs`. See [Build a Hermes Plugin → Lazy-install](/guides/build-a-hermes-plugin#lazy-install-optional-python-dependencies) for the security model.
|
||||
|
||||
## Reference implementations
|
||||
|
||||
|
|
@ -256,10 +251,10 @@ If your provider wraps a third-party SDK (like DDGS does with the `ddgs` package
|
|||
my-backend-web = "my_backend_web_package"
|
||||
```
|
||||
|
||||
`my_backend_web_package` must expose a top-level `register` function. See [Distribute via pip](/docs/guides/build-a-hermes-plugin#distribute-via-pip) in the general plugin guide for the full setup.
|
||||
`my_backend_web_package` must expose a top-level `register` function. See [Distribute via pip](/guides/build-a-hermes-plugin#distribute-via-pip) in the general plugin guide for the full setup.
|
||||
|
||||
## Related pages
|
||||
|
||||
- [Web Search](/docs/user-guide/features/web-search) — user-facing feature documentation and per-backend configuration
|
||||
- [Plugins overview](/docs/user-guide/features/plugins) — all plugin types at a glance
|
||||
- [Build a Hermes Plugin](/docs/guides/build-a-hermes-plugin) — general tools/hooks/slash commands guide
|
||||
- [Web Search](/user-guide/features/web-search) — user-facing feature documentation and per-backend configuration
|
||||
- [Plugins overview](/user-guide/features/plugins) — all plugin types at a glance
|
||||
- [Build a Hermes Plugin](/guides/build-a-hermes-plugin) — general tools/hooks/slash commands guide
|
||||
|
|
|
|||
|
|
@ -1,79 +1,37 @@
|
|||
---
|
||||
sidebar_position: 2
|
||||
title: "Installation"
|
||||
description: "Install Hermes Agent on Linux, macOS, WSL2, native Windows (early beta), or Android via Termux"
|
||||
description: "Install Hermes Agent on Linux, macOS, WSL2, native Windows, or Android via Termux"
|
||||
---
|
||||
|
||||
# Installation
|
||||
|
||||
Get Hermes Agent up and running in under two minutes with the one-line installer.
|
||||
Get Hermes Agent up and running in under two minutes!
|
||||
|
||||
## Quick Install
|
||||
### With the Hermes Desktop installer on macOS or Windows (recommended)
|
||||
To easily install the command-line and desktop applications, [download the Hermes Desktop installer](https://hermes-agent.nousresearch.com/desktop) from our website and run it.
|
||||
|
||||
### One-Line Installer (Linux / macOS / WSL2)
|
||||
|
||||
For a git-based install that tracks `main` and gives you the latest changes immediately:
|
||||
### Without Hermes Desktop:
|
||||
For a command-line only install without Hermes Desktop, run:
|
||||
|
||||
#### Linux / macOS / WSL2 / Android (Termux)
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
|
||||
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash
|
||||
```
|
||||
|
||||
### Windows (native, PowerShell) — Early Beta
|
||||
|
||||
:::warning Early BETA
|
||||
Native Windows support is **early beta**. It installs and works for the common paths, but hasn't been road-tested as broadly as our POSIX installers. Please [file issues](https://github.com/NousResearch/hermes-agent/issues) when you hit rough edges. For the most battle-tested setup on Windows today, use the Linux/macOS one-liner above inside **WSL2** instead.
|
||||
:::
|
||||
|
||||
Open PowerShell and run:
|
||||
#### Windows (native)
|
||||
|
||||
Run in powershell:
|
||||
```powershell
|
||||
iex (irm https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.ps1)
|
||||
iex (irm https://hermes-agent.nousresearch.com/install.ps1)
|
||||
```
|
||||
|
||||
The installer handles **everything**: `uv`, Python 3.11, Node.js 22, `ripgrep`, `ffmpeg`, **and a portable Git Bash** (PortableGit — a self-contained Git-for-Windows distribution that ships `bash.exe` and the full POSIX toolchain Hermes uses for shell commands; on 32-bit Windows the installer falls back to MinGit, which lacks bash and disables terminal-tool / agent-browser features). It clones the repo under `%LOCALAPPDATA%\hermes\hermes-agent`, creates a virtualenv, and adds `hermes` to your **User PATH**. Restart your terminal (or open a new PowerShell window) after the install so PATH picks up.
|
||||
|
||||
**How Git is handled:**
|
||||
1. If `git` is already on your PATH, the installer uses your existing install.
|
||||
2. Otherwise it downloads portable **PortableGit** (~50MB, from the official `git-for-windows` GitHub release) and unpacks it to `%LOCALAPPDATA%\hermes\git`. No admin rights required. Completely isolated — it won't interfere with any system Git install, broken or otherwise. (On 32-bit Windows it falls back to MinGit because PortableGit ships only 64-bit and ARM64 assets; bash-dependent Hermes features won't work on 32-bit hosts.)
|
||||
|
||||
**Why not use winget?** Earlier designs auto-installed Git via `winget install Git.Git`, but winget fails badly when a system Git install is in a partial or broken state (exactly when users need the installer to just work). The portable Git approach sidesteps winget, the Windows installer registry, and any existing system Git entirely. If the Hermes Git install itself ever breaks, `Remove-Item %LOCALAPPDATA%\hermes\git` and re-run the installer — no system impact, no uninstall drama.
|
||||
|
||||
The installer also sets `HERMES_GIT_BASH_PATH` to the located `bash.exe` so Hermes resolves it deterministically in fresh shells.
|
||||
|
||||
If you prefer WSL2, the Linux installer above works inside it; both native and WSL installs can coexist without conflict (native data lives under `%LOCALAPPDATA%\hermes`, WSL data lives under `~/.hermes`).
|
||||
|
||||
**Desktop installer (alternative):** A thin GUI installer is also available — download Hermes Desktop, run the `.exe`, and on first launch it calls `install.ps1` under the hood to provision Python (via `uv`), Node, PortableGit, and the rest of the dependencies. The desktop app and the PowerShell-installed CLI share the same install and data directories, so you can use either or both. See the [Windows (Native) guide](../user-guide/windows-native#desktop-installer-alternative) for details.
|
||||
|
||||
### Android / Termux
|
||||
|
||||
Hermes now ships a Termux-aware installer path too:
|
||||
|
||||
If you want to install & run Hermes Desktop after a command-line only install, simply run
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
|
||||
hermes desktop
|
||||
```
|
||||
|
||||
The installer detects Termux automatically and switches to a tested Android flow:
|
||||
- uses Termux `pkg` for system dependencies (`git`, `python`, `nodejs`, `ripgrep`, `ffmpeg`, build tools)
|
||||
- creates the virtualenv with `python -m venv`
|
||||
- exports `ANDROID_API_LEVEL` automatically for Android wheel builds
|
||||
- prefers the broad `.[termux-all]` extra and falls back to the smaller `.[termux]` extra (and finally a base install) if the first attempt fails to compile
|
||||
- skips the untested browser / WhatsApp bootstrap by default
|
||||
|
||||
If you want the fully explicit path, follow the dedicated [Termux guide](./termux.md).
|
||||
|
||||
:::note Windows Feature Parity (Early Beta)
|
||||
|
||||
Native Windows is in **early beta**. Everything except the browser-based dashboard chat terminal runs natively on Windows:
|
||||
- **CLI (`hermes chat`, `hermes setup`, `hermes gateway`, …)** — native, uses your default terminal
|
||||
- **Gateway (Telegram, Discord, Slack, …)** — native, runs as a background PowerShell process
|
||||
- **Cron scheduler** — native
|
||||
- **Browser tool** — native (Chromium via Node.js)
|
||||
- **MCP servers** — native (stdio and HTTP transports both supported)
|
||||
- **Dashboard `/chat` terminal pane** — **WSL2 only** (uses a POSIX PTY; native Windows has no equivalent). The rest of the dashboard (sessions, jobs, metrics) works natively — only the embedded PTY terminal tab is gated.
|
||||
|
||||
Set `HERMES_DISABLE_WINDOWS_UTF8=1` in your environment if you hit an encoding-related bug and want to fall back to the legacy cp1252 stdio path (useful for bisecting).
|
||||
:::
|
||||
|
||||
### What the Installer Does
|
||||
|
||||
The installer handles everything automatically — all dependencies (Python, Node.js, ripgrep, ffmpeg), the repo clone, virtual environment, global `hermes` command setup, and LLM provider configuration. By the end, you're ready to chat.
|
||||
|
|
@ -109,13 +67,21 @@ hermes config set # Set individual config values
|
|||
hermes setup # Or run the full setup wizard to configure everything at once
|
||||
```
|
||||
|
||||
:::tip Fastest path: Nous Portal
|
||||
One subscription covers 300+ models plus the [Tool Gateway](/user-guide/features/tool-gateway) (web search, image generation, TTS, cloud browser). Skip the per-tool key juggling:
|
||||
|
||||
```bash
|
||||
hermes setup --portal
|
||||
```
|
||||
|
||||
That logs you in, sets Nous as your provider, and turns on the Tool Gateway in one command.
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
**pip install:** No prerequisites beyond Python 3.11+. Everything else is handled automatically.
|
||||
|
||||
**Git installer:** The only prerequisite is **Git**. The installer automatically handles everything else:
|
||||
**Installer:** On non-Windows platforms, the only prerequisite is **Git**. The installer automatically handles everything else:
|
||||
|
||||
- **uv** (fast Python package manager)
|
||||
- **Python 3.11** (via uv, no sudo needed)
|
||||
|
|
@ -153,12 +119,12 @@ Running Hermes as a dedicated unprivileged user (e.g. a `hermes` systemd service
|
|||
|
||||
2. **As the unprivileged service user**, run the regular installer. It will detect the missing sudo, skip `--with-deps`, and install Chromium into the user's local Playwright cache:
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
|
||||
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash
|
||||
```
|
||||
|
||||
If you want to skip the Playwright step entirely — for example because you're running headless and don't need browser automation — pass `--skip-browser`:
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash -s -- --skip-browser
|
||||
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash -s -- --skip-browser
|
||||
```
|
||||
|
||||
3. **Make `hermes` available to the service user's shells.** The installer writes the launcher to `~/.local/bin/hermes`. System service accounts often have a minimal PATH that doesn't include `~/.local/bin`. Either add it to the user's environment, or symlink the launcher into a system location:
|
||||
|
|
|
|||
|
|
@ -9,7 +9,11 @@ description: 'Choose your learning path through the Hermes Agent documentation b
|
|||
Hermes Agent can do a lot — CLI assistant, Telegram/Discord bot, task automation, RL training, and more. This page helps you figure out where to start and what to read based on your experience level and what you're trying to accomplish.
|
||||
|
||||
:::tip Start Here
|
||||
If you haven't installed Hermes Agent yet, begin with the [Installation guide](/docs/getting-started/installation) and then run through the [Quickstart](/docs/getting-started/quickstart). Everything below assumes you have a working installation.
|
||||
If you haven't installed Hermes Agent yet, begin with the [Installation guide](/getting-started/installation) and then run through the [Quickstart](/getting-started/quickstart). Everything below assumes you have a working installation.
|
||||
:::
|
||||
|
||||
:::tip First-time provider setup
|
||||
First-time users almost always want `hermes setup --portal` — one OAuth covers a model plus the four Tool Gateway tools (search/image/TTS/browser). See [Nous Portal](/integrations/nous-portal).
|
||||
:::
|
||||
|
||||
## How to Use This Page
|
||||
|
|
@ -22,9 +26,9 @@ If you haven't installed Hermes Agent yet, begin with the [Installation guide](/
|
|||
|
||||
| Level | Goal | Recommended Reading | Time Estimate |
|
||||
|---|---|---|---|
|
||||
| **Beginner** | Get up and running, have basic conversations, use built-in tools | [Installation](/docs/getting-started/installation) → [Quickstart](/docs/getting-started/quickstart) → [CLI Usage](/docs/user-guide/cli) → [Configuration](/docs/user-guide/configuration) | ~1 hour |
|
||||
| **Intermediate** | Set up messaging bots, use advanced features like memory, cron jobs, and skills | [Sessions](/docs/user-guide/sessions) → [Messaging](/docs/user-guide/messaging) → [Tools](/docs/user-guide/features/tools) → [Skills](/docs/user-guide/features/skills) → [Memory](/docs/user-guide/features/memory) → [Cron](/docs/user-guide/features/cron) | ~2–3 hours |
|
||||
| **Advanced** | Build custom tools, create skills, train models with RL, contribute to the project | [Architecture](/docs/developer-guide/architecture) → [Adding Tools](/docs/developer-guide/adding-tools) → [Creating Skills](/docs/developer-guide/creating-skills) → [RL Training](/docs/user-guide/features/rl-training) → [Contributing](/docs/developer-guide/contributing) | ~4–6 hours |
|
||||
| **Beginner** | Get up and running, have basic conversations, use built-in tools | [Installation](/getting-started/installation) → [Quickstart](/getting-started/quickstart) → [CLI Usage](/user-guide/cli) → [Configuration](/user-guide/configuration) | ~1 hour |
|
||||
| **Intermediate** | Set up messaging bots, use advanced features like memory, cron jobs, and skills | [Sessions](/user-guide/sessions) → [Messaging](/user-guide/messaging) → [Tools](/user-guide/features/tools) → [Skills](/user-guide/features/skills) → [Memory](/user-guide/features/memory) → [Cron](/user-guide/features/cron) | ~2–3 hours |
|
||||
| **Advanced** | Build custom tools, create skills, train models with RL, contribute to the project | [Architecture](/developer-guide/architecture) → [Adding Tools](/developer-guide/adding-tools) → [Creating Skills](/developer-guide/creating-skills) → [Contributing](/developer-guide/contributing) | ~4–6 hours |
|
||||
|
||||
## By Use Case
|
||||
|
||||
|
|
@ -34,12 +38,12 @@ Pick the scenario that matches what you want to do. Each one links you to the re
|
|||
|
||||
Use Hermes Agent as an interactive terminal assistant for writing, reviewing, and running code.
|
||||
|
||||
1. [Installation](/docs/getting-started/installation)
|
||||
2. [Quickstart](/docs/getting-started/quickstart)
|
||||
3. [CLI Usage](/docs/user-guide/cli)
|
||||
4. [Code Execution](/docs/user-guide/features/code-execution)
|
||||
5. [Context Files](/docs/user-guide/features/context-files)
|
||||
6. [Tips & Tricks](/docs/guides/tips)
|
||||
1. [Installation](/getting-started/installation)
|
||||
2. [Quickstart](/getting-started/quickstart)
|
||||
3. [CLI Usage](/user-guide/cli)
|
||||
4. [Code Execution](/user-guide/features/code-execution)
|
||||
5. [Context Files](/user-guide/features/context-files)
|
||||
6. [Tips & Tricks](/guides/tips)
|
||||
|
||||
:::tip
|
||||
Pass files directly into your conversation with context files. Hermes Agent can read, edit, and run code in your projects.
|
||||
|
|
@ -49,28 +53,28 @@ Pass files directly into your conversation with context files. Hermes Agent can
|
|||
|
||||
Deploy Hermes Agent as a bot on your favorite messaging platform.
|
||||
|
||||
1. [Installation](/docs/getting-started/installation)
|
||||
2. [Configuration](/docs/user-guide/configuration)
|
||||
3. [Messaging Overview](/docs/user-guide/messaging)
|
||||
4. [Telegram Setup](/docs/user-guide/messaging/telegram)
|
||||
5. [Discord Setup](/docs/user-guide/messaging/discord)
|
||||
6. [Voice Mode](/docs/user-guide/features/voice-mode)
|
||||
7. [Use Voice Mode with Hermes](/docs/guides/use-voice-mode-with-hermes)
|
||||
8. [Security](/docs/user-guide/security)
|
||||
1. [Installation](/getting-started/installation)
|
||||
2. [Configuration](/user-guide/configuration)
|
||||
3. [Messaging Overview](/user-guide/messaging)
|
||||
4. [Telegram Setup](/user-guide/messaging/telegram)
|
||||
5. [Discord Setup](/user-guide/messaging/discord)
|
||||
6. [Voice Mode](/user-guide/features/voice-mode)
|
||||
7. [Use Voice Mode with Hermes](/guides/use-voice-mode-with-hermes)
|
||||
8. [Security](/user-guide/security)
|
||||
|
||||
For full project examples, see:
|
||||
- [Daily Briefing Bot](/docs/guides/daily-briefing-bot)
|
||||
- [Team Telegram Assistant](/docs/guides/team-telegram-assistant)
|
||||
- [Daily Briefing Bot](/guides/daily-briefing-bot)
|
||||
- [Team Telegram Assistant](/guides/team-telegram-assistant)
|
||||
|
||||
### "I want to automate tasks"
|
||||
|
||||
Schedule recurring tasks, run batch jobs, or chain agent actions together.
|
||||
|
||||
1. [Quickstart](/docs/getting-started/quickstart)
|
||||
2. [Cron Scheduling](/docs/user-guide/features/cron)
|
||||
3. [Batch Processing](/docs/user-guide/features/batch-processing)
|
||||
4. [Delegation](/docs/user-guide/features/delegation)
|
||||
5. [Hooks](/docs/user-guide/features/hooks)
|
||||
1. [Quickstart](/getting-started/quickstart)
|
||||
2. [Cron Scheduling](/user-guide/features/cron)
|
||||
3. [Batch Processing](/user-guide/features/batch-processing)
|
||||
4. [Delegation](/user-guide/features/delegation)
|
||||
5. [Hooks](/user-guide/features/hooks)
|
||||
|
||||
:::tip
|
||||
Cron jobs let Hermes Agent run tasks on a schedule — daily summaries, periodic checks, automated reports — without you being present.
|
||||
|
|
@ -80,29 +84,29 @@ Cron jobs let Hermes Agent run tasks on a schedule — daily summaries, periodic
|
|||
|
||||
Extend Hermes Agent with your own tools and reusable skill packages.
|
||||
|
||||
1. [Plugins](/docs/user-guide/features/plugins)
|
||||
2. [Build a Hermes Plugin](/docs/guides/build-a-hermes-plugin)
|
||||
3. [Tools Overview](/docs/user-guide/features/tools)
|
||||
4. [Skills Overview](/docs/user-guide/features/skills)
|
||||
5. [MCP (Model Context Protocol)](/docs/user-guide/features/mcp)
|
||||
6. [Architecture](/docs/developer-guide/architecture)
|
||||
7. [Adding Tools](/docs/developer-guide/adding-tools)
|
||||
8. [Creating Skills](/docs/developer-guide/creating-skills)
|
||||
1. [Plugins](/user-guide/features/plugins)
|
||||
2. [Build a Hermes Plugin](/guides/build-a-hermes-plugin)
|
||||
3. [Tools Overview](/user-guide/features/tools)
|
||||
4. [Skills Overview](/user-guide/features/skills)
|
||||
5. [MCP (Model Context Protocol)](/user-guide/features/mcp)
|
||||
6. [Architecture](/developer-guide/architecture)
|
||||
7. [Adding Tools](/developer-guide/adding-tools)
|
||||
8. [Creating Skills](/developer-guide/creating-skills)
|
||||
|
||||
:::tip
|
||||
For most custom tool creation, start with plugins. The [Adding Tools](/docs/developer-guide/adding-tools)
|
||||
For most custom tool creation, start with plugins. The [Adding Tools](/developer-guide/adding-tools)
|
||||
page is for built-in Hermes core development, not the usual user/custom-tool path.
|
||||
:::
|
||||
|
||||
### "I want to train models"
|
||||
|
||||
Use reinforcement learning to fine-tune model behavior with Hermes Agent's built-in RL training pipeline.
|
||||
Use reinforcement learning to fine-tune model behavior with Hermes Agent's RL training pipeline (powered by [Atropos](https://github.com/NousResearch/atropos)).
|
||||
|
||||
1. [Quickstart](/docs/getting-started/quickstart)
|
||||
2. [Configuration](/docs/user-guide/configuration)
|
||||
3. [RL Training](/docs/user-guide/features/rl-training)
|
||||
4. [Provider Routing](/docs/user-guide/features/provider-routing)
|
||||
5. [Architecture](/docs/developer-guide/architecture)
|
||||
1. [Quickstart](/getting-started/quickstart)
|
||||
2. [Configuration](/user-guide/configuration)
|
||||
3. [Atropos RL Environments](https://github.com/NousResearch/atropos) (external)
|
||||
4. [Provider Routing](/user-guide/features/provider-routing)
|
||||
5. [Architecture](/developer-guide/architecture)
|
||||
|
||||
:::tip
|
||||
RL training works best when you already understand the basics of how Hermes Agent handles conversations and tool calls. Run through the Beginner path first if you're new.
|
||||
|
|
@ -112,12 +116,12 @@ RL training works best when you already understand the basics of how Hermes Agen
|
|||
|
||||
Integrate Hermes Agent into your own Python applications programmatically.
|
||||
|
||||
1. [Installation](/docs/getting-started/installation)
|
||||
2. [Quickstart](/docs/getting-started/quickstart)
|
||||
3. [Python Library Guide](/docs/guides/python-library)
|
||||
4. [Architecture](/docs/developer-guide/architecture)
|
||||
5. [Tools](/docs/user-guide/features/tools)
|
||||
6. [Sessions](/docs/user-guide/sessions)
|
||||
1. [Installation](/getting-started/installation)
|
||||
2. [Quickstart](/getting-started/quickstart)
|
||||
3. [Python Library Guide](/guides/python-library)
|
||||
4. [Architecture](/developer-guide/architecture)
|
||||
5. [Tools](/user-guide/features/tools)
|
||||
6. [Sessions](/user-guide/sessions)
|
||||
|
||||
## Key Features at a Glance
|
||||
|
||||
|
|
@ -125,30 +129,29 @@ Not sure what's available? Here's a quick directory of major features:
|
|||
|
||||
| Feature | What It Does | Link |
|
||||
|---|---|---|
|
||||
| **Tools** | Built-in tools the agent can call (file I/O, search, shell, etc.) | [Tools](/docs/user-guide/features/tools) |
|
||||
| **Skills** | Installable plugin packages that add new capabilities | [Skills](/docs/user-guide/features/skills) |
|
||||
| **Memory** | Persistent memory across sessions | [Memory](/docs/user-guide/features/memory) |
|
||||
| **Context Files** | Feed files and directories into conversations | [Context Files](/docs/user-guide/features/context-files) |
|
||||
| **MCP** | Connect to external tool servers via Model Context Protocol | [MCP](/docs/user-guide/features/mcp) |
|
||||
| **Cron** | Schedule recurring agent tasks | [Cron](/docs/user-guide/features/cron) |
|
||||
| **Delegation** | Spawn sub-agents for parallel work | [Delegation](/docs/user-guide/features/delegation) |
|
||||
| **Code Execution** | Run Python scripts that call Hermes tools programmatically | [Code Execution](/docs/user-guide/features/code-execution) |
|
||||
| **Browser** | Web browsing and scraping | [Browser](/docs/user-guide/features/browser) |
|
||||
| **Hooks** | Event-driven callbacks and middleware | [Hooks](/docs/user-guide/features/hooks) |
|
||||
| **Batch Processing** | Process multiple inputs in bulk | [Batch Processing](/docs/user-guide/features/batch-processing) |
|
||||
| **RL Training** | Fine-tune models with reinforcement learning | [RL Training](/docs/user-guide/features/rl-training) |
|
||||
| **Provider Routing** | Route requests across multiple LLM providers | [Provider Routing](/docs/user-guide/features/provider-routing) |
|
||||
| **Tools** | Built-in tools the agent can call (file I/O, search, shell, etc.) | [Tools](/user-guide/features/tools) |
|
||||
| **Skills** | Installable plugin packages that add new capabilities | [Skills](/user-guide/features/skills) |
|
||||
| **Memory** | Persistent memory across sessions | [Memory](/user-guide/features/memory) |
|
||||
| **Context Files** | Feed files and directories into conversations | [Context Files](/user-guide/features/context-files) |
|
||||
| **MCP** | Connect to external tool servers via Model Context Protocol | [MCP](/user-guide/features/mcp) |
|
||||
| **Cron** | Schedule recurring agent tasks | [Cron](/user-guide/features/cron) |
|
||||
| **Delegation** | Spawn sub-agents for parallel work | [Delegation](/user-guide/features/delegation) |
|
||||
| **Code Execution** | Run Python scripts that call Hermes tools programmatically | [Code Execution](/user-guide/features/code-execution) |
|
||||
| **Browser** | Web browsing and scraping | [Browser](/user-guide/features/browser) |
|
||||
| **Hooks** | Event-driven callbacks and middleware | [Hooks](/user-guide/features/hooks) |
|
||||
| **Batch Processing** | Process multiple inputs in bulk | [Batch Processing](/user-guide/features/batch-processing) |
|
||||
| **Provider Routing** | Route requests across multiple LLM providers | [Provider Routing](/user-guide/features/provider-routing) |
|
||||
|
||||
## What to Read Next
|
||||
|
||||
Based on where you are right now:
|
||||
|
||||
- **Just finished installing?** → Head to the [Quickstart](/docs/getting-started/quickstart) to run your first conversation.
|
||||
- **Completed the Quickstart?** → Read [CLI Usage](/docs/user-guide/cli) and [Configuration](/docs/user-guide/configuration) to customize your setup.
|
||||
- **Comfortable with the basics?** → Explore [Tools](/docs/user-guide/features/tools), [Skills](/docs/user-guide/features/skills), and [Memory](/docs/user-guide/features/memory) to unlock the full power of the agent.
|
||||
- **Setting up for a team?** → Read [Security](/docs/user-guide/security) and [Sessions](/docs/user-guide/sessions) to understand access control and conversation management.
|
||||
- **Ready to build?** → Jump into the [Developer Guide](/docs/developer-guide/architecture) to understand the internals and start contributing.
|
||||
- **Want practical examples?** → Check out the [Guides](/docs/guides/tips) section for real-world projects and tips.
|
||||
- **Just finished installing?** → Head to the [Quickstart](/getting-started/quickstart) to run your first conversation.
|
||||
- **Completed the Quickstart?** → Read [CLI Usage](/user-guide/cli) and [Configuration](/user-guide/configuration) to customize your setup.
|
||||
- **Comfortable with the basics?** → Explore [Tools](/user-guide/features/tools), [Skills](/user-guide/features/skills), and [Memory](/user-guide/features/memory) to unlock the full power of the agent.
|
||||
- **Setting up for a team?** → Read [Security](/user-guide/security) and [Sessions](/user-guide/sessions) to understand access control and conversation management.
|
||||
- **Ready to build?** → Jump into the [Developer Guide](/developer-guide/architecture) to understand the internals and start contributing.
|
||||
- **Want practical examples?** → Check out the [Guides](/guides/tips) section for real-world projects and tips.
|
||||
|
||||
:::tip
|
||||
You don't need to read everything. Pick the path that matches your goal, follow the links in order, and you'll be productive quickly. You can always come back to this page to find your next step.
|
||||
|
|
|
|||
|
|
@ -46,6 +46,22 @@ hermes chat
|
|||
|
||||
After `nix profile install`, `hermes`, `hermes-agent`, and `hermes-acp` are on your PATH. From here, the workflow is identical to the [standard installation](./installation.md) — `hermes setup` walks you through provider selection, `hermes gateway install` sets up a launchd (macOS) or systemd user service, and config lives in `~/.hermes/`.
|
||||
|
||||
:::warning Messaging platforms (Discord, Telegram, Slack)
|
||||
The default package doesn't include messaging platform libraries — they were moved to on-demand installation, which can't work in Nix's read-only environment. If you plan to connect the agent to Discord, Telegram, or Slack, install the `messaging` variant:
|
||||
|
||||
```bash
|
||||
nix profile install github:NousResearch/hermes-agent#messaging
|
||||
```
|
||||
|
||||
For all optional extras (voice, all providers, all platforms):
|
||||
|
||||
```bash
|
||||
nix profile install github:NousResearch/hermes-agent#full
|
||||
```
|
||||
|
||||
The `full` variant adds ~700 MB to the closure. If you only need messaging platforms, `#messaging` adds just ~33 MB.
|
||||
:::
|
||||
|
||||
<details>
|
||||
<summary><strong>Building from a local clone</strong></summary>
|
||||
|
||||
|
|
@ -319,6 +335,7 @@ Quick reference for the most common things Nix users want to customize:
|
|||
| Add API keys | `environmentFiles` | `[ config.sops.secrets."hermes-env".path ]` |
|
||||
| Give the agent a personality | `${services.hermes-agent.stateDir}/.hermes/SOUL.md` | manage the file directly |
|
||||
| Add MCP tool servers | `mcpServers.<name>` | See [MCP Servers](#mcp-servers) |
|
||||
| Enable Discord/Telegram/Slack | `extraDependencyGroups` | `[ "messaging" ]` |
|
||||
| Mount host directories into container | `container.extraVolumes` | `[ "/data:/data:rw" ]` |
|
||||
| Pass GPU access to container | `container.extraOptions` | `[ "--gpus" "all" ]` |
|
||||
| Use Podman instead of Docker | `container.backend` | `"podman"` |
|
||||
|
|
@ -566,7 +583,7 @@ Host Container
|
|||
│ ├── state.db, sessions/, memories/ (runtime state)
|
||||
│ └── mcp-tokens/ (OAuth tokens for MCP servers)
|
||||
├── home/ ──► /home/hermes (rw)
|
||||
└── workspace/ (MESSAGING_CWD)
|
||||
└── workspace/ (agent working directory)
|
||||
├── SOUL.md (from documents option)
|
||||
└── (agent-created files)
|
||||
|
||||
|
|
@ -647,16 +664,44 @@ The package's `site-packages` is added to PYTHONPATH in the hermes wrapper. `imp
|
|||
|
||||
### Optional Dependency Groups (`extraDependencyGroups`)
|
||||
|
||||
For optional extras already declared in hermes-agent's `pyproject.toml` (e.g., memory providers like `hindsight` or `honcho`), use `extraDependencyGroups` to include them in the sealed venv at build time:
|
||||
For optional extras declared in hermes-agent's `pyproject.toml`, use `extraDependencyGroups` to include them in the sealed venv at build time. This is required for any extra not in the default `[all]` set — on Nix, runtime installation into the read-only store is not possible.
|
||||
|
||||
```nix
|
||||
# Enable Discord, Telegram, Slack
|
||||
services.hermes-agent.extraDependencyGroups = [ "messaging" ];
|
||||
```
|
||||
|
||||
```nix
|
||||
# Enable a memory provider
|
||||
services.hermes-agent = {
|
||||
extraDependencyGroups = [ "hindsight" ];
|
||||
settings.memory.provider = "hindsight";
|
||||
};
|
||||
```
|
||||
|
||||
This is resolved by uv alongside core dependencies in a single pass — no PYTHONPATH patching, no collision risk. Available groups match the `[project.optional-dependencies]` keys in `pyproject.toml` (e.g., `"hindsight"`, `"honcho"`, `"voice"`, `"matrix"`, `"mistral"`, `"bedrock"`).
|
||||
This is resolved by uv alongside core dependencies — no PYTHONPATH patching, no collision risk. Available groups:
|
||||
|
||||
| Group | What it enables |
|
||||
|-------|-----------------|
|
||||
| `messaging` | Discord, Telegram, Slack |
|
||||
| `matrix` | Matrix/Element (mautrix with encryption; Linux only) |
|
||||
| `dingtalk` | DingTalk |
|
||||
| `feishu` | Feishu/Lark |
|
||||
| `voice` | Local speech-to-text (faster-whisper) |
|
||||
| `edge-tts` | Edge TTS provider |
|
||||
| `tts-premium` | ElevenLabs TTS |
|
||||
| `anthropic` | Native Anthropic SDK (not needed via OpenRouter) |
|
||||
| `bedrock` | AWS Bedrock (boto3) |
|
||||
| `azure-identity` | Azure Entra ID auth |
|
||||
| `honcho` | Honcho memory provider |
|
||||
| `hindsight` | Hindsight memory provider |
|
||||
| `modal` | Modal terminal backend |
|
||||
| `daytona` | Daytona terminal backend |
|
||||
| `exa` | Exa web search |
|
||||
| `firecrawl` | Firecrawl web search |
|
||||
| `fal` | FAL image generation |
|
||||
|
||||
Or use the pre-built `#messaging` or `#full` flake packages instead of per-extra configuration (see [Quick Start](#quick-start-any-nix-user)).
|
||||
|
||||
**When to use which:**
|
||||
|
||||
|
|
@ -786,7 +831,7 @@ nix build .#checks.x86_64-linux.config-roundtrip # merge script preserves use
|
|||
| `group` | `str` | `"hermes"` | System group |
|
||||
| `createUser` | `bool` | `true` | Auto-create user/group |
|
||||
| `stateDir` | `str` | `"/var/lib/hermes"` | State directory (`HERMES_HOME` parent) |
|
||||
| `workingDirectory` | `str` | `"${stateDir}/workspace"` | Agent working directory (`MESSAGING_CWD`) |
|
||||
| `workingDirectory` | `str` | `"${stateDir}/workspace"` | Agent working directory |
|
||||
| `addToSystemPackages` | `bool` | `false` | Add `hermes` CLI to system PATH and set `HERMES_HOME` system-wide |
|
||||
|
||||
### Configuration
|
||||
|
|
@ -873,7 +918,7 @@ nix build .#checks.x86_64-linux.config-roundtrip # merge script preserves use
|
|||
│ ├── cron/
|
||||
│ └── logs/
|
||||
├── home/ # Agent HOME
|
||||
└── workspace/ # MESSAGING_CWD
|
||||
└── workspace/ # Agent working directory
|
||||
├── SOUL.md # From documents option
|
||||
└── (agent-created files)
|
||||
```
|
||||
|
|
@ -966,6 +1011,7 @@ nix-store --query --roots $(docker exec hermes-agent readlink /data/current-pack
|
|||
| Symptom | Cause | Fix |
|
||||
|---|---|---|
|
||||
| `Cannot save configuration: managed by NixOS` | CLI guards active | Edit `configuration.nix` and `nixos-rebuild switch` |
|
||||
| `No adapter available for discord` (or telegram/slack) | Messaging deps missing from the sealed Nix venv | Install `#messaging` variant: `nix profile install ...#messaging`. For NixOS module: `extraDependencyGroups = [ "messaging" ]`. Check `journalctl -u hermes-agent` for `FeatureUnavailable` or `requirements not met` for the underlying error. |
|
||||
| Container recreated unexpectedly | `extraVolumes`, `extraOptions`, or `image` changed | Expected — writable layer resets. Reinstall packages or use a custom image |
|
||||
| `hermes version` shows old version | Container not restarted | `systemctl restart hermes-agent` |
|
||||
| Permission denied on `/var/lib/hermes` | State dir is `0750 hermes:hermes` | Use `docker exec` or `sudo -u hermes` |
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ This guide gets you from zero to a working Hermes setup that survives real use.
|
|||
|
||||
## Prefer to watch?
|
||||
|
||||
**Onchain AI Garage** put together a Masterclass walkthrough of installation, setup, and basic commands — a good companion to this page if you'd rather follow along on video. For more, see the full [Hermes Agent Tutorials & Use Cases](https://www.youtube.com/channel/UCqB1bhMwGsW-yefBxYwFCCg) playlist.
|
||||
**Onchain AI Garage** put together a Masterclass walkthrough of installation, setup, and basic commands — a good companion to this page if you'd rather follow along on video. For more, see the full [Hermes Agent Tutorials & Use Cases](https://www.youtube.com/playlist?list=PLmpUb_PWAkDxewld5ZYyKifuHxgIbiq2d) playlist.
|
||||
|
||||
<div style={{position: 'relative', paddingBottom: '56.25%', height: 0, overflow: 'hidden', maxWidth: '100%', marginBottom: '1.5rem'}}>
|
||||
<iframe
|
||||
|
|
@ -47,31 +47,28 @@ Pick the row that matches your goal:
|
|||
---
|
||||
|
||||
## 1. Install Hermes Agent
|
||||
### With the Hermes Desktop installer on macOS or Windows (recommended)
|
||||
To easily install the command-line and desktop applications, [download the Hermes Desktop installer](https://hermes-agent.nousresearch.com/desktop) from our website and run it.
|
||||
|
||||
**Option A — pip (simplest):**
|
||||
### Without Hermes Desktop:
|
||||
For a command-line only install without Hermes Desktop, run:
|
||||
|
||||
#### Linux / macOS / WSL2 / Android (Termux)
|
||||
```bash
|
||||
pip install hermes-agent
|
||||
hermes postinstall # optional: installs Node.js, browser, ripgrep, ffmpeg + runs setup
|
||||
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash
|
||||
```
|
||||
|
||||
PyPI releases track tagged versions (major/minor releases), not every commit on `main`. For bleeding-edge, use Option B.
|
||||
#### Windows (native)
|
||||
|
||||
**Option B — git installer (tracks main branch):**
|
||||
|
||||
```bash
|
||||
# Linux / macOS / WSL2 / Android (Termux)
|
||||
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
|
||||
Run in powershell:
|
||||
```powershell
|
||||
iex (irm https://hermes-agent.nousresearch.com/install.ps1)
|
||||
```
|
||||
|
||||
:::tip Android / Termux
|
||||
If you're installing on a phone, see the dedicated [Termux guide](./termux.md) for the tested manual path, supported extras, and current Android-specific limitations.
|
||||
:::
|
||||
|
||||
:::tip Windows Users
|
||||
Install [WSL2](https://learn.microsoft.com/en-us/windows/wsl/install) first, then run the command above inside your WSL2 terminal.
|
||||
:::
|
||||
|
||||
After it finishes, reload your shell:
|
||||
|
||||
```bash
|
||||
|
|
@ -88,6 +85,16 @@ The single most important setup step. Use `hermes model` to walk through the cho
|
|||
hermes model
|
||||
```
|
||||
|
||||
:::tip Easiest path: Nous Portal
|
||||
One subscription covers 300+ models plus the [Tool Gateway](../user-guide/features/tool-gateway.md) (web search, image generation, TTS, cloud browser). On a fresh install:
|
||||
|
||||
```bash
|
||||
hermes setup --portal
|
||||
```
|
||||
|
||||
That logs you in, sets Nous as your provider, and turns on the Tool Gateway in one command.
|
||||
:::
|
||||
|
||||
Good defaults:
|
||||
|
||||
| Provider | What it is | How to set up |
|
||||
|
|
@ -96,17 +103,29 @@ Good defaults:
|
|||
| **OpenAI Codex** | ChatGPT OAuth, uses Codex models | Device code auth via `hermes model` |
|
||||
| **Anthropic** | Claude models directly — Max plan + extra usage credits (OAuth), or API key for pay-per-token | `hermes model` → OAuth login (requires Max + extra credits), or an Anthropic API key |
|
||||
| **OpenRouter** | Multi-provider routing across many models | Enter your API key |
|
||||
| **Z.AI** | GLM / Zhipu-hosted models | Set `GLM_API_KEY` / `ZAI_API_KEY` |
|
||||
| **Z.AI** | GLM / Zhipu-hosted models | Set `GLM_API_KEY` / `ZAI_API_KEY` (also accepts `Z_AI_API_KEY`) |
|
||||
| **Kimi / Moonshot** | Moonshot-hosted coding and chat models | Set `KIMI_API_KEY` (or the Kimi-Coding-specific `KIMI_CODING_API_KEY`) |
|
||||
| **Kimi / Moonshot China** | China-region Moonshot endpoint | Set `KIMI_CN_API_KEY` |
|
||||
| **Arcee AI** | Trinity models | Set `ARCEEAI_API_KEY` |
|
||||
| **GMI Cloud** | Multi-model direct API | Set `GMI_API_KEY` |
|
||||
| **MiniMax (OAuth)** | MiniMax-M2.7 via browser OAuth — no API key needed | `hermes model` → MiniMax (OAuth) |
|
||||
| **MiniMax (OAuth)** | MiniMax frontier model via browser OAuth — no API key needed (model name in `hermes_cli/models.py` may change between releases) | `hermes model` → MiniMax (OAuth) |
|
||||
| **MiniMax** | International MiniMax endpoint | Set `MINIMAX_API_KEY` |
|
||||
| **MiniMax China** | China-region MiniMax endpoint | Set `MINIMAX_CN_API_KEY` |
|
||||
| **Alibaba Cloud** | Qwen models via DashScope | Set `DASHSCOPE_API_KEY` |
|
||||
| **Alibaba Cloud** | Qwen models via DashScope | Set `DASHSCOPE_API_KEY` (Qwen Coding Plan also accepts `ALIBABA_CODING_PLAN_API_KEY`) |
|
||||
| **Hugging Face** | 20+ open models via unified router (Qwen, DeepSeek, Kimi, etc.) | Set `HF_TOKEN` |
|
||||
| **AWS Bedrock** | Claude, Nova, Llama, DeepSeek via native Converse API | IAM role or `aws configure` ([guide](../guides/aws-bedrock.md)) |
|
||||
| **Azure Foundry** | Azure AI Foundry-hosted models | Set `AZURE_FOUNDRY_API_KEY` + `AZURE_FOUNDRY_BASE_URL` |
|
||||
| **Google AI Studio** | Gemini models via direct API | Set `GOOGLE_API_KEY` / `GEMINI_API_KEY` |
|
||||
| **Google Gemini (OAuth)** | Gemini via the `google-gemini-cli` OAuth flow — no key needed | `hermes model` → Google Gemini (OAuth) |
|
||||
| **xAI** | Grok models via direct API | Set `XAI_API_KEY` |
|
||||
| **xAI Grok OAuth** | SuperGrok / Premium+ subscription, no API key needed | `hermes model` → xAI Grok OAuth |
|
||||
| **NovitaAI** | Multi-model API gateway | Set `NOVITA_API_KEY` |
|
||||
| **StepFun** | Step Plan models | Set `STEPFUN_API_KEY` |
|
||||
| **Xiaomi MiMo** | Xiaomi-hosted models | Set `XIAOMI_API_KEY` |
|
||||
| **Tencent TokenHub** | Tencent-hosted models | Set `TOKENHUB_API_KEY` |
|
||||
| **Ollama Cloud** | Managed Ollama-hosted models | Set `OLLAMA_API_KEY` |
|
||||
| **LM Studio** | Local desktop app exposing an OpenAI-compatible API | Set `LM_API_KEY` (and `LM_BASE_URL` if non-default) |
|
||||
| **Qwen OAuth** | Qwen Portal browser OAuth — no API key needed | `hermes model` → Qwen OAuth |
|
||||
| **Kilo Code** | KiloCode-hosted models | Set `KILOCODE_API_KEY` |
|
||||
| **OpenCode Zen** | Pay-as-you-go access to curated models | Set `OPENCODE_ZEN_API_KEY` |
|
||||
| **OpenCode Go** | $10/month subscription for open models | Set `OPENCODE_GO_API_KEY` |
|
||||
|
|
@ -114,7 +133,6 @@ Good defaults:
|
|||
| **NVIDIA NIM** | Nemotron models via build.nvidia.com or local NIM | Set `NVIDIA_API_KEY` (optional: `NVIDIA_BASE_URL`) |
|
||||
| **GitHub Copilot** | GitHub Copilot subscription (GPT-5.x, Claude, Gemini, etc.) | OAuth via `hermes model`, or `COPILOT_GITHUB_TOKEN` / `GH_TOKEN` |
|
||||
| **GitHub Copilot ACP** | Copilot ACP agent backend (spawns local `copilot` CLI) | `hermes model` (requires `copilot` CLI + `copilot login`) |
|
||||
| **Vercel AI Gateway** | Vercel AI Gateway routing | Set `AI_GATEWAY_API_KEY` |
|
||||
| **Custom Endpoint** | VLLM, SGLang, Ollama, or any OpenAI-compatible API | Set base URL + API key |
|
||||
|
||||
For most first-time users: choose a provider, accept the defaults unless you know why you're changing them. The full provider catalog with env vars and setup steps lives on the [Providers](../integrations/providers.md) page.
|
||||
|
|
@ -229,7 +247,7 @@ Only after the base chat works. Pick what you need:
|
|||
hermes gateway setup # Interactive platform configuration
|
||||
```
|
||||
|
||||
Connect [Telegram](/docs/user-guide/messaging/telegram), [Discord](/docs/user-guide/messaging/discord), [Slack](/docs/user-guide/messaging/slack), [WhatsApp](/docs/user-guide/messaging/whatsapp), [Signal](/docs/user-guide/messaging/signal), [Email](/docs/user-guide/messaging/email), or [Home Assistant](/docs/user-guide/messaging/homeassistant), or [Microsoft Teams](/docs/user-guide/messaging/teams).
|
||||
Connect [Telegram](/user-guide/messaging/telegram), [Discord](/user-guide/messaging/discord), [Slack](/user-guide/messaging/slack), [WhatsApp](/user-guide/messaging/whatsapp), [Signal](/user-guide/messaging/signal), [Email](/user-guide/messaging/email), or [Home Assistant](/user-guide/messaging/homeassistant), or [Microsoft Teams](/user-guide/messaging/teams).
|
||||
|
||||
### Automation and tools
|
||||
|
||||
|
|
@ -260,12 +278,30 @@ Then in the CLI: `/voice on`. Press `Ctrl+B` to record. See [Voice Mode](../user
|
|||
|
||||
### Skills
|
||||
|
||||
Skills are on-demand instruction documents that teach Hermes how to do a specific task — deploy to Kubernetes, open a GitHub PR, fine-tune a model, search for GIFs. Each is a `SKILL.md` file with a name, a description, and a step-by-step procedure. The agent reads the short descriptions for free and only loads a skill's full content when a task actually calls for it, so adding skills doesn't bloat every request.
|
||||
|
||||
Hermes ships with a catalog of bundled skills already installed in `~/.hermes/skills/`. You can add more from the Skills Hub, or write your own.
|
||||
|
||||
**Browse and install from the hub:**
|
||||
|
||||
```bash
|
||||
hermes skills search kubernetes
|
||||
hermes skills install openai/skills/k8s
|
||||
hermes skills browse # list everything available
|
||||
hermes skills search kubernetes # find skills by keyword
|
||||
hermes skills install openai/skills/k8s # install one (runs a security scan first)
|
||||
```
|
||||
|
||||
Or use `/skills` inside a chat session.
|
||||
The install argument is a `source/path` slug from the hub — `openai/skills/k8s` means the `k8s` skill from OpenAI's catalog. `hermes skills browse` shows the exact slugs to use.
|
||||
|
||||
**Use a skill** — every installed skill becomes a slash command automatically:
|
||||
|
||||
```bash
|
||||
/k8s deploy the staging manifest # run the skill with a request
|
||||
/k8s # load it and let Hermes ask what you need
|
||||
```
|
||||
|
||||
This works in the CLI and in any connected messaging platform. You don't have to install everything up front — the agent picks the right bundled skill on its own during normal conversation when a task matches one.
|
||||
|
||||
See [Skills System](../user-guide/features/skills.md) for writing your own, external skill directories, and the full hub source list.
|
||||
|
||||
### MCP servers
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ That does not stop Hermes from working well as a phone-native CLI agent — it j
|
|||
Hermes now ships a Termux-aware installer path:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
|
||||
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash
|
||||
```
|
||||
|
||||
On Termux, the installer automatically:
|
||||
|
|
@ -80,16 +80,10 @@ Why these packages?
|
|||
### 2. Clone Hermes
|
||||
|
||||
```bash
|
||||
git clone --recurse-submodules https://github.com/NousResearch/hermes-agent.git
|
||||
git clone https://github.com/NousResearch/hermes-agent.git
|
||||
cd hermes-agent
|
||||
```
|
||||
|
||||
If you already cloned without submodules:
|
||||
|
||||
```bash
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
|
||||
### 3. Create a virtual environment
|
||||
|
||||
```bash
|
||||
|
|
|
|||
|
|
@ -43,9 +43,39 @@ When you run `hermes update`, the following steps occur:
|
|||
|
||||
1. **Pairing-data snapshot** — a lightweight pre-update state snapshot is saved (covers `~/.hermes/pairing/`, Feishu comment rules, and other state files that get modified at runtime). Recoverable via the snapshot restore flow described under [Snapshots and rollback](../user-guide/checkpoints-and-rollback.md), or by extracting the most recent quick-snapshot zip Hermes wrote next to your `~/.hermes/` directory.
|
||||
2. **Git pull** — pulls the latest code from the `main` branch and updates submodules
|
||||
3. **Dependency install** — runs `uv pip install -e ".[all]"` to pick up new or changed dependencies
|
||||
4. **Config migration** — detects new config options added since your version and prompts you to set them
|
||||
5. **Gateway auto-restart** — running gateways are refreshed after the update completes so the new code takes effect immediately. Service-managed gateways (systemd on Linux, launchd on macOS) are restarted through the service manager. Manual gateways are relaunched automatically when Hermes can map the running PID back to a profile.
|
||||
3. **Post-pull syntax validation + auto-rollback** — after the pull, Hermes compiles the eight critical files every `hermes` invocation imports at startup. If any fails to parse (e.g. an orphan merge-conflict marker, an accidentally truncated file), Hermes runs `git reset --hard <pre-pull-sha>` to roll the install back so your shell stays bootable. Re-run `hermes update` once the upstream fix lands.
|
||||
4. **Dependency install** — runs `uv pip install -e ".[all]"` to pick up new or changed dependencies
|
||||
5. **Config migration** — detects new config options added since your version and prompts you to set them
|
||||
6. **Gateway auto-restart** — running gateways are refreshed after the update completes so the new code takes effect immediately. Service-managed gateways (systemd on Linux, launchd on macOS) are restarted through the service manager. Manual gateways are relaunched automatically when Hermes can map the running PID back to a profile.
|
||||
|
||||
### Updating against a non-default branch: `--branch`
|
||||
|
||||
By default `hermes update` tracks `origin/main`. Pass `--branch <name>` to update against a different branch — useful for QA channels, feature branches, or release-candidate testing:
|
||||
|
||||
```bash
|
||||
hermes update --branch release-candidate
|
||||
hermes update --check --branch experimental # preview behindness only
|
||||
```
|
||||
|
||||
If your local checkout is on a different branch, Hermes auto-stashes any uncommitted work, switches HEAD to the target branch, and then pulls. Branches that don't exist locally are auto-tracked from `origin/<name>` (`git checkout -B <name> origin/<name>`). Branches that don't exist anywhere fail cleanly — your stashed changes are restored before exit so you're never stranded in a weird state. The `main`-only fork-upstream sync logic is automatically skipped on non-`main` branches.
|
||||
|
||||
### Local changes on non-interactive updates
|
||||
|
||||
When you run `hermes update` in a terminal, Hermes stashes any uncommitted source-tree changes, pulls, then **asks** whether to restore them — exactly as it always has. Nothing changes for interactive updates.
|
||||
|
||||
When the update runs **without a terminal** — from the desktop/chat app's "Update" button or a gateway-triggered update — there's no prompt to answer. The `updates.non_interactive_local_changes` setting decides what happens to your stashed changes:
|
||||
|
||||
```yaml
|
||||
# ~/.hermes/config.yaml
|
||||
updates:
|
||||
non_interactive_local_changes: stash # default: keep + auto-restore
|
||||
# non_interactive_local_changes: discard # throw local source edits away
|
||||
```
|
||||
|
||||
- `stash` (default) — auto-stash, pull, then auto-restore your changes on top of the updated code. Nothing is lost; if a restore hits conflicts they're preserved in a git stash for manual recovery.
|
||||
- `discard` — auto-stash and drop the stash after the pull, so the update always lands on a clean tree. Use this only on machines where you never intend to keep local edits to the Hermes source. It stash-drops (not `git reset --hard` + `git clean -fd`), so ignored paths like `node_modules`, `venv`, and build outputs are never touched.
|
||||
|
||||
In the desktop app this is **Settings → Advanced → In-App Update Local Changes**.
|
||||
|
||||
### Preview-only: `hermes update --check`
|
||||
|
||||
|
|
@ -183,18 +213,16 @@ git log --oneline -10
|
|||
|
||||
# Roll back to a specific commit
|
||||
git checkout <commit-hash>
|
||||
git submodule update --init --recursive
|
||||
uv pip install -e ".[all]"
|
||||
|
||||
# Restart the gateway if running
|
||||
hermes gateway restart
|
||||
```
|
||||
|
||||
To roll back to a specific release tag:
|
||||
To roll back to a specific release tag (substitute your previous tag — e.g. a recent release like `v2026.5.16`, or any earlier tag from `git tag --sort=-version:refname`):
|
||||
|
||||
```bash
|
||||
git checkout v0.6.0
|
||||
git submodule update --init --recursive
|
||||
git checkout vX.Y.Z
|
||||
uv pip install -e ".[all]"
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -6,17 +6,17 @@ description: "Real-world automation patterns using Hermes cron — monitoring, r
|
|||
|
||||
# Automate Anything with Cron
|
||||
|
||||
The [daily briefing bot tutorial](/docs/guides/daily-briefing-bot) covers the basics. This guide goes further — five real-world automation patterns you can adapt for your own workflows.
|
||||
The [daily briefing bot tutorial](/guides/daily-briefing-bot) covers the basics. This guide goes further — five real-world automation patterns you can adapt for your own workflows.
|
||||
|
||||
For the full feature reference, see [Scheduled Tasks (Cron)](/docs/user-guide/features/cron).
|
||||
For the full feature reference, see [Scheduled Tasks (Cron)](/user-guide/features/cron).
|
||||
|
||||
:::info Key Concept
|
||||
Cron jobs run in fresh agent sessions with no memory of your current chat. Prompts must be **completely self-contained** — include everything the agent needs to know.
|
||||
:::
|
||||
|
||||
:::tip Don't need the LLM? You have two zero-token options.
|
||||
- **Recurring watchdog** where the script already produces the exact message (memory alerts, disk alerts, heartbeats): use [script-only cron jobs](/docs/guides/cron-script-only). Same scheduler, no LLM. You can ask Hermes to set one up for you in chat — the `cronjob` tool knows when to pick `no_agent=True` and writes the script for you.
|
||||
- **One-shot from a script that's already running** (CI step, post-commit hook, deploy script, externally-scheduled monitor): use [`hermes send`](/docs/guides/pipe-script-output) to pipe stdout or a file straight to Telegram / Discord / Slack / etc. without setting up a cron entry.
|
||||
- **Recurring watchdog** where the script already produces the exact message (memory alerts, disk alerts, heartbeats): use [script-only cron jobs](/guides/cron-script-only). Same scheduler, no LLM. You can ask Hermes to set one up for you in chat — the `cronjob` tool knows when to pick `no_agent=True` and writes the script for you.
|
||||
- **One-shot from a script that's already running** (CI step, post-commit hook, deploy script, externally-scheduled monitor): use [`hermes send`](/guides/pipe-script-output) to pipe stdout or a file straight to Telegram / Discord / Slack / etc. without setting up a cron entry.
|
||||
:::
|
||||
|
||||
---
|
||||
|
|
@ -263,4 +263,4 @@ The `--deliver` flag controls where results go:
|
|||
|
||||
---
|
||||
|
||||
*For the complete cron reference — all parameters, edge cases, and internals — see [Scheduled Tasks (Cron)](/docs/user-guide/features/cron).*
|
||||
*For the complete cron reference — all parameters, edge cases, and internals — see [Scheduled Tasks (Cron)](/user-guide/features/cron).*
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ description: "Ready-to-use automation recipes — scheduled tasks, GitHub event
|
|||
|
||||
# Automation Templates
|
||||
|
||||
Copy-paste recipes for common automation patterns. Each template uses Hermes's built-in [cron scheduler](/docs/user-guide/features/cron) for time-based triggers and [webhook platform](/docs/user-guide/messaging/webhooks) for event-driven triggers.
|
||||
Copy-paste recipes for common automation patterns. Each template uses Hermes's built-in [cron scheduler](/user-guide/features/cron) for time-based triggers and [webhook platform](/user-guide/messaging/webhooks) for event-driven triggers.
|
||||
|
||||
Every template works with **any model** — not locked to a single provider.
|
||||
|
||||
|
|
|
|||
|
|
@ -328,7 +328,7 @@ Verify the same `Azure AI User` (or `Foundry User`) role is assigned on the Foun
|
|||
|
||||
## Related
|
||||
|
||||
- [Environment variables](/docs/reference/environment-variables)
|
||||
- [Configuration](/docs/user-guide/configuration)
|
||||
- [AWS Bedrock](/docs/guides/aws-bedrock) — the other major cloud provider integration
|
||||
- [Environment variables](/reference/environment-variables)
|
||||
- [Configuration](/user-guide/configuration)
|
||||
- [AWS Bedrock](/guides/aws-bedrock) — the other major cloud provider integration
|
||||
- [Microsoft: Configure Entra ID for Foundry](https://learn.microsoft.com/azure/ai-foundry/foundry-models/how-to/configure-entra-id) — upstream documentation for the keyless path
|
||||
|
|
|
|||
|
|
@ -15,21 +15,21 @@ Hermes has several distinct pluggable interfaces — some use Python `register_*
|
|||
| If you want to add… | Read |
|
||||
|---|---|
|
||||
| Custom tools, hooks, slash commands, skills, or CLI subcommands | **This guide** (the general plugin surface) |
|
||||
| An **LLM / inference backend** (new provider) | [Model Provider Plugins](/docs/developer-guide/model-provider-plugin) |
|
||||
| A **gateway channel** (Discord/Telegram/IRC/Teams/etc.) | [Adding Platform Adapters](/docs/developer-guide/adding-platform-adapters) |
|
||||
| A **memory backend** (Honcho/Mem0/Supermemory/etc.) | [Memory Provider Plugins](/docs/developer-guide/memory-provider-plugin) |
|
||||
| A **context-compression engine** | [Context Engine Plugins](/docs/developer-guide/context-engine-plugin) |
|
||||
| An **image-generation backend** | [Image Generation Provider Plugins](/docs/developer-guide/image-gen-provider-plugin) |
|
||||
| A **video-generation backend** | [Video Generation Provider Plugins](/docs/developer-guide/video-gen-provider-plugin) |
|
||||
| A **TTS backend** (any CLI — Piper, VoxCPM, Kokoro, voice cloning, …) | [TTS custom command providers](/docs/user-guide/features/tts#custom-command-providers) — config-driven, no Python needed |
|
||||
| An **STT backend** (custom whisper / ASR CLI) | [Voice Message Transcription](/docs/user-guide/features/tts#voice-message-transcription-stt) — set `HERMES_LOCAL_STT_COMMAND` to a shell template |
|
||||
| **External tools via MCP** (filesystem, GitHub, Linear, any MCP server) | [MCP](/docs/user-guide/features/mcp) — declare `mcp_servers.<name>` in `config.yaml` |
|
||||
| **Gateway event hooks** (fire on startup, session events, commands) | [Event Hooks](/docs/user-guide/features/hooks#gateway-event-hooks) — drop `HOOK.yaml` + `handler.py` into `~/.hermes/hooks/<name>/` |
|
||||
| **Shell hooks** (run a shell command on events) | [Shell Hooks](/docs/user-guide/features/hooks#shell-hooks) — declare under `hooks:` in `config.yaml` |
|
||||
| **Additional skill sources** (custom GitHub repos, private skill indexes) | [Skills](/docs/user-guide/features/skills) — `hermes skills tap add <repo>` · [Publishing a tap](/docs/user-guide/features/skills#publishing-a-custom-skill-tap) |
|
||||
| A first-class **core** inference provider (not a plugin) | [Adding Providers](/docs/developer-guide/adding-providers) |
|
||||
| An **LLM / inference backend** (new provider) | [Model Provider Plugins](/developer-guide/model-provider-plugin) |
|
||||
| A **gateway channel** (Discord/Telegram/IRC/Teams/etc.) | [Adding Platform Adapters](/developer-guide/adding-platform-adapters) |
|
||||
| A **memory backend** (Honcho/Mem0/Supermemory/etc.) | [Memory Provider Plugins](/developer-guide/memory-provider-plugin) |
|
||||
| A **context-compression engine** | [Context Engine Plugins](/developer-guide/context-engine-plugin) |
|
||||
| An **image-generation backend** | [Image Generation Provider Plugins](/developer-guide/image-gen-provider-plugin) |
|
||||
| A **video-generation backend** | [Video Generation Provider Plugins](/developer-guide/video-gen-provider-plugin) |
|
||||
| A **TTS backend** (any CLI — Piper, VoxCPM, Kokoro, voice cloning, …) | [TTS custom command providers](/user-guide/features/tts#custom-command-providers) — config-driven, no Python needed |
|
||||
| An **STT backend** (custom whisper / ASR CLI) | [Voice Message Transcription](/user-guide/features/tts#voice-message-transcription-stt) — set `HERMES_LOCAL_STT_COMMAND` to a shell template |
|
||||
| **External tools via MCP** (filesystem, GitHub, Linear, any MCP server) | [MCP](/user-guide/features/mcp) — declare `mcp_servers.<name>` in `config.yaml` |
|
||||
| **Gateway event hooks** (fire on startup, session events, commands) | [Event Hooks](/user-guide/features/hooks#gateway-event-hooks) — drop `HOOK.yaml` + `handler.py` into `~/.hermes/hooks/<name>/` |
|
||||
| **Shell hooks** (run a shell command on events) | [Shell Hooks](/user-guide/features/hooks#shell-hooks) — declare under `hooks:` in `config.yaml` |
|
||||
| **Additional skill sources** (custom GitHub repos, private skill indexes) | [Skills](/user-guide/features/skills) — `hermes skills tap add <repo>` · [Publishing a tap](/user-guide/features/skills#publishing-a-custom-skill-tap) |
|
||||
| A first-class **core** inference provider (not a plugin) | [Adding Providers](/developer-guide/adding-providers) |
|
||||
|
||||
See the full [Pluggable interfaces table](/docs/user-guide/features/plugins#pluggable-interfaces--where-to-go-for-each) for a consolidated view of every extension surface including config-driven (TTS, STT, MCP, shell hooks) and drop-in directory (gateway hooks) styles.
|
||||
See the full [Pluggable interfaces table](/user-guide/features/plugins#pluggable-interfaces--where-to-go-for-each) for a consolidated view of every extension surface including config-driven (TTS, STT, MCP, shell hooks) and drop-in directory (gateway hooks) styles.
|
||||
:::
|
||||
|
||||
## What you're building
|
||||
|
|
@ -272,13 +272,18 @@ def register(ctx):
|
|||
**`dispatch_tool` example — a slash command that runs a tool:**
|
||||
|
||||
```python
|
||||
def handle_scan(ctx, argstr):
|
||||
def handle_scan(ctx, raw_args: str):
|
||||
"""Implement /scan by invoking the terminal tool through the registry."""
|
||||
result = ctx.dispatch_tool("terminal", {"command": f"find . -name '{argstr}'"})
|
||||
result = ctx.dispatch_tool("terminal", {"command": f"find . -name '{raw_args}'"})
|
||||
return result # returned to the caller's chat UI
|
||||
|
||||
def register(ctx):
|
||||
ctx.register_command("scan", handle_scan, help="Find files matching a glob")
|
||||
# Handlers receive a single raw_args string; close over ctx via a lambda.
|
||||
ctx.register_command(
|
||||
"scan",
|
||||
lambda raw: handle_scan(ctx, raw),
|
||||
description="Find files matching a glob",
|
||||
)
|
||||
```
|
||||
|
||||
The dispatched tool goes through the normal approval, redaction, and budget pipelines — it's a real tool invocation, not a shortcut around them.
|
||||
|
|
@ -483,6 +488,53 @@ When `security.allow_lazy_installs: false` is set globally, `ensure()` raises `F
|
|||
|
||||
|
||||
|
||||
### Thread-safe lazy singletons
|
||||
|
||||
Plugins often cache an expensive object — an SDK client, an HTTP session, a connection pool — in a module-level variable built on first use:
|
||||
|
||||
```python
|
||||
_client = None
|
||||
|
||||
def get_client():
|
||||
global _client
|
||||
if _client is not None:
|
||||
return _client
|
||||
_client = ExpensiveClient(...) # ← TOCTOU race
|
||||
return _client
|
||||
```
|
||||
|
||||
This is a footgun. Hermes runs multiple threads in one process (delegated tool calls, background workers, the self-improvement fork), so two threads can hit `get_client()` before `_client` is set, **both** pass the `is not None` check, **both** run the expensive build, and the second write clobbers the first — leaking whatever resource the loser opened (connection, file handle, background thread).
|
||||
|
||||
Don't hand-roll the lock. Use the helpers in `plugins/plugin_utils.py`:
|
||||
|
||||
```python
|
||||
from plugins.plugin_utils import lazy_singleton, SingletonSlot
|
||||
|
||||
# Zero-arg accessor → decorate it:
|
||||
@lazy_singleton
|
||||
def get_client():
|
||||
return ExpensiveClient(load_config()) # runs exactly once
|
||||
|
||||
client = get_client() # safe across threads
|
||||
get_client.reset() # drop the instance (tests / teardown)
|
||||
|
||||
|
||||
# Accessor that takes a build argument → use a slot:
|
||||
_slot: SingletonSlot = SingletonSlot()
|
||||
|
||||
def get_client(config=None):
|
||||
return _slot.get(lambda: ExpensiveClient(resolve(config)))
|
||||
|
||||
def reset_client():
|
||||
_slot.reset()
|
||||
```
|
||||
|
||||
Both serialize concurrent first calls with double-checked locking and run the factory at most once. If the factory raises, nothing is cached and the next call retries. The honcho memory plugin (`plugins/memory/honcho/client.py`) is the reference consumer.
|
||||
|
||||
> Rule of thumb: any time you write `global _something` followed by a `is None` check and a build, reach for one of these instead.
|
||||
|
||||
|
||||
|
||||
### Conditional tool availability
|
||||
|
||||
For tools that depend on optional libraries:
|
||||
|
|
@ -533,18 +585,18 @@ def register(ctx):
|
|||
|
||||
### Hook reference
|
||||
|
||||
Each hook is documented in full on the **[Event Hooks reference](/docs/user-guide/features/hooks#plugin-hooks)** — callback signatures, parameter tables, exactly when each fires, and examples. Here's the summary:
|
||||
Each hook is documented in full on the **[Event Hooks reference](/user-guide/features/hooks#plugin-hooks)** — callback signatures, parameter tables, exactly when each fires, and examples. Here's the summary:
|
||||
|
||||
| Hook | Fires when | Callback signature | Returns |
|
||||
|------|-----------|-------------------|---------|
|
||||
| [`pre_tool_call`](/docs/user-guide/features/hooks#pre_tool_call) | Before any tool executes | `tool_name: str, args: dict, task_id: str` | ignored |
|
||||
| [`post_tool_call`](/docs/user-guide/features/hooks#post_tool_call) | After any tool returns | `tool_name: str, args: dict, result: str, task_id: str, duration_ms: int` | ignored |
|
||||
| [`pre_llm_call`](/docs/user-guide/features/hooks#pre_llm_call) | Once per turn, before the tool-calling loop | `session_id: str, user_message: str, conversation_history: list, is_first_turn: bool, model: str, platform: str` | [context injection](#pre_llm_call-context-injection) |
|
||||
| [`post_llm_call`](/docs/user-guide/features/hooks#post_llm_call) | Once per turn, after the tool-calling loop (successful turns only) | `session_id: str, user_message: str, assistant_response: str, conversation_history: list, model: str, platform: str` | ignored |
|
||||
| [`on_session_start`](/docs/user-guide/features/hooks#on_session_start) | New session created (first turn only) | `session_id: str, model: str, platform: str` | ignored |
|
||||
| [`on_session_end`](/docs/user-guide/features/hooks#on_session_end) | End of every `run_conversation` call + CLI exit | `session_id: str, completed: bool, interrupted: bool, model: str, platform: str` | ignored |
|
||||
| [`on_session_finalize`](/docs/user-guide/features/hooks#on_session_finalize) | CLI/gateway tears down an active session | `session_id: str \| None, platform: str` | ignored |
|
||||
| [`on_session_reset`](/docs/user-guide/features/hooks#on_session_reset) | Gateway swaps in a new session key (`/new`, `/reset`) | `session_id: str, platform: str` | ignored |
|
||||
| [`pre_tool_call`](/user-guide/features/hooks#pre_tool_call) | Before any tool executes | `tool_name: str, args: dict, task_id: str` | ignored |
|
||||
| [`post_tool_call`](/user-guide/features/hooks#post_tool_call) | After any tool returns | `tool_name: str, args: dict, result: str, task_id: str, duration_ms: int` | ignored |
|
||||
| [`pre_llm_call`](/user-guide/features/hooks#pre_llm_call) | Once per turn, before the tool-calling loop | `session_id: str, user_message: str, conversation_history: list, is_first_turn: bool, model: str, platform: str` | [context injection](#pre_llm_call-context-injection) |
|
||||
| [`post_llm_call`](/user-guide/features/hooks#post_llm_call) | Once per turn, after the tool-calling loop (successful turns only) | `session_id: str, user_message: str, assistant_response: str, conversation_history: list, model: str, platform: str` | ignored |
|
||||
| [`on_session_start`](/user-guide/features/hooks#on_session_start) | New session created (first turn only) | `session_id: str, model: str, platform: str` | ignored |
|
||||
| [`on_session_end`](/user-guide/features/hooks#on_session_end) | End of every `run_conversation` call + CLI exit | `session_id: str, completed: bool, interrupted: bool, model: str, platform: str` | ignored |
|
||||
| [`on_session_finalize`](/user-guide/features/hooks#on_session_finalize) | CLI/gateway tears down an active session | `session_id: str \| None, platform: str` | ignored |
|
||||
| [`on_session_reset`](/user-guide/features/hooks#on_session_reset) | Gateway swaps in a new session key (`/new`, `/reset`) | `session_id: str, platform: str` | ignored |
|
||||
|
||||
Most hooks are fire-and-forget observers — their return values are ignored. The exception is `pre_llm_call`, which can inject context into the conversation.
|
||||
|
||||
|
|
@ -681,7 +733,7 @@ def register(ctx):
|
|||
|
||||
After registration, users can run `hermes my-plugin status`, `hermes my-plugin config`, etc.
|
||||
|
||||
**Memory provider plugins** use a convention-based approach instead: add a `register_cli(subparser)` function to your plugin's `cli.py` file. The memory plugin discovery system finds it automatically — no `ctx.register_cli_command()` call needed. See the [Memory Provider Plugin guide](/docs/developer-guide/memory-provider-plugin#adding-cli-commands) for details.
|
||||
**Memory provider plugins** use a convention-based approach instead: add a `register_cli(subparser)` function to your plugin's `cli.py` file. The memory plugin discovery system finds it automatically — no `ctx.register_cli_command()` call needed. See the [Memory Provider Plugin guide](/developer-guide/memory-provider-plugin#adding-cli-commands) for details.
|
||||
|
||||
**Active-provider gating:** Memory plugin CLI commands only appear when their provider is the active `memory.provider` in config. If a user hasn't set up your provider, your CLI commands won't clutter the help output.
|
||||
|
||||
|
|
@ -706,7 +758,7 @@ def register(ctx):
|
|||
|
||||
After registration, users can type `/mystatus` in any session. The command appears in autocomplete, `/help` output, and the Telegram bot menu.
|
||||
|
||||
**Signature:** `ctx.register_command(name: str, handler: Callable, description: str = "")`
|
||||
**Signature:** `ctx.register_command(name: str, handler: Callable, description: str = "", args_hint: str = "")`
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
|
|
@ -770,7 +822,7 @@ def register(ctx):
|
|||
**Runtime behavior:**
|
||||
|
||||
- **CLI mode:** `parent_agent` is resolved from the active CLI agent so workspace hints, spinner, and model selection inherit as expected.
|
||||
- **Gateway mode:** There is no CLI agent, so tools degrade gracefully — workspace is read from `TERMINAL_CWD` and no spinner is shown.
|
||||
- **Gateway mode:** There is no CLI agent, so tools degrade gracefully — workspace is read from the configured terminal working directory and no spinner is shown.
|
||||
- **Explicit override:** If the caller passes `parent_agent=` explicitly, it is respected and not overwritten.
|
||||
|
||||
This is the public, stable interface for tool dispatch from plugin commands. Plugins should not reach into `ctx._cli_ref.agent` or similar private state.
|
||||
|
|
@ -814,7 +866,7 @@ description: Acme Inference — OpenAI-compatible direct API
|
|||
|
||||
Lazy-discovered the first time anything calls `get_provider_profile()` or `list_providers()` — `auth.py`, `config.py`, `doctor.py`, `models.py`, `runtime_provider.py`, and the chat_completions transport auto-wire to it. User plugins override bundled ones by name.
|
||||
|
||||
**Full guide:** [Model Provider Plugins](/docs/developer-guide/model-provider-plugin) — field reference, overridable hooks (`prepare_messages`, `build_extra_body`, `build_api_kwargs_extras`, `fetch_models`), api_mode selection, auth types, testing.
|
||||
**Full guide:** [Model Provider Plugins](/developer-guide/model-provider-plugin) — field reference, overridable hooks (`prepare_messages`, `build_extra_body`, `build_api_kwargs_extras`, `fetch_models`), api_mode selection, auth types, testing.
|
||||
|
||||
### Platform plugins — add a gateway channel
|
||||
|
||||
|
|
@ -874,7 +926,7 @@ optional_env:
|
|||
password: false
|
||||
```
|
||||
|
||||
**Full guide:** [Adding Platform Adapters](/docs/developer-guide/adding-platform-adapters) — complete `BasePlatformAdapter` contract, message routing, auth gating, setup wizard integration. Look at `plugins/platforms/irc/` for a stdlib-only working example.
|
||||
**Full guide:** [Adding Platform Adapters](/developer-guide/adding-platform-adapters) — complete `BasePlatformAdapter` contract, message routing, auth gating, setup wizard integration. Look at `plugins/platforms/irc/` for a stdlib-only working example.
|
||||
|
||||
### Memory provider plugins — add a cross-session knowledge backend
|
||||
|
||||
|
|
@ -896,19 +948,23 @@ class MyMemoryProvider(MemoryProvider):
|
|||
def initialize(self, session_id: str, **kwargs) -> None:
|
||||
self._session_id = session_id
|
||||
|
||||
def sync_turn(self, user_message, assistant_response, **kwargs) -> None:
|
||||
def sync_turn(self, user_content, assistant_content, *,
|
||||
session_id="", messages=None) -> None:
|
||||
...
|
||||
|
||||
def prefetch(self, query: str, **kwargs) -> str | None:
|
||||
def prefetch(self, query, *, session_id="") -> str:
|
||||
...
|
||||
|
||||
def get_tool_schemas(self) -> list[dict]:
|
||||
return [] # required @abstractmethod — see full guide
|
||||
|
||||
def register(ctx):
|
||||
ctx.register_memory_provider(MyMemoryProvider())
|
||||
```
|
||||
|
||||
Memory providers are single-select — only one is active at a time, chosen via `memory.provider` in `config.yaml`.
|
||||
|
||||
**Full guide:** [Memory Provider Plugins](/docs/developer-guide/memory-provider-plugin) — full `MemoryProvider` ABC, threading contract, profile isolation, CLI command registration via `cli.py`.
|
||||
**Full guide:** [Memory Provider Plugins](/developer-guide/memory-provider-plugin) — full `MemoryProvider` ABC, threading contract, profile isolation, CLI command registration via `cli.py`.
|
||||
|
||||
### Context engine plugins — replace the context compressor
|
||||
|
||||
|
|
@ -921,8 +977,9 @@ class MyContextEngine(ContextEngine):
|
|||
def name(self) -> str:
|
||||
return "my-engine"
|
||||
|
||||
def should_compress(self, messages, model) -> bool: ...
|
||||
def compress(self, messages, model) -> list[dict]: ...
|
||||
def update_from_response(self, usage) -> None: ...
|
||||
def should_compress(self, prompt_tokens: int = None) -> bool: ...
|
||||
def compress(self, messages, current_tokens=None, focus_topic=None) -> list: ...
|
||||
|
||||
def register(ctx):
|
||||
ctx.register_context_engine(MyContextEngine())
|
||||
|
|
@ -930,7 +987,7 @@ def register(ctx):
|
|||
|
||||
Context engines are single-select — chosen via `context.engine` in `config.yaml`.
|
||||
|
||||
**Full guide:** [Context Engine Plugins](/docs/developer-guide/context-engine-plugin).
|
||||
**Full guide:** [Context Engine Plugins](/developer-guide/context-engine-plugin).
|
||||
|
||||
### Image-generation backends
|
||||
|
||||
|
|
@ -946,7 +1003,9 @@ class MyImageGenProvider(ImageGenProvider):
|
|||
return "my-imggen"
|
||||
|
||||
def is_available(self) -> bool: ...
|
||||
def generate(self, prompt: str, **kwargs) -> str: ... # returns image path
|
||||
def generate(self, prompt: str, aspect_ratio="landscape", **kwargs) -> dict:
|
||||
# returns success_response(...) / error_response(...)
|
||||
...
|
||||
|
||||
def register(ctx):
|
||||
ctx.register_image_gen_provider(MyImageGenProvider())
|
||||
|
|
@ -960,13 +1019,13 @@ version: 1.0.0
|
|||
description: Custom image generation backend
|
||||
```
|
||||
|
||||
**Full guide:** [Image Generation Provider Plugins](/docs/developer-guide/image-gen-provider-plugin) — full `ImageGenProvider` ABC, `list_models()` / `get_setup_schema()` metadata, `success_response()`/`error_response()` helpers, base64 vs URL output, user overrides, pip distribution.
|
||||
**Full guide:** [Image Generation Provider Plugins](/developer-guide/image-gen-provider-plugin) — full `ImageGenProvider` ABC, `list_models()` / `get_setup_schema()` metadata, `success_response()`/`error_response()` helpers, base64 vs URL output, user overrides, pip distribution.
|
||||
|
||||
**Reference examples:** `plugins/image_gen/openai/` (DALL-E / GPT-Image via OpenAI SDK), `plugins/image_gen/openai-codex/`, `plugins/image_gen/xai/` (Grok image gen).
|
||||
|
||||
## Non-Python extension surfaces
|
||||
|
||||
Hermes also accepts extensions that aren't Python plugins at all. These are shown in the [Pluggable interfaces table](/docs/user-guide/features/plugins#pluggable-interfaces--where-to-go-for-each); the sections below sketch each authoring style briefly.
|
||||
Hermes also accepts extensions that aren't Python plugins at all. These are shown in the [Pluggable interfaces table](/user-guide/features/plugins#pluggable-interfaces--where-to-go-for-each); the sections below sketch each authoring style briefly.
|
||||
|
||||
### MCP servers — register external tools
|
||||
|
||||
|
|
@ -985,7 +1044,7 @@ mcp_servers:
|
|||
type: "oauth"
|
||||
```
|
||||
|
||||
Hermes connects to each server at startup, lists its tools, and registers them alongside built-ins. The LLM sees them exactly like any other tool. **Full guide:** [MCP](/docs/user-guide/features/mcp).
|
||||
Hermes connects to each server at startup, lists its tools, and registers them alongside built-ins. The LLM sees them exactly like any other tool. **Full guide:** [MCP](/user-guide/features/mcp).
|
||||
|
||||
### Gateway event hooks — fire on lifecycle events
|
||||
|
||||
|
|
@ -1009,7 +1068,7 @@ async def handle(event_type: str, context: dict) -> None:
|
|||
|
||||
Events include `gateway:startup`, `session:start`, `session:end`, `session:reset`, `agent:start`, `agent:step`, `agent:end`, and wildcard `command:*`. Errors in hooks are caught and logged — they never block the main pipeline.
|
||||
|
||||
**Full guide:** [Gateway Event Hooks](/docs/user-guide/features/hooks#gateway-event-hooks).
|
||||
**Full guide:** [Gateway Event Hooks](/user-guide/features/hooks#gateway-event-hooks).
|
||||
|
||||
### Shell hooks — run a shell command on tool calls
|
||||
|
||||
|
|
@ -1025,7 +1084,7 @@ hooks:
|
|||
|
||||
Supports all the same events as Python plugin hooks (`pre_tool_call`, `post_tool_call`, `pre_llm_call`, `post_llm_call`, `on_session_start`, `on_session_end`, `pre_gateway_dispatch`) plus structured JSON output for `pre_tool_call` blocking decisions.
|
||||
|
||||
**Full guide:** [Shell Hooks](/docs/user-guide/features/hooks#shell-hooks).
|
||||
**Full guide:** [Shell Hooks](/user-guide/features/hooks#shell-hooks).
|
||||
|
||||
### Skill sources — add a custom skill registry
|
||||
|
||||
|
|
@ -1039,7 +1098,7 @@ hermes skills install myorg/skills-repo/my-workflow
|
|||
|
||||
Publishing your own tap is just a GitHub repo with `skills/<skill-name>/SKILL.md` directories — no server or registry signup needed.
|
||||
|
||||
**Full guides:** [Skills Hub](/docs/user-guide/features/skills#skills-hub) · [Publishing a custom tap](/docs/user-guide/features/skills#publishing-a-custom-skill-tap) (repo layout, minimal example, non-default paths, trust levels).
|
||||
**Full guides:** [Skills Hub](/user-guide/features/skills#skills-hub) · [Publishing a custom tap](/user-guide/features/skills#publishing-a-custom-skill-tap) (repo layout, minimal example, non-default paths, trust levels).
|
||||
|
||||
### TTS / STT via command templates
|
||||
|
||||
|
|
@ -1058,7 +1117,7 @@ tts:
|
|||
|
||||
For STT, point `HERMES_LOCAL_STT_COMMAND` at a shell template. Supported placeholders: `{input_path}`, `{output_path}`, `{format}`, `{voice}`, `{model}`, `{speed}` (TTS); `{input_path}`, `{output_dir}`, `{language}`, `{model}` (STT). Any path-interacting CLI is automatically a plugin.
|
||||
|
||||
**Full guides:** [TTS custom command providers](/docs/user-guide/features/tts#custom-command-providers) · [STT](/docs/user-guide/features/tts#voice-message-transcription-stt).
|
||||
**Full guides:** [TTS custom command providers](/user-guide/features/tts#custom-command-providers) · [STT](/user-guide/features/tts#voice-message-transcription-stt).
|
||||
|
||||
## Distribute via pip
|
||||
|
||||
|
|
@ -1110,7 +1169,7 @@ services.hermes-agent.extraPlugins = [
|
|||
];
|
||||
```
|
||||
|
||||
See the [Nix Setup guide](/docs/getting-started/nix-setup#plugins) for complete documentation including overlay usage and collision checking.
|
||||
See the [Nix Setup guide](/getting-started/nix-setup#plugins) for complete documentation including overlay usage and collision checking.
|
||||
|
||||
## Common mistakes
|
||||
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ hermes cron create "0 9 * * *" # standard cron: 9am daily
|
|||
hermes cron create "30m" # one-shot: run once in 30 minutes
|
||||
```
|
||||
|
||||
See the [cron feature reference](/docs/user-guide/features/cron) for the full syntax.
|
||||
See the [cron feature reference](/user-guide/features/cron) for the full syntax.
|
||||
|
||||
## Delivery Targets
|
||||
|
||||
|
|
@ -235,13 +235,13 @@ Silent when both filesystems are under 90%; fires exactly one line per over-thre
|
|||
|----------|-----------|-------------|
|
||||
| `cronjob --no-agent` (this page) | Your script on Hermes' schedule | Recurring watchdogs / alerts / metrics that don't need reasoning |
|
||||
| `cronjob` (default, LLM) | Agent with optional pre-check script | When the message content requires reasoning over data |
|
||||
| OS cron + `curl` to a [webhook subscription](/docs/user-guide/messaging/webhooks) | Your script on the OS schedule | When Hermes might be unhealthy (the thing you're monitoring) |
|
||||
| OS cron + `curl` to a [webhook subscription](/user-guide/messaging/webhooks) | Your script on the OS schedule | When Hermes might be unhealthy (the thing you're monitoring) |
|
||||
|
||||
For critical system-health watchdogs that must fire *even when the gateway is down*, use OS-level cron with a plain `curl` to a Hermes webhook subscription (or any external alerting endpoint) — those run as independent OS processes and don't depend on Hermes being up. The in-gateway scheduler is the right choice when the thing being monitored is external.
|
||||
|
||||
## Related
|
||||
|
||||
- [Automate Anything with Cron](/docs/guides/automate-with-cron) — LLM-driven cron patterns.
|
||||
- [Scheduled Tasks (Cron) reference](/docs/user-guide/features/cron) — full schedule syntax, lifecycle, delivery routing.
|
||||
- [Webhook Subscriptions](/docs/user-guide/messaging/webhooks) — fire-and-forget HTTP entry points for external schedulers.
|
||||
- [Gateway Internals](/docs/developer-guide/gateway-internals) — delivery-router internals.
|
||||
- [Automate Anything with Cron](/guides/automate-with-cron) — LLM-driven cron patterns.
|
||||
- [Scheduled Tasks (Cron) reference](/user-guide/features/cron) — full schedule syntax, lifecycle, delivery routing.
|
||||
- [Webhook Subscriptions](/user-guide/messaging/webhooks) — fire-and-forget HTTP entry points for external schedulers.
|
||||
- [Gateway Internals](/developer-guide/gateway-internals) — delivery-router internals.
|
||||
|
|
|
|||
|
|
@ -222,4 +222,4 @@ If you've worked through this guide and the issue persists:
|
|||
|
||||
---
|
||||
|
||||
*For the complete cron reference, see [Automate Anything with Cron](/docs/guides/automate-with-cron) and [Scheduled Tasks (Cron)](/docs/user-guide/features/cron).*
|
||||
*For the complete cron reference, see [Automate Anything with Cron](/guides/automate-with-cron) and [Scheduled Tasks (Cron)](/user-guide/features/cron).*
|
||||
|
|
|
|||
|
|
@ -10,6 +10,10 @@ In this tutorial, you'll build a personal briefing bot that wakes up every morni
|
|||
|
||||
By the end, you'll have a fully automated workflow combining **web search**, **cron scheduling**, **delegation**, and **messaging delivery** — no code required.
|
||||
|
||||
:::tip
|
||||
This recipe hits web search, summarization, and optional TTS — all bundled in a Portal subscription. The fastest setup is `hermes setup --portal`. See [Nous Portal](/integrations/nous-portal).
|
||||
:::
|
||||
|
||||
## What We're Building
|
||||
|
||||
Here's the flow:
|
||||
|
|
@ -26,7 +30,7 @@ The whole thing runs hands-free. You just read your briefing with your morning c
|
|||
|
||||
Before starting, make sure you have:
|
||||
|
||||
- **Hermes Agent installed** — see the [Installation guide](/docs/getting-started/installation)
|
||||
- **Hermes Agent installed** — see the [Installation guide](/getting-started/installation)
|
||||
- **Gateway running** — the gateway daemon handles cron execution:
|
||||
```bash
|
||||
hermes gateway install # Install as a user service
|
||||
|
|
@ -35,7 +39,7 @@ Before starting, make sure you have:
|
|||
hermes gateway # Run in foreground
|
||||
```
|
||||
- **Firecrawl API key** — set `FIRECRAWL_API_KEY` in your environment for web search
|
||||
- **Messaging configured** (optional but recommended) — [Telegram](/docs/user-guide/messaging/telegram) or Discord set up with a home channel
|
||||
- **Messaging configured** (optional but recommended) — [Telegram](/user-guide/messaging/telegram) or Discord set up with a home channel
|
||||
|
||||
:::tip No messaging? No problem
|
||||
You can still follow this tutorial using `deliver: "local"`. Briefings will be saved to `~/.hermes/cron/output/` and you can read them anytime.
|
||||
|
|
@ -167,7 +171,7 @@ For faster briefings, tell Hermes to delegate each topic to a sub-agent:
|
|||
Collect all results and combine them into a single clean briefing with section headers, emoji formatting, and source links. Add today's date as a header."
|
||||
```
|
||||
|
||||
Each sub-agent searches independently and in parallel, then the main agent combines everything into one polished briefing. See the [Delegation docs](/docs/user-guide/features/delegation) for more on how this works.
|
||||
Each sub-agent searches independently and in parallel, then the main agent combines everything into one polished briefing. See the [Delegation docs](/user-guide/features/delegation) for more on how this works.
|
||||
|
||||
### Weekday-Only Schedule
|
||||
|
||||
|
|
@ -188,7 +192,7 @@ Get a morning overview and an evening recap:
|
|||
|
||||
### Adding Personal Context with Memory
|
||||
|
||||
If you have [memory](/docs/user-guide/features/memory) enabled, you can store preferences that persist across sessions. But remember — cron jobs run in fresh sessions without conversational memory. To add personal context, bake it directly into the prompt:
|
||||
If you have [memory](/user-guide/features/memory) enabled, you can store preferences that persist across sessions. But remember — cron jobs run in fresh sessions without conversational memory. To add personal context, bake it directly into the prompt:
|
||||
|
||||
```
|
||||
/cron add "0 8 * * *" "You are creating a briefing for a senior ML engineer who cares about: PyTorch ecosystem, transformer architectures, open-weight models, and AI regulation in the EU. Skip stories about product launches or funding rounds unless they involve open source.
|
||||
|
|
@ -257,11 +261,11 @@ sudo hermes gateway install --system
|
|||
|
||||
You've built a working daily briefing bot. Here are some directions to explore next:
|
||||
|
||||
- **[Scheduled Tasks (Cron)](/docs/user-guide/features/cron)** — Full reference for schedule formats, repeat limits, and delivery options
|
||||
- **[Delegation](/docs/user-guide/features/delegation)** — Deep dive into parallel sub-agent workflows
|
||||
- **[Messaging Platforms](/docs/user-guide/messaging)** — Set up Telegram, Discord, or other delivery targets
|
||||
- **[Memory](/docs/user-guide/features/memory)** — Persistent context across sessions
|
||||
- **[Tips & Best Practices](/docs/guides/tips)** — More prompt engineering advice
|
||||
- **[Scheduled Tasks (Cron)](/user-guide/features/cron)** — Full reference for schedule formats, repeat limits, and delivery options
|
||||
- **[Delegation](/user-guide/features/delegation)** — Deep dive into parallel sub-agent workflows
|
||||
- **[Messaging Platforms](/user-guide/messaging)** — Set up Telegram, Discord, or other delivery targets
|
||||
- **[Memory](/user-guide/features/memory)** — Persistent context across sessions
|
||||
- **[Tips & Best Practices](/guides/tips)** — More prompt engineering advice
|
||||
|
||||
:::tip What else can you schedule?
|
||||
The briefing bot pattern works for anything: competitor monitoring, GitHub repo summaries, weather forecasts, portfolio tracking, server health checks, or even a daily joke. If you can describe it in a prompt, you can schedule it.
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ description: "When and how to use subagent delegation — patterns for parallel
|
|||
|
||||
Hermes can spawn isolated child agents to work on tasks in parallel. Each subagent gets its own conversation, terminal session, and toolset. Only the final summary comes back — intermediate tool calls never enter your context window.
|
||||
|
||||
For the full feature reference, see [Subagent Delegation](/docs/user-guide/features/delegation).
|
||||
For the full feature reference, see [Subagent Delegation](/user-guide/features/delegation).
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -218,14 +218,14 @@ Restricting toolsets keeps the subagent focused and prevents accidental side eff
|
|||
## Constraints
|
||||
|
||||
- **Default 3 parallel tasks**: batches default to 3 concurrent subagents (configurable via `delegation.max_concurrent_children` in config.yaml, no hard ceiling, only a floor of 1)
|
||||
- **Nested delegation is opt-in**: leaf subagents (default) cannot call `delegate_task`, `clarify`, `memory`, `send_message`, or `execute_code`. Orchestrator subagents (`role="orchestrator"`) retain `delegate_task` for further delegation, but only when `delegation.max_spawn_depth` is raised above the default of 1 (1-3 supported); the other four remain blocked. Disable globally via `delegation.orchestrator_enabled: false`.
|
||||
- **Nested delegation is opt-in**: leaf subagents (default) cannot call `delegate_task`, `clarify`, `memory`, `send_message`, or `execute_code`. Orchestrator subagents (`role="orchestrator"`) retain `delegate_task` for further delegation, but only when `delegation.max_spawn_depth` is raised above the default of 1 (floor 1, no ceiling); the other four remain blocked. Disable globally via `delegation.orchestrator_enabled: false`.
|
||||
|
||||
### Tuning Concurrency and Depth
|
||||
|
||||
| Config | Default | Range | Effect |
|
||||
|--------|---------|-------|--------|
|
||||
| `max_concurrent_children` | 3 | >=1 | Parallel batch size per `delegate_task` call |
|
||||
| `max_spawn_depth` | 1 | 1-3 | How many delegation levels can spawn further |
|
||||
| `max_spawn_depth` | 1 | >=1 | How many delegation levels can spawn further |
|
||||
|
||||
Example: running 30 parallel workers with nested subagents:
|
||||
|
||||
|
|
@ -254,4 +254,4 @@ delegation:
|
|||
|
||||
---
|
||||
|
||||
*For the complete delegation reference — all parameters, ACP integration, and advanced configuration — see [Subagent Delegation](/docs/user-guide/features/delegation).*
|
||||
*For the complete delegation reference — all parameters, ACP integration, and advanced configuration — see [Subagent Delegation](/user-guide/features/delegation).*
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ If you have a public endpoint available, check out [Automated GitHub PR Comments
|
|||
|
||||
## Prerequisites
|
||||
|
||||
- **Hermes Agent installed** — see the [Installation guide](/docs/getting-started/installation)
|
||||
- **Hermes Agent installed** — see the [Installation guide](/getting-started/installation)
|
||||
- **Gateway running** for cron jobs:
|
||||
```bash
|
||||
hermes gateway install # Install as a service
|
||||
|
|
@ -50,7 +50,7 @@ If you have a public endpoint available, check out [Automated GitHub PR Comments
|
|||
# Authenticate
|
||||
gh auth login
|
||||
```
|
||||
- **Messaging configured** (optional) — [Telegram](/docs/user-guide/messaging/telegram) or [Discord](/docs/user-guide/messaging/discord)
|
||||
- **Messaging configured** (optional) — [Telegram](/user-guide/messaging/telegram) or [Discord](/user-guide/messaging/discord)
|
||||
|
||||
:::tip No messaging? No problem
|
||||
Use `deliver: "local"` to save reviews to `~/.hermes/cron/output/`. Great for testing before wiring up notifications.
|
||||
|
|
@ -297,7 +297,7 @@ GitHub allows 5,000 API requests/hour for authenticated users. Each PR review us
|
|||
## What's Next?
|
||||
|
||||
- **[Webhook-Based PR Reviews](./webhook-github-pr-review.md)** — get instant reviews when PRs are opened (requires a public endpoint)
|
||||
- **[Daily Briefing Bot](/docs/guides/daily-briefing-bot)** — combine PR reviews with your morning news digest
|
||||
- **[Build a Plugin](/docs/guides/build-a-hermes-plugin)** — wrap the review logic into a shareable plugin
|
||||
- **[Profiles](/docs/user-guide/profiles)** — run a dedicated reviewer profile with its own memory and config
|
||||
- **[Fallback Providers](/docs/user-guide/features/fallback-providers)** — ensure reviews run even when one provider is down
|
||||
- **[Daily Briefing Bot](/guides/daily-briefing-bot)** — combine PR reviews with your morning news digest
|
||||
- **[Build a Plugin](/guides/build-a-hermes-plugin)** — wrap the review logic into a shareable plugin
|
||||
- **[Profiles](/user-guide/profiles)** — run a dedicated reviewer profile with its own memory and config
|
||||
- **[Fallback Providers](/user-guide/features/fallback-providers)** — ensure reviews run even when one provider is down
|
||||
|
|
|
|||
|
|
@ -274,7 +274,7 @@ Upgrade Hermes and rerun `hermes model`. The native Gemini adapter sanitizes too
|
|||
|
||||
## Related
|
||||
|
||||
- [AI Providers](/docs/integrations/providers)
|
||||
- [Configuration](/docs/user-guide/configuration)
|
||||
- [Fallback Providers](/docs/user-guide/features/fallback-providers)
|
||||
- [AWS Bedrock](/docs/guides/aws-bedrock) — native cloud-provider integration using AWS credentials
|
||||
- [AI Providers](/integrations/providers)
|
||||
- [Configuration](/user-guide/configuration)
|
||||
- [Fallback Providers](/user-guide/features/fallback-providers)
|
||||
- [AWS Bedrock](/guides/aws-bedrock) — native cloud-provider integration using AWS credentials
|
||||
|
|
|
|||
|
|
@ -110,9 +110,9 @@ The `--cache-type-k q4_0 --cache-type-v q4_0` flags are the most important optim
|
|||
| q8_0 | ~8 GB |
|
||||
| **q4_0** | **~4 GB** |
|
||||
|
||||
On an 8 GB Mac, use `q4_0` KV cache and reduce context to `-c 32768` (32K). On 16 GB, you can comfortably do 128K context. On 32 GB+, you can run larger models or multiple parallel slots.
|
||||
On an 8 GB Mac, use `q4_0` KV cache and choose a smaller model that can still fit Hermes' 64K minimum context. On 16 GB, you can comfortably do 128K context. On 32 GB+, you can run larger models or multiple parallel slots.
|
||||
|
||||
If you're still running out of memory, reduce context size first (`-c`), then try a smaller quantization (Q3_K_M instead of Q4_K_M).
|
||||
If you're still running out of memory, reduce context only while staying at or above Hermes' 64K minimum; otherwise switch to a smaller model or smaller quantization (Q3_K_M instead of Q4_K_M).
|
||||
|
||||
### Test it
|
||||
|
||||
|
|
|
|||
|
|
@ -156,19 +156,19 @@ Switch models on the fly inside a session:
|
|||
|
||||
### Increase Ollama's Context Window
|
||||
|
||||
By default, Ollama uses a 2048-token context. For agentic work (tool calls, long conversations), you need more:
|
||||
By default, Ollama uses a 2048-token context. Hermes requires at least 64,000 tokens for agentic work with tools:
|
||||
|
||||
```bash
|
||||
# Create a Modelfile that extends context
|
||||
cat > /tmp/Modelfile << 'EOF'
|
||||
FROM gemma4:31b
|
||||
PARAMETER num_ctx 16384
|
||||
PARAMETER num_ctx 64000
|
||||
EOF
|
||||
|
||||
ollama create gemma4-16k -f /tmp/Modelfile
|
||||
ollama create gemma4-64k -f /tmp/Modelfile
|
||||
```
|
||||
|
||||
Then update your Hermes config to use `gemma4-16k` as the model name.
|
||||
Then update your Hermes config to use `gemma4-64k` as the model name.
|
||||
|
||||
### Keep the Model Loaded
|
||||
|
||||
|
|
@ -311,7 +311,7 @@ Your only cost is electricity — roughly $0.01–0.05 per session depending on
|
|||
## What's Better with Cloud Models
|
||||
|
||||
- **Very complex multi-step reasoning** — 70B+ or cloud models like Claude Opus are noticeably better
|
||||
- **Long context windows** — cloud models offer 100K–1M tokens; local models are typically 8K–32K
|
||||
- **Long context windows** — cloud models offer 100K–1M tokens; local runtimes often default below Hermes' 64K minimum unless you configure them
|
||||
- **Speed on large responses** — cloud inference is faster than CPU-only local for long generations
|
||||
|
||||
The sweet spot: use local for everyday tasks, set up a cloud fallback for the hard stuff.
|
||||
|
|
|
|||
|
|
@ -8,6 +8,10 @@ description: "Complete guide to migrating your OpenClaw / Clawdbot setup to Herm
|
|||
|
||||
`hermes claw migrate` imports your OpenClaw (or legacy Clawdbot/Moldbot) setup into Hermes. This guide covers exactly what gets migrated, the config key mappings, and what to verify after migration.
|
||||
|
||||
:::tip
|
||||
If your OpenClaw setup was multi-provider, `hermes setup --portal` collapses it to one OAuth — 300+ models plus the Tool Gateway in a single login. See [Nous Portal](/integrations/nous-portal).
|
||||
:::
|
||||
|
||||
## Quick start
|
||||
|
||||
```bash
|
||||
|
|
@ -156,7 +160,7 @@ TTS settings are read from **two** OpenClaw config locations with this priority:
|
|||
| Browser headless | `browser.headless` | `config.yaml` → `browser.headless` | |
|
||||
| Brave search key | `tools.web.search.brave.apiKey` | `.env` → `BRAVE_API_KEY` | Requires `--migrate-secrets` |
|
||||
| Gateway auth token | `gateway.auth.token` | `.env` → `HERMES_GATEWAY_TOKEN` | Requires `--migrate-secrets` |
|
||||
| Working directory | `agents.defaults.workspace` | `.env` → `MESSAGING_CWD` | |
|
||||
| Working directory | `agents.defaults.workspace` | `config.yaml` → `terminal.cwd` | Legacy migrations may still emit `MESSAGING_CWD` as a compatibility fallback |
|
||||
|
||||
### Archived (no direct Hermes equivalent)
|
||||
|
||||
|
|
@ -169,7 +173,7 @@ These are saved to `~/.hermes/migration/openclaw/<timestamp>/archive/` for manua
|
|||
| `HEARTBEAT.md` | `archive/workspace/HEARTBEAT.md` | Use cron jobs for periodic tasks |
|
||||
| `BOOTSTRAP.md` | `archive/workspace/BOOTSTRAP.md` | Use context files or skills |
|
||||
| Cron jobs | `archive/cron-config.json` | Recreate with `hermes cron create` |
|
||||
| Plugins | `archive/plugins-config.json` | See [plugins guide](/docs/user-guide/features/hooks) |
|
||||
| Plugins | `archive/plugins-config.json` | See [plugins guide](/user-guide/features/hooks) |
|
||||
| Hooks/webhooks | `archive/hooks-config.json` | Use `hermes webhook` or gateway hooks |
|
||||
| Memory backend | `archive/memory-backend-config.json` | Configure via `hermes honcho` |
|
||||
| Skills registry | `archive/skills-registry-config.json` | Use `hermes skills config` |
|
||||
|
|
@ -225,7 +229,7 @@ The migration resolves all three formats. For env templates and SecretRef object
|
|||
|
||||
5. **Test messaging** — if you migrated platform tokens, restart the gateway: `systemctl --user restart hermes-gateway`
|
||||
|
||||
6. **Check session policies** — verify `hermes config get session_reset` matches your expectations.
|
||||
6. **Check session policies** — run `hermes config show` and verify the `session_reset` value matches your expectations.
|
||||
|
||||
7. **Re-pair WhatsApp** — WhatsApp uses QR code pairing (Baileys), not token migration. Run `hermes whatsapp` to pair.
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ The transport reuses the `anthropic_messages` adapter (MiniMax exposes an Anthro
|
|||
|------|-------|
|
||||
| Provider ID | `minimax-oauth` |
|
||||
| Display name | MiniMax (OAuth) |
|
||||
| Auth type | Browser OAuth (PKCE device-code flow) |
|
||||
| Auth type | Browser OAuth (PKCE redirect flow) |
|
||||
| Transport | Anthropic Messages-compatible (`anthropic_messages`) |
|
||||
| Models | `MiniMax-M2.7`, `MiniMax-M2.7-highspeed` |
|
||||
| Global endpoint | `https://api.minimax.io/anthropic` |
|
||||
|
|
@ -56,11 +56,9 @@ hermes auth add minimax-oauth
|
|||
|
||||
### China region
|
||||
|
||||
If your account is on the China platform (`minimaxi.com`), use the China-region OAuth provider id `minimax-cn` instead, or skip OAuth and configure `MINIMAX_CN_API_KEY` / `MINIMAX_CN_BASE_URL` directly. The `--region cn` flag described in older docs is **not** wired through the CLI's argument parser; use the `minimax-cn` provider instead:
|
||||
If your account is on the China platform (`minimaxi.com`), use the API-key-based `minimax-cn` provider instead — `minimax-cn` is registered with `auth_type="api_key"` only (no OAuth flow). Configure `MINIMAX_CN_API_KEY` (and optionally `MINIMAX_CN_BASE_URL`) directly:
|
||||
|
||||
```bash
|
||||
hermes auth add minimax-cn --type oauth # if OAuth is supported on your CN account
|
||||
# or simpler:
|
||||
echo 'MINIMAX_CN_API_KEY=your-key' >> ~/.hermes/.env
|
||||
```
|
||||
|
||||
|
|
@ -76,7 +74,7 @@ Hermes will print the verification URL and user code — open the URL on any dev
|
|||
|
||||
## The OAuth Flow
|
||||
|
||||
Hermes implements a PKCE device-code flow against the MiniMax OAuth endpoints:
|
||||
Hermes implements a PKCE browser OAuth flow against the MiniMax OAuth endpoints:
|
||||
|
||||
1. Hermes generates a PKCE verifier / challenge pair and a random state value.
|
||||
2. It POSTs to `{base_url}/oauth/code` with the challenge and receives a `user_code` and `verification_uri`.
|
||||
|
|
@ -115,8 +113,8 @@ hermes model
|
|||
Or set the model directly:
|
||||
|
||||
```bash
|
||||
hermes config set model MiniMax-M2.7
|
||||
hermes config set provider minimax-oauth
|
||||
hermes config set model.default MiniMax-M2.7
|
||||
hermes config set model.provider minimax-oauth
|
||||
```
|
||||
|
||||
## Configuration Reference
|
||||
|
|
@ -157,10 +155,10 @@ The `minimax-oauth` provider does **not** use `MINIMAX_API_KEY` or `MINIMAX_BASE
|
|||
| `MINIMAX_API_KEY` | Used by `minimax` provider only — ignored for `minimax-oauth` |
|
||||
| `MINIMAX_CN_API_KEY` | Used by `minimax-cn` provider only — ignored for `minimax-oauth` |
|
||||
|
||||
To force the `minimax-oauth` provider at runtime:
|
||||
To use `minimax-oauth` as the active provider, set `model.provider: minimax-oauth` in `config.yaml` (use `hermes setup` for the guided flow), or pass `--provider minimax-oauth` for a single invocation:
|
||||
|
||||
```bash
|
||||
HERMES_INFERENCE_PROVIDER=minimax-oauth hermes
|
||||
hermes --provider minimax-oauth
|
||||
```
|
||||
|
||||
## Models
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
---
|
||||
sidebar_position: 17
|
||||
title: "OAuth over SSH / Remote Hosts"
|
||||
description: "How to complete browser-based OAuth (xAI, Spotify) when Hermes runs on a remote machine, container, or behind a jump box"
|
||||
description: "How to complete browser-based OAuth (xAI, Spotify, MCP servers) when Hermes runs on a remote machine, container, or behind a jump box"
|
||||
---
|
||||
|
||||
# OAuth over SSH / Remote Hosts
|
||||
|
||||
Some Hermes providers — currently **xAI Grok OAuth** and **Spotify** — use a *loopback redirect* OAuth flow. The auth server (xAI, Spotify) redirects your browser to `http://127.0.0.1:<port>/callback` so a tiny HTTP listener started by the `hermes auth ...` command can grab the authorization code.
|
||||
Some Hermes providers — **xAI Grok OAuth**, **Spotify**, and **remote MCP servers** (Linear, Sentry, Atlassian, Asana, Figma, …) — use a *loopback redirect* OAuth flow. The auth server redirects your browser to `http://127.0.0.1:<port>/callback` so a tiny HTTP listener started by Hermes can grab the authorization code.
|
||||
|
||||
This works perfectly when Hermes and your browser are on the same machine. It breaks the moment they aren't: your laptop's browser tries to reach `127.0.0.1` on **your laptop**, but the listener is bound to `127.0.0.1` on **the remote server**.
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ hermes auth add xai-oauth --manual-paste
|
|||
# → Paste it back into the terminal at the "Callback URL:" prompt.
|
||||
```
|
||||
|
||||
The same flag works on `hermes model --manual-paste` for the integrated model picker. A bare `?code=...&state=...` query fragment is accepted too if you don't want to paste the whole URL.
|
||||
The same flag works on `hermes model --manual-paste` for the integrated model picker. Hermes accepts three callback paste forms interchangeably: the full URL, a bare `?code=...&state=...` query fragment, or — when the upstream consent page renders the authorization code in-page instead of redirecting (xAI's current behavior on browser-based consoles) — just the bare code value on its own.
|
||||
|
||||
Hermes uses the **same PKCE verifier, state and nonce** for both paths, so the upstream OAuth flow is byte-identical — `--manual-paste` is purely a transport change for the callback hop and is not a security downgrade.
|
||||
|
||||
|
|
@ -50,12 +50,44 @@ Hermes uses the **same PKCE verifier, state and nonce** for both paths, so the u
|
|||
|----------|---------------|----------------|
|
||||
| `xai-oauth` (Grok SuperGrok) | `56121` | Yes, when Hermes is remote |
|
||||
| Spotify | `43827` | Yes, when Hermes is remote |
|
||||
| MCP servers (`auth: oauth`) | auto-picked per server | Yes, when Hermes is remote |
|
||||
| `anthropic` (Claude Pro/Max) | n/a | No — paste-the-code flow |
|
||||
| `openai-codex` (ChatGPT Plus/Pro) | n/a | No — device code flow |
|
||||
| `minimax`, `nous-portal` | n/a | No — device code flow |
|
||||
|
||||
If your provider isn't in the table, you don't need a tunnel.
|
||||
|
||||
## MCP Servers
|
||||
|
||||
Remote MCP servers (Linear, Sentry, Atlassian, Asana, Figma, etc.) use the same loopback redirect flow. Hermes auto-picks a free port per server and prints the authorize URL when the OAuth flow kicks off — either at startup (when a new server appears in `mcp_servers:`) or when you run `hermes mcp login <server>`.
|
||||
|
||||
You have two ways to complete it from a remote host:
|
||||
|
||||
**Option 1 — paste the redirect URL back (no setup, works anywhere).** On an interactive terminal, Hermes prompts you to paste the redirect URL alongside running the local listener. After approving in your browser, the redirect to `http://127.0.0.1:<port>/callback` will show a connection error — that's expected. Copy the **full URL from the browser's address bar** and paste it at the Hermes prompt:
|
||||
|
||||
```
|
||||
MCP OAuth: authorization required.
|
||||
Open this URL in your browser:
|
||||
|
||||
https://mcp.linear.app/authorize?response_type=code&...
|
||||
|
||||
Or paste the redirect URL here (or the ?code=...&state=... portion) and press Enter:
|
||||
> https://mcp.linear.app/callback?code=abc123&state=xyz
|
||||
Got authorization code from paste — completing flow.
|
||||
```
|
||||
|
||||
A bare `?code=...&state=...` query string is accepted too. This works for any MCP server with `auth: oauth` and requires no SSH config changes.
|
||||
|
||||
**Option 2 — SSH port forward (same as xAI / Spotify).** Hermes prints the exact port it bound to in the SSH-session hint. Open a separate terminal on your laptop:
|
||||
|
||||
```bash
|
||||
ssh -N -L <port>:127.0.0.1:<port> user@remote-host
|
||||
```
|
||||
|
||||
Then open the authorize URL in your browser as normal; the redirect tunnels through and the listener picks it up. Use this when you need the flow to complete unattended (e.g. scripted re-auth where you can't paste interactively).
|
||||
|
||||
**Pitfall — the 30s config-reload race.** If you edit `~/.hermes/config.yaml` to add an OAuth MCP server from inside a running Hermes session, the CLI auto-reloads MCP connections with a 30s timeout. That's not enough time to complete an interactive OAuth flow, and the reload will give up. Use `hermes mcp login <server>` from a fresh terminal instead — it has no such cap and waits the full 5 min for you to paste back.
|
||||
|
||||
## Why the listener can't just bind 0.0.0.0
|
||||
|
||||
xAI and Spotify both validate the `redirect_uri` parameter against an allowlist. Both require the loopback form (`http://127.0.0.1:<exact-port>/callback`). Binding the listener to `0.0.0.0` or a different port would cause the auth server to reject the request as a redirect_uri mismatch. The SSH tunnel keeps the loopback URI intact end-to-end.
|
||||
|
|
@ -151,4 +183,5 @@ The tokens are written under the Linux user that ran `hermes auth add ...`. If y
|
|||
|
||||
- [xAI Grok OAuth](./xai-grok-oauth.md)
|
||||
- [Spotify (`Running over SSH`)](../user-guide/features/spotify.md#running-over-ssh--in-a-headless-environment)
|
||||
- [Native MCP client (OAuth section)](../user-guide/features/mcp.md#oauth-authenticated-http-servers)
|
||||
- [SSH `-J` / ProxyJump (man page)](https://man.openbsd.org/ssh#J)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ description: "Runbook, go-live checklist, and operator worksheet for the Microso
|
|||
|
||||
# Operate the Teams Meeting Pipeline
|
||||
|
||||
Use this guide after you have already enabled the feature from [Teams Meetings](/docs/user-guide/messaging/teams-meetings).
|
||||
Use this guide after you have already enabled the feature from [Teams Meetings](/user-guide/messaging/teams-meetings).
|
||||
|
||||
This page covers:
|
||||
- operator CLI flows
|
||||
|
|
@ -284,5 +284,5 @@ Use this before changing the deployment:
|
|||
|
||||
## Related Docs
|
||||
|
||||
- [Teams Meetings setup](/docs/user-guide/messaging/teams-meetings)
|
||||
- [Microsoft Teams bot setup](/docs/user-guide/messaging/teams)
|
||||
- [Teams Meetings setup](/user-guide/messaging/teams-meetings)
|
||||
- [Microsoft Teams bot setup](/user-guide/messaging/teams)
|
||||
|
|
|
|||
|
|
@ -241,9 +241,9 @@ If you just need to pipe a raw string, reach for `hermes send`.
|
|||
|
||||
## Related
|
||||
|
||||
- [Automate Anything with Cron](/docs/guides/automate-with-cron) —
|
||||
- [Automate Anything with Cron](/guides/automate-with-cron) —
|
||||
scheduled jobs whose output auto-delivers to any platform.
|
||||
- [Gateway Internals](/docs/developer-guide/gateway-internals) —
|
||||
- [Gateway Internals](/developer-guide/gateway-internals) —
|
||||
the delivery router that `hermes send` shares with cron delivery.
|
||||
- [Messaging Platform Setup](/docs/user-guide/messaging/) —
|
||||
- [Messaging Platform Setup](/user-guide/messaging/) —
|
||||
one-time configuration for each platform.
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ The simplest way to use Hermes is the `chat()` method — pass a message, get a
|
|||
from run_agent import AIAgent
|
||||
|
||||
agent = AIAgent(
|
||||
model="anthropic/claude-sonnet-4",
|
||||
model="anthropic/claude-sonnet-4.6",
|
||||
quiet_mode=True,
|
||||
)
|
||||
response = agent.chat("What is the capital of France?")
|
||||
|
|
@ -65,7 +65,7 @@ For more control over the conversation, use `run_conversation()` directly. It re
|
|||
|
||||
```python
|
||||
agent = AIAgent(
|
||||
model="anthropic/claude-sonnet-4",
|
||||
model="anthropic/claude-sonnet-4.6",
|
||||
quiet_mode=True,
|
||||
)
|
||||
|
||||
|
|
@ -102,14 +102,14 @@ Control which toolsets the agent has access to using `enabled_toolsets` or `disa
|
|||
```python
|
||||
# Only enable web tools (browsing, search)
|
||||
agent = AIAgent(
|
||||
model="anthropic/claude-sonnet-4",
|
||||
model="anthropic/claude-sonnet-4.6",
|
||||
enabled_toolsets=["web"],
|
||||
quiet_mode=True,
|
||||
)
|
||||
|
||||
# Enable everything except terminal access
|
||||
agent = AIAgent(
|
||||
model="anthropic/claude-sonnet-4",
|
||||
model="anthropic/claude-sonnet-4.6",
|
||||
disabled_toolsets=["terminal"],
|
||||
quiet_mode=True,
|
||||
)
|
||||
|
|
@ -127,7 +127,7 @@ Maintain conversation state across multiple turns by passing the message history
|
|||
|
||||
```python
|
||||
agent = AIAgent(
|
||||
model="anthropic/claude-sonnet-4",
|
||||
model="anthropic/claude-sonnet-4.6",
|
||||
quiet_mode=True,
|
||||
)
|
||||
|
||||
|
|
@ -153,7 +153,7 @@ Enable trajectory saving to capture conversations in ShareGPT format — useful
|
|||
|
||||
```python
|
||||
agent = AIAgent(
|
||||
model="anthropic/claude-sonnet-4",
|
||||
model="anthropic/claude-sonnet-4.6",
|
||||
save_trajectories=True,
|
||||
quiet_mode=True,
|
||||
)
|
||||
|
|
@ -311,7 +311,7 @@ print(review)
|
|||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `model` | `str` | `"anthropic/claude-opus-4.6"` | Model in OpenRouter format |
|
||||
| `model` | `str` | `""` | Model in OpenRouter format (defaults to empty; resolved from your hermes config at runtime) |
|
||||
| `quiet_mode` | `bool` | `False` | Suppress CLI output |
|
||||
| `enabled_toolsets` | `List[str]` | `None` | Whitelist specific toolsets |
|
||||
| `disabled_toolsets` | `List[str]` | `None` | Blacklist specific toolsets |
|
||||
|
|
|
|||
276
website/docs/guides/run-hermes-with-nous-portal.md
Normal file
276
website/docs/guides/run-hermes-with-nous-portal.md
Normal file
|
|
@ -0,0 +1,276 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
title: "Run Hermes Agent with Nous Portal"
|
||||
description: "Start-to-finish walkthrough: subscribe, set up, switch models, enable gateway tools, and verify routing"
|
||||
---
|
||||
|
||||
# Run Hermes Agent with Nous Portal
|
||||
|
||||
This guide walks you through running Hermes Agent on a [Nous Portal](https://portal.nousresearch.com) subscription end to end — from signing up to verifying that every tool routes correctly. If you just want the overview of what the Portal is and what's in the subscription, see the [Nous Portal integration page](/integrations/nous-portal). This page is the task script.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Hermes Agent installed ([Quickstart](/getting-started/quickstart))
|
||||
- A web browser on the machine you're setting up (or SSH port forwarding — see [OAuth over SSH](/guides/oauth-over-ssh))
|
||||
- About 5 minutes
|
||||
|
||||
You do **not** need: an OpenAI key, an Anthropic key, a Firecrawl account, a FAL account, a Browser Use account, or any other per-vendor credential. That's the whole point.
|
||||
|
||||
## 1. Get a subscription
|
||||
|
||||
Open [portal.nousresearch.com/manage-subscription](https://portal.nousresearch.com/manage-subscription), sign up, and pick a plan.
|
||||
|
||||
Already subscribed? Skip to step 2.
|
||||
|
||||
## 2. Run the one-shot setup
|
||||
|
||||
```bash
|
||||
hermes setup --portal
|
||||
```
|
||||
|
||||
This single command does five things:
|
||||
|
||||
1. Opens your browser to portal.nousresearch.com for OAuth login
|
||||
2. Stores the refresh token at `~/.hermes/auth.json`
|
||||
3. Sets `model.provider: nous` in `~/.hermes/config.yaml`
|
||||
4. Picks a default agentic model (`anthropic/claude-sonnet-4.6` or similar)
|
||||
5. Turns on the Tool Gateway for web search, image generation, TTS, and browser automation
|
||||
|
||||
When it finishes, you're back at your terminal ready to chat.
|
||||
|
||||
### What if I'm SSH'd into a server?
|
||||
|
||||
OAuth needs a browser, but the loopback callback runs on the machine where Hermes is running. Two options:
|
||||
|
||||
```bash
|
||||
# Option A: SSH port forwarding (preferred)
|
||||
ssh -N -L 8642:127.0.0.1:8642 user@remote-host # in a local terminal
|
||||
hermes setup --portal # on the remote, open the printed URL in your local browser
|
||||
|
||||
# Option B: manual paste (for Cloud Shell, Codespaces, EC2 Instance Connect)
|
||||
hermes auth add nous --type oauth --manual-paste
|
||||
# Then re-run `hermes setup --portal` to wire the provider + gateway
|
||||
```
|
||||
|
||||
See [OAuth over SSH / Remote Hosts](/guides/oauth-over-ssh) for the full walkthrough including ProxyJump chains, mosh/tmux, and ControlMaster gotchas.
|
||||
|
||||
## 3. Verify it worked
|
||||
|
||||
```bash
|
||||
hermes portal info
|
||||
```
|
||||
|
||||
You should see:
|
||||
|
||||
```
|
||||
Nous Portal
|
||||
───────────
|
||||
Auth: ✓ logged in
|
||||
Portal: https://portal.nousresearch.com
|
||||
Model: ✓ using Nous as inference provider
|
||||
|
||||
Tool Gateway
|
||||
────────────
|
||||
Web search & extract via Nous Portal
|
||||
Image generation via Nous Portal
|
||||
Text-to-speech via Nous Portal
|
||||
Browser automation via Nous Portal
|
||||
```
|
||||
|
||||
If any line shows something other than "via Nous Portal" or the auth line says "not logged in", jump to [Troubleshooting](#troubleshooting) below.
|
||||
|
||||
## 4. Run your first conversation
|
||||
|
||||
```bash
|
||||
hermes chat
|
||||
```
|
||||
|
||||
Try something that exercises both the model and the Tool Gateway:
|
||||
|
||||
```
|
||||
Hey, search the web for "Hermes Agent release notes" and summarize the top 3 hits.
|
||||
```
|
||||
|
||||
You should see Hermes call `web_search` (Firecrawl-backed, through the gateway) and respond with a summary. If the search runs and the response makes sense, you're done — the Portal is wired up end to end.
|
||||
|
||||
## 5. Pick the model you actually want
|
||||
|
||||
`hermes setup --portal` lets you pick a model during setup, but the whole point of the subscription is access to the full catalog — switch any time with `/model` mid-session:
|
||||
|
||||
```bash
|
||||
/model anthropic/claude-sonnet-4.6 # best general-purpose agentic
|
||||
/model openai/gpt-5.4 # strong reasoning + tool calling
|
||||
/model google/gemini-2.5-pro # huge context window
|
||||
/model deepseek/deepseek-v3.2 # cost-effective coder
|
||||
/model anthropic/claude-opus-4.6 # heavyweight for hard problems
|
||||
```
|
||||
|
||||
Or pop the picker to browse:
|
||||
|
||||
```bash
|
||||
/model
|
||||
```
|
||||
|
||||
Pick a different default permanently:
|
||||
|
||||
```bash
|
||||
# in your terminal, outside any session
|
||||
hermes config set model.default anthropic/claude-sonnet-4.6
|
||||
```
|
||||
|
||||
### Don't pick Hermes-4 for agent work
|
||||
|
||||
Hermes-4-70B and Hermes-4-405B are available on the Portal at deep discounts, but they're **chat/reasoning models**, not tool-call-tuned. They will struggle with multi-step agent loops. Use them via [Nous Chat](https://chat.nousresearch.com) for conversation/research work, or through the [subscription proxy](/user-guide/features/subscription-proxy) from non-agent tools. For Hermes Agent itself, stick to the frontier agentic models above.
|
||||
|
||||
The Portal's own [info page](https://portal.nousresearch.com/info) carries this warning too — it's the official Nous guidance, not just a Hermes-side opinion.
|
||||
|
||||
## 6. (Optional) Customize Tool Gateway routing
|
||||
|
||||
The gateway is opt-in per tool, not all-or-nothing. If you already have a Browserbase account and want to keep using it while routing web search and image generation through Nous, that's supported:
|
||||
|
||||
```bash
|
||||
hermes tools
|
||||
# → Web search → "Nous Subscription" (recommended)
|
||||
# → Image generation → "Nous Subscription" (recommended)
|
||||
# → Browser → "Browserbase" (your existing key)
|
||||
# → TTS → "Nous Subscription" (recommended)
|
||||
```
|
||||
|
||||
These rows appear in `hermes tools` even before you've logged into Nous Portal — if you pick "Nous Subscription" without an active session, Hermes runs the Portal login inline (without changing your inference provider or your other tools).
|
||||
|
||||
Verify your mix with:
|
||||
|
||||
```bash
|
||||
hermes portal tools
|
||||
```
|
||||
|
||||
You'll see per-tool routing — `via Nous Portal` for the ones routed through the subscription, and the partner name (`browserbase`, `firecrawl`, etc.) for the ones using your own keys.
|
||||
|
||||
## 7. (Optional) Enable voice mode
|
||||
|
||||
Because the Tool Gateway includes OpenAI TTS, [voice mode](/user-guide/features/voice-mode) works without a separate OpenAI key:
|
||||
|
||||
```bash
|
||||
hermes setup voice
|
||||
# → pick "Nous Subscription" for TTS
|
||||
# → pick a speech-to-text backend (local faster-whisper is free, no setup)
|
||||
```
|
||||
|
||||
Then in any messaging-platform session (Telegram, Discord, Signal, etc.), send a voice message and Hermes will transcribe it, respond, and reply with synthesized voice — all on your Portal subscription.
|
||||
|
||||
## 8. (Optional) Cron + always-on workflows
|
||||
|
||||
The Portal subscription works for [cron jobs](/user-guide/features/cron) and [batch processing](/user-guide/features/batch-processing) the same way it works for interactive chat — the OAuth refresh token is reused automatically. No additional setup; just schedule cron jobs and they'll bill against your subscription.
|
||||
|
||||
```bash
|
||||
hermes cron create "every day at 9am" \
|
||||
"Search the web for top AI news and summarize the 5 most important stories" \
|
||||
--name "Daily AI news"
|
||||
```
|
||||
|
||||
The cron job runs unattended, calls the model + web search + summarization all through your Portal subscription.
|
||||
|
||||
## Profiles and multi-user setups
|
||||
|
||||
If you use [Hermes profiles](/user-guide/profiles) (e.g. a separate config per project), the Portal refresh token is automatically shared across all profiles via a shared token store. Sign in once on any profile, and the rest pick it up automatically.
|
||||
|
||||
For team setups where multiple humans share a machine, each human has their own Portal account → each home directory holds its own `~/.hermes/auth.json` → no token sharing across users. This is the right boundary.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### `hermes portal info` shows "not logged in" after `hermes setup --portal`
|
||||
|
||||
The OAuth flow didn't complete. Re-run it:
|
||||
|
||||
```bash
|
||||
hermes portal
|
||||
```
|
||||
|
||||
If your browser doesn't open or the callback fails, you're likely on a remote/headless host — see [OAuth over SSH](/guides/oauth-over-ssh) for the port-forwarding and manual-paste workarounds.
|
||||
|
||||
### "Model: currently openrouter" (or some other provider) instead of "using Nous as inference provider"
|
||||
|
||||
Your local config drifted. The OAuth worked but `model.provider` is still pointing at a different provider. Fix:
|
||||
|
||||
```bash
|
||||
hermes config set model.provider nous
|
||||
```
|
||||
|
||||
Or interactively:
|
||||
|
||||
```bash
|
||||
hermes model
|
||||
# pick Nous Portal
|
||||
```
|
||||
|
||||
Re-verify with `hermes portal info`.
|
||||
|
||||
### Tool Gateway tools showing partner names instead of "via Nous Portal"
|
||||
|
||||
Per-tool config is overriding the gateway. Run:
|
||||
|
||||
```bash
|
||||
hermes tools
|
||||
# pick "Nous Subscription" for any tool you want gateway-routed
|
||||
```
|
||||
|
||||
Some users intentionally mix — e.g. routing web through Nous but using their own Browserbase key for browser. If that's intentional, leave it alone. If not, this command fixes it.
|
||||
|
||||
### "Re-authentication required" mid-session
|
||||
|
||||
Your Portal refresh token was invalidated (password change, manual revoke, session expiry). The token is now quarantined locally so Hermes doesn't replay it endlessly. Just log in again:
|
||||
|
||||
```bash
|
||||
hermes auth add nous
|
||||
```
|
||||
|
||||
The quarantine clears automatically on successful re-login.
|
||||
|
||||
### Model I want isn't in the `/model` picker
|
||||
|
||||
The Portal catalog mirrors OpenRouter's model list (300+). If a model is missing, try typing the OpenRouter-style slug directly:
|
||||
|
||||
```bash
|
||||
/model anthropic/claude-opus-4.6
|
||||
/model openai/o1-2025-12-17
|
||||
```
|
||||
|
||||
If a model is genuinely unavailable, [open an issue](https://github.com/NousResearch/hermes-agent/issues) — most gaps are routing config we can update.
|
||||
|
||||
### Billing not appearing on my Portal account
|
||||
|
||||
`hermes portal info` will tell you whether you're actually routing through the Portal or some other provider. Common causes:
|
||||
|
||||
- `model.provider` set to `openrouter`/`anthropic`/etc. instead of `nous`
|
||||
- An OAuth refresh failure that fell back to a different configured provider
|
||||
- Multiple Hermes profiles where you're using the wrong one (check `hermes profile current`)
|
||||
|
||||
### Want to revoke and start clean
|
||||
|
||||
```bash
|
||||
hermes auth remove nous # wipes the local refresh token
|
||||
# Then re-run setup or remove the subscription from the Portal web UI
|
||||
```
|
||||
|
||||
## What this gets you, in plain numbers
|
||||
|
||||
| Without Portal | With Portal |
|
||||
|----------------|-------------|
|
||||
| 1× OpenRouter / Anthropic / OpenAI key in `.env` | 1× OAuth refresh token, no `.env` keys |
|
||||
| 1× Firecrawl key for web | Web routed through gateway |
|
||||
| 1× FAL key for image gen | Image gen routed through gateway |
|
||||
| 1× Browser Use / Browserbase key for browser | Browser routed through gateway |
|
||||
| 1× OpenAI key for TTS / voice mode | TTS routed through gateway |
|
||||
| 5 separate dashboards, top-ups, invoices | 1 subscription, 1 invoice |
|
||||
| Cross-machine: replicate all 5 keys | Cross-machine: re-OAuth once |
|
||||
|
||||
That's the deal. If you're using more than two of those backends anyway, the subscription pays for itself.
|
||||
|
||||
## See also
|
||||
|
||||
- **[Nous Portal integration page](/integrations/nous-portal)** — Overview of what's in the subscription
|
||||
- **[Tool Gateway](/user-guide/features/tool-gateway)** — Full details on every gateway-routed tool
|
||||
- **[Subscription proxy](/user-guide/features/subscription-proxy)** — Use your Portal subscription from non-Hermes tools
|
||||
- **[Voice mode](/user-guide/features/voice-mode)** — Set up voice conversations on the Portal subscription
|
||||
- **[OAuth over SSH](/guides/oauth-over-ssh)** — Remote / headless login patterns
|
||||
- **[Profiles](/user-guide/profiles)** — Share one Portal login across multiple Hermes configurations
|
||||
123
website/docs/guides/run-nemotron-3-ultra-free.md
Normal file
123
website/docs/guides/run-nemotron-3-ultra-free.md
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
---
|
||||
sidebar_position: 0
|
||||
title: "Run Nemotron 3 Ultra free in Hermes Agent"
|
||||
description: "Try NVIDIA Nemotron 3 Ultra on Nous Portal — free June 4–18 — with day 0 support in Hermes Agent"
|
||||
---
|
||||
|
||||
# Run Nemotron 3 Ultra free in Hermes Agent
|
||||
|
||||
Nous Research has been inducted into the **Nemotron Coalition** of leading AI labs working with **NVIDIA** to advance open frontier foundation models. In honor of this, we've partnered with **Nebius** to provide **Nemotron 3 Ultra** free on [Nous Portal](https://portal.nousresearch.com) for two weeks (**June 4th – June 18th**). Follow the instructions below to try the model in your Hermes Agent today.
|
||||
|
||||
:::info Limited-time offer
|
||||
The `nvidia/nemotron-3-ultra:free` tier is available from **June 4th to June 18th**. The `:free` tag is what keeps it on the no-cost plan — pick that exact variant.
|
||||
:::
|
||||
|
||||
Pick whichever install fits you. The **desktop app** is the easiest — no terminal required. If you live in a terminal, the **command-line** install is right below it.
|
||||
|
||||
## Option A — Desktop app (recommended)
|
||||
|
||||
The simplest path: a one-click installer with a guided, point-and-click setup. No terminal needed.
|
||||
|
||||
### 1. Download and install
|
||||
|
||||
[Download the Hermes Desktop installer](https://hermes-agent.nousresearch.com/desktop) for macOS or Windows, then open it. On first launch it finishes setting itself up (usually under a minute).
|
||||
|
||||
### 2. Connect Nous Portal
|
||||
|
||||
When the app opens, you'll see a "Let's get you set up" screen. Click **Nous Portal** (marked **Recommended**). Your browser opens — create a [Nous Portal](https://portal.nousresearch.com) account (or sign in), choose the **Free** plan, and authorize Hermes. The app connects automatically.
|
||||
|
||||
### 3. Pick the free Nemotron 3 Ultra model
|
||||
|
||||
After connecting, the app shows a **Default model** card. Click **Change**, search for **nemotron 3 ultra**, and select the variant tagged **Free tier**:
|
||||
|
||||
```
|
||||
nvidia/nemotron-3-ultra:free
|
||||
```
|
||||
|
||||
The `:free` tag is what keeps it on the no-cost tier — pick that variant.
|
||||
|
||||
### 4. Start chatting
|
||||
|
||||
Click **Start chatting**. That's it — you're talking to Nemotron 3 Ultra, free.
|
||||
|
||||
## Option B — Command line
|
||||
|
||||
Prefer the terminal?
|
||||
|
||||
### 1. Install Hermes Agent
|
||||
|
||||
On macOS/Linux/WSL2/Android, run
|
||||
|
||||
```bash
|
||||
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash
|
||||
```
|
||||
|
||||
On Windows, run
|
||||
|
||||
```powershell
|
||||
iex (irm https://hermes-agent.nousresearch.com/install.ps1)
|
||||
```
|
||||
|
||||
Prefer to review first? Download [`install.sh`](https://hermes-agent.nousresearch.com/install.sh), inspect it, then run it.
|
||||
|
||||
After it finishes, reload your shell:
|
||||
|
||||
```bash
|
||||
source ~/.bashrc # or source ~/.zshrc
|
||||
```
|
||||
|
||||
### 2. Run Quick Setup
|
||||
|
||||
```bash
|
||||
hermes setup
|
||||
```
|
||||
|
||||
Select **Quick Setup**. Hermes opens a browser tab and waits for you to finish the next steps.
|
||||
|
||||
### 3. Create a Nous Portal account
|
||||
|
||||
In the browser, create a [Nous Portal](https://portal.nousresearch.com) account (or sign in) and choose the **Free** plan.
|
||||
|
||||
### 4. Connect your account
|
||||
|
||||
When prompted to connect your account to Hermes Agent, click **Connect**. You'll see a confirmation once it's linked.
|
||||
|
||||
### 5. Select the free Nemotron 3 Ultra model
|
||||
|
||||
Return to your terminal. From the model list, select:
|
||||
|
||||
```
|
||||
nvidia/nemotron-3-ultra:free
|
||||
```
|
||||
|
||||
The `:free` tag is what keeps it on the no-cost tier, so make sure you pick that variant.
|
||||
|
||||
### 6. Start chatting
|
||||
|
||||
Complete the remaining Quick Setup prompts, then run:
|
||||
|
||||
```bash
|
||||
hermes
|
||||
```
|
||||
|
||||
That's it — you're talking to Nemotron 3 Ultra, free.
|
||||
|
||||
## Switching to it later
|
||||
|
||||
Already set up with another model?
|
||||
|
||||
- **Desktop app:** open the model picker, search for **nemotron 3 ultra**, and select the **Free tier** variant.
|
||||
- **CLI / TUI:** switch any time from inside a session with `/model nvidia/nemotron-3-ultra:free`, or run `/model` to open the picker and choose it from the list.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **Don't see the model in the list?** Make sure you finished the Nous Portal connection and that you're on the **Free** plan. In the CLI, `hermes portal info` confirms you're logged in and routing through Nous.
|
||||
- **Picked the wrong variant?** Re-select `nvidia/nemotron-3-ultra:free` — the `:free` suffix is required to stay on the no-cost tier.
|
||||
- **Browser didn't open / you're on a remote host (CLI)?** See [OAuth over SSH / Remote Hosts](/guides/oauth-over-ssh) for port-forwarding and manual-paste workarounds.
|
||||
|
||||
## See also
|
||||
|
||||
- **[Desktop App](/user-guide/desktop)** — The native one-click app (macOS, Windows, Linux)
|
||||
- **[Run Hermes Agent with Nous Portal](/guides/run-hermes-with-nous-portal)** — Full Portal walkthrough: models, Tool Gateway, and verification
|
||||
- **[Nous Portal integration](/integrations/nous-portal)** — What's in the subscription
|
||||
- **[Quickstart](/getting-started/quickstart)** — Install-to-chat in under 5 minutes
|
||||
|
|
@ -24,7 +24,7 @@ A Telegram bot that:
|
|||
|
||||
Before starting, make sure you have:
|
||||
|
||||
- **Hermes Agent installed** on a server or VPS (not your laptop — the bot needs to stay running). Follow the [installation guide](/docs/getting-started/installation) if you haven't yet.
|
||||
- **Hermes Agent installed** on a server or VPS (not your laptop — the bot needs to stay running). Follow the [installation guide](/getting-started/installation) if you haven't yet.
|
||||
- **A Telegram account** for yourself (the bot owner)
|
||||
- **An LLM provider configured** — at minimum, an API key for OpenAI, Anthropic, or another supported provider in `~/.hermes/.env`
|
||||
|
||||
|
|
@ -291,7 +291,7 @@ Users can also change this per-session with the `/verbose` command in chat.
|
|||
|
||||
Customize how the bot communicates by editing `~/.hermes/SOUL.md`:
|
||||
|
||||
For a full guide, see [Use SOUL.md with Hermes](/docs/guides/use-soul-with-hermes).
|
||||
For a full guide, see [Use SOUL.md with Hermes](/guides/use-soul-with-hermes).
|
||||
|
||||
```markdown
|
||||
# Soul
|
||||
|
|
@ -428,13 +428,13 @@ hermes gateway stop && hermes gateway start
|
|||
|
||||
You've got a working team Telegram assistant. Here are some next steps:
|
||||
|
||||
- **[Security Guide](/docs/user-guide/security)** — deep dive into authorization, container isolation, and command approval
|
||||
- **[Messaging Gateway](/docs/user-guide/messaging)** — full reference for gateway architecture, session management, and chat commands
|
||||
- **[Telegram Setup](/docs/user-guide/messaging/telegram)** — platform-specific details including voice messages and TTS
|
||||
- **[Scheduled Tasks](/docs/user-guide/features/cron)** — advanced cron scheduling with delivery options and cron expressions
|
||||
- **[Context Files](/docs/user-guide/features/context-files)** — AGENTS.md, SOUL.md, and .cursorrules for project knowledge
|
||||
- **[Personality](/docs/user-guide/features/personality)** — built-in personality presets and custom persona definitions
|
||||
- **Add more platforms** — the same gateway can simultaneously run [Discord](/docs/user-guide/messaging/discord), [Slack](/docs/user-guide/messaging/slack), and [WhatsApp](/docs/user-guide/messaging/whatsapp)
|
||||
- **[Security Guide](/user-guide/security)** — deep dive into authorization, container isolation, and command approval
|
||||
- **[Messaging Gateway](/user-guide/messaging)** — full reference for gateway architecture, session management, and chat commands
|
||||
- **[Telegram Setup](/user-guide/messaging/telegram)** — platform-specific details including voice messages and TTS
|
||||
- **[Scheduled Tasks](/user-guide/features/cron)** — advanced cron scheduling with delivery options and cron expressions
|
||||
- **[Context Files](/user-guide/features/context-files)** — AGENTS.md, SOUL.md, and .cursorrules for project knowledge
|
||||
- **[Personality](/user-guide/features/personality)** — built-in personality presets and custom persona definitions
|
||||
- **Add more platforms** — the same gateway can simultaneously run [Discord](/user-guide/messaging/discord), [Slack](/user-guide/messaging/slack), and [WhatsApp](/user-guide/messaging/whatsapp)
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,10 @@ description: "Practical advice to get the most out of Hermes Agent — prompt ti
|
|||
|
||||
A quick-wins collection of practical tips that make you immediately more effective with Hermes Agent. Each section targets a different aspect — scan the headers and jump to what's relevant.
|
||||
|
||||
:::tip Confused which model to pick?
|
||||
Run `hermes setup --portal` — you get 300+ models including Claude, GPT-5, and Gemini under one subscription. See [Nous Portal](/integrations/nous-portal).
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## Getting the Best Results
|
||||
|
|
@ -80,7 +84,7 @@ Create an `AGENTS.md` in your project root with architecture decisions, coding c
|
|||
|
||||
Want Hermes to have a stable default voice? Edit `~/.hermes/SOUL.md` (or `$HERMES_HOME/SOUL.md` if you use a custom Hermes home). Hermes now seeds a starter SOUL automatically and uses that global file as the instance-wide personality source.
|
||||
|
||||
For a full walkthrough, see [Use SOUL.md with Hermes](/docs/guides/use-soul-with-hermes).
|
||||
For a full walkthrough, see [Use SOUL.md with Hermes](/guides/use-soul-with-hermes).
|
||||
|
||||
```markdown
|
||||
# Soul
|
||||
|
|
|
|||
|
|
@ -485,6 +485,6 @@ Not-great first servers:
|
|||
|
||||
## Related docs
|
||||
|
||||
- [MCP (Model Context Protocol)](/docs/user-guide/features/mcp)
|
||||
- [FAQ](/docs/reference/faq)
|
||||
- [Slash Commands](/docs/reference/slash-commands)
|
||||
- [MCP (Model Context Protocol)](/user-guide/features/mcp)
|
||||
- [FAQ](/reference/faq)
|
||||
- [Slash Commands](/reference/slash-commands)
|
||||
|
|
|
|||
|
|
@ -258,7 +258,7 @@ Move project instructions into `AGENTS.md` and keep `SOUL.md` focused on identit
|
|||
|
||||
## Related docs
|
||||
|
||||
- [Personality & SOUL.md](/docs/user-guide/features/personality)
|
||||
- [Context Files](/docs/user-guide/features/context-files)
|
||||
- [Configuration](/docs/user-guide/configuration)
|
||||
- [Tips & Best Practices](/docs/guides/tips)
|
||||
- [Personality & SOUL.md](/user-guide/features/personality)
|
||||
- [Context Files](/user-guide/features/context-files)
|
||||
- [Configuration](/user-guide/configuration)
|
||||
- [Tips & Best Practices](/guides/tips)
|
||||
|
|
|
|||
|
|
@ -6,10 +6,14 @@ description: "A practical guide to setting up and using Hermes voice mode across
|
|||
|
||||
# Use Voice Mode with Hermes
|
||||
|
||||
This guide is the practical companion to the [Voice Mode feature reference](/docs/user-guide/features/voice-mode).
|
||||
This guide is the practical companion to the [Voice Mode feature reference](/user-guide/features/voice-mode).
|
||||
|
||||
If the feature page explains what voice mode can do, this guide shows how to actually use it well.
|
||||
|
||||
:::tip
|
||||
[Nous Portal](/integrations/nous-portal) bundles both the LLM and TTS through one OAuth — voice mode works end-to-end with no extra credentials.
|
||||
:::
|
||||
|
||||
## What voice mode is good for
|
||||
|
||||
Voice mode is especially useful when:
|
||||
|
|
@ -449,8 +453,8 @@ That progression keeps the debugging surface small.
|
|||
|
||||
## Where to read next
|
||||
|
||||
- [Voice Mode feature reference](/docs/user-guide/features/voice-mode)
|
||||
- [Messaging Gateway](/docs/user-guide/messaging)
|
||||
- [Discord setup](/docs/user-guide/messaging/discord)
|
||||
- [Telegram setup](/docs/user-guide/messaging/telegram)
|
||||
- [Configuration](/docs/user-guide/configuration)
|
||||
- [Voice Mode feature reference](/user-guide/features/voice-mode)
|
||||
- [Messaging Gateway](/user-guide/messaging)
|
||||
- [Discord setup](/user-guide/messaging/discord)
|
||||
- [Telegram setup](/user-guide/messaging/telegram)
|
||||
- [Configuration](/user-guide/configuration)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ If you don't have a public URL or just want to get started quickly, check out [B
|
|||
:::
|
||||
|
||||
:::info Reference docs
|
||||
For the full webhook platform reference (all config options, delivery types, dynamic subscriptions, security model) see [Webhooks](/docs/user-guide/messaging/webhooks).
|
||||
For the full webhook platform reference (all config options, delivery types, dynamic subscriptions, security model) see [Webhooks](/user-guide/messaging/webhooks).
|
||||
:::
|
||||
|
||||
:::warning Prompt injection risk
|
||||
|
|
@ -196,7 +196,7 @@ The "stop here" instruction prevents a meaningful review, but the agent still ru
|
|||
|
||||
## Using a skill for consistent review style
|
||||
|
||||
Load a [Hermes skill](/docs/user-guide/features/skills) to give the agent a consistent review persona. Add `skills` to your route inside `platforms.webhook.extra.routes` in `config.yaml`:
|
||||
Load a [Hermes skill](/user-guide/features/skills) to give the agent a consistent review persona. Add `skills` to your route inside `platforms.webhook.extra.routes` in `config.yaml`:
|
||||
|
||||
```yaml
|
||||
platforms:
|
||||
|
|
@ -324,6 +324,6 @@ platforms:
|
|||
## What's Next?
|
||||
|
||||
- **[Cron-Based PR Reviews](./github-pr-review-agent.md)** — poll for PRs on a schedule, no public endpoint needed
|
||||
- **[Webhook Reference](/docs/user-guide/messaging/webhooks)** — full config reference for the webhook platform
|
||||
- **[Build a Plugin](/docs/guides/build-a-hermes-plugin)** — package review logic into a shareable plugin
|
||||
- **[Profiles](/docs/user-guide/profiles)** — run a dedicated reviewer profile with its own memory and config
|
||||
- **[Webhook Reference](/user-guide/messaging/webhooks)** — full config reference for the webhook platform
|
||||
- **[Build a Plugin](/guides/build-a-hermes-plugin)** — package review logic into a shareable plugin
|
||||
- **[Profiles](/user-guide/profiles)** — run a dedicated reviewer profile with its own memory and config
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ description: "Find, install, use, and create skills — on-demand knowledge that
|
|||
|
||||
Skills are on-demand knowledge documents that teach Hermes how to handle specific tasks — from generating ASCII art to managing GitHub PRs. This guide walks you through using them day to day.
|
||||
|
||||
For the full technical reference, see [Skills System](/docs/user-guide/features/skills).
|
||||
For the full technical reference, see [Skills System](/user-guide/features/skills).
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -135,7 +135,7 @@ skill_view("writing-plans")
|
|||
|
||||
Plugin skills are **not** listed in the system prompt and don't appear in `skills_list`. They're opt-in — load them explicitly when you know a plugin provides one. When loaded, the agent sees a banner listing sibling skills from the same plugin.
|
||||
|
||||
For how to ship skills in your own plugin, see [Build a Hermes Plugin → Bundle skills](/docs/guides/build-a-hermes-plugin#bundle-skills).
|
||||
For how to ship skills in your own plugin, see [Build a Hermes Plugin → Bundle skills](/guides/build-a-hermes-plugin#bundle-skills).
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -162,7 +162,7 @@ Manage skill config from the CLI:
|
|||
hermes skills config gif-search
|
||||
|
||||
# View all skill config
|
||||
hermes config get skills.config
|
||||
hermes config show | grep '^skills\.config'
|
||||
```
|
||||
|
||||
---
|
||||
|
|
@ -287,4 +287,4 @@ Both are persistent across sessions, but they serve different purposes:
|
|||
|
||||
---
|
||||
|
||||
*For the complete skills reference — frontmatter fields, conditional activation, external directories, and more — see [Skills System](/docs/user-guide/features/skills).*
|
||||
*For the complete skills reference — frontmatter fields, conditional activation, external directories, and more — see [Skills System](/user-guide/features/skills).*
|
||||
|
|
|
|||
|
|
@ -94,6 +94,8 @@ hermes model --manual-paste
|
|||
|
||||
See [OAuth over SSH / Remote Hosts](./oauth-over-ssh.md#browser-only-remote-cloud-shell--codespaces--ec2-instance-connect) for the full walkthrough. Regression fix for [#26923](https://github.com/NousResearch/hermes-agent/issues/26923).
|
||||
|
||||
If the consent page renders the authorization code directly on the page (xAI's current behavior on browser-based consoles) instead of redirecting to your `127.0.0.1:56121/callback`, paste **just the bare code value** at the `Callback URL:` prompt — Hermes accepts the full URL, a bare `?code=...&state=...` query fragment, or a bare code interchangeably.
|
||||
|
||||
## How the Login Works
|
||||
|
||||
1. Hermes opens your browser to `accounts.x.ai`.
|
||||
|
|
@ -180,7 +182,8 @@ The `x_search` toolset auto-enables whenever xAI credentials (a SuperGrok / X Pr
|
|||
| Chat | `grok-4.20-multi-agent-0309` | Multi-agent variant |
|
||||
| Image | `grok-imagine-image` | Default; ~5–10 s |
|
||||
| Image | `grok-imagine-image-quality` | Higher fidelity; ~10–20 s |
|
||||
| Video | `grok-imagine-video` | Text-to-video and image-to-video; up to 7 reference images |
|
||||
| Video | `grok-imagine-video` | Text-to-video |
|
||||
| Video | `grok-imagine-video-1.5-preview` | Image-to-video; dated alias `grok-imagine-video-1.5-2026-05-30` |
|
||||
| TTS | (default voice) | xAI `/v1/tts` endpoint |
|
||||
|
||||
The chat catalog is derived live from the on-disk `models.dev` cache; new xAI releases appear automatically once that cache refreshes. `grok-4.3` is always pinned to the top of the list.
|
||||
|
|
@ -190,7 +193,8 @@ The chat catalog is derived live from the on-disk `models.dev` cache; new xAI re
|
|||
| Variable | Effect |
|
||||
|----------|--------|
|
||||
| `XAI_BASE_URL` | Override the default `https://api.x.ai/v1` endpoint (rarely needed). |
|
||||
| `HERMES_INFERENCE_PROVIDER` | Force the active provider at runtime, e.g. `HERMES_INFERENCE_PROVIDER=xai-oauth hermes`. |
|
||||
|
||||
To select xAI as the active provider, set `model.provider: xai-oauth` in `config.yaml` (use `hermes setup` for the guided flow) or pass `--provider xai-oauth` for a single invocation.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
|
|
|||
|
|
@ -1,84 +0,0 @@
|
|||
---
|
||||
slug: /
|
||||
sidebar_position: 0
|
||||
title: "Hermes Agent Documentation"
|
||||
description: "The self-improving AI agent built by Nous Research. A built-in learning loop that creates skills from experience, improves them during use, and remembers across sessions."
|
||||
hide_table_of_contents: true
|
||||
displayed_sidebar: docs
|
||||
---
|
||||
|
||||
# Hermes Agent
|
||||
|
||||
The self-improving AI agent built by [Nous Research](https://nousresearch.com). The only agent with a built-in learning loop — it creates skills from experience, improves them during use, nudges itself to persist knowledge, and builds a deepening model of who you are across sessions.
|
||||
|
||||
<div style={{display: 'flex', gap: '1rem', marginBottom: '2rem', flexWrap: 'wrap'}}>
|
||||
<a href="/docs/getting-started/installation" style={{display: 'inline-block', padding: '0.6rem 1.2rem', backgroundColor: '#FFD700', color: '#07070d', borderRadius: '8px', fontWeight: 600, textDecoration: 'none'}}>Get Started →</a>
|
||||
<a href="https://github.com/NousResearch/hermes-agent" style={{display: 'inline-block', padding: '0.6rem 1.2rem', border: '1px solid rgba(255,215,0,0.2)', borderRadius: '8px', textDecoration: 'none'}}>View on GitHub</a>
|
||||
</div>
|
||||
|
||||
## Install
|
||||
|
||||
**Linux / macOS / WSL2**
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
|
||||
```
|
||||
|
||||
**Windows (native, PowerShell)** — *early beta, [details →](/docs/user-guide/windows-native)*
|
||||
|
||||
```powershell
|
||||
iex (irm https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.ps1)
|
||||
```
|
||||
|
||||
**Android (Termux)** — same curl one-liner as Linux; the installer auto-detects Termux.
|
||||
|
||||
See the full **[Installation Guide](/docs/getting-started/installation)** for what the installer does, the per-user vs root layout, and Windows-specific notes.
|
||||
|
||||
## What is Hermes Agent?
|
||||
|
||||
It's not a coding copilot tethered to an IDE or a chatbot wrapper around a single API. It's an **autonomous agent** that gets more capable the longer it runs. It lives wherever you put it — a $5 VPS, a GPU cluster, or serverless infrastructure (Daytona, Modal) that costs nearly nothing when idle. Talk to it from Telegram while it works on a cloud VM you never SSH into yourself. It's not tied to your laptop.
|
||||
|
||||
## Quick Links
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| 🚀 **[Installation](/docs/getting-started/installation)** | Install in 60 seconds on Linux, macOS, WSL2, or native Windows (early beta) |
|
||||
| 📖 **[Quickstart Tutorial](/docs/getting-started/quickstart)** | Your first conversation and key features to try |
|
||||
| 🗺️ **[Learning Path](/docs/getting-started/learning-path)** | Find the right docs for your experience level |
|
||||
| ⚙️ **[Configuration](/docs/user-guide/configuration)** | Config file, providers, models, and options |
|
||||
| 💬 **[Messaging Gateway](/docs/user-guide/messaging)** | Set up Telegram, Discord, Slack, WhatsApp, Teams, or more |
|
||||
| 🔧 **[Tools & Toolsets](/docs/user-guide/features/tools)** | 70+ built-in tools and how to configure them |
|
||||
| 🧠 **[Memory System](/docs/user-guide/features/memory)** | Persistent memory that grows across sessions |
|
||||
| 📚 **[Skills System](/docs/user-guide/features/skills)** | Procedural memory the agent creates and reuses |
|
||||
| 🔌 **[MCP Integration](/docs/user-guide/features/mcp)** | Connect to MCP servers, filter their tools, and extend Hermes safely |
|
||||
| 🧭 **[Use MCP with Hermes](/docs/guides/use-mcp-with-hermes)** | Practical MCP setup patterns, examples, and tutorials |
|
||||
| 🎙️ **[Voice Mode](/docs/user-guide/features/voice-mode)** | Real-time voice interaction in CLI, Telegram, Discord, and Discord VC |
|
||||
| 🗣️ **[Use Voice Mode with Hermes](/docs/guides/use-voice-mode-with-hermes)** | Hands-on setup and usage patterns for Hermes voice workflows |
|
||||
| 🎭 **[Personality & SOUL.md](/docs/user-guide/features/personality)** | Define Hermes' default voice with a global SOUL.md |
|
||||
| 📄 **[Context Files](/docs/user-guide/features/context-files)** | Project context files that shape every conversation |
|
||||
| 🔒 **[Security](/docs/user-guide/security)** | Command approval, authorization, container isolation |
|
||||
| 💡 **[Tips & Best Practices](/docs/guides/tips)** | Quick wins to get the most out of Hermes |
|
||||
| 🏗️ **[Architecture](/docs/developer-guide/architecture)** | How it works under the hood |
|
||||
| ❓ **[FAQ & Troubleshooting](/docs/reference/faq)** | Common questions and solutions |
|
||||
|
||||
## Key Features
|
||||
|
||||
- **A closed learning loop** — Agent-curated memory with periodic nudges, autonomous skill creation, skill self-improvement during use, FTS5 cross-session recall with LLM summarization, and [Honcho](https://github.com/plastic-labs/honcho) dialectic user modeling
|
||||
- **Runs anywhere, not just your laptop** — 6 terminal backends: local, Docker, SSH, Daytona, Singularity, Modal. Daytona and Modal offer serverless persistence — your environment hibernates when idle, costing nearly nothing
|
||||
- **Lives where you do** — CLI, Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Mattermost, Email, SMS, DingTalk, Feishu, WeCom, Weixin, QQ Bot, Yuanbao, BlueBubbles, Home Assistant, Microsoft Teams, Google Chat, and more — 20+ platforms from one gateway
|
||||
- **Built by model trainers** — Created by [Nous Research](https://nousresearch.com), the lab behind Hermes, Nomos, and Psyche. Works with [Nous Portal](https://portal.nousresearch.com), [OpenRouter](https://openrouter.ai), OpenAI, or any endpoint
|
||||
- **Scheduled automations** — Built-in cron with delivery to any platform
|
||||
- **Delegates & parallelizes** — Spawn isolated subagents for parallel workstreams. Programmatic Tool Calling via `execute_code` collapses multi-step pipelines into single inference calls
|
||||
- **Open standard skills** — Compatible with [agentskills.io](https://agentskills.io). Skills are portable, shareable, and community-contributed via the Skills Hub
|
||||
- **Full web control** — Search, extract, browse, vision, image generation, TTS
|
||||
- **MCP support** — Connect to any MCP server for extended tool capabilities
|
||||
- **Research-ready** — Batch processing, trajectory export, RL training with Atropos. Built by [Nous Research](https://nousresearch.com) — the lab behind Hermes, Nomos, and Psyche models
|
||||
|
||||
## For LLMs and coding agents
|
||||
|
||||
Machine-readable entry points to this documentation:
|
||||
|
||||
- **[`/llms.txt`](/llms.txt)** — curated index of every doc page with short descriptions. ~17 KB, safe to load into an LLM context.
|
||||
- **[`/llms-full.txt`](/llms-full.txt)** — every doc page concatenated into a single markdown file for one-shot ingestion. ~1.8 MB.
|
||||
|
||||
Both files also resolve at `/docs/llms.txt` and `/docs/llms-full.txt`. Generated fresh on every deploy.
|
||||
141
website/docs/index.mdx
Normal file
141
website/docs/index.mdx
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
---
|
||||
slug: /
|
||||
sidebar_position: 0
|
||||
title: "Hermes Agent Documentation"
|
||||
description: "The self-improving AI agent built by Nous Research. A built-in learning loop that creates skills from experience, improves them during use, and remembers across sessions."
|
||||
hide_table_of_contents: true
|
||||
displayed_sidebar: docs
|
||||
---
|
||||
|
||||
import Link from "@docusaurus/Link";
|
||||
|
||||
# Hermes Agent
|
||||
|
||||
The self-improving AI agent built by [Nous Research](https://nousresearch.com). The only agent with a built-in learning loop — it creates skills from experience, improves them during use, nudges itself to persist knowledge, and builds a deepening model of who you are across sessions.
|
||||
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
gap: "1rem",
|
||||
marginBottom: "2rem",
|
||||
flexWrap: "wrap",
|
||||
}}
|
||||
>
|
||||
<Link
|
||||
to="/getting-started/installation"
|
||||
style={{
|
||||
display: "inline-block",
|
||||
padding: "0.6rem 1.2rem",
|
||||
backgroundColor: "#FFD700",
|
||||
color: "#07070d",
|
||||
borderRadius: "8px",
|
||||
fontWeight: 600,
|
||||
textDecoration: "none",
|
||||
}}
|
||||
>
|
||||
Get Started →
|
||||
</Link>
|
||||
<a
|
||||
href="https://hermes-agent.nousresearch.com/desktop"
|
||||
style={{
|
||||
display: "inline-block",
|
||||
padding: "0.6rem 1.2rem",
|
||||
border: "1px solid rgba(255,215,0,0.2)",
|
||||
borderRadius: "8px",
|
||||
textDecoration: "none",
|
||||
}}
|
||||
>
|
||||
Download Desktop
|
||||
</a>
|
||||
<a
|
||||
href="https://github.com/NousResearch/hermes-agent"
|
||||
style={{
|
||||
display: "inline-block",
|
||||
padding: "0.6rem 1.2rem",
|
||||
border: "1px solid rgba(255,215,0,0.2)",
|
||||
borderRadius: "8px",
|
||||
textDecoration: "none",
|
||||
}}
|
||||
>
|
||||
View on GitHub
|
||||
</a>
|
||||
</div>
|
||||
|
||||
## Install
|
||||
|
||||
### Windows or macOS
|
||||
|
||||
To easily install the command-line and desktop applications, [download the Hermes Desktop installer](https://hermes-agent.nousresearch.com/desktop) from our website and run it.
|
||||
|
||||
### Without Hermes Desktop:
|
||||
|
||||
For a command-line only install without Hermes Desktop, run:
|
||||
|
||||
#### Linux / macOS / WSL2 / Android (Termux)
|
||||
|
||||
```bash
|
||||
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash
|
||||
```
|
||||
|
||||
#### Windows (native)
|
||||
|
||||
Run in powershell:
|
||||
|
||||
```powershell
|
||||
iex (irm https://hermes-agent.nousresearch.com/install.ps1)
|
||||
```
|
||||
|
||||
See the full **[Installation Guide](/getting-started/installation)** for what the installer does, the per-user vs root layout, and Windows-specific notes.
|
||||
|
||||
:::tip Fastest path to a working agent
|
||||
After installing, run `hermes setup --portal` — one OAuth covers a model plus all four Tool Gateway tools (web search, image generation, TTS, browser). See [Nous Portal](/integrations/nous-portal).
|
||||
:::
|
||||
|
||||
## What is Hermes Agent?
|
||||
|
||||
It's not a coding copilot tethered to an IDE or a chatbot wrapper around a single API. It's an **autonomous agent** that gets more capable the longer it runs. It lives wherever you put it — a $5 VPS, a GPU cluster, or serverless infrastructure (Daytona, Modal) that costs nearly nothing when idle. Talk to it from Telegram while it works on a cloud VM you never SSH into yourself. It's not tied to your laptop.
|
||||
|
||||
## Quick Links
|
||||
|
||||
| | |
|
||||
| ----------------------------------------------------------------------- | --------------------------------------------------------------------- |
|
||||
| 🚀 **[Installation](/getting-started/installation)** | Install in 60 seconds on Linux, macOS, WSL2, or native Windows |
|
||||
| 📖 **[Quickstart Tutorial](/getting-started/quickstart)** | Your first conversation and key features to try |
|
||||
| 🗺️ **[Learning Path](/getting-started/learning-path)** | Find the right docs for your experience level |
|
||||
| ⚙️ **[Configuration](/user-guide/configuration)** | Config file, providers, models, and options |
|
||||
| 💬 **[Messaging Gateway](/user-guide/messaging)** | Set up Telegram, Discord, Slack, WhatsApp, Teams, or more |
|
||||
| 🔧 **[Tools & Toolsets](/user-guide/features/tools)** | 60+ built-in tools and how to configure them |
|
||||
| 🧠 **[Memory System](/user-guide/features/memory)** | Persistent memory that grows across sessions |
|
||||
| 📚 **[Skills System](/user-guide/features/skills)** | Procedural memory the agent creates and reuses |
|
||||
| 🔌 **[MCP Integration](/user-guide/features/mcp)** | Connect to MCP servers, filter their tools, and extend Hermes safely |
|
||||
| 🧭 **[Use MCP with Hermes](/guides/use-mcp-with-hermes)** | Practical MCP setup patterns, examples, and tutorials |
|
||||
| 🎙️ **[Voice Mode](/user-guide/features/voice-mode)** | Real-time voice interaction in CLI, Telegram, Discord, and Discord VC |
|
||||
| 🗣️ **[Use Voice Mode with Hermes](/guides/use-voice-mode-with-hermes)** | Hands-on setup and usage patterns for Hermes voice workflows |
|
||||
| 🎭 **[Personality & SOUL.md](/user-guide/features/personality)** | Define Hermes' default voice with a global SOUL.md |
|
||||
| 📄 **[Context Files](/user-guide/features/context-files)** | Project context files that shape every conversation |
|
||||
| 🔒 **[Security](/user-guide/security)** | Command approval, authorization, container isolation |
|
||||
| 💡 **[Tips & Best Practices](/guides/tips)** | Quick wins to get the most out of Hermes |
|
||||
| 🏗️ **[Architecture](/developer-guide/architecture)** | How it works under the hood |
|
||||
| ❓ **[FAQ & Troubleshooting](/reference/faq)** | Common questions and solutions |
|
||||
|
||||
## Key Features
|
||||
|
||||
- **A closed learning loop** — Agent-curated memory with periodic nudges, autonomous skill creation, skill self-improvement during use, FTS5 cross-session recall with LLM summarization, and [Honcho](https://github.com/plastic-labs/honcho) dialectic user modeling
|
||||
- **Runs anywhere, not just your laptop** — 6 terminal backends: local, Docker, SSH, Daytona, Singularity, Modal. Daytona and Modal offer serverless persistence — your environment hibernates when idle, costing nearly nothing
|
||||
- **Lives where you do** — CLI, Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Mattermost, Email, SMS, DingTalk, Feishu, WeCom, Weixin, QQ Bot, Yuanbao, BlueBubbles, Home Assistant, Microsoft Teams, Google Chat, and more — 20+ platforms from one gateway
|
||||
- **Built by model trainers** — Created by [Nous Research](https://nousresearch.com), the lab behind Hermes, Nomos, and Psyche. Works with [Nous Portal](https://portal.nousresearch.com), [OpenRouter](https://openrouter.ai), OpenAI, or any endpoint
|
||||
- **Scheduled automations** — Built-in cron with delivery to any platform
|
||||
- **Delegates & parallelizes** — Spawn isolated subagents for parallel workstreams. Programmatic Tool Calling via `execute_code` collapses multi-step pipelines into single inference calls
|
||||
- **Open standard skills** — Compatible with [agentskills.io](https://agentskills.io). Skills are portable, shareable, and community-contributed via the Skills Hub
|
||||
- **Full web control** — Search, extract, browse, vision, image generation, TTS — one subscription via [Nous Portal](/integrations/nous-portal) bundles all of them
|
||||
- **MCP support** — Connect to any MCP server for extended tool capabilities
|
||||
- **Research-ready** — Batch processing, trajectory export, RL training with Atropos. Built by [Nous Research](https://nousresearch.com) — the lab behind Hermes, Nomos, and Psyche models
|
||||
|
||||
## For LLMs and coding agents
|
||||
|
||||
Machine-readable entry points to this documentation:
|
||||
|
||||
- **[`/llms.txt`](/llms.txt)** — curated index of every doc page with short descriptions. ~17 KB, safe to load into an LLM context.
|
||||
- **[`/llms-full.txt`](/llms-full.txt)** — every doc page concatenated into a single markdown file for one-shot ingestion. ~1.8 MB.
|
||||
|
||||
Both files also resolve at `/docs/llms.txt` and `/docs/llms-full.txt`. Generated fresh on every deploy.
|
||||
|
|
@ -8,34 +8,42 @@ sidebar_position: 0
|
|||
|
||||
Hermes Agent connects to external systems for AI inference, tool servers, IDE workflows, programmatic access, and more. These integrations extend what Hermes can do and where it can run.
|
||||
|
||||
:::tip Start here
|
||||
If you only have time to set up one integration, set up [Nous Portal](/integrations/nous-portal) — a single OAuth login covers 300+ models plus the four Tool Gateway tools (web search, image generation, TTS, and browser automation).
|
||||
:::
|
||||
|
||||
## AI Providers & Routing
|
||||
|
||||
Hermes supports multiple AI inference providers out of the box. Use `hermes model` to configure interactively, or set them in `config.yaml`.
|
||||
|
||||
- **[AI Providers](/docs/user-guide/features/provider-routing)** — OpenRouter, Anthropic, OpenAI, Google, and any OpenAI-compatible endpoint. Hermes auto-detects capabilities like vision, streaming, and tool use per provider.
|
||||
- **[Provider Routing](/docs/user-guide/features/provider-routing)** — Fine-grained control over which underlying providers handle your OpenRouter requests. Optimize for cost, speed, or quality with sorting, whitelists, blacklists, and explicit priority ordering.
|
||||
- **[Fallback Providers](/docs/user-guide/features/fallback-providers)** — Automatic failover to backup LLM providers when your primary model encounters errors. Includes primary model fallback and independent auxiliary task fallback for vision, compression, and web extraction.
|
||||
- **[AI Providers](/user-guide/features/provider-routing)** — OpenRouter, Anthropic, OpenAI, Google, and any OpenAI-compatible endpoint. Hermes auto-detects capabilities like vision, streaming, and tool use per provider.
|
||||
- **[Provider Routing](/user-guide/features/provider-routing)** — Fine-grained control over which underlying providers handle your OpenRouter requests. Optimize for cost, speed, or quality with sorting, whitelists, blacklists, and explicit priority ordering.
|
||||
- **[Fallback Providers](/user-guide/features/fallback-providers)** — Automatic failover to backup LLM providers when your primary model encounters errors. Includes primary model fallback and independent auxiliary task fallback for vision, compression, and web extraction.
|
||||
|
||||
## Tool Servers (MCP)
|
||||
|
||||
- **[MCP Servers](/docs/user-guide/features/mcp)** — Connect Hermes to external tool servers via Model Context Protocol. Access tools from GitHub, databases, file systems, browser stacks, internal APIs, and more without writing native Hermes tools. Supports both stdio and SSE transports, per-server tool filtering, and capability-aware resource/prompt registration.
|
||||
- **[MCP Servers](/user-guide/features/mcp)** — Connect Hermes to external tool servers via Model Context Protocol. Access tools from GitHub, databases, file systems, browser stacks, internal APIs, and more without writing native Hermes tools. Supports both stdio and SSE transports, per-server tool filtering, and capability-aware resource/prompt registration.
|
||||
|
||||
## Web Search Backends
|
||||
|
||||
The `web_search` and `web_extract` tools support four backend providers, configured via `config.yaml` or `hermes tools`:
|
||||
The `web_search` and `web_extract` tools support eight backend providers, configured via `config.yaml` or `hermes tools`:
|
||||
|
||||
| Backend | Env Var | Search | Extract | Crawl |
|
||||
|---------|---------|--------|---------|-------|
|
||||
| **Firecrawl** (default) | `FIRECRAWL_API_KEY` | ✔ | ✔ | ✔ |
|
||||
| **Parallel** | `PARALLEL_API_KEY` | ✔ | ✔ | — |
|
||||
| **SearXNG** | `SEARXNG_URL` | ✔ | — | — |
|
||||
| **Brave** (free tier) | `BRAVE_SEARCH_API_KEY` | ✔ | — | — |
|
||||
| **DuckDuckGo** (ddgs) | _(none)_ | ✔ | — | — |
|
||||
| **Tavily** | `TAVILY_API_KEY` | ✔ | ✔ | ✔ |
|
||||
| **Exa** | `EXA_API_KEY` | ✔ | ✔ | — |
|
||||
| **Parallel** | `PARALLEL_API_KEY` | ✔ | ✔ | — |
|
||||
| **xAI** | `XAI_API_KEY` | ✔ | — | — |
|
||||
|
||||
Quick setup example:
|
||||
|
||||
```yaml
|
||||
web:
|
||||
backend: firecrawl # firecrawl | parallel | tavily | exa
|
||||
backend: firecrawl # firecrawl | searxng | brave-free | ddgs | tavily | exa | parallel | xai
|
||||
```
|
||||
|
||||
If `web.backend` is not set, the backend is auto-detected from whichever API key is available. Self-hosted Firecrawl is also supported via `FIRECRAWL_API_URL`.
|
||||
|
|
@ -49,7 +57,7 @@ Hermes includes full browser automation with multiple backend options for naviga
|
|||
- **Local Chromium-family CDP** — Connect to your running Chrome, Brave, Chromium, or Edge browser using `/browser connect`
|
||||
- **Local Chromium** — Headless local browser via the `agent-browser` CLI
|
||||
|
||||
See [Browser Automation](/docs/user-guide/features/browser) for setup and usage.
|
||||
See [Browser Automation](/user-guide/features/browser) for setup and usage.
|
||||
|
||||
## Voice & TTS Providers
|
||||
|
||||
|
|
@ -61,40 +69,41 @@ Text-to-speech and speech-to-text across all messaging platforms:
|
|||
| **ElevenLabs** | Excellent | Paid | `ELEVENLABS_API_KEY` |
|
||||
| **OpenAI TTS** | Good | Paid | `VOICE_TOOLS_OPENAI_KEY` |
|
||||
| **MiniMax** | Good | Paid | `MINIMAX_API_KEY` |
|
||||
| **xAI TTS** | Good | Paid | `XAI_API_KEY` |
|
||||
| **NeuTTS** | Good | Free | None needed |
|
||||
|
||||
Speech-to-text supports six providers: local faster-whisper (free, runs on-device), a local command wrapper, Groq, OpenAI Whisper API, Mistral, and xAI. Voice message transcription works across Telegram, Discord, WhatsApp, and other messaging platforms. See [Voice & TTS](/docs/user-guide/features/tts) and [Voice Mode](/docs/user-guide/features/voice-mode) for details.
|
||||
Speech-to-text supports six providers: local faster-whisper (free, runs on-device), a local command wrapper, Groq, OpenAI Whisper API, Mistral, and xAI. Voice message transcription works across Telegram, Discord, WhatsApp, and other messaging platforms. See [Voice & TTS](/user-guide/features/tts) and [Voice Mode](/user-guide/features/voice-mode) for details.
|
||||
|
||||
## IDE & Editor Integration
|
||||
|
||||
- **[IDE Integration (ACP)](/docs/user-guide/features/acp)** — Use Hermes Agent inside ACP-compatible editors such as VS Code, Zed, and JetBrains. Hermes runs as an ACP server, rendering chat messages, tool activity, file diffs, and terminal commands inside your editor.
|
||||
- **[IDE Integration (ACP)](/user-guide/features/acp)** — Use Hermes Agent inside ACP-compatible editors such as VS Code, Zed, and JetBrains. Hermes runs as an ACP server, rendering chat messages, tool activity, file diffs, and terminal commands inside your editor.
|
||||
|
||||
## Programmatic Access
|
||||
|
||||
- **[API Server](/docs/user-guide/features/api-server)** — Expose Hermes as an OpenAI-compatible HTTP endpoint. Any frontend that speaks the OpenAI format — Open WebUI, LobeChat, LibreChat, NextChat, ChatBox — can connect and use Hermes as a backend with its full toolset.
|
||||
- **[API Server](/user-guide/features/api-server)** — Expose Hermes as an OpenAI-compatible HTTP endpoint. Any frontend that speaks the OpenAI format — Open WebUI, LobeChat, LibreChat, NextChat, ChatBox — can connect and use Hermes as a backend with its full toolset.
|
||||
|
||||
## Memory & Personalization
|
||||
|
||||
- **[Built-in Memory](/docs/user-guide/features/memory)** — Persistent, curated memory via `MEMORY.md` and `USER.md` files. The agent maintains bounded stores of personal notes and user profile data that survive across sessions.
|
||||
- **[Memory Providers](/docs/user-guide/features/memory-providers)** — Plug in external memory backends for deeper personalization. Eight providers are supported: Honcho (dialectic reasoning), OpenViking (tiered retrieval), Mem0 (cloud extraction), Hindsight (knowledge graphs), Holographic (local SQLite), RetainDB (hybrid search), ByteRover (CLI-based), and Supermemory.
|
||||
- **[Built-in Memory](/user-guide/features/memory)** — Persistent, curated memory via `MEMORY.md` and `USER.md` files. The agent maintains bounded stores of personal notes and user profile data that survive across sessions.
|
||||
- **[Memory Providers](/user-guide/features/memory-providers)** — Plug in external memory backends for deeper personalization. Eight providers are supported: Honcho (dialectic reasoning), OpenViking (tiered retrieval), Mem0 (cloud extraction), Hindsight (knowledge graphs), Holographic (local SQLite), RetainDB (hybrid search), ByteRover (CLI-based), and Supermemory.
|
||||
|
||||
## Messaging Platforms
|
||||
|
||||
Hermes runs as a gateway bot on 19+ messaging platforms, all configured through the same `gateway` subsystem:
|
||||
Hermes runs as a gateway bot on 27+ messaging platforms, all configured through the same `gateway` subsystem:
|
||||
|
||||
- **[Telegram](/docs/user-guide/messaging/telegram)**, **[Discord](/docs/user-guide/messaging/discord)**, **[Slack](/docs/user-guide/messaging/slack)**, **[WhatsApp](/docs/user-guide/messaging/whatsapp)**, **[Signal](/docs/user-guide/messaging/signal)**, **[Matrix](/docs/user-guide/messaging/matrix)**, **[Mattermost](/docs/user-guide/messaging/mattermost)**, **[Email](/docs/user-guide/messaging/email)**, **[SMS](/docs/user-guide/messaging/sms)**, **[DingTalk](/docs/user-guide/messaging/dingtalk)**, **[Feishu/Lark](/docs/user-guide/messaging/feishu)**, **[WeCom](/docs/user-guide/messaging/wecom)**, **[WeCom Callback](/docs/user-guide/messaging/wecom-callback)**, **[Weixin](/docs/user-guide/messaging/weixin)**, **[BlueBubbles](/docs/user-guide/messaging/bluebubbles)**, **[QQ Bot](/docs/user-guide/messaging/qqbot)**, **[Yuanbao](/docs/user-guide/messaging/yuanbao)**, **[Home Assistant](/docs/user-guide/messaging/homeassistant)**, **[Microsoft Teams](/docs/user-guide/messaging/teams)**, **[Webhooks](/docs/user-guide/messaging/webhooks)**
|
||||
- **[Telegram](/user-guide/messaging/telegram)**, **[Discord](/user-guide/messaging/discord)**, **[Slack](/user-guide/messaging/slack)**, **[WhatsApp](/user-guide/messaging/whatsapp)**, **[Signal](/user-guide/messaging/signal)**, **[Matrix](/user-guide/messaging/matrix)**, **[Mattermost](/user-guide/messaging/mattermost)**, **[Email](/user-guide/messaging/email)**, **[SMS](/user-guide/messaging/sms)**, **[DingTalk](/user-guide/messaging/dingtalk)**, **[Feishu/Lark](/user-guide/messaging/feishu)**, **[WeCom](/user-guide/messaging/wecom)**, **[WeCom Callback](/user-guide/messaging/wecom-callback)**, **[Weixin](/user-guide/messaging/weixin)**, **[BlueBubbles](/user-guide/messaging/bluebubbles)**, **[QQ Bot](/user-guide/messaging/qqbot)**, **[Yuanbao](/user-guide/messaging/yuanbao)**, **[Home Assistant](/user-guide/messaging/homeassistant)**, **[Microsoft Teams](/user-guide/messaging/teams)**, **[Microsoft Teams Meetings](/user-guide/messaging/teams-meetings)**, **[Microsoft Graph Webhook](/user-guide/messaging/msgraph-webhook)**, **[Google Chat](/user-guide/messaging/google_chat)**, **[LINE](/user-guide/messaging/line)**, **[ntfy](/user-guide/messaging/ntfy)**, **[SimpleX](/user-guide/messaging/simplex)**, **[Open WebUI](/user-guide/messaging/open-webui)**, **[Webhooks](/user-guide/messaging/webhooks)**
|
||||
|
||||
See the [Messaging Gateway overview](/docs/user-guide/messaging) for the platform comparison table and setup guide.
|
||||
See the [Messaging Gateway overview](/user-guide/messaging) for the platform comparison table and setup guide.
|
||||
|
||||
## Home Automation
|
||||
|
||||
- **[Home Assistant](/docs/user-guide/messaging/homeassistant)** — Control smart home devices via four dedicated tools (`ha_list_entities`, `ha_get_state`, `ha_list_services`, `ha_call_service`). The Home Assistant toolset activates automatically when `HASS_TOKEN` is configured.
|
||||
- **[Home Assistant](/user-guide/messaging/homeassistant)** — Control smart home devices via four dedicated tools (`ha_list_entities`, `ha_get_state`, `ha_list_services`, `ha_call_service`). The Home Assistant toolset activates automatically when `HASS_TOKEN` is configured.
|
||||
|
||||
## Plugins
|
||||
|
||||
- **[Plugin System](/docs/user-guide/features/plugins)** — Extend Hermes with custom tools, lifecycle hooks, and CLI commands without modifying core code. Plugins are discovered from `~/.hermes/plugins/`, project-local `.hermes/plugins/`, and pip-installed entry points.
|
||||
- **[Build a Plugin](/docs/guides/build-a-hermes-plugin)** — Step-by-step guide for creating Hermes plugins with tools, hooks, and CLI commands.
|
||||
- **[Plugin System](/user-guide/features/plugins)** — Extend Hermes with custom tools, lifecycle hooks, and CLI commands without modifying core code. Plugins are discovered from `~/.hermes/plugins/`, project-local `.hermes/plugins/`, and pip-installed entry points.
|
||||
- **[Build a Plugin](/guides/build-a-hermes-plugin)** — Step-by-step guide for creating Hermes plugins with tools, hooks, and CLI commands.
|
||||
|
||||
## Training & Evaluation
|
||||
|
||||
- **[Batch Processing](/docs/user-guide/features/batch-processing)** — Run the agent across hundreds of prompts in parallel, generating structured ShareGPT-format trajectory data for training data generation or evaluation.
|
||||
- **[Batch Processing](/user-guide/features/batch-processing)** — Run the agent across hundreds of prompts in parallel, generating structured ShareGPT-format trajectory data for training data generation or evaluation.
|
||||
|
|
|
|||
277
website/docs/integrations/nous-portal.md
Normal file
277
website/docs/integrations/nous-portal.md
Normal file
|
|
@ -0,0 +1,277 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
title: "Nous Portal"
|
||||
description: "One subscription, 300+ frontier models, the Tool Gateway, and Nous Chat — the recommended way to run Hermes Agent"
|
||||
---
|
||||
|
||||
# Nous Portal
|
||||
|
||||
[Nous Portal](https://portal.nousresearch.com) is Nous Research's unified subscription gateway and **the recommended way to run Hermes Agent**. One OAuth login replaces the juggling act of separate accounts, API keys, and billing relationships across every model lab, search API, image generator, and browser provider you'd otherwise need to wire up by hand.
|
||||
|
||||
If you only have time to set up one thing, set up this. The fastest path:
|
||||
|
||||
```bash
|
||||
hermes setup --portal
|
||||
```
|
||||
|
||||
That single command runs the Portal OAuth, lets you pick a Nous model, sets Nous as your inference provider in `config.yaml`, and turns on the Tool Gateway. You're ready to `hermes chat` immediately after.
|
||||
|
||||
Don't have a subscription yet? [portal.nousresearch.com/manage-subscription](https://portal.nousresearch.com/manage-subscription) — sign up, then come back and run the command above.
|
||||
|
||||
## What's in the subscription
|
||||
|
||||
### 300+ frontier models, one bill
|
||||
|
||||
The Portal proxies a curated catalog of agentic models from across the ecosystem — billed against your Nous subscription instead of one credit balance per lab.
|
||||
|
||||
| Family | Models |
|
||||
|--------|--------|
|
||||
| **Anthropic Claude** | Opus 4.7, Opus 4.6, Sonnet 4.6, Haiku 4.5 |
|
||||
| **OpenAI** | GPT-5.5, GPT-5.5 Pro, GPT-5.4 Mini, GPT-5.4 Nano, GPT-5.3 Codex |
|
||||
| **Google Gemini** | Gemini 3 Pro Preview, Gemini 3 Flash Preview, Gemini 3.1 Pro Preview, Gemini 3.1 Flash Lite Preview |
|
||||
| **DeepSeek** | DeepSeek V4 Pro |
|
||||
| **Qwen** | Qwen3.7-Max, Qwen3.6-35B-A3B |
|
||||
| **Kimi / Moonshot** | Kimi K2.6 |
|
||||
| **GLM / Zhipu** | GLM-5.1 |
|
||||
| **MiniMax** | MiniMax M2.7 |
|
||||
| **xAI** | Grok 4.3 |
|
||||
| **NVIDIA** | Nemotron-3 Super 120B-A12B |
|
||||
| **Tencent** | Hunyuan 3 Preview |
|
||||
| **Xiaomi** | MiMo V2.5 Pro |
|
||||
| **StepFun** | Step 3.5 Flash |
|
||||
| **Hermes** | Hermes-4-70B, Hermes-4-405B (chat, see [note below](#a-note-on-hermes-4)) |
|
||||
| **+ everything else** | 280+ additional models — the full agentic frontier |
|
||||
|
||||
Routing happens through OpenRouter under the hood, so model availability and failover behavior matches what you'd get with an OpenRouter key — just billed against your Nous subscription instead. Switch between Claude Sonnet 4.6 for code and Gemini 3 Pro for long context with `/model` mid-session — no new credentials, no top-ups, no surprise zero-balance errors.
|
||||
|
||||
### The Nous Tool Gateway
|
||||
|
||||
The same subscription unlocks the [Tool Gateway](/user-guide/features/tool-gateway), which routes Hermes Agent's tool calls through Nous-managed infrastructure. Five backends, one login:
|
||||
|
||||
| Tool | Partner | What it does |
|
||||
|------|---------|--------------|
|
||||
| **Web search & extract** | Firecrawl | Agent-grade search and full-page extraction. No Firecrawl API key, no rate limit babysitting. |
|
||||
| **Image generation** | FAL | Nine models under one endpoint: FLUX 2 Klein 9B, FLUX 2 Pro, Z-Image Turbo, Nano Banana Pro (Gemini 3 Pro Image), GPT Image 1.5, GPT Image 2, Ideogram V3, Recraft V4 Pro, Qwen Image. |
|
||||
| **Text-to-speech** | OpenAI TTS | High-quality TTS without a separate OpenAI key. Enables [voice mode](/user-guide/features/voice-mode) across messaging platforms. |
|
||||
| **Cloud browser automation** | Browser Use | Headless Chromium sessions for `browser_navigate`, `browser_click`, `browser_type`, `browser_vision`. No Browserbase account needed. |
|
||||
| **Cloud terminal sandbox** | Modal | Serverless terminal sandboxes for code execution (optional add-on). |
|
||||
|
||||
Without the gateway, hooking each of those up means a Firecrawl account, a FAL account, a Browser Use account, an OpenAI key, and a Modal account — five separate signups, five separate dashboards, five separate top-up flows. With the gateway, all of it routes through one subscription.
|
||||
|
||||
You can also enable just specific gateway tools (e.g. web search but not image generation) — see [Mixing the gateway with your own backends](#mixing-the-gateway-with-your-own-backends) below.
|
||||
|
||||
### Nous Chat
|
||||
|
||||
Your Portal account also covers [chat.nousresearch.com](https://chat.nousresearch.com) — Nous Research's web chat interface with the same model catalog. Useful when you're away from your terminal, or for non-agent conversation work.
|
||||
|
||||
### No credentials in your dotfiles
|
||||
|
||||
Because everything routes through one OAuth-authenticated Portal session, you don't accumulate a `.env` file with a dozen long-lived API keys. The refresh token at `~/.hermes/auth.json` is the only credential on disk, and Hermes mints short-lived JWTs from it per request — see [Token handling](#token-handling) below.
|
||||
|
||||
### Cross-platform parity
|
||||
|
||||
[Native Windows](/user-guide/windows-native) makes per-tool API key setup its rough edge — installing a Firecrawl account, a FAL account, a Browser Use account, an OpenAI key from Windows is the highest-friction part of getting a useful agent. A Portal subscription smooths that out: one OAuth covers the model and every gateway tool, so Windows users get the same experience as macOS/Linux without manually configuring four backends.
|
||||
|
||||
## A note on Hermes 4
|
||||
|
||||
Nous Research's own **Hermes 4** family (Hermes-4-70B, Hermes-4-405B) is available through the Portal at heavily discounted rates. These are **frontier hybrid-reasoning chat models** — strong at math, science, instruction following, schema adherence, roleplay, and long-form writing.
|
||||
|
||||
They are **not recommended for use inside Hermes Agent**, however. Hermes 4 is tuned for chat and reasoning, not the rapid-fire tool-calling loop the agent relies on. Use them for [Nous Chat](https://chat.nousresearch.com), for research workflows, or via the [subscription proxy](/user-guide/features/subscription-proxy) from other tooling — but for agent work, pick a frontier agentic model from the catalog instead:
|
||||
|
||||
```bash
|
||||
/model anthropic/claude-sonnet-4.6 # best general-purpose agentic model
|
||||
/model openai/gpt-5.5-pro # strong reasoning + tool calling
|
||||
/model google/gemini-3-pro-preview # huge context window
|
||||
/model deepseek/deepseek-v4-pro # cost-effective coder
|
||||
```
|
||||
|
||||
The Portal's own [model info page](https://portal.nousresearch.com/info) carries the same warning, so this isn't a Hermes-side opinion — it's the official guidance from Nous Research.
|
||||
|
||||
## Setup
|
||||
|
||||
### Fresh install — one command
|
||||
|
||||
```bash
|
||||
hermes setup --portal
|
||||
```
|
||||
|
||||
This runs the full setup in one shot:
|
||||
|
||||
1. Opens your browser to portal.nousresearch.com for OAuth login
|
||||
2. Stores the refresh token at `~/.hermes/auth.json`
|
||||
3. Lets you pick a Nous model from the curated list (or skip to keep your current one)
|
||||
4. Sets Nous as your inference provider in `~/.hermes/config.yaml` (when you pick a model)
|
||||
5. Turns on the Tool Gateway (web, image, TTS, browser routing)
|
||||
6. Returns you to your terminal ready to `hermes chat`
|
||||
|
||||
If you don't have a subscription yet, sign up at [portal.nousresearch.com/manage-subscription](https://portal.nousresearch.com/manage-subscription) first.
|
||||
|
||||
### Existing install — add Portal alongside other providers
|
||||
|
||||
If you already have Hermes configured with OpenRouter, Anthropic, or any other provider and you want to add the Portal alongside them:
|
||||
|
||||
```bash
|
||||
hermes model
|
||||
# pick "Nous Portal" from the provider list
|
||||
# browser opens, sign in, done
|
||||
```
|
||||
|
||||
Your existing providers stay configured. You can switch between them with `/model` mid-session or `hermes model` between sessions — the Portal becomes one of your available providers, not your only one.
|
||||
|
||||
### Headless / SSH / remote setup
|
||||
|
||||
OAuth needs a browser, but the loopback callback runs on the machine where Hermes is running. For remote hosts, see [OAuth over SSH / Remote Hosts](/guides/oauth-over-ssh) — the same patterns work for the Portal as for any other OAuth-based provider (`ssh -L` port forwarding, `--manual-paste` for browser-only environments like Cloud Shell / Codespaces).
|
||||
|
||||
### Profile setup
|
||||
|
||||
If you use [Hermes profiles](/user-guide/profiles), the Portal refresh token is automatically shared across all profiles via a shared token store. Sign in once on any profile, and the rest pick it up automatically — no need to repeat the OAuth flow per profile.
|
||||
|
||||
## Using the Portal day-to-day
|
||||
|
||||
### Inspecting what's wired up
|
||||
|
||||
```bash
|
||||
hermes portal # log in to Nous Portal + set it up (one-shot onboarding)
|
||||
hermes portal info # login status, subscription info, model + gateway routing
|
||||
hermes portal status # alias for `portal info`
|
||||
hermes portal tools # detailed Tool Gateway catalog with per-tool routing
|
||||
hermes portal open # open the subscription management page in your browser
|
||||
```
|
||||
|
||||
`hermes portal` (with no subcommand) is the human-readable alias for `hermes auth add nous --type oauth` — it logs you in, lets you pick a Nous model, sets Nous as your inference provider, and offers the Tool Gateway opt-in (identical to `hermes setup --portal`, and the same Nous flow as the first-time quick setup).
|
||||
|
||||
`hermes portal info` gives you the high-level overview:
|
||||
|
||||
```
|
||||
Nous Portal
|
||||
───────────
|
||||
Auth: ✓ logged in
|
||||
Portal: https://portal.nousresearch.com
|
||||
Model: ✓ using Nous as inference provider
|
||||
|
||||
Tool Gateway
|
||||
────────────
|
||||
Web search & extract via Nous Portal
|
||||
Image generation via Nous Portal
|
||||
Text-to-speech via Nous Portal
|
||||
Browser automation via Nous Portal
|
||||
Cloud terminal not configured
|
||||
```
|
||||
|
||||
### Switching models
|
||||
|
||||
Inside a session:
|
||||
|
||||
```bash
|
||||
/model anthropic/claude-sonnet-4.6
|
||||
/model openai/gpt-5.5-pro
|
||||
/model google/gemini-3-pro-preview
|
||||
```
|
||||
|
||||
Or open the picker:
|
||||
|
||||
```bash
|
||||
/model
|
||||
# arrow keys, enter to select
|
||||
```
|
||||
|
||||
Outside a session (the full setup wizard, useful when adding a new provider):
|
||||
|
||||
```bash
|
||||
hermes model
|
||||
```
|
||||
|
||||
### Mixing the gateway with your own backends
|
||||
|
||||
If you already have, say, a Browserbase account and want to keep using it while routing web search and image generation through Nous, that's supported. Use `hermes tools` to pick backends per tool:
|
||||
|
||||
```bash
|
||||
hermes tools
|
||||
# → Web search → "Nous Subscription"
|
||||
# → Image generation → "Nous Subscription"
|
||||
# → Browser → "Browserbase" (your existing key)
|
||||
# → TTS → "Nous Subscription"
|
||||
```
|
||||
|
||||
The Tool Gateway is opt-in per tool, not all-or-nothing. The managed backends show up in `hermes tools` whether or not you're logged into Nous Portal — if you pick "Nous Subscription" before authenticating, Hermes runs the Portal login inline (it won't change your inference provider or touch your other tools). See the [Tool Gateway docs](/user-guide/features/tool-gateway) for the full per-tool configuration matrix.
|
||||
|
||||
### Subscription management
|
||||
|
||||
Manage your plan, view usage, or upgrade/cancel at any time:
|
||||
|
||||
- **Web:** [portal.nousresearch.com/manage-subscription](https://portal.nousresearch.com/manage-subscription)
|
||||
- **CLI shortcut:** `hermes portal open` (opens the same page in your default browser)
|
||||
|
||||
## Configuration reference
|
||||
|
||||
After `hermes setup --portal`, `~/.hermes/config.yaml` will look like:
|
||||
|
||||
```yaml
|
||||
model:
|
||||
provider: nous
|
||||
default: anthropic/claude-sonnet-4.6 # or whatever model you picked
|
||||
base_url: https://inference-api.nousresearch.com/v1
|
||||
```
|
||||
|
||||
The Tool Gateway settings live under their respective tool sections:
|
||||
|
||||
```yaml
|
||||
web:
|
||||
backend: nous # web search/extract routes through Tool Gateway
|
||||
|
||||
image_gen:
|
||||
provider: nous
|
||||
|
||||
tts:
|
||||
provider: nous
|
||||
|
||||
browser:
|
||||
backend: nous
|
||||
```
|
||||
|
||||
The OAuth refresh token is stored separately at `~/.hermes/auth.json` (not in `config.yaml` — credentials and configuration are kept separate by design).
|
||||
|
||||
## Token handling
|
||||
|
||||
Hermes mints a short-lived JWT from your stored Portal refresh token on each inference call rather than reusing a long-lived API key. The token lifecycle is fully automatic — refresh, mint, retry on transient 401 — and you never see it.
|
||||
|
||||
If the Portal invalidates the refresh token (password change, manual revoke, session expiry), the invalid refresh token is **quarantined locally** so Hermes stops replaying it and you don't see a stream of identical 401s. The next call surfaces a clear "re-authentication required" message. Run `hermes auth add nous` to log in again; the quarantine clears on the next successful login.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### `hermes portal info` shows "not logged in"
|
||||
|
||||
You haven't completed the OAuth flow, or your refresh token was wiped. Run:
|
||||
|
||||
```bash
|
||||
hermes portal
|
||||
```
|
||||
|
||||
or use `hermes model` and re-select Nous Portal.
|
||||
|
||||
### Got a "re-authentication required" message mid-session
|
||||
|
||||
Your Portal refresh token was invalidated (password change, manual revoke, or session expiry). Run `hermes auth add nous` and your next request will use the new credentials. Any quarantine on the old token clears automatically on successful re-login.
|
||||
|
||||
### Want to use a specific provider model that the Portal doesn't expose
|
||||
|
||||
The Portal proxies through OpenRouter, so any model that OpenRouter supports is generally available. If a specific model isn't appearing in `/model`, try the OpenRouter-style slug directly:
|
||||
|
||||
```bash
|
||||
/model anthropic/claude-opus-4.6
|
||||
```
|
||||
|
||||
If a model is genuinely missing, [open an issue](https://github.com/NousResearch/hermes-agent/issues) — we surface the Portal's catalog to Hermes and gaps usually mean a routing config we can update.
|
||||
|
||||
### Bills not appearing on my Portal account
|
||||
|
||||
Check `hermes portal info` first — if it shows you're using a different provider (`Model: currently openrouter` instead of `using Nous as inference provider`), your local config has drifted. Run `hermes model`, pick Nous Portal, and the next request will route through your subscription.
|
||||
|
||||
## See also
|
||||
|
||||
- **[Tool Gateway](/user-guide/features/tool-gateway)** — Full details on every gateway tool, per-tool config, and pricing
|
||||
- **[Subscription proxy](/user-guide/features/subscription-proxy)** — Use your Portal subscription from non-Hermes tools (other agents, scripts, third-party clients)
|
||||
- **[Voice mode](/user-guide/features/voice-mode)** — Voice conversations using the Portal's OpenAI TTS
|
||||
- **[AI Providers](/integrations/providers)** — Full provider catalog if you want to compare alternatives
|
||||
- **[OAuth over SSH](/guides/oauth-over-ssh)** — Login from remote hosts or browser-only environments
|
||||
- **[Profiles](/user-guide/profiles)** — Multiple Hermes configurations sharing one Portal login
|
||||
|
|
@ -21,7 +21,6 @@ You need at least one way to connect to an LLM. Use `hermes model` to switch pro
|
|||
| **Anthropic** | `hermes model` (Claude Max + extra usage credits via OAuth; also supports Anthropic API key or manual setup-token — see note below) |
|
||||
| **OpenRouter** | `OPENROUTER_API_KEY` in `~/.hermes/.env` |
|
||||
| **NovitaAI** | `NOVITA_API_KEY` in `~/.hermes/.env` (provider: `novita`, 200+ models, Model API, Agent Sandbox, GPU Cloud) |
|
||||
| **AI Gateway** | `AI_GATEWAY_API_KEY` in `~/.hermes/.env` (provider: `ai-gateway`) |
|
||||
| **z.ai / GLM** | `GLM_API_KEY` in `~/.hermes/.env` (provider: `zai`) |
|
||||
| **Kimi / Moonshot** | `KIMI_API_KEY` in `~/.hermes/.env` (provider: `kimi-coding`) |
|
||||
| **Kimi / Moonshot (China)** | `KIMI_CN_API_KEY` in `~/.hermes/.env` (provider: `kimi-coding-cn`; aliases: `kimi-cn`, `moonshot-cn`) |
|
||||
|
|
@ -30,7 +29,7 @@ You need at least one way to connect to an LLM. Use `hermes model` to switch pro
|
|||
| **MiniMax** | `MINIMAX_API_KEY` in `~/.hermes/.env` (provider: `minimax`) |
|
||||
| **MiniMax China** | `MINIMAX_CN_API_KEY` in `~/.hermes/.env` (provider: `minimax-cn`) |
|
||||
| **xAI (Grok) — Responses API** | `XAI_API_KEY` in `~/.hermes/.env` (provider: `xai`) |
|
||||
| **xAI Grok OAuth (SuperGrok)** | `hermes model` → "xAI Grok OAuth (SuperGrok Subscription)" — browser login, no API key. See [guide](../guides/xai-grok-oauth.md) |
|
||||
| **xAI Grok OAuth (SuperGrok)** | `hermes model` → "xAI Grok OAuth (SuperGrok / Premium+)" — browser login, no API key. See [guide](../guides/xai-grok-oauth.md) |
|
||||
| **Qwen Cloud (Alibaba DashScope)** | `DASHSCOPE_API_KEY` in `~/.hermes/.env` (provider: `alibaba`) |
|
||||
| **Alibaba Cloud (Coding Plan)** | `DASHSCOPE_API_KEY` (provider: `alibaba-coding-plan`, alias: `alibaba_coding`) — separate billing SKU, different endpoint |
|
||||
| **Kilo Code** | `KILOCODE_API_KEY` in `~/.hermes/.env` (provider: `kilocode`) |
|
||||
|
|
@ -42,100 +41,42 @@ You need at least one way to connect to an LLM. Use `hermes model` to switch pro
|
|||
| **Hugging Face** | `HF_TOKEN` in `~/.hermes/.env` (provider: `huggingface`, aliases: `hf`) |
|
||||
| **Google / Gemini** | `GOOGLE_API_KEY` (or `GEMINI_API_KEY`) in `~/.hermes/.env` (provider: `gemini`) |
|
||||
| **Google Gemini (OAuth)** | `hermes model` → "Google Gemini (OAuth)" (provider: `google-gemini-cli`, free tier supported, browser PKCE login) |
|
||||
| **OpenAI API (direct)** | `OPENAI_API_KEY` in `~/.hermes/.env` (provider: `openai-api`, optional `OPENAI_BASE_URL`) |
|
||||
| **Azure AI Foundry** | `hermes model` → "Azure AI Foundry" (provider: `azure-foundry`; uses Azure OpenAI / Foundry endpoint and key) |
|
||||
| **AWS Bedrock** | `hermes model` → "AWS Bedrock" (provider: `bedrock`; standard AWS credentials chain via boto3) |
|
||||
| **NVIDIA Build** | `NVIDIA_API_KEY` in `~/.hermes/.env` (provider: `nvidia`; NIM-hosted models on build.nvidia.com) |
|
||||
| **Ollama Cloud** | `hermes model` → "Ollama Cloud" (provider: `ollama-cloud`; cloud-hosted Ollama API) |
|
||||
| **Qwen OAuth** | `hermes model` → "Qwen OAuth" (provider: `qwen-oauth`; browser PKCE login) |
|
||||
| **MiniMax OAuth** | `hermes model` → "MiniMax (OAuth)" (provider: `minimax-oauth`; browser PKCE login) |
|
||||
| **StepFun** | `STEPFUN_API_KEY` in `~/.hermes/.env` (provider: `stepfun`) |
|
||||
| **LM Studio** | `hermes model` → "LM Studio" (provider: `lmstudio`, optional `LM_API_KEY`) |
|
||||
| **Custom Endpoint** | `hermes model` → choose "Custom endpoint" (saved in `config.yaml`) |
|
||||
|
||||
For the official API-key path, see the dedicated [Google Gemini guide](/docs/guides/google-gemini).
|
||||
For the official API-key path, see the dedicated [Google Gemini guide](/guides/google-gemini).
|
||||
|
||||
:::tip Model key alias
|
||||
In the `model:` config section, you can use either `default:` or `model:` as the key name for your model ID. Both `model: { default: my-model }` and `model: { model: my-model }` work identically.
|
||||
:::
|
||||
|
||||
|
||||
### Google Gemini via OAuth (`google-gemini-cli`)
|
||||
### Nous Portal
|
||||
|
||||
The `google-gemini-cli` provider uses Google's Cloud Code Assist backend — the
|
||||
same API that Google's own `gemini-cli` tool uses. This supports both the
|
||||
**free tier** (generous daily quota for personal accounts) and **paid tiers**
|
||||
(Standard/Enterprise via a GCP project).
|
||||
|
||||
**Quick start:**
|
||||
[Nous Portal](https://portal.nousresearch.com) is Nous Research's unified subscription gateway and **the recommended way to run Hermes Agent**. One OAuth login covers 300+ frontier agentic models (Claude, GPT, Gemini, DeepSeek, Qwen, Kimi, GLM, MiniMax, Grok, ...) plus the [Tool Gateway](/user-guide/features/tool-gateway) (web search, image generation, TTS, browser automation) plus [Nous Chat](https://chat.nousresearch.com) — billed against your Nous subscription instead of separate per-provider accounts.
|
||||
|
||||
```bash
|
||||
hermes model
|
||||
# → pick "Google Gemini (OAuth)"
|
||||
# → see policy warning, confirm
|
||||
# → browser opens to accounts.google.com, sign in
|
||||
# → done — Hermes auto-provisions your free tier on first request
|
||||
hermes setup --portal # fresh install — OAuth + provider + gateway in one command
|
||||
hermes model # existing install — pick "Nous Portal" from the list
|
||||
hermes portal info # inspect login + routing at any time
|
||||
```
|
||||
|
||||
Hermes ships Google's **public** `gemini-cli` desktop OAuth client by default —
|
||||
the same credentials Google includes in their open-source `gemini-cli`. Desktop
|
||||
OAuth clients are not confidential (PKCE provides the security). You do not
|
||||
need to install `gemini-cli` or register your own GCP OAuth client.
|
||||
Don't have a subscription yet? Get one at [portal.nousresearch.com/manage-subscription](https://portal.nousresearch.com/manage-subscription).
|
||||
|
||||
**How auth works:**
|
||||
- PKCE Authorization Code flow against `accounts.google.com`
|
||||
- Browser callback at `http://127.0.0.1:8085/oauth2callback` (with ephemeral-port fallback if busy)
|
||||
- Tokens stored at `~/.hermes/auth/google_oauth.json` (chmod 0600, atomic write, cross-process `fcntl` lock)
|
||||
- Automatic refresh 60 s before expiry
|
||||
- Headless environments (SSH, `HERMES_HEADLESS=1`) → paste-mode fallback
|
||||
- Inflight refresh deduplication — two concurrent requests won't double-refresh
|
||||
- `invalid_grant` (revoked refresh) → credential file wiped, user prompted to re-login
|
||||
**For full details:** see the dedicated [Nous Portal integration page](/integrations/nous-portal) (what's in the subscription, model catalog, troubleshooting) and the step-by-step [Run Hermes Agent with Nous Portal guide](/guides/run-hermes-with-nous-portal).
|
||||
|
||||
**How inference works:**
|
||||
- Traffic goes to `https://cloudcode-pa.googleapis.com/v1internal:generateContent`
|
||||
(or `:streamGenerateContent?alt=sse` for streaming), NOT the paid `v1beta/openai` endpoint
|
||||
- Request body wrapped `{project, model, user_prompt_id, request}`
|
||||
- OpenAI-shaped `messages[]`, `tools[]`, `tool_choice` are translated to Gemini's native
|
||||
`contents[]`, `tools[].functionDeclarations`, `toolConfig` shape
|
||||
- Responses translated back to OpenAI shape so the rest of Hermes works unchanged
|
||||
**Client identification.** Every Portal request from Hermes Agent carries a `client=hermes-client-v<version>` tag (e.g. `client=hermes-client-v0.13.0`) auto-aligned to your installed release. This is sent on all Portal pathways — main chat loop, auxiliary calls, compression summarizer, web extraction — and lets Portal-side telemetry distinguish Hermes traffic from other clients. No config required; the tag updates automatically when you `hermes update`.
|
||||
|
||||
**Tiers & project IDs:**
|
||||
**JWT auth (automatic).** Hermes prefers scoped `inference:invoke` JWTs for Portal requests with the legacy opaque session-key path as a fallback. No configuration is required — credentials are managed by the OAuth flow and rotate transparently. Revoked refresh tokens are quarantined to avoid replay loops.
|
||||
|
||||
| Your situation | What to do |
|
||||
|---|---|
|
||||
| Personal Google account, want free tier | Nothing — sign in, start chatting |
|
||||
| Workspace / Standard / Enterprise account | Set `HERMES_GEMINI_PROJECT_ID` or `GOOGLE_CLOUD_PROJECT` to your GCP project ID |
|
||||
| VPC-SC-protected org | Hermes detects `SECURITY_POLICY_VIOLATED` and forces `standard-tier` automatically |
|
||||
|
||||
Free tier auto-provisions a Google-managed project on first use. No GCP setup required.
|
||||
|
||||
**Quota monitoring:**
|
||||
|
||||
```
|
||||
/gquota
|
||||
```
|
||||
|
||||
Shows remaining Code Assist quota per model with progress bars:
|
||||
|
||||
```
|
||||
Gemini Code Assist quota (project: 123-abc)
|
||||
|
||||
gemini-2.5-pro ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░ 85%
|
||||
gemini-2.5-flash [input] ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░ 92%
|
||||
```
|
||||
|
||||
:::warning Policy risk
|
||||
Google considers using the Gemini CLI OAuth client with third-party software a
|
||||
policy violation. Some users have reported account restrictions. For the lowest-risk
|
||||
experience, use your own API key via the `gemini` provider instead. Hermes shows
|
||||
an upfront warning and requires explicit confirmation before OAuth begins.
|
||||
:::
|
||||
|
||||
**Custom OAuth client (optional):**
|
||||
|
||||
If you'd rather register your own Google OAuth client — e.g., to keep quota
|
||||
and consent scoped to your own GCP project — set:
|
||||
|
||||
```bash
|
||||
HERMES_GEMINI_CLIENT_ID=your-client.apps.googleusercontent.com
|
||||
HERMES_GEMINI_CLIENT_SECRET=... # optional for Desktop clients
|
||||
```
|
||||
|
||||
Register a **Desktop app** OAuth client at
|
||||
[console.cloud.google.com/apis/credentials](https://console.cloud.google.com/apis/credentials)
|
||||
with the Generative Language API enabled.
|
||||
|
||||
:::info Codex Note
|
||||
The OpenAI Codex provider authenticates via device code (open a URL, enter a code). Hermes stores the resulting credentials in its own auth store under `~/.hermes/auth.json` and can import existing Codex CLI credentials from `~/.codex/auth.json` when present. No Codex CLI installation is required.
|
||||
|
|
@ -144,11 +85,11 @@ If a token refresh fails with a terminal error (HTTP 4xx, `invalid_grant`, revok
|
|||
:::
|
||||
|
||||
:::warning
|
||||
Even when using Nous Portal, Codex, or a custom endpoint, some tools (vision, web summarization, MoA) use a separate "auxiliary" model. By default (`auxiliary.*.provider: "auto"`), Hermes routes these tasks to your **main chat model** — the same model you picked in `hermes model`. You can override each task individually to route it to a cheaper/faster model (e.g. Gemini Flash on OpenRouter) — see [Auxiliary Models](/docs/user-guide/configuration#auxiliary-models).
|
||||
Even when using Nous Portal, Codex, or a custom endpoint, some tools (vision, web summarization, MoA) use a separate "auxiliary" model. By default (`auxiliary.*.provider: "auto"`), Hermes routes these tasks to your **main chat model** — the same model you picked in `hermes model`. You can override each task individually to route it to a cheaper/faster model (e.g. Gemini Flash on OpenRouter) — see [Auxiliary Models](/user-guide/configuration#auxiliary-models).
|
||||
:::
|
||||
|
||||
:::tip Nous Tool Gateway
|
||||
Paid Nous Portal subscribers also get access to the **[Tool Gateway](/docs/user-guide/features/tool-gateway)** — web search, image generation, TTS, and browser automation routed through your subscription. No extra API keys needed. It's offered automatically during `hermes model` setup, or enable it later with `hermes tools`.
|
||||
Paid Nous Portal subscribers also get access to the **[Tool Gateway](/user-guide/features/tool-gateway)** — web search, image generation, TTS, and browser automation routed through your subscription. No extra API keys needed. On a fresh install, `hermes setup --portal` logs you in, sets Nous as your provider, and turns the gateway on in one command. Existing users can enable it from `hermes model` or per-tool from `hermes tools`. Inspect routing at any time with `hermes portal info`.
|
||||
:::
|
||||
|
||||
### Two Commands for Model Management
|
||||
|
|
@ -162,17 +103,6 @@ Hermes has **two** model commands that serve different purposes:
|
|||
|
||||
If you're trying to switch to a provider you haven't set up yet (e.g. you only have OpenRouter configured and want to use Anthropic), you need `hermes model`, not `/model`. Exit your session first (`Ctrl+C` or `/quit`), run `hermes model`, complete the provider setup, then start a new session.
|
||||
|
||||
### Nous Portal
|
||||
|
||||
Subscription-based access to Hermes-4 models (`Hermes-4-70B`, `Hermes-4.3-36B`, `Hermes-4-405B`) via Nous Research's portal. Run `hermes model`, pick **Nous Portal**, sign in through the browser — Hermes stores a long-lived refresh token at `~/.hermes/auth.json`.
|
||||
|
||||
The refresh token is also shared across profiles via a shared token store, so logging in on one profile carries over to the others.
|
||||
|
||||
#### Token handling
|
||||
|
||||
Hermes mints a short-lived JWT from your stored Nous refresh token on each inference call rather than reusing a long-lived API key. The token lifecycle is fully automatic — refresh, mint, retry on transient 401 — and you never see it.
|
||||
|
||||
If the portal invalidates the refresh token (password change, manual revoke, session expiry), the invalid refresh token is quarantined locally so Hermes stops replaying it and you don't see a stream of identical 401s. The next call surfaces a clear "re-authentication required" message. Run `hermes auth add nous` to log in again; the quarantine clears on the next successful login.
|
||||
|
||||
### Anthropic (Native)
|
||||
|
||||
|
|
@ -345,9 +275,9 @@ When using the Z.AI / GLM provider, Hermes automatically probes multiple endpoin
|
|||
|
||||
### xAI (Grok) — Responses API + Prompt Caching
|
||||
|
||||
xAI is wired through the Responses API (`codex_responses` transport) for automatic reasoning support on Grok 4 models — no `reasoning_effort` parameter needed, the server reasons by default. Set `XAI_API_KEY` in `~/.hermes/.env` and pick xAI in `hermes model`, or drop `grok` as a shortcut into `/model grok-4-1-fast-reasoning`.
|
||||
xAI is wired through the Responses API (`codex_responses` transport) for automatic reasoning support on Grok 4 models — no `reasoning_effort` parameter needed, the server reasons by default. Set `XAI_API_KEY` in `~/.hermes/.env` and pick xAI in `hermes model`, or drop `grok` as a shortcut into `/model grok-4-fast-reasoning`.
|
||||
|
||||
SuperGrok and X Premium+ subscribers can sign in with browser OAuth instead of using an API key — pick **xAI Grok OAuth (SuperGrok Subscription)** in `hermes model`, or run `hermes auth add xai-oauth`. The same OAuth bearer token is automatically reused by direct-to-xAI tools (TTS, image gen, video gen, transcription). See the [xAI Grok OAuth guide](../guides/xai-grok-oauth.md) for the full flow — and if Hermes runs on a remote host, also see [OAuth over SSH / Remote Hosts](../guides/oauth-over-ssh.md) for the required `ssh -L` tunnel.
|
||||
SuperGrok and X Premium+ subscribers can sign in with browser OAuth instead of using an API key — pick **xAI Grok OAuth (SuperGrok / Premium+)** in `hermes model`, or run `hermes auth add xai-oauth`. The same OAuth bearer token is automatically reused by direct-to-xAI tools (TTS, image gen, video gen, transcription). See the [xAI Grok OAuth guide](../guides/xai-grok-oauth.md) for the full flow — and if Hermes runs on a remote host, also see [OAuth over SSH / Remote Hosts](../guides/oauth-over-ssh.md) for the required `ssh -L` tunnel.
|
||||
|
||||
When using xAI as a provider (any base URL containing `x.ai`), Hermes automatically enables prompt caching by sending the `x-grok-conv-id` header with every API request. This routes requests to the same server within a conversation session, allowing xAI's infrastructure to reuse cached system prompts and conversation history.
|
||||
|
||||
|
|
@ -355,6 +285,15 @@ No configuration is needed — caching activates automatically when an xAI endpo
|
|||
|
||||
xAI also ships a dedicated TTS endpoint (`/v1/tts`). Select **xAI TTS** in `hermes tools` → Voice & TTS, or see the [Voice & TTS](../user-guide/features/tts.md#text-to-speech) page for config.
|
||||
|
||||
**Retired xAI model migration (May 15, 2026):** xAI is retiring `grok-4*`, `grok-3`, `grok-code-fast-1`, and `grok-imagine-image-pro` on 2026-05-15. `hermes doctor` and `hermes chat` startup both detect any config still pointing at a retired ref and print the recommended replacement. Use `hermes migrate xai` for a one-shot config rewrite — dry-run by default, add `--apply` to write changes (a timestamped `config.yaml.bak-pre-migrate-xai-*` backup is created automatically).
|
||||
|
||||
```bash
|
||||
hermes migrate xai # preview replacements
|
||||
hermes migrate xai --apply # rewrite ~/.hermes/config.yaml in place
|
||||
```
|
||||
|
||||
**xAI Web Search backend.** When the [Web Search](../user-guide/features/web-search.md) toolset is enabled, `web.backend: xai` routes search through xAI's hosted search endpoint using the same `XAI_API_KEY` / OAuth credentials. No additional setup required if xAI is already configured as a provider.
|
||||
|
||||
### NovitaAI
|
||||
|
||||
[NovitaAI](https://novita.ai) is the AI-native cloud for builders and agents. Its three product lines are Model API for 200+ models, Agent Sandbox for building and running AI agents, and GPU Cloud for scalable compute, all available from one platform.
|
||||
|
|
@ -432,7 +371,7 @@ Authentication uses the standard boto3 chain: explicit `AWS_ACCESS_KEY_ID`/`AWS_
|
|||
|
||||
Bedrock uses the **Converse API** under the hood — requests are translated to Bedrock's model-agnostic shape, so the same config works for Claude, Nova, DeepSeek, and Llama models. Set `BEDROCK_BASE_URL` only if you're calling a non-default regional endpoint.
|
||||
|
||||
See the [AWS Bedrock guide](/docs/guides/aws-bedrock) for a walkthrough of IAM setup, region selection, and cross-region inference.
|
||||
See the [AWS Bedrock guide](/guides/aws-bedrock) for a walkthrough of IAM setup, region selection, and cross-region inference.
|
||||
|
||||
### Qwen Portal (OAuth)
|
||||
|
||||
|
|
@ -501,7 +440,7 @@ model:
|
|||
Supported models: `MiniMax-M2.7` (main) and `MiniMax-M2.7-highspeed` (wired as the default auxiliary model). The OAuth path ignores `MINIMAX_API_KEY` / `MINIMAX_BASE_URL`.
|
||||
|
||||
:::tip MiniMax OAuth vs API key
|
||||
`minimax-oauth` uses MiniMax's consumer-facing portal with OAuth login — no billing setup required. The `minimax` and `minimax-cn` providers use `MINIMAX_API_KEY` / `MINIMAX_CN_API_KEY` — for programmatic access. See the [MiniMax OAuth guide](/docs/guides/minimax-oauth) for a full walkthrough.
|
||||
`minimax-oauth` uses MiniMax's consumer-facing portal with OAuth login — no billing setup required. The `minimax` and `minimax-cn` providers use `MINIMAX_API_KEY` / `MINIMAX_CN_API_KEY` — for programmatic access. See the [MiniMax OAuth guide](/guides/minimax-oauth) for a full walkthrough.
|
||||
:::
|
||||
|
||||
### NVIDIA NIM
|
||||
|
|
@ -536,7 +475,7 @@ Open and reasoning models via [GMI Cloud](https://www.gmicloud.ai/) — OpenAI-c
|
|||
|
||||
```bash
|
||||
# GMI Cloud
|
||||
hermes chat --provider gmi --model deepseek-ai/DeepSeek-R1
|
||||
hermes chat --provider gmi --model deepseek-ai/DeepSeek-V3.2
|
||||
# Requires: GMI_API_KEY in ~/.hermes/.env
|
||||
```
|
||||
|
||||
|
|
@ -544,7 +483,7 @@ Or set it permanently in `config.yaml`:
|
|||
```yaml
|
||||
model:
|
||||
provider: "gmi"
|
||||
default: "deepseek-ai/DeepSeek-R1"
|
||||
default: "deepseek-ai/DeepSeek-V3.2"
|
||||
```
|
||||
|
||||
The base URL can be overridden with `GMI_BASE_URL` (default: `https://api.gmi-serving.com/v1`).
|
||||
|
|
@ -555,7 +494,7 @@ Step-series models via [StepFun](https://platform.stepfun.com) — OpenAI-compat
|
|||
|
||||
```bash
|
||||
# StepFun
|
||||
hermes chat --provider stepfun --model step-3-mini
|
||||
hermes chat --provider stepfun --model step-3.5-flash
|
||||
# Requires: STEPFUN_API_KEY in ~/.hermes/.env
|
||||
```
|
||||
|
||||
|
|
@ -563,7 +502,7 @@ Or set it permanently in `config.yaml`:
|
|||
```yaml
|
||||
model:
|
||||
provider: "stepfun"
|
||||
default: "step-3-mini"
|
||||
default: "step-3.5-flash"
|
||||
```
|
||||
|
||||
The base URL can be overridden with `STEPFUN_BASE_URL` (default: `https://api.stepfun.com/v1`).
|
||||
|
|
@ -574,7 +513,7 @@ The base URL can be overridden with `STEPFUN_BASE_URL` (default: `https://api.st
|
|||
|
||||
```bash
|
||||
# Use any available model
|
||||
hermes chat --provider huggingface --model Qwen/Qwen3-235B-A22B-Thinking-2507
|
||||
hermes chat --provider huggingface --model Qwen/Qwen3.5-397B-A17B
|
||||
# Requires: HF_TOKEN in ~/.hermes/.env
|
||||
|
||||
# Short alias
|
||||
|
|
@ -585,7 +524,7 @@ Or set it permanently in `config.yaml`:
|
|||
```yaml
|
||||
model:
|
||||
provider: "huggingface"
|
||||
default: "Qwen/Qwen3-235B-A22B-Thinking-2507"
|
||||
default: "Qwen/Qwen3.5-397B-A17B"
|
||||
```
|
||||
|
||||
Get your token at [huggingface.co/settings/tokens](https://huggingface.co/settings/tokens) — make sure to enable the "Make calls to Inference Providers" permission. Free tier included ($0.10/month credit, no markup on provider rates).
|
||||
|
|
@ -594,6 +533,91 @@ You can append routing suffixes to model names: `:fastest` (default), `:cheapest
|
|||
|
||||
The base URL can be overridden with `HF_BASE_URL`.
|
||||
|
||||
### Google Gemini via OAuth (`google-gemini-cli`)
|
||||
|
||||
The `google-gemini-cli` provider uses Google's Cloud Code Assist backend — the
|
||||
same API that Google's own `gemini-cli` tool uses. This supports both the
|
||||
**free tier** (generous daily quota for personal accounts) and **paid tiers**
|
||||
(Standard/Enterprise via a GCP project).
|
||||
|
||||
**Quick start:**
|
||||
|
||||
```bash
|
||||
hermes model
|
||||
# → pick "Google Gemini (OAuth)"
|
||||
# → see policy warning, confirm
|
||||
# → browser opens to accounts.google.com, sign in
|
||||
# → done — Hermes auto-provisions your free tier on first request
|
||||
```
|
||||
|
||||
Hermes ships Google's **public** `gemini-cli` desktop OAuth client by default —
|
||||
the same credentials Google includes in their open-source `gemini-cli`. Desktop
|
||||
OAuth clients are not confidential (PKCE provides the security). You do not
|
||||
need to install `gemini-cli` or register your own GCP OAuth client.
|
||||
|
||||
**How auth works:**
|
||||
- PKCE Authorization Code flow against `accounts.google.com`
|
||||
- Browser callback at `http://127.0.0.1:8085/oauth2callback` (with ephemeral-port fallback if busy)
|
||||
- Tokens stored at `~/.hermes/auth/google_oauth.json` (chmod 0600, atomic write, cross-process `fcntl` lock)
|
||||
- Automatic refresh 60 s before expiry
|
||||
- Headless environments (SSH, `HERMES_HEADLESS=1`) → paste-mode fallback
|
||||
- Inflight refresh deduplication — two concurrent requests won't double-refresh
|
||||
- `invalid_grant` (revoked refresh) → credential file wiped, user prompted to re-login
|
||||
|
||||
**How inference works:**
|
||||
- Traffic goes to `https://cloudcode-pa.googleapis.com/v1internal:generateContent`
|
||||
(or `:streamGenerateContent?alt=sse` for streaming), NOT the paid `v1beta/openai` endpoint
|
||||
- Request body wrapped `{project, model, user_prompt_id, request}`
|
||||
- OpenAI-shaped `messages[]`, `tools[]`, `tool_choice` are translated to Gemini's native
|
||||
`contents[]`, `tools[].functionDeclarations`, `toolConfig` shape
|
||||
- Responses translated back to OpenAI shape so the rest of Hermes works unchanged
|
||||
|
||||
**Tiers & project IDs:**
|
||||
|
||||
| Your situation | What to do |
|
||||
|---|---|
|
||||
| Personal Google account, want free tier | Nothing — sign in, start chatting |
|
||||
| Workspace / Standard / Enterprise account | Set `HERMES_GEMINI_PROJECT_ID` or `GOOGLE_CLOUD_PROJECT` to your GCP project ID |
|
||||
| VPC-SC-protected org | Hermes detects `SECURITY_POLICY_VIOLATED` and forces `standard-tier` automatically |
|
||||
|
||||
Free tier auto-provisions a Google-managed project on first use. No GCP setup required.
|
||||
|
||||
**Quota monitoring:**
|
||||
|
||||
```
|
||||
/gquota
|
||||
```
|
||||
|
||||
Shows remaining Code Assist quota per model with progress bars:
|
||||
|
||||
```
|
||||
Gemini Code Assist quota (project: 123-abc)
|
||||
|
||||
gemini-2.5-pro ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░ 85%
|
||||
gemini-2.5-flash [input] ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░ 92%
|
||||
```
|
||||
|
||||
:::warning Policy risk
|
||||
Google considers using the Gemini CLI OAuth client with third-party software a
|
||||
policy violation. Some users have reported account restrictions. For the lowest-risk
|
||||
experience, use your own API key via the `gemini` provider instead. Hermes shows
|
||||
an upfront warning and requires explicit confirmation before OAuth begins.
|
||||
:::
|
||||
|
||||
**Custom OAuth client (optional):**
|
||||
|
||||
If you'd rather register your own Google OAuth client — e.g., to keep quota
|
||||
and consent scoped to your own GCP project — set:
|
||||
|
||||
```bash
|
||||
HERMES_GEMINI_CLIENT_ID=your-client.apps.googleusercontent.com
|
||||
HERMES_GEMINI_CLIENT_SECRET=... # optional for Desktop clients
|
||||
```
|
||||
|
||||
Register a **Desktop app** OAuth client at
|
||||
[console.cloud.google.com/apis/credentials](https://console.cloud.google.com/apis/credentials)
|
||||
with the Generative Language API enabled.
|
||||
|
||||
## Custom & Self-Hosted LLM Providers
|
||||
|
||||
Hermes Agent works with **any OpenAI-compatible API endpoint**. If a server implements `/v1/chat/completions`, you can point Hermes at it. This means you can use local models, GPU inference servers, multi-provider routers, or any third-party API.
|
||||
|
|
@ -620,7 +644,7 @@ model:
|
|||
```
|
||||
|
||||
:::warning Legacy env vars
|
||||
`OPENAI_BASE_URL` and `LLM_MODEL` in `.env` are **removed**. Neither is read by any part of Hermes — `config.yaml` is the single source of truth for model and endpoint configuration. If you have stale entries in your `.env`, they are automatically cleared on the next `hermes setup` or config migration. Use `hermes model` or edit `config.yaml` directly.
|
||||
`LLM_MODEL` in `.env` is **removed** — `config.yaml` is the single source of truth for model and endpoint configuration. `OPENAI_BASE_URL` is still honored, but **only** for the `openai-api` provider (it overrides the OpenAI endpoint for direct API-key access). For other providers and custom endpoints, use `hermes model` or set `model.base_url` in `config.yaml` directly. If you have stale entries in your `.env`, they are automatically cleared on the next `hermes setup` or config migration.
|
||||
:::
|
||||
|
||||
Both approaches persist to `config.yaml`, which is the source of truth for model, provider, and base URL.
|
||||
|
|
@ -687,7 +711,7 @@ model:
|
|||
default: qwen2.5-coder:32b
|
||||
provider: custom
|
||||
base_url: http://localhost:11434/v1
|
||||
context_length: 32768 # See warning below
|
||||
context_length: 64000 # See warning below
|
||||
```
|
||||
|
||||
:::caution Ollama defaults to very low context lengths
|
||||
|
|
@ -699,22 +723,22 @@ Ollama does **not** use your model's full context window by default. Depending o
|
|||
| 24–48 GB | 32,768 tokens |
|
||||
| 48+ GB | 256,000 tokens |
|
||||
|
||||
For agent use with tools, **you need at least 16k–32k context**. At 4k, the system prompt + tool schemas alone can fill the window, leaving no room for conversation.
|
||||
Hermes Agent requires at least **64,000 tokens** of context for agent use with tools. Smaller windows are rejected at startup because the system prompt, tool schemas, and working conversation state need enough room for reliable multi-step workflows.
|
||||
|
||||
**How to increase it** (pick one):
|
||||
|
||||
```bash
|
||||
# Option 1: Set server-wide via environment variable (recommended)
|
||||
OLLAMA_CONTEXT_LENGTH=32768 ollama serve
|
||||
OLLAMA_CONTEXT_LENGTH=64000 ollama serve
|
||||
|
||||
# Option 2: For systemd-managed Ollama
|
||||
sudo systemctl edit ollama.service
|
||||
# Add: Environment="OLLAMA_CONTEXT_LENGTH=32768"
|
||||
# Add: Environment="OLLAMA_CONTEXT_LENGTH=64000"
|
||||
# Then: sudo systemctl daemon-reload && sudo systemctl restart ollama
|
||||
|
||||
# Option 3: Bake it into a custom model (persistent per-model)
|
||||
echo -e "FROM qwen2.5-coder:32b\nPARAMETER num_ctx 32768" > Modelfile
|
||||
ollama create qwen2.5-coder-32k -f Modelfile
|
||||
echo -e "FROM qwen2.5-coder:32b\nPARAMETER num_ctx 64000" > Modelfile
|
||||
ollama create qwen2.5-coder-64k -f Modelfile
|
||||
```
|
||||
|
||||
**You cannot set context length through the OpenAI-compatible API** (`/v1/chat/completions`). It must be configured server-side or via a Modelfile. This is the #1 source of confusion when integrating Ollama with tools like Hermes.
|
||||
|
|
@ -816,13 +840,13 @@ If responses seem truncated, add `max_tokens` to your requests or set `--default
|
|||
cmake -B build && cmake --build build --config Release
|
||||
./build/bin/llama-server \
|
||||
--jinja -fa \
|
||||
-c 32768 \
|
||||
-c 64000 \
|
||||
-ngl 99 \
|
||||
-m models/qwen2.5-coder-32b-instruct-Q4_K_M.gguf \
|
||||
--port 8080 --host 0.0.0.0
|
||||
```
|
||||
|
||||
**Context length (`-c`):** Recent builds default to `0` which reads the model's training context from the GGUF metadata. For models with 128k+ training context, this can OOM trying to allocate the full KV cache. Set `-c` explicitly to what you need (32k–64k is a good range for agent use). If using parallel slots (`-np`), the total context is divided among slots — with `-c 32768 -np 4`, each slot only gets 8k.
|
||||
**Context length (`-c`):** Recent builds default to `0` which reads the model's training context from the GGUF metadata. For models with 128k+ training context, this can OOM trying to allocate the full KV cache. Set `-c` explicitly to at least 64,000 tokens for Hermes. If using parallel slots (`-np`), the total context is divided among slots — with `-c 64000 -np 4`, each slot only gets 16k, which is below Hermes' minimum per active session.
|
||||
|
||||
Then configure Hermes to point at it:
|
||||
|
||||
|
|
@ -858,7 +882,7 @@ Start the server from the LM Studio app (Developer tab → Start Server), or use
|
|||
|
||||
```bash
|
||||
lms server start # Starts on port 1234
|
||||
lms load qwen2.5-coder --context-length 32768
|
||||
lms load qwen2.5-coder --context-length 64000
|
||||
```
|
||||
|
||||
Then configure Hermes:
|
||||
|
|
@ -1040,7 +1064,7 @@ The model outputs something like `{"name": "web_search", "arguments": {...}}` as
|
|||
# vLLM: check --max-model-len in startup args
|
||||
```
|
||||
|
||||
**Fix:** Set context to at least **32,768 tokens** for agent use. See each server's section above for the specific flag.
|
||||
**Fix:** Set context to at least **64,000 tokens** for agent use. See each server's section above for the specific flag.
|
||||
|
||||
#### "Context limit: 2048 tokens" at startup
|
||||
|
||||
|
|
@ -1053,14 +1077,14 @@ model:
|
|||
default: your-model
|
||||
provider: custom
|
||||
base_url: http://localhost:11434/v1
|
||||
context_length: 32768
|
||||
context_length: 64000
|
||||
```
|
||||
|
||||
#### Responses get cut off mid-sentence
|
||||
|
||||
**Possible causes:**
|
||||
1. **Low output cap (`max_tokens`) on the server** — SGLang defaults to 128 tokens per response. Set `--default-max-tokens` on the server or configure Hermes with `model.max_tokens` in config.yaml. Note: `max_tokens` controls response length only — it is unrelated to how long your conversation history can be (that is `context_length`).
|
||||
2. **Context exhaustion** — The model filled its context window. Increase `model.context_length` or enable [context compression](/docs/user-guide/configuration#context-compression) in Hermes.
|
||||
2. **Context exhaustion** — The model filled its context window. Increase `model.context_length` or enable [context compression](/user-guide/configuration#context-compression) in Hermes.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -1194,7 +1218,7 @@ custom_providers:
|
|||
base_url: "http://localhost:11434/v1"
|
||||
models:
|
||||
qwen3.5:27b:
|
||||
context_length: 32768
|
||||
context_length: 64000
|
||||
deepseek-r1:70b:
|
||||
context_length: 65536
|
||||
```
|
||||
|
|
@ -1250,6 +1274,18 @@ extra_body:
|
|||
|
||||
The `hermes model` → Custom Endpoint wizard now prompts for `api_mode` explicitly and persists your answer to `config.yaml`. URL-based auto-detection (e.g. `/anthropic` paths → `anthropic_messages`) still happens as a fallback when the field is left blank.
|
||||
|
||||
**Native vision for custom-provider models.** If your custom endpoint serves a vision-capable model that isn't in models.dev, set `model.supports_vision: true` so Hermes routes attached images natively (as `image_url` parts) instead of pre-processing them through `vision_analyze`. Single knob — no need to also set `agent.image_input_mode: native`.
|
||||
|
||||
```yaml
|
||||
model:
|
||||
provider: custom
|
||||
base_url: http://localhost:8080/v1
|
||||
default: qwen3.6-35b-a3b
|
||||
supports_vision: true # send images natively; otherwise vision_analyze pre-describes them
|
||||
```
|
||||
|
||||
The same key is honored on per-named-provider models (`custom_providers[*].models[*].supports_vision`) and accepts standard YAML booleans (`true/false/yes/no/on/off/1/0`).
|
||||
|
||||
Switch between them mid-session with the triple syntax:
|
||||
|
||||
```
|
||||
|
|
@ -1460,7 +1496,7 @@ Notes:
|
|||
- Set to empty string (or remove the line) to let OpenRouter pick the strongest available coder — its documented behavior when the plugins block is omitted.
|
||||
- Selection is deterministic per score on a given day, but the actual model chosen can shift as the Pareto frontier moves (new models, benchmark updates).
|
||||
- See OpenRouter's [Pareto Router docs](https://openrouter.ai/docs/guides/routing/routers/pareto-router) for the full router behavior.
|
||||
- To use the Pareto Code router for a specific **auxiliary task** (compression, vision, etc.) instead of the main agent, set `extra_body.plugins` under that task — see [Auxiliary Models → OpenRouter routing & Pareto Code for auxiliary tasks](/docs/user-guide/configuration#openrouter-routing--pareto-code-for-auxiliary-tasks).
|
||||
- To use the Pareto Code router for a specific **auxiliary task** (compression, vision, etc.) instead of the main agent, set `extra_body.plugins` under that task — see [Auxiliary Models → OpenRouter routing & Pareto Code for auxiliary tasks](/user-guide/configuration#openrouter-routing--pareto-code-for-auxiliary-tasks).
|
||||
|
||||
## Fallback Providers
|
||||
|
||||
|
|
@ -1486,15 +1522,15 @@ fallback_model:
|
|||
|
||||
When activated, the fallback swaps the model and provider mid-session without losing your conversation. The chain is tried entry-by-entry; activation is one-shot per session.
|
||||
|
||||
Supported providers: `openrouter`, `nous`, `openai-codex`, `copilot`, `copilot-acp`, `anthropic`, `gemini`, `google-gemini-cli`, `qwen-oauth`, `huggingface`, `zai`, `kimi-coding`, `kimi-coding-cn`, `minimax`, `minimax-cn`, `minimax-oauth`, `deepseek`, `nvidia`, `xai`, `xai-oauth`, `ollama-cloud`, `bedrock`, `ai-gateway`, `azure-foundry`, `opencode-zen`, `opencode-go`, `kilocode`, `xiaomi`, `arcee`, `gmi`, `stepfun`, `lmstudio`, `alibaba`, `alibaba-coding-plan`, `tencent-tokenhub`, `custom`.
|
||||
Supported providers: `openrouter`, `nous`, `novita`, `openai-codex`, `copilot`, `copilot-acp`, `anthropic`, `gemini`, `google-gemini-cli`, `qwen-oauth`, `huggingface`, `zai`, `kimi-coding`, `kimi-coding-cn`, `minimax`, `minimax-cn`, `minimax-oauth`, `deepseek`, `nvidia`, `xai`, `xai-oauth`, `ollama-cloud`, `bedrock`, `azure-foundry`, `opencode-zen`, `opencode-go`, `kilocode`, `xiaomi`, `arcee`, `gmi`, `stepfun`, `lmstudio`, `alibaba`, `alibaba-coding-plan`, `tencent-tokenhub`, `custom`.
|
||||
|
||||
:::tip
|
||||
Fallback is configured exclusively through `config.yaml` — or interactively via `hermes fallback`. For full details on when it triggers, how the chain advances, and how it interacts with auxiliary tasks and delegation, see [Fallback Providers](/docs/user-guide/features/fallback-providers).
|
||||
Fallback is configured exclusively through `config.yaml` — or interactively via `hermes fallback`. For full details on when it triggers, how the chain advances, and how it interacts with auxiliary tasks and delegation, see [Fallback Providers](/user-guide/features/fallback-providers).
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- [Configuration](/docs/user-guide/configuration) — General configuration (directory structure, config precedence, terminal backends, memory, compression, and more)
|
||||
- [Environment Variables](/docs/reference/environment-variables) — Complete reference of all environment variables
|
||||
- [Configuration](/user-guide/configuration) — General configuration (directory structure, config precedence, terminal backends, memory, compression, and more)
|
||||
- [Environment Variables](/reference/environment-variables) — Complete reference of all environment variables
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@ hermes [global-options] <command> [subcommand/options]
|
|||
| `--pass-session-id` | Include the session ID in the agent's system prompt. |
|
||||
| `--ignore-user-config` | Ignore `~/.hermes/config.yaml` and fall back to built-in defaults. Credentials in `.env` are still loaded. |
|
||||
| `--ignore-rules` | Skip auto-injection of `AGENTS.md`, `SOUL.md`, `.cursorrules`, memory, and preloaded skills. |
|
||||
| `--tui` | Launch the [TUI](../user-guide/tui.md) instead of the classic CLI. Equivalent to `HERMES_TUI=1`. |
|
||||
| `--tui` | Launch the [TUI](../user-guide/tui.md) instead of the classic CLI. Equivalent to `HERMES_TUI=1`. Always wins over `display.interface`. |
|
||||
| `--cli` | Force the classic prompt_toolkit REPL. Use this to override `display.interface: tui` for a single invocation. |
|
||||
| `--dev` | With `--tui`: run the TypeScript sources directly via `tsx` instead of the prebuilt bundle (for TUI contributors). |
|
||||
|
||||
## Top-level commands
|
||||
|
|
@ -47,13 +48,18 @@ hermes [global-options] <command> [subcommand/options]
|
|||
| `hermes slack` | Slack helpers (currently: generate the app manifest with every command as a native slash). |
|
||||
| `hermes auth` | Manage credentials — add, list, remove, reset, set strategy. Handles OAuth flows for Codex/Nous/Anthropic. |
|
||||
| `hermes login` / `logout` | **Deprecated** — use `hermes auth` instead. |
|
||||
| `hermes send` | Send a one-shot message to a configured messaging platform (Telegram, Discord, Slack, Signal, SMS, …). Useful from shell scripts, cron jobs, CI hooks, and monitoring daemons — no agent loop, no LLM. |
|
||||
| `hermes secrets` | Manage external secret sources (currently Bitwarden Secrets Manager) for pulling API keys at process startup instead of from `~/.hermes/.env`. |
|
||||
| `hermes migrate` | Diagnose and (optionally) rewrite `config.yaml` to replace references to retired models or deprecated settings (e.g. `migrate xai`). |
|
||||
| `hermes status` | Show agent, auth, and platform status. |
|
||||
| `hermes cron` | Inspect and tick the cron scheduler. |
|
||||
| `hermes kanban` | Multi-profile collaboration board (tasks, links, dispatcher). |
|
||||
| `hermes webhook` | Manage dynamic webhook subscriptions for event-driven activation. |
|
||||
| `hermes hooks` | Inspect, approve, or remove shell-script hooks declared in `config.yaml`. |
|
||||
| `hermes doctor` | Diagnose config and dependency issues. |
|
||||
| `hermes security audit` | On-demand supply-chain audit (OSV.dev) for the venv, plugin requirements, and pinned MCP servers. |
|
||||
| `hermes dump` | Copy-pasteable setup summary for support/debugging. |
|
||||
| `hermes prompt-size` | Show a byte breakdown of the system prompt + tool schemas (skills index, memory, profile). Runs offline. |
|
||||
| `hermes debug` | Debug tools — upload logs and system info for support. |
|
||||
| `hermes backup` | Back up Hermes home directory to a zip file. |
|
||||
| `hermes checkpoints` | Inspect / prune / clear `~/.hermes/checkpoints/` (the shadow store used by `/rollback`). Run with no args for a status overview. |
|
||||
|
|
@ -68,6 +74,7 @@ hermes [global-options] <command> [subcommand/options]
|
|||
| `hermes acp` | Run Hermes as an ACP server for editor integration. |
|
||||
| `hermes mcp` | Manage MCP server configurations and run Hermes as an MCP server. |
|
||||
| `hermes plugins` | Manage Hermes Agent plugins (install, enable, disable, remove). |
|
||||
| `hermes portal` | Nous Portal status, subscription link, and Tool Gateway routing. See [Tool Gateway](../user-guide/features/tool-gateway.md). |
|
||||
| `hermes tools` | Configure enabled tools per platform. |
|
||||
| `hermes computer-use` | Install or check the cua-driver backend (macOS Computer Use). |
|
||||
| `hermes sessions` | Browse, export, prune, rename, and delete sessions. |
|
||||
|
|
@ -93,7 +100,7 @@ Common options:
|
|||
| `-q`, `--query "..."` | One-shot, non-interactive prompt. |
|
||||
| `-m`, `--model <model>` | Override the model for this run. |
|
||||
| `-t`, `--toolsets <csv>` | Enable a comma-separated set of toolsets. |
|
||||
| `--provider <provider>` | Force a provider: `auto`, `openrouter`, `nous`, `openai-codex`, `copilot-acp`, `copilot`, `anthropic`, `gemini`, `google-gemini-cli`, `huggingface`, `novita`, `zai`, `kimi-coding`, `kimi-coding-cn`, `minimax`, `minimax-cn`, `minimax-oauth`, `kilocode`, `xiaomi`, `arcee`, `gmi`, `alibaba`, `alibaba-coding-plan` (alias `alibaba_coding`), `deepseek`, `nvidia`, `ollama-cloud`, `xai` (alias `grok`), `xai-oauth` (alias `grok-oauth`), `qwen-oauth`, `bedrock`, `opencode-zen`, `opencode-go`, `ai-gateway`, `azure-foundry`, `lmstudio`, `stepfun`, `tencent-tokenhub` (alias `tencent`, `tokenhub`). |
|
||||
| `--provider <provider>` | Force a provider: `auto`, `openrouter`, `nous`, `openai-codex`, `copilot-acp`, `copilot`, `anthropic`, `gemini`, `google-gemini-cli`, `huggingface`, `novita` (aliases `novita-ai`, `novitaai`), `openai-api`, `zai`, `kimi-coding`, `kimi-coding-cn`, `minimax`, `minimax-cn`, `minimax-oauth`, `kilocode`, `xiaomi`, `arcee`, `gmi`, `alibaba`, `alibaba-coding-plan` (alias `alibaba_coding`), `deepseek`, `nvidia`, `ollama-cloud`, `xai` (alias `grok`), `xai-oauth` (alias `grok-oauth`), `qwen-oauth`, `bedrock`, `opencode-zen`, `opencode-go`, `azure-foundry`, `lmstudio`, `stepfun`, `tencent-tokenhub` (alias `tencent`, `tokenhub`). |
|
||||
| `-s`, `--skills <name>` | Preload one or more skills for the session (can be repeated or comma-separated). |
|
||||
| `-v`, `--verbose` | Verbose output. |
|
||||
| `-Q`, `--quiet` | Programmatic mode: suppress banner/spinner/tool previews. |
|
||||
|
|
@ -137,7 +144,7 @@ Per-run overrides (no mutation to `~/.hermes/config.yaml`):
|
|||
| Flag | Equivalent env var | Purpose |
|
||||
|---|---|---|
|
||||
| `-m` / `--model <model>` | `HERMES_INFERENCE_MODEL` | Override the model for this run |
|
||||
| `--provider <provider>` | `HERMES_INFERENCE_PROVIDER` | Override the provider for this run |
|
||||
| `--provider <provider>` | _(none)_ | Override the provider for this run |
|
||||
|
||||
```bash
|
||||
hermes -z "…" --provider openrouter --model openai/gpt-5.5
|
||||
|
|
@ -222,9 +229,10 @@ Options:
|
|||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `--all` | On `start` / `restart` / `stop`: act on **every profile's** gateway, not just the active `HERMES_HOME`. Useful if you run multiple profiles side-by-side and want to restart them all after `hermes update`. |
|
||||
| `--no-supervise` | On `run`: inside the s6-overlay Docker image, opt out of auto-supervision and use pre-s6 foreground semantics — gateway runs as the container's main process with no auto-restart. No-op outside the s6 image. Equivalent to setting `HERMES_GATEWAY_NO_SUPERVISE=1`. |
|
||||
|
||||
:::tip WSL users
|
||||
Use `hermes gateway run` instead of `hermes gateway start` — WSL's systemd support is unreliable. Wrap it in tmux for persistence: `tmux new -s hermes 'hermes gateway run'`. See [WSL FAQ](/docs/reference/faq#wsl-gateway-keeps-disconnecting-or-hermes-gateway-start-fails) for details.
|
||||
Use `hermes gateway run` instead of `hermes gateway start` — WSL's systemd support is unreliable. Wrap it in tmux for persistence: `tmux new -s hermes 'hermes gateway run'`. See [WSL FAQ](/reference/faq#wsl-gateway-keeps-disconnecting-or-hermes-gateway-start-fails) for details.
|
||||
:::
|
||||
|
||||
## `hermes lsp`
|
||||
|
|
@ -251,15 +259,17 @@ Subcommands:
|
|||
| `restart` | Tear down running clients so the next edit re-spawns. |
|
||||
| `which <id>` | Print the resolved binary path for one server. |
|
||||
|
||||
See [LSP — Semantic Diagnostics](/docs/user-guide/features/lsp) for
|
||||
See [LSP — Semantic Diagnostics](/user-guide/features/lsp) for
|
||||
the full guide, supported languages, and configuration knobs.
|
||||
|
||||
## `hermes setup`
|
||||
|
||||
```bash
|
||||
hermes setup [model|tts|terminal|gateway|tools|agent] [--non-interactive] [--reset] [--quick] [--reconfigure]
|
||||
hermes setup [model|tts|terminal|gateway|tools|agent] [--non-interactive] [--reset] [--quick] [--reconfigure] [--portal]
|
||||
```
|
||||
|
||||
**Easiest path:** `hermes setup --portal` — OAuth into Nous Portal and opt into the [Tool Gateway](../user-guide/features/tool-gateway.md) in one shot.
|
||||
|
||||
**First run:** launches the first-time wizard.
|
||||
|
||||
**Returning user (already configured):** drops straight into the full reconfigure wizard — every prompt shows your current value as its default, press Enter to keep or type a new value. No menu.
|
||||
|
|
@ -282,6 +292,23 @@ Options:
|
|||
| `--non-interactive` | Use defaults / environment values without prompts. |
|
||||
| `--reset` | Reset configuration to defaults before setup. |
|
||||
| `--reconfigure` | Backwards-compat alias — bare `hermes setup` on an existing install now does this by default. |
|
||||
| `--portal` | One-shot Nous Portal setup: log in via OAuth, set Nous as the inference provider, and opt into the [Tool Gateway](../user-guide/features/tool-gateway.md). Skips the rest of the wizard. |
|
||||
|
||||
## `hermes portal`
|
||||
|
||||
```bash
|
||||
hermes portal [status|open|tools]
|
||||
```
|
||||
|
||||
Inspect Nous Portal auth, Tool Gateway routing, and reach the subscription page. Subcommand-less invocation runs `status`.
|
||||
|
||||
| Subcommand | Description |
|
||||
|------------|-------------|
|
||||
| `status` (default) | Portal auth state + per-tool Tool Gateway routing summary. Also shown when no subcommand is given. |
|
||||
| `open` | Open `portal.nousresearch.com/manage-subscription` in your default browser. |
|
||||
| `tools` | List every Tool Gateway partner (Firecrawl, FAL, OpenAI TTS, Browser Use, Modal) and which are routed via Nous. |
|
||||
|
||||
For configuration of the gateway itself, see [Tool Gateway](../user-guide/features/tool-gateway.md). For the one-shot setup path, see `hermes setup --portal` above.
|
||||
|
||||
## `hermes whatsapp`
|
||||
|
||||
|
|
@ -318,6 +345,122 @@ Run `hermes slack manifest --write` again after `hermes update` to pick
|
|||
up any new commands.
|
||||
|
||||
|
||||
## `hermes send`
|
||||
|
||||
```bash
|
||||
hermes send --to <target> "message text"
|
||||
hermes send --to <target> --file <path>
|
||||
echo "message" | hermes send --to <target>
|
||||
hermes send --list [platform]
|
||||
```
|
||||
|
||||
Send a one-shot message to a configured messaging platform without spinning up an agent or gateway loop. Reuses the gateway's already-configured credentials (`~/.hermes/.env` + `~/.hermes/config.yaml`) so ops scripts, cron jobs, CI hooks, and monitoring daemons can post status updates without reimplementing each platform's REST client.
|
||||
|
||||
For bot-token platforms (Telegram, Discord, Slack, Signal, SMS, WhatsApp-CloudAPI) no running gateway is required — `hermes send` talks directly to the platform's REST endpoint. Plugin platforms that need a persistent adapter still require a live gateway.
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `-t`, `--to <TARGET>` | Delivery target. Formats: `platform` (uses home channel), `platform:chat_id`, `platform:chat_id:thread_id`, or `platform:#channel-name`. Examples: `telegram`, `telegram:-1001234567890`, `discord:#ops`, `slack:C0123ABCD`, `signal:+15551234567`. |
|
||||
| `-f`, `--file <PATH>` | Read the message body from `PATH`. Pass `-` to force reading from stdin. |
|
||||
| `-s`, `--subject <LINE>` | Prepend a subject/header line before the message body. |
|
||||
| `-l`, `--list [platform]` | List configured targets across all platforms (or only the given platform). |
|
||||
| `-q`, `--quiet` | Suppress stdout on success — useful in scripts (rely on exit code only). |
|
||||
| `--json` | Emit raw JSON result instead of human-readable output. |
|
||||
|
||||
If neither a positional `message` argument nor `--file` is provided, `hermes send` reads from stdin when it is not a TTY. Exit codes: `0` on success, `1` on delivery/backend failure, `2` on usage errors.
|
||||
|
||||
Examples:
|
||||
|
||||
```bash
|
||||
hermes send --to telegram "deploy finished"
|
||||
echo "RAM 92%" | hermes send --to telegram:-1001234567890
|
||||
hermes send --to discord:#ops --file /tmp/report.md
|
||||
hermes send --to slack:#eng --subject "[CI]" --file build.log
|
||||
hermes send --list # all platforms
|
||||
hermes send --list telegram # filter by platform
|
||||
```
|
||||
|
||||
|
||||
## `hermes secrets`
|
||||
|
||||
```bash
|
||||
hermes secrets bitwarden <subcommand>
|
||||
hermes secrets bw <subcommand> # short alias
|
||||
```
|
||||
|
||||
Pull API keys from an external secret manager at process startup instead of storing them in `~/.hermes/.env`. Currently supports **Bitwarden Secrets Manager**. See the full guide: [Bitwarden integration](../user-guide/secrets/bitwarden.md).
|
||||
|
||||
`bitwarden` (alias `bw`) subcommands:
|
||||
|
||||
| Subcommand | Description |
|
||||
|------------|-------------|
|
||||
| `setup` | Interactive wizard: install the pinned `bws` binary, store an access token, and pick a project. Accepts `--project-id`, `--access-token`, and `--server-url` for non-interactive use. |
|
||||
| `status` | Show current config, binary path/version, and last fetch info. |
|
||||
| `sync` | Fetch secrets now and report what changed. Add `--apply` to actually export the secrets into the current shell's environment (default is dry-run). |
|
||||
| `install` | Download and verify the pinned `bws` binary. `--force` re-downloads even if a managed copy already exists. |
|
||||
| `disable` | Turn off the Bitwarden integration. |
|
||||
|
||||
|
||||
## `hermes migrate`
|
||||
|
||||
```bash
|
||||
hermes migrate <type>
|
||||
```
|
||||
|
||||
Diagnose and (optionally) rewrite the active `config.yaml` to replace references to retired models or deprecated settings. A timestamped backup of the original `config.yaml` is taken before any rewrite (skip with `--no-backup`).
|
||||
|
||||
| Subcommand | Description |
|
||||
|------------|-------------|
|
||||
| `xai` | Scan `config.yaml` for references to xAI models scheduled for retirement on May 15, 2026 and (with `--apply`) rewrite them in-place to the official replacements per the xAI migration guide. Defaults to dry-run. |
|
||||
|
||||
Common flags for migration subcommands:
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--apply` | Rewrite `config.yaml` in-place (default: dry-run, no writes). |
|
||||
| `--no-backup` | Skip the timestamped backup of `config.yaml` when applying. |
|
||||
|
||||
> Not to be confused with `hermes claw migrate` (one-shot import of OpenClaw configuration into Hermes) — `hermes migrate` is the top-level config-rewrite command.
|
||||
|
||||
|
||||
## `hermes proxy`
|
||||
|
||||
```bash
|
||||
hermes proxy <subcommand>
|
||||
```
|
||||
|
||||
Run a local OpenAI-compatible HTTP server that forwards requests to an OAuth-authenticated upstream provider (e.g. Nous Portal, xAI). External apps can point at the proxy with any bearer token; the proxy attaches your real OAuth credentials on the way out. See [Subscription Proxy](../user-guide/features/subscription-proxy.md) for the full guide.
|
||||
|
||||
| Subcommand | Description |
|
||||
|------------|-------------|
|
||||
| `start` | Run the proxy in the foreground. Flags: `--provider <nous\|xai>` (default `nous`), `--host <addr>` (default `127.0.0.1`; use `0.0.0.0` to expose on LAN), `--port <int>` (default `8645`). |
|
||||
| `status` | Show which proxy upstreams are ready (credentials present, OAuth valid). |
|
||||
| `providers` | List available proxy upstream providers. |
|
||||
|
||||
|
||||
## `hermes security`
|
||||
|
||||
```bash
|
||||
hermes security <subcommand>
|
||||
```
|
||||
|
||||
On-demand vulnerability scan against [OSV.dev](https://osv.dev). Covers the Hermes venv (installed PyPI distributions), Python dependencies declared by plugins under `~/.hermes/plugins/`, and pinned `npx`/`uvx` MCP servers in `config.yaml`. Does NOT scan globally-installed packages or editor/browser extensions.
|
||||
|
||||
| Subcommand | Description |
|
||||
|------------|-------------|
|
||||
| `audit` | Run a one-shot supply-chain audit. |
|
||||
|
||||
`audit` flags:
|
||||
|
||||
| Flag | Default | Description |
|
||||
|------|---------|-------------|
|
||||
| `--json` | off | Emit machine-readable JSON instead of human-readable text. |
|
||||
| `--fail-on <level>` | `critical` | Exit non-zero when any finding meets this severity (`low`, `moderate`, `high`, `critical`). |
|
||||
| `--skip-venv` | off | Skip scanning the Hermes Python venv. |
|
||||
| `--skip-plugins` | off | Skip scanning plugin requirements files. |
|
||||
| `--skip-mcp` | off | Skip scanning pinned MCP servers in `config.yaml`. |
|
||||
|
||||
|
||||
## `hermes login` / `hermes logout` *(Deprecated)*
|
||||
|
||||
:::caution
|
||||
|
|
@ -326,7 +469,7 @@ up any new commands.
|
|||
|
||||
## `hermes auth`
|
||||
|
||||
Manage credential pools for same-provider key rotation. See [Credential Pools](/docs/user-guide/features/credential-pools) for full documentation.
|
||||
Manage credential pools for same-provider key rotation. See [Credential Pools](/user-guide/features/credential-pools) for full documentation.
|
||||
|
||||
```bash
|
||||
hermes auth # Interactive wizard
|
||||
|
|
@ -386,7 +529,7 @@ Multi-profile, multi-project collaboration board. Each install can host many boa
|
|||
|------|---------|
|
||||
| `--board <slug>` | Operate on a specific board. Defaults to the current board (set via `hermes kanban boards switch`, the `HERMES_KANBAN_BOARD` env var, or `default`). |
|
||||
|
||||
**This is the human / scripting surface.** Agent workers spawned by the dispatcher drive the board through a dedicated `kanban_*` [toolset](/docs/user-guide/features/kanban#how-workers-interact-with-the-board) (`kanban_show`, `kanban_complete`, `kanban_block`, `kanban_create`, `kanban_link`, `kanban_comment`, `kanban_heartbeat`; orchestrator profiles also get `kanban_list` and `kanban_unblock`) instead of shelling to `hermes kanban`. Workers have `HERMES_KANBAN_BOARD` pinned in their env so they physically cannot see other boards.
|
||||
**This is the human / scripting surface.** Agent workers spawned by the dispatcher drive the board through a dedicated `kanban_*` [toolset](/user-guide/features/kanban#how-workers-interact-with-the-board) (`kanban_show`, `kanban_complete`, `kanban_block`, `kanban_create`, `kanban_link`, `kanban_comment`, `kanban_heartbeat`; orchestrator profiles also get `kanban_list` and `kanban_unblock`) instead of shelling to `hermes kanban`. Workers have `HERMES_KANBAN_BOARD` pinned in their env so they physically cannot see other boards.
|
||||
|
||||
| Action | Purpose |
|
||||
|--------|---------|
|
||||
|
|
@ -414,7 +557,7 @@ Multi-profile, multi-project collaboration board. Each install can host many boa
|
|||
| `dispatch` | One dispatcher pass on the active board. Flags: `--dry-run`, `--max N`, `--failure-limit N`, `--json`. |
|
||||
| `context <id>` | Print the full context a worker would see (title + body + parent results + comments). |
|
||||
| `specify <id>` / `specify --all` | Flesh out a triage-column task into a concrete spec (title + body with goal, approach, acceptance criteria) via the auxiliary LLM, then promote it to `todo`. Flags: `--tenant` (scope `--all` to one tenant), `--author`, `--json`. Configure the model under `auxiliary.triage_specifier` in `config.yaml`. |
|
||||
| `decompose <id>` / `decompose --all` | Fan a triage-column task out into a graph of child tasks routed to specialist profiles by description (the orchestrator-driven path). Falls back to specify-style single-task promotion when the LLM decides the task doesn't benefit from fan-out. Same flags as `specify`. Configure the model under `auxiliary.kanban_decomposer` in `config.yaml`. Also runs automatically every dispatcher tick when `kanban.auto_decompose: true` (the default). See [Auto vs Manual orchestration](/docs/user-guide/features/kanban#auto-vs-manual-orchestration). |
|
||||
| `decompose <id>` / `decompose --all` | Fan a triage-column task out into a graph of child tasks routed to specialist profiles by description. Falls back to specify-style single-task promotion when the LLM decides the task doesn't benefit from fan-out. Same flags as `specify`. Configure the decomposer model under `auxiliary.kanban_decomposer` in `config.yaml`; `kanban.orchestrator_profile` only controls who owns the root/orchestration task after fan-out. Also runs automatically every dispatcher tick when `kanban.auto_decompose: true` (the default). See [Auto vs Manual orchestration](/user-guide/features/kanban#auto-vs-manual-orchestration). |
|
||||
| `gc` | Remove scratch workspaces for archived tasks. |
|
||||
|
||||
Examples:
|
||||
|
|
@ -437,7 +580,7 @@ Board resolution order (highest precedence first): `--board <slug>` flag → `HE
|
|||
|
||||
All actions are also available as a slash command in the gateway (`/kanban …`), with the same argument surface — including `boards` subcommands and the `--board` flag.
|
||||
|
||||
For the full design — comparison with Cline Kanban / Paperclip / NanoClaw / Gemini Enterprise, eight collaboration patterns, four user stories, concurrency correctness proof — see `docs/hermes-kanban-v1-spec.pdf` in the repository or the [Kanban user guide](/docs/user-guide/features/kanban).
|
||||
For the full design — comparison with Cline Kanban / Paperclip / NanoClaw / Gemini Enterprise, eight collaboration patterns, four user stories, concurrency correctness proof — see `docs/hermes-kanban-v1-spec.pdf` in the repository or the [Kanban user guide](/user-guide/features/kanban).
|
||||
|
||||
## `hermes webhook`
|
||||
|
||||
|
|
@ -692,6 +835,8 @@ View, tail, and filter Hermes log files. All logs are stored in `~/.hermes/logs/
|
|||
| `agent` (default) | `agent.log` | All agent activity — API calls, tool dispatch, session lifecycle (INFO and above) |
|
||||
| `errors` | `errors.log` | Warnings and errors only — a filtered subset of agent.log |
|
||||
| `gateway` | `gateway.log` | Messaging gateway activity — platform connections, message dispatch, webhook events |
|
||||
| `gui` | `gui.log` | Dashboard / TUI-gateway / PTY-bridge / websocket events |
|
||||
| `desktop` | `desktop.log` | Electron desktop app — boot, backend spawn output, and recent Python tracebacks |
|
||||
|
||||
### Options
|
||||
|
||||
|
|
@ -745,6 +890,50 @@ Lines without a parseable timestamp are included when `--since` is active (they
|
|||
|
||||
Hermes uses Python's `RotatingFileHandler`. Old logs are rotated automatically — look for `agent.log.1`, `agent.log.2`, etc. The `hermes logs list` subcommand shows all log files including rotated ones.
|
||||
|
||||
|
||||
## `hermes prompt-size`
|
||||
|
||||
```bash
|
||||
hermes prompt-size [--platform <name>] [--json]
|
||||
```
|
||||
|
||||
Reports the fixed prompt budget for a fresh session — what gets sent on every
|
||||
API call *before* any conversation content. Useful when a downstream adapter or
|
||||
proxy has a tighter prompt budget than the model's context window, or when you
|
||||
want to see which block (skills index, memory, profile) dominates.
|
||||
|
||||
It builds the same system prompt the agent would, then breaks it down:
|
||||
|
||||
- **System prompt total** — full assembled prompt (identity, guidance, skills
|
||||
index, context files, memory, profile, timestamp).
|
||||
- **Skills index** — the `<available_skills>` block. This is often the largest
|
||||
single block when many skills are installed.
|
||||
- **Memory** and **user profile** — your `MEMORY.md` / `USER.md` snapshots.
|
||||
- **Prompt tiers** — stable / context / volatile, matching how Hermes layers
|
||||
the prompt for cache-friendliness.
|
||||
- **Tool schemas** — the JSON for all enabled tools (the other half of the
|
||||
fixed per-call payload).
|
||||
|
||||
Runs entirely offline — no API call, works with no credentials configured.
|
||||
|
||||
```bash
|
||||
# Human-readable breakdown for the CLI platform (default)
|
||||
hermes prompt-size
|
||||
|
||||
# Simulate a messaging platform's prompt (different platform hint)
|
||||
hermes prompt-size --platform telegram
|
||||
|
||||
# Machine-readable output for scripts
|
||||
hermes prompt-size --json
|
||||
```
|
||||
|
||||
:::tip
|
||||
The skills index and tool schemas scale with how many skills and tools you have
|
||||
enabled. To shrink the prompt, disable unused toolsets (`hermes tools`) or
|
||||
uninstall skills you don't need (`hermes skills`). Context files (AGENTS.md,
|
||||
.cursorrules) in your current directory also count toward the total.
|
||||
:::
|
||||
|
||||
## `hermes config`
|
||||
|
||||
```bash
|
||||
|
|
@ -796,6 +985,8 @@ Subcommands:
|
|||
| `audit` | Re-scan installed hub skills. |
|
||||
| `uninstall` | Remove a hub-installed skill. |
|
||||
| `reset` | Un-stick a bundled skill flagged as `user_modified` by clearing its manifest entry. With `--restore`, also replaces the user copy with the bundled version. |
|
||||
| `opt-out` | Stop bundled skills from being seeded into the active profile. Writes a `.no-bundled-skills` marker so the installer, `hermes update`, and any sync skip bundled-skill seeding. Safe by default — nothing on disk is touched. With `--remove`, also deletes already-present bundled skills that are **unmodified** (user-edited, hub-installed, and hand-written skills are never removed; previews and confirms first, `--yes` to skip). |
|
||||
| `opt-in` | Undo `opt-out` by removing the `.no-bundled-skills` marker so bundled skills are seeded again on the next `hermes update`. With `--sync`, re-seed immediately. |
|
||||
| `publish` | Publish a skill to a registry. |
|
||||
| `snapshot` | Export/import skill configurations. |
|
||||
| `tap` | Manage custom skill sources. |
|
||||
|
|
@ -819,6 +1010,9 @@ hermes skills update
|
|||
hermes skills config
|
||||
hermes skills reset google-workspace
|
||||
hermes skills reset google-workspace --restore --yes
|
||||
hermes skills opt-out # stop future bundled-skill seeding (nothing deleted)
|
||||
hermes skills opt-out --remove --yes # also delete UNMODIFIED bundled skills
|
||||
hermes skills opt-in --sync # undo: remove marker and re-seed now
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
|
@ -982,8 +1176,11 @@ Manage MCP (Model Context Protocol) server configurations and run Hermes as an M
|
|||
|
||||
| Subcommand | Description |
|
||||
|------------|-------------|
|
||||
| *(none)* or `picker` | Interactive catalog picker — browse Nous-approved MCPs and install/enable/disable. |
|
||||
| `catalog` | List Nous-approved MCPs (plain text, scriptable). |
|
||||
| `install <name>` | Install a catalog entry (e.g. `hermes mcp install n8n`). |
|
||||
| `serve [-v\|--verbose]` | Run Hermes as an MCP server — expose conversations to other agents. |
|
||||
| `add <name> [--url URL] [--command CMD] [--args ...] [--auth oauth\|header]` | Add an MCP server with automatic tool discovery. |
|
||||
| `add <name> [--url URL] [--command CMD] [--args ...] [--auth oauth\|header]` | Add a custom MCP server with automatic tool discovery. |
|
||||
| `remove <name>` (alias: `rm`) | Remove an MCP server from config. |
|
||||
| `list` (alias: `ls`) | List configured MCP servers. |
|
||||
| `test <name>` | Test connection to an MCP server. |
|
||||
|
|
@ -1145,14 +1342,13 @@ hermes claw migrate --source /home/user/old-openclaw
|
|||
hermes dashboard [options]
|
||||
```
|
||||
|
||||
Launch the web dashboard — a browser-based UI for managing configuration, API keys, and monitoring sessions. Requires `pip install hermes-agent[web]` (FastAPI + Uvicorn). The embedded browser Chat tab requires `--tui` plus the `pty` extra. See [Web Dashboard](/docs/user-guide/features/web-dashboard) for full documentation.
|
||||
Launch the web dashboard — a browser-based UI for managing configuration, API keys, and monitoring sessions. Requires `pip install hermes-agent[web]` (FastAPI + Uvicorn). The embedded browser Chat tab is always available and additionally needs the `pty` extra (`pip install 'hermes-agent[web,pty]'`) plus a POSIX PTY environment such as Linux, macOS, or WSL2. See [Web Dashboard](/user-guide/features/web-dashboard) for full documentation.
|
||||
|
||||
| Option | Default | Description |
|
||||
|--------|---------|-------------|
|
||||
| `--port` | `9119` | Port to run the web server on |
|
||||
| `--host` | `127.0.0.1` | Bind address |
|
||||
| `--no-open` | — | Don't auto-open the browser |
|
||||
| `--tui` | off | Enable the in-browser Chat tab by running `hermes --tui` behind a PTY/WebSocket bridge. Requires `pip install 'hermes-agent[web,pty]'` and a POSIX PTY environment such as Linux, macOS, or WSL2. |
|
||||
| `--insecure` | off | Allow binding to non-localhost hosts. Exposes dashboard credentials on the network; use only behind trusted network controls. |
|
||||
| `--stop` | — | Stop running `hermes dashboard` processes and exit. |
|
||||
| `--status` | — | List running `hermes dashboard` processes and exit. |
|
||||
|
|
@ -1163,9 +1359,6 @@ hermes dashboard
|
|||
|
||||
# Custom port, no browser
|
||||
hermes dashboard --port 8080 --no-open
|
||||
|
||||
# Enable the browser Chat tab
|
||||
hermes dashboard --tui
|
||||
```
|
||||
|
||||
## `hermes profile`
|
||||
|
|
@ -1229,21 +1422,28 @@ hermes completion fish > ~/.config/fish/completions/hermes.fish
|
|||
## `hermes update`
|
||||
|
||||
```bash
|
||||
hermes update [--check] [--backup] [--restart-gateway]
|
||||
hermes update [--gateway] [--check] [--no-backup] [--backup] [--yes]
|
||||
```
|
||||
|
||||
Pulls the latest `hermes-agent` code and reinstalls dependencies in your venv, then re-runs the post-install hooks (MCP servers, skills sync, completion install). Safe to run on a live install.
|
||||
|
||||
**pip installs:** `hermes update` detects pip-based installations automatically — it queries PyPI for the latest release and runs `pip install --upgrade hermes-agent` instead of `git pull`. PyPI releases track tagged versions (major/minor releases), not every commit on `main`. Use `--check` to see if a newer PyPI release is available without installing.
|
||||
|
||||
**git installs:** `hermes update` pulls the configured update branch (default: `main`). If your checkout is on another branch, Hermes may check out the update branch before pulling. Commit branch work before updating when you want to keep it outside the update autostash flow.
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `--check` | Print the current commit and the latest `origin/main` commit side by side, and exit 0 if in sync or 1 if behind. Does not pull, install, or restart anything. |
|
||||
| `--backup` | Create a labeled pre-update snapshot of `HERMES_HOME` (config, auth, sessions, skills, pairing data) before pulling. Default is **off** — the previous always-backup behavior was adding minutes to every update on large homes. Flip it on permanently via `update.backup: true` in `config.yaml`. |
|
||||
| `--restart-gateway` | After a successful update, restart the running gateway service. Implies `--all` semantics if multiple profiles are installed. |
|
||||
| `--gateway` | Internal mode used by the messaging `/update` command. Uses file-based IPC for prompts and progress streaming instead of reading from terminal stdin. Not a gateway restart flag. |
|
||||
| `--check` | Check whether an update is available without pulling, installing dependencies, or restarting anything. |
|
||||
| `--no-backup` | Skip the pre-update backup for this run, even if `updates.pre_update_backup` is enabled in `config.yaml`. |
|
||||
| `--backup` | Create a labeled pre-update snapshot of `HERMES_HOME` (config, auth, sessions, skills, pairing data) before pulling. Default is **off** — the previous always-backup behavior was adding minutes to every update on large homes. Flip it on permanently via `updates.pre_update_backup: true` in `config.yaml`. |
|
||||
| `--yes`, `-y` | Assume yes for interactive prompts such as config migration and stash restore. API-key entry is skipped; run `hermes config migrate` separately for those. |
|
||||
|
||||
Additional behavior:
|
||||
|
||||
- **Gateway restart.** After a successful update, Hermes attempts to restart all running gateway profiles automatically so they pick up the new code. Use `hermes gateway restart` when you want to restart a gateway without applying an update.
|
||||
- **Local source changes.** For git installs, dirty tracked files and untracked files are auto-stashed before branch checkout or pull (`git stash push --include-untracked`). Interactive terminal updates ask before restoring the stash. Non-interactive updates restore it by default; set `updates.non_interactive_local_changes: discard` only on managed installs where local source edits should be thrown away after a successful pull. If stash restore conflicts or the pull fails, the stash is left in place for manual recovery.
|
||||
- **npm lockfile churn.** Before stashing or switching branches, Hermes makes a best-effort cleanup of tracked `package-lock.json` diffs produced by npm install/build steps. Commit or manually stash intentional lockfile edits before running `hermes update`.
|
||||
- **Pairing data snapshot.** Even when `--backup` is off, `hermes update` takes a lightweight snapshot of `~/.hermes/pairing/` and the Feishu comment rules before `git pull`. You can roll it back with `hermes backup restore --state pre-update` if a pull rewrites a file you were editing.
|
||||
- **Legacy `hermes.service` warning.** If Hermes detects a pre-rename `hermes.service` systemd unit (instead of the current `hermes-gateway.service`), it prints a one-time migration hint so you can avoid flap-loop issues.
|
||||
- **Exit codes.** `0` on success, `1` on pull/install/post-install errors, `2` on unexpected working-tree changes that block `git pull`.
|
||||
|
|
@ -1254,7 +1454,8 @@ Additional behavior:
|
|||
|---------|-------------|
|
||||
| `hermes version` | Print version information. |
|
||||
| `hermes update` | Pull latest changes and reinstall dependencies. |
|
||||
| `hermes uninstall [--full] [--yes]` | Remove Hermes, optionally deleting all config/data. |
|
||||
| `hermes postinstall` | Internal bootstrap. Runs once after `pip install hermes-agent` (or `hermes update` on pip installs) to install non-Python dependencies that pip cannot provide — Node.js runtime, headless browser, ripgrep, ffmpeg — and then trigger `hermes setup` if the profile has not been configured yet. Safe to re-run idempotently. |
|
||||
| `hermes uninstall [--full] [--gui] [--yes]` | Remove Hermes, optionally deleting all config/data. `--gui` removes only the desktop Chat GUI, leaving the agent intact; `--full` also deletes config/data; `--yes` skips prompts. |
|
||||
|
||||
## See also
|
||||
|
||||
|
|
|
|||
|
|
@ -18,10 +18,10 @@ All variables go in `~/.hermes/.env`. You can also set them with `hermes config
|
|||
| `HERMES_OPENROUTER_CACHE_TTL` | Cache TTL in seconds (1-86400). Overrides `openrouter.response_cache_ttl` in config.yaml. |
|
||||
| `NOUS_BASE_URL` | Override Nous Portal base URL (rarely needed; development/testing only) |
|
||||
| `NOUS_INFERENCE_BASE_URL` | Override Nous inference endpoint directly |
|
||||
| `AI_GATEWAY_API_KEY` | Vercel AI Gateway API key ([ai-gateway.vercel.sh](https://ai-gateway.vercel.sh)) |
|
||||
| `AI_GATEWAY_BASE_URL` | Override AI Gateway base URL (default: `https://ai-gateway.vercel.sh/v1`) |
|
||||
| `OPENAI_API_KEY` | API key for custom OpenAI-compatible endpoints (used with `OPENAI_BASE_URL`) |
|
||||
| `OPENAI_BASE_URL` | Base URL for custom endpoint (VLLM, SGLang, etc.) |
|
||||
| `LM_API_KEY` | API key for LM Studio (`lmstudio` provider). Often a placeholder for local servers |
|
||||
| `LM_BASE_URL` | LM Studio base URL (default: `http://localhost:1234/v1`) |
|
||||
| `COPILOT_GITHUB_TOKEN` | GitHub token for Copilot API — first priority (OAuth `gho_*` or fine-grained PAT `github_pat_*`; classic PATs `ghp_*` are **not supported**) |
|
||||
| `GH_TOKEN` | GitHub token — second priority for Copilot (also used by `gh` CLI) |
|
||||
| `GITHUB_TOKEN` | GitHub token — third priority for Copilot |
|
||||
|
|
@ -29,11 +29,13 @@ All variables go in `~/.hermes/.env`. You can also set them with `hermes config
|
|||
| `COPILOT_CLI_PATH` | Alias for `HERMES_COPILOT_ACP_COMMAND` |
|
||||
| `HERMES_COPILOT_ACP_ARGS` | Override Copilot ACP arguments (default: `--acp --stdio`) |
|
||||
| `COPILOT_ACP_BASE_URL` | Override Copilot ACP base URL |
|
||||
| `COPILOT_API_BASE_URL` | Override the Copilot API base URL (`copilot` provider) |
|
||||
| `GLM_API_KEY` | z.ai / ZhipuAI GLM API key ([z.ai](https://z.ai)) |
|
||||
| `ZAI_API_KEY` | Alias for `GLM_API_KEY` |
|
||||
| `Z_AI_API_KEY` | Alias for `GLM_API_KEY` |
|
||||
| `GLM_BASE_URL` | Override z.ai base URL (default: `https://api.z.ai/api/paas/v4`) |
|
||||
| `KIMI_API_KEY` | Kimi / Moonshot AI API key ([moonshot.ai](https://platform.moonshot.ai)) |
|
||||
| `KIMI_CODING_API_KEY` | Alias key for the `kimi-coding` provider (accepted alongside `KIMI_API_KEY`) |
|
||||
| `KIMI_BASE_URL` | Override Kimi base URL (default: `https://api.moonshot.ai/v1`) |
|
||||
| `KIMI_CN_API_KEY` | Kimi / Moonshot China API key ([moonshot.cn](https://platform.moonshot.cn)) |
|
||||
| `ARCEEAI_API_KEY` | Arcee AI API key ([chat.arcee.ai](https://chat.arcee.ai/)) |
|
||||
|
|
@ -58,7 +60,7 @@ All variables go in `~/.hermes/.env`. You can also set them with `hermes config
|
|||
| `AZURE_CLIENT_SECRET` | Service principal secret used by `EnvironmentCredential` |
|
||||
| `AZURE_CLIENT_CERTIFICATE_PATH` | Service principal certificate (alternative to `AZURE_CLIENT_SECRET`) |
|
||||
| `AZURE_FEDERATED_TOKEN_FILE` | Federated token file path for AKS Workload Identity / OIDC flows |
|
||||
| `AZURE_AUTHORITY_HOST` | Sovereign-cloud authority override (e.g. `https://login.microsoftonline.us` for Azure Government). See [Azure Foundry guide](/docs/guides/azure-foundry#sovereign-clouds-government-china) |
|
||||
| `AZURE_AUTHORITY_HOST` | Sovereign-cloud authority override (e.g. `https://login.microsoftonline.us` for Azure Government). See [Azure Foundry guide](/guides/azure-foundry#sovereign-clouds-government-china) |
|
||||
| `IDENTITY_ENDPOINT` / `MSI_ENDPOINT` | Managed Identity endpoint for App Service, Functions, and Container Apps; VMs usually use IMDS instead and do not set these |
|
||||
| `HF_TOKEN` | Hugging Face token for Inference Providers ([huggingface.co/settings/tokens](https://huggingface.co/settings/tokens)) |
|
||||
| `HF_BASE_URL` | Override Hugging Face base URL (default: `https://router.huggingface.co/v1`) |
|
||||
|
|
@ -69,9 +71,12 @@ All variables go in `~/.hermes/.env`. You can also set them with `hermes config
|
|||
| `HERMES_GEMINI_CLIENT_SECRET` | OAuth client secret for `google-gemini-cli` (optional) |
|
||||
| `HERMES_GEMINI_PROJECT_ID` | GCP project ID for paid Gemini tiers (free tier auto-provisions) |
|
||||
| `ANTHROPIC_API_KEY` | Anthropic Console API key ([console.anthropic.com](https://console.anthropic.com/)) |
|
||||
| `ANTHROPIC_BASE_URL` | Override the Anthropic API base URL |
|
||||
| `ANTHROPIC_TOKEN` | Manual or legacy Anthropic OAuth/setup-token override |
|
||||
| `DASHSCOPE_API_KEY` | Qwen Cloud (Alibaba DashScope) API key for Qwen models ([modelstudio.console.alibabacloud.com](https://modelstudio.console.alibabacloud.com/)) |
|
||||
| `DASHSCOPE_BASE_URL` | Custom DashScope base URL (default: `https://dashscope-intl.aliyuncs.com/compatible-mode/v1`; use `https://dashscope.aliyuncs.com/compatible-mode/v1` for mainland-China region) |
|
||||
| `ALIBABA_CODING_PLAN_API_KEY` | Qwen Coding Plan API key (`alibaba-coding-plan` provider) |
|
||||
| `ALIBABA_CODING_PLAN_BASE_URL` | Override the Qwen Coding Plan base URL |
|
||||
| `DEEPSEEK_API_KEY` | DeepSeek API key for direct DeepSeek access ([platform.deepseek.com](https://platform.deepseek.com/api_keys)) |
|
||||
| `DEEPSEEK_BASE_URL` | Custom DeepSeek API base URL |
|
||||
| `NOVITA_API_KEY` | NovitaAI API key — AI-native cloud for Model API, Agent Sandbox, and GPU Cloud ([novita.ai/settings/key-management](https://novita.ai/settings/key-management)) |
|
||||
|
|
@ -113,7 +118,6 @@ For native Anthropic auth, Hermes prefers Claude Code's own credential files whe
|
|||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `HERMES_INFERENCE_PROVIDER` | Override provider selection: `auto`, `custom`, `openrouter`, `nous`, `openai-codex`, `copilot`, `copilot-acp`, `anthropic`, `huggingface`, `novita`, `gemini`, `zai`, `kimi-coding`, `kimi-coding-cn`, `minimax`, `minimax-cn`, `minimax-oauth` (browser OAuth login — no API key required; see [MiniMax OAuth guide](../guides/minimax-oauth.md)), `kilocode`, `xiaomi`, `arcee`, `gmi`, `stepfun`, `alibaba`, `alibaba-coding-plan` (alias `alibaba_coding`), `deepseek`, `nvidia`, `ollama-cloud`, `xai` (alias `grok`), `xai-oauth` (browser OAuth login for SuperGrok subscribers — no API key required; see [xAI Grok OAuth guide](../guides/xai-grok-oauth.md)), `google-gemini-cli`, `qwen-oauth`, `bedrock`, `opencode-zen`, `opencode-go`, `ai-gateway`, `tencent-tokenhub` (default: `auto`) |
|
||||
| `HERMES_PORTAL_BASE_URL` | Override Nous Portal URL (for development/testing) |
|
||||
| `NOUS_INFERENCE_BASE_URL` | Override Nous inference API URL |
|
||||
| `HERMES_NOUS_MIN_KEY_TTL_SECONDS` | Min agent key TTL before re-mint (default: 1800 = 30min) |
|
||||
|
|
@ -157,14 +161,10 @@ For native Anthropic auth, Hermes prefers Claude Code's own credential files whe
|
|||
| `HINDSIGHT_TIMEOUT` | Timeout in seconds for Hindsight memory-provider API calls (default: `60`). Bump this if your Hindsight instance is slow to respond during `/sync` or `on_session_switch` and you're seeing timeouts in `errors.log`. |
|
||||
| `SUPERMEMORY_API_KEY` | Semantic long-term memory with profile recall and session ingest ([supermemory.ai](https://supermemory.ai)) |
|
||||
| `DAYTONA_API_KEY` | Daytona cloud sandboxes ([daytona.io](https://daytona.io/)) |
|
||||
| `VERCEL_TOKEN` | Vercel Sandbox access token ([vercel.com](https://vercel.com/)) |
|
||||
| `VERCEL_PROJECT_ID` | Vercel project ID (required with `VERCEL_TOKEN`) |
|
||||
| `VERCEL_TEAM_ID` | Vercel team ID (required with `VERCEL_TOKEN`) |
|
||||
| `VERCEL_OIDC_TOKEN` | Vercel short-lived OIDC token (development-only alternative) |
|
||||
|
||||
### Langfuse Observability
|
||||
|
||||
Environment variables for the bundled [`observability/langfuse`](/docs/user-guide/features/built-in-plugins#observabilitylangfuse) plugin. Set these in `~/.hermes/.env`. The plugin must also be enabled (`hermes plugins enable observability/langfuse`, or check the box in `hermes plugins`) before any of these take effect.
|
||||
Environment variables for the bundled [`observability/langfuse`](/user-guide/features/built-in-plugins#observabilitylangfuse) plugin. Set these in `~/.hermes/.env`. The plugin must also be enabled (`hermes plugins enable observability/langfuse`, or check the box in `hermes plugins`) before any of these take effect.
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
|
|
@ -180,7 +180,7 @@ Environment variables for the bundled [`observability/langfuse`](/docs/user-guid
|
|||
|
||||
### Nous Tool Gateway
|
||||
|
||||
These variables configure the [Tool Gateway](/docs/user-guide/features/tool-gateway) for paid Nous subscribers or self-hosted gateway deployments. Most users don't need to set these — the gateway is configured automatically via `hermes model` or `hermes tools`.
|
||||
These variables configure the [Tool Gateway](/user-guide/features/tool-gateway) for paid Nous subscribers or self-hosted gateway deployments. Most users don't need to set these — the gateway is configured automatically via `hermes model` or `hermes tools`.
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
|
|
@ -193,7 +193,7 @@ These variables configure the [Tool Gateway](/docs/user-guide/features/tool-gate
|
|||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `TERMINAL_ENV` | Backend: `local`, `docker`, `ssh`, `singularity`, `modal`, `daytona`, `vercel_sandbox` |
|
||||
| `TERMINAL_ENV` | Backend: `local`, `docker`, `ssh`, `singularity`, `modal`, `daytona` |
|
||||
| `HERMES_DOCKER_BINARY` | Override the container binary Hermes shells out to (e.g. `podman`, `/usr/local/bin/docker`). When unset, Hermes auto-discovers `docker` or `podman` on `PATH`. Needed when both are installed and you want the non-default, or when the binary lives outside `PATH`. |
|
||||
| `TERMINAL_DOCKER_IMAGE` | Docker image (default: `nikolaik/python-nodejs:python3.11-nodejs20`) |
|
||||
| `TERMINAL_DOCKER_FORWARD_ENV` | JSON array of env var names to explicitly forward into Docker terminal sessions. Note: skill-declared `required_environment_variables` are forwarded automatically — you only need this for vars not declared by any skill. |
|
||||
|
|
@ -202,10 +202,9 @@ These variables configure the [Tool Gateway](/docs/user-guide/features/tool-gate
|
|||
| `TERMINAL_SINGULARITY_IMAGE` | Singularity image or `.sif` path |
|
||||
| `TERMINAL_MODAL_IMAGE` | Modal container image |
|
||||
| `TERMINAL_DAYTONA_IMAGE` | Daytona sandbox image |
|
||||
| `TERMINAL_VERCEL_RUNTIME` | Vercel Sandbox runtime (`node24`, `node22`, `python3.13`) |
|
||||
| `TERMINAL_TIMEOUT` | Command timeout in seconds |
|
||||
| `TERMINAL_LIFETIME_SECONDS` | Max lifetime for terminal sessions in seconds |
|
||||
| `TERMINAL_CWD` | Working directory for terminal sessions (gateway/cron only; CLI uses launch dir) |
|
||||
| `TERMINAL_CWD` | Deprecated direct override for gateway/cron terminal sessions. Prefer `terminal.cwd` in `config.yaml`; CLI still uses the launch directory. |
|
||||
| `SUDO_PASSWORD` | Enable sudo without interactive prompt |
|
||||
|
||||
For cloud sandbox backends, persistence is filesystem-oriented. `TERMINAL_LIFETIME_SECONDS` controls when Hermes cleans up an idle terminal session, and later resumes may recreate the sandbox rather than keep the same live processes running.
|
||||
|
|
@ -426,20 +425,40 @@ For cloud sandbox backends, persistence is filesystem-oriented. `TERMINAL_LIFETI
|
|||
| `WEBHOOK_PORT` | HTTP server port for receiving webhooks (default: `8644`) |
|
||||
| `WEBHOOK_SECRET` | Global HMAC secret for webhook signature validation (used as fallback when routes don't specify their own) |
|
||||
| `API_SERVER_ENABLED` | Enable the OpenAI-compatible API server (`true`/`false`). Runs alongside other platforms. |
|
||||
| `API_SERVER_KEY` | Bearer token for API server authentication. Enforced for non-loopback binding. |
|
||||
| `API_SERVER_KEY` | Bearer token for API server authentication. Required whenever the API server is enabled. |
|
||||
| `API_SERVER_CORS_ORIGINS` | Comma-separated browser origins allowed to call the API server directly (for example `http://localhost:3000,http://127.0.0.1:3000`). Default: disabled. |
|
||||
| `API_SERVER_PORT` | Port for the API server (default: `8642`) |
|
||||
| `API_SERVER_HOST` | Host/bind address for the API server (default: `127.0.0.1`). Use `0.0.0.0` for network access — requires `API_SERVER_KEY` and a narrow `API_SERVER_CORS_ORIGINS` allowlist. |
|
||||
| `API_SERVER_HOST` | Host/bind address for the API server (default: `127.0.0.1`). `API_SERVER_KEY` is still required on loopback; use a narrow `API_SERVER_CORS_ORIGINS` allowlist for browser access. |
|
||||
| `API_SERVER_MODEL_NAME` | Model name advertised on `/v1/models`. Defaults to the profile name (or `hermes-agent` for the default profile). Useful for multi-user setups where frontends like Open WebUI need distinct model names per connection. |
|
||||
| `GATEWAY_PROXY_URL` | URL of a remote Hermes API server to forward messages to ([proxy mode](/docs/user-guide/messaging/matrix#proxy-mode-e2ee-on-macos)). When set, the gateway handles platform I/O only — all agent work is delegated to the remote server. Also configurable via `gateway.proxy_url` in `config.yaml`. |
|
||||
| `GATEWAY_PROXY_URL` | URL of a remote Hermes API server to forward messages to ([proxy mode](/user-guide/messaging/matrix#proxy-mode-e2ee-on-macos)). When set, the gateway handles platform I/O only — all agent work is delegated to the remote server. Also configurable via `gateway.proxy_url` in `config.yaml`. |
|
||||
| `GATEWAY_PROXY_KEY` | Bearer token for authenticating with the remote API server in proxy mode. Must match `API_SERVER_KEY` on the remote host. |
|
||||
| `MESSAGING_CWD` | Working directory for terminal commands in messaging mode (default: `~`) |
|
||||
| `MESSAGING_CWD` | Deprecated compatibility fallback for gateway working directory. Prefer `terminal.cwd` in `config.yaml`. |
|
||||
| `GATEWAY_ALLOWED_USERS` | Comma-separated user IDs allowed across all platforms |
|
||||
| `GATEWAY_ALLOW_ALL_USERS` | Allow all users without allowlists (`true`/`false`, default: `false`) |
|
||||
|
||||
### Web Dashboard & Hermes Desktop
|
||||
|
||||
Auth for the [web dashboard](/user-guide/features/web-dashboard) and for connecting [Hermes Desktop to a remote backend](/user-guide/features/web-dashboard#connecting-hermes-desktop-to-a-remote-backend). Per the secrets-only convention, credentials belong in `~/.hermes/.env`; the OAuth `client_id` is better set under `dashboard.oauth` in `config.yaml` (env wins when set).
|
||||
|
||||
Three dashboard-auth providers ship in the box. For a remote Hermes Desktop connection or any internet-facing dashboard, the recommended provider is **OAuth (Nous Portal)** — set `HERMES_DASHBOARD_OAUTH_CLIENT_ID` (provision it with `hermes dashboard register`). The bundled **username/password** provider (`HERMES_DASHBOARD_BASIC_AUTH_*`) is the quickest option for a backend on a trusted LAN or behind a VPN, but is not suitable for direct public-internet exposure. To authenticate against your own identity provider, use the **self-hosted OIDC** provider (`HERMES_DASHBOARD_OIDC_*`). Either way, a non-loopback bind (`hermes dashboard --host 0.0.0.0`) engages the auth gate. See [Web Dashboard → Authentication](/user-guide/features/web-dashboard#authentication-gated-mode) for the full picture.
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `HERMES_DASHBOARD_BASIC_AUTH_USERNAME` | Username for the bundled username/password dashboard-auth provider (`plugins/dashboard_auth/basic`). Activates the provider when set together with a password. Overrides `dashboard.basic_auth.username`. |
|
||||
| `HERMES_DASHBOARD_BASIC_AUTH_PASSWORD` | Plaintext password for the basic provider (hashed in-memory at load). Wins over a config `password_hash` so you can rotate via env. Overrides `dashboard.basic_auth.password`. |
|
||||
| `HERMES_DASHBOARD_BASIC_AUTH_PASSWORD_HASH` | scrypt password hash for the basic provider (preferred — no plaintext at rest). Compute with `python -c "from plugins.dashboard_auth.basic import hash_password; print(hash_password('PW'))"`. Overrides `dashboard.basic_auth.password_hash`. |
|
||||
| `HERMES_DASHBOARD_BASIC_AUTH_SECRET` | HMAC key (32+ bytes, base64/hex/raw) signing the basic provider's stateless session tokens. Set explicitly so sessions survive restarts / span multiple workers; blank → random per-process (you'll be logged out on every restart). Overrides `dashboard.basic_auth.secret`. |
|
||||
| `HERMES_DASHBOARD_BASIC_AUTH_TTL_SECONDS` | Access-token lifetime for the basic provider (default 12h). Overrides `dashboard.basic_auth.session_ttl_seconds`. |
|
||||
| `HERMES_DASHBOARD_OAUTH_CLIENT_ID` | OAuth client id (`agent:{instance_id}`) for the gated/public dashboard, activating the Nous (`plugins/dashboard_auth/nous`) provider. Overrides `dashboard.oauth.client_id`. Provision it with `hermes dashboard register`. |
|
||||
| `HERMES_DASHBOARD_PUBLIC_URL` | Complete public URL the dashboard is reached at, for OAuth callback construction behind reverse proxies. Overrides `dashboard.public_url`. |
|
||||
| `HERMES_DASHBOARD_OIDC_ISSUER` | OIDC issuer URL for the bundled self-hosted OIDC provider (`plugins/dashboard_auth/self_hosted`). Required to activate it. Overrides `dashboard.oauth.self_hosted.issuer`. |
|
||||
| `HERMES_DASHBOARD_OIDC_CLIENT_ID` | Public OIDC client id (authorization-code + PKCE) for the self-hosted OIDC provider. Required to activate it. Overrides `dashboard.oauth.self_hosted.client_id`. |
|
||||
| `HERMES_DASHBOARD_OIDC_SCOPES` | Requested OIDC scopes for the self-hosted OIDC provider (default `openid profile email`). Overrides `dashboard.oauth.self_hosted.scopes`. |
|
||||
| `HERMES_DESKTOP_REMOTE_URL` | (Desktop side) Base URL of the remote backend, e.g. `http://host:9119`. When set, overrides the in-app Gateway URL; you still sign in from the Gateway settings panel (OAuth redirect or username/password, whichever the backend advertises). |
|
||||
|
||||
### Microsoft Graph (Teams Meetings)
|
||||
|
||||
App-only credentials for the Microsoft Graph REST client used by the upcoming Teams meeting summary pipeline. See [Register a Microsoft Graph application](/docs/guides/microsoft-graph-app-registration) for the Azure portal walkthrough and the exact API permissions required.
|
||||
App-only credentials for the Microsoft Graph REST client used by the upcoming Teams meeting summary pipeline. See [Register a Microsoft Graph application](/guides/microsoft-graph-app-registration) for the Azure portal walkthrough and the exact API permissions required.
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
|
|
@ -451,7 +470,7 @@ App-only credentials for the Microsoft Graph REST client used by the upcoming Te
|
|||
|
||||
### Microsoft Graph Webhook Listener
|
||||
|
||||
Inbound change-notification listener for Graph events (Teams meetings, calendar, chat, etc.). See [Microsoft Graph Webhook Listener](/docs/user-guide/messaging/msgraph-webhook) for setup and security hardening.
|
||||
Inbound change-notification listener for Graph events (Teams meetings, calendar, chat, etc.). See [Microsoft Graph Webhook Listener](/user-guide/messaging/msgraph-webhook) for setup and security hardening.
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
|
|
@ -463,7 +482,7 @@ Inbound change-notification listener for Graph events (Teams meetings, calendar,
|
|||
|
||||
### Teams Meeting Summary Delivery
|
||||
|
||||
Only used when the [`teams_pipeline` plugin](/docs/user-guide/messaging/msgraph-webhook) is enabled. Settings are also configurable under `platforms.teams.extra` in `config.yaml` — env vars take priority when both are set. See [Microsoft Teams → Meeting Summary Delivery](/docs/user-guide/messaging/teams#meeting-summary-delivery-teams-meeting-pipeline).
|
||||
Only used when the [`teams_pipeline` plugin](/user-guide/messaging/msgraph-webhook) is enabled. Settings are also configurable under `platforms.teams.extra` in `config.yaml` — env vars take priority when both are set. See [Microsoft Teams → Meeting Summary Delivery](/user-guide/messaging/teams#meeting-summary-delivery-teams-meeting-pipeline).
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
|
|
@ -476,7 +495,7 @@ Only used when the [`teams_pipeline` plugin](/docs/user-guide/messaging/msgraph-
|
|||
|
||||
### LINE Messaging API
|
||||
|
||||
Used by the bundled LINE platform plugin (`plugins/platforms/line/`). See [Messaging Gateway → LINE](/docs/user-guide/messaging/line) for full setup.
|
||||
Used by the bundled LINE platform plugin (`plugins/platforms/line/`). See [Messaging Gateway → LINE](/user-guide/messaging/line) for full setup.
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
|
|
@ -496,6 +515,24 @@ Used by the bundled LINE platform plugin (`plugins/platforms/line/`). See [Messa
|
|||
| `LINE_DELIVERED_TEXT` | Reply when an already-delivered postback is tapped again (default: `Already replied ✅`). |
|
||||
| `LINE_INTERRUPTED_TEXT` | Reply when a `/stop`-orphaned postback button is tapped (default: `Run was interrupted before completion.`). |
|
||||
|
||||
### ntfy (push notifications)
|
||||
|
||||
[ntfy](https://ntfy.sh/) is a lightweight HTTP-based push notification service. Subscribe to a topic from the [ntfy mobile app](https://ntfy.sh/docs/subscribe/phone/), publish to that topic to talk to the agent.
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `NTFY_TOPIC` | Topic to subscribe to (incoming messages). Required. |
|
||||
| `NTFY_SERVER_URL` | Server URL (default: `https://ntfy.sh`). Point at a self-hosted ntfy for privacy. |
|
||||
| `NTFY_TOKEN` | Optional auth token. Bearer token (e.g. `tk_xyz`) or `user:pass` for Basic auth. |
|
||||
| `NTFY_PUBLISH_TOPIC` | Topic for outgoing replies (defaults to `NTFY_TOPIC`). |
|
||||
| `NTFY_MARKDOWN` | Set `true` to send replies with `X-Markdown: true` header. Default: `false`. |
|
||||
| `NTFY_ALLOWED_USERS` | Allowlist (treated as user IDs; on ntfy these are topic names). Typically set to the same value as `NTFY_TOPIC`. |
|
||||
| `NTFY_ALLOW_ALL_USERS` | Dev-only escape hatch — only safe on access-controlled private topics. Default: `false`. |
|
||||
| `NTFY_HOME_CHANNEL` | Default delivery target for cron jobs with `deliver: ntfy`. |
|
||||
| `NTFY_HOME_CHANNEL_NAME` | Human label for the home channel (defaults to the topic name). |
|
||||
|
||||
See [the ntfy messaging guide](/user-guide/messaging/ntfy) — particularly the **identity model** section — before deploying with untrusted topics.
|
||||
|
||||
### Advanced Messaging Tuning
|
||||
|
||||
Advanced per-platform knobs for throttling the outbound message batcher. Most users never need to touch these; defaults are set to respect each platform's rate limits without feeling sluggish.
|
||||
|
|
@ -521,6 +558,8 @@ Advanced per-platform knobs for throttling the outbound message batcher. Most us
|
|||
| `HERMES_GATEWAY_PLATFORM_CONNECT_TIMEOUT` | Per-platform connect timeout during gateway startup (seconds). |
|
||||
| `HERMES_GATEWAY_BUSY_INPUT_MODE` | Default gateway busy-input behavior: `queue`, `steer`, or `interrupt`. Can be overridden per chat with `/busy`. |
|
||||
| `HERMES_GATEWAY_BUSY_ACK_ENABLED` | Whether the gateway sends an acknowledgment message (⚡/⏳/⏩) when a user sends input while the agent is busy (default: `true`). Set to `false` to suppress these messages entirely — the input is still queued/steered/interrupts as normal, only the chat reply is silenced. Bridged from `display.busy_ack_enabled` in `config.yaml`. |
|
||||
| `HERMES_GATEWAY_NO_SUPERVISE` | Inside the s6-overlay Docker image, opt out of auto-supervision when running `hermes gateway run` and use pre-s6 foreground semantics (no auto-restart, gateway is the container's main process). Truthy values: `1`, `true`, `yes`. Equivalent to the `--no-supervise` CLI flag. No-op outside the s6 image. |
|
||||
| `HERMES_GATEWAY_BOOTSTRAP_STATE` | Inside the s6-overlay Docker image, declare the gateway's **initial** supervised state on a fresh volume. On a blank volume there is no persisted `gateway_state.json`, so the boot reconciler registers the `gateway-default` slot but leaves it **down** (it only auto-starts when the last recorded state was `running`). Set this to `running` and the first-boot setup hook seeds `gateway_state.json` *before* the reconciler runs, so the gateway comes up on the very first boot. Only the literal value `running` is honoured. First-boot-only: an existing `gateway_state.json` is never overwritten, so a deliberately-stopped gateway stays stopped across restarts. No-op outside the s6 image. |
|
||||
| `HERMES_FILE_MUTATION_VERIFIER` | Enable the per-turn file-mutation verifier footer (default: `true`). When enabled, Hermes appends an advisory listing any `write_file` / `patch` calls that failed during the turn and were not superseded by a successful write. Set to `0`, `false`, `no`, or `off` to suppress. Mirrors `display.file_mutation_verifier` in `config.yaml`; the env var wins when set. |
|
||||
| `HERMES_CRON_TIMEOUT` | Inactivity timeout for cron job agent runs in seconds (default: `600`). The agent can run indefinitely while actively calling tools or receiving stream tokens — this only triggers when idle. Set to `0` for unlimited. |
|
||||
| `HERMES_CRON_SCRIPT_TIMEOUT` | Timeout for pre-run scripts attached to cron jobs in seconds (default: `120`). Override for scripts that need longer execution (e.g., randomized delays for anti-bot timing). Also configurable via `cron.script_timeout_seconds` in `config.yaml`. |
|
||||
|
|
@ -555,7 +594,7 @@ Advanced per-platform knobs for throttling the outbound message batcher. Most us
|
|||
| `HERMES_AGENT_NOTIFY_INTERVAL` | Gateway: interval in seconds between progress notifications on long-running agent turns. |
|
||||
| `HERMES_CHECKPOINT_TIMEOUT` | Timeout for filesystem checkpoint creation in seconds (default: `30`). |
|
||||
| `HERMES_EXEC_ASK` | Enable execution approval prompts in gateway mode (`true`/`false`) |
|
||||
| `HERMES_ENABLE_PROJECT_PLUGINS` | Enable auto-discovery of repo-local plugins from `./.hermes/plugins/` (`true`/`false`, default: `false`) |
|
||||
| `HERMES_ENABLE_PROJECT_PLUGINS` | Enable auto-discovery of repo-local plugins from `./.hermes/plugins/` for both the agent loader and the dashboard web server. Accepts the standard truthy set: `1` / `true` / `yes` / `on` (case-insensitive). Everything else — including `0`, `false`, `no`, `off`, and the empty string — is treated as **disabled** (default). Note: as of GHSA-5qr3-c538-wm9j (#29156) the dashboard web server refuses to auto-import a project plugin's Python `api` file even when this var is enabled — project plugins may extend the UI via static JS/CSS but their backend routes are only loaded when moved under `~/.hermes/plugins/`. |
|
||||
| `HERMES_PLUGINS_DEBUG` | `1`/`true` to surface verbose plugin-discovery logs on stderr — directories scanned, manifests parsed, skip reasons, and full tracebacks on parse or `register()` failure. Aimed at plugin authors. |
|
||||
| `HERMES_BACKGROUND_NOTIFICATIONS` | Background process notification mode in gateway: `all` (default), `result`, `error`, `off` |
|
||||
| `HERMES_EPHEMERAL_SYSTEM_PROMPT` | Ephemeral system prompt injected at API-call time (never persisted to sessions) |
|
||||
|
|
@ -584,7 +623,7 @@ Advanced per-platform knobs for throttling the outbound message batcher. Most us
|
|||
| `HERMES_TUI_DIR` | Path to a prebuilt `ui-tui/` directory (must contain `dist/entry.js` and populated `node_modules`). Used by distros and Nix to skip the first-launch `npm install`. |
|
||||
| `HERMES_TUI_RESUME` | Resume a specific TUI session by ID on launch. When set, `hermes --tui` skips forging a fresh session and picks up the named session instead — useful for re-attaching after a disconnect or terminal crash. |
|
||||
| `HERMES_TUI_THEME` | Force the TUI color theme: `light`, `dark`, or a raw 6-character background hex (e.g. `ffffff` or `1a1a2e`). When unset, Hermes auto-detects using `COLORFGBG` and terminal background queries; this variable overrides detection on terminals (Ghostty, Warp, iTerm2, etc.) that don't set `COLORFGBG`. |
|
||||
| `HERMES_INFERENCE_MODEL` | Force the model for `hermes -z` / `hermes chat` without mutating `config.yaml`. Pairs with `HERMES_INFERENCE_PROVIDER`. Useful for scripted callers (sweeper, CI, batch runners) that need to override the default model per run. |
|
||||
| `HERMES_INFERENCE_MODEL` | Force the model for `hermes -z` / `hermes chat` without mutating `config.yaml`. Pairs with the `--provider` flag. Useful for scripted callers (sweeper, CI, batch runners) that need to override the default model per run. |
|
||||
|
||||
## Session Settings
|
||||
|
||||
|
|
@ -637,7 +676,7 @@ fallback_providers:
|
|||
|
||||
The older top-level `fallback_model` single-provider shape is still read for backward compatibility, but new configuration should use `fallback_providers`.
|
||||
|
||||
See [Fallback Providers](/docs/user-guide/features/fallback-providers) for full details.
|
||||
See [Fallback Providers](/user-guide/features/fallback-providers) for full details.
|
||||
|
||||
## Provider Routing (config.yaml only)
|
||||
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@ Quick answers and fixes for the most common questions and issues.
|
|||
Hermes Agent works with any OpenAI-compatible API. Supported providers include:
|
||||
|
||||
- **[OpenRouter](https://openrouter.ai/)** — access hundreds of models through one API key (recommended for flexibility)
|
||||
- **Nous Portal** — Nous Research's own inference endpoint
|
||||
- **[Nous Portal](/integrations/nous-portal)** — Nous Research's subscription gateway — 300+ models plus web/image/TTS/browser through one OAuth login (recommended for newcomers)
|
||||
- **OpenAI** — GPT-5.4, GPT-5-codex, GPT-4.1, GPT-4o, etc.
|
||||
- **Anthropic** — Claude models (direct API, OAuth via `hermes login anthropic`, OpenRouter, or any compatible proxy)
|
||||
- **Anthropic** — Claude models (direct API, OAuth via `hermes auth add anthropic`, OpenRouter, or any compatible proxy)
|
||||
- **Google** — Gemini models (direct API via `gemini` provider, the `google-gemini-cli` OAuth provider, OpenRouter, or compatible proxy)
|
||||
- **z.ai / ZhipuAI** — GLM models
|
||||
- **Kimi / Moonshot AI** — Kimi models
|
||||
|
|
@ -30,10 +30,18 @@ Set your provider with `hermes model` or by editing `~/.hermes/.env`. See the [E
|
|||
|
||||
### Does it work on Windows?
|
||||
|
||||
**Not natively.** Hermes Agent requires a Unix-like environment. On Windows, install [WSL2](https://learn.microsoft.com/en-us/windows/wsl/install) and run Hermes from inside it. The standard install command works perfectly in WSL2:
|
||||
**Yes, natively.** Hermes supports native Windows via the PowerShell installer — no WSL required. Run in PowerShell:
|
||||
|
||||
```powershell
|
||||
iex (irm https://hermes-agent.nousresearch.com/install.ps1)
|
||||
```
|
||||
|
||||
The installer provisions a PortableGit that backs the terminal tool's shell. See the [Windows (Native) Guide](../user-guide/windows-native.md) for details.
|
||||
|
||||
WSL2 remains a fully supported alternative. To run Hermes inside WSL2, install [WSL2](https://learn.microsoft.com/en-us/windows/wsl/install) and use the standard install command:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
|
||||
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash
|
||||
```
|
||||
|
||||
### I run Hermes in WSL2. What's the best way to control my normal Windows Chrome?
|
||||
|
|
@ -61,7 +69,7 @@ Yes — Hermes now has a tested Termux install path for Android phones.
|
|||
Quick install:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
|
||||
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash
|
||||
```
|
||||
|
||||
For the fully explicit manual steps, supported extras, and current limitations, see the [Termux guide](../getting-started/termux.md).
|
||||
|
|
@ -82,7 +90,7 @@ hermes model
|
|||
# API base URL: http://localhost:11434/v1
|
||||
# API key: ollama
|
||||
# Model name: qwen3.5:27b
|
||||
# Context length: 32768 ← set this to match your server's actual context window
|
||||
# Context length: 64000 ← Hermes minimum; set this to match your server's actual context window
|
||||
```
|
||||
|
||||
Or configure it directly in `config.yaml`:
|
||||
|
|
@ -99,7 +107,7 @@ Hermes persists the endpoint, provider, and base URL in `config.yaml` so it surv
|
|||
This works with Ollama, vLLM, llama.cpp server, SGLang, LocalAI, and others. See the [Configuration guide](../user-guide/configuration.md) for details.
|
||||
|
||||
:::tip Ollama users
|
||||
If you set a custom `num_ctx` in Ollama (e.g., `ollama run --num_ctx 16384`), make sure to set the matching context length in Hermes — Ollama's `/api/show` reports the model's *maximum* context, not the effective `num_ctx` you configured.
|
||||
If you set a custom `num_ctx` in Ollama (e.g., `ollama run --num_ctx 64000`), make sure to set the matching context length in Hermes — Ollama's `/api/show` reports the model's *maximum* context, not the effective `num_ctx` you configured.
|
||||
:::
|
||||
|
||||
:::tip Timeouts with local models
|
||||
|
|
@ -225,7 +233,7 @@ source ~/.bashrc
|
|||
# If you previously installed with sudo, clean up:
|
||||
sudo rm /usr/local/bin/hermes
|
||||
# Then re-run the standard installer
|
||||
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
|
||||
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash
|
||||
```
|
||||
|
||||
---
|
||||
|
|
@ -340,7 +348,7 @@ custom_providers:
|
|||
base_url: "http://localhost:11434/v1"
|
||||
models:
|
||||
qwen3.5:27b:
|
||||
context_length: 32768
|
||||
context_length: 64000
|
||||
```
|
||||
|
||||
See [Context Length Detection](../integrations/providers.md#context-length-detection) for how auto-detection works and all override options.
|
||||
|
|
@ -595,9 +603,9 @@ hermes chat
|
|||
```
|
||||
|
||||
See also:
|
||||
- [MCP (Model Context Protocol)](/docs/user-guide/features/mcp)
|
||||
- [Use MCP with Hermes](/docs/guides/use-mcp-with-hermes)
|
||||
- [MCP Config Reference](/docs/reference/mcp-config-reference)
|
||||
- [MCP (Model Context Protocol)](/user-guide/features/mcp)
|
||||
- [Use MCP with Hermes](/guides/use-mcp-with-hermes)
|
||||
- [MCP Config Reference](/reference/mcp-config-reference)
|
||||
|
||||
#### MCP timeout errors
|
||||
|
||||
|
|
@ -751,7 +759,7 @@ Skills with very long descriptions are truncated to 40 characters in the Telegra
|
|||
|
||||
1. Install Hermes Agent on the new machine:
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
|
||||
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash
|
||||
```
|
||||
|
||||
2. On the **source machine**, create a full backup:
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ description: "Reference for Hermes Agent MCP configuration keys, filtering seman
|
|||
This page is the compact reference companion to the main MCP docs.
|
||||
|
||||
For conceptual guidance, see:
|
||||
- [MCP (Model Context Protocol)](/docs/user-guide/features/mcp)
|
||||
- [Use MCP with Hermes](/docs/guides/use-mcp-with-hermes)
|
||||
- [MCP (Model Context Protocol)](/user-guide/features/mcp)
|
||||
- [Use MCP with Hermes](/guides/use-mcp-with-hermes)
|
||||
|
||||
## Root config shape
|
||||
|
||||
|
|
@ -25,6 +25,11 @@ mcp_servers:
|
|||
url: "..." # HTTP servers
|
||||
headers: {}
|
||||
|
||||
# Optional HTTP/SSE TLS settings:
|
||||
ssl_verify: true # bool or path to a CA bundle (PEM)
|
||||
client_cert: "/path/to/cert.pem" # mTLS client certificate (see below)
|
||||
# client_key: "/path/to/key.pem" # optional, when key lives in a separate file
|
||||
|
||||
enabled: true
|
||||
timeout: 120
|
||||
connect_timeout: 60
|
||||
|
|
@ -45,6 +50,9 @@ mcp_servers:
|
|||
| `env` | mapping | stdio | Environment passed to the subprocess |
|
||||
| `url` | string | HTTP | Remote MCP endpoint |
|
||||
| `headers` | mapping | HTTP | Headers for remote server requests |
|
||||
| `ssl_verify` | bool or string | HTTP | TLS verification. `true` (default) uses system CAs, `false` disables verification (insecure), or a string path to a custom CA bundle (PEM) |
|
||||
| `client_cert` | string or list | HTTP | mTLS client certificate. String = path to a PEM file containing cert + key. List `[cert, key]` = separate files. List `[cert, key, password]` = encrypted key |
|
||||
| `client_key` | string | HTTP | Path to the client private key, when `client_cert` is a string and the key is in a separate file |
|
||||
| `enabled` | bool | both | Skip the server entirely when false |
|
||||
| `timeout` | number | both | Tool call timeout |
|
||||
| `connect_timeout` | number | both | Initial connection timeout |
|
||||
|
|
@ -191,6 +199,40 @@ mcp_servers:
|
|||
prompts: false
|
||||
```
|
||||
|
||||
### TLS client certificate (mTLS)
|
||||
|
||||
For HTTP/SSE servers that require a client certificate, set `client_cert` (and optionally `client_key`):
|
||||
|
||||
```yaml
|
||||
mcp_servers:
|
||||
# Combined cert + key in a single PEM file
|
||||
internal_api:
|
||||
url: "https://mcp.internal.example.com/mcp"
|
||||
client_cert: "~/secrets/mcp-client.pem"
|
||||
|
||||
# Separate cert and key files
|
||||
partner_api:
|
||||
url: "https://mcp.partner.example.com/mcp"
|
||||
client_cert: "~/secrets/client.crt"
|
||||
client_key: "~/secrets/client.key"
|
||||
|
||||
# Encrypted key with a passphrase (3-element list form)
|
||||
bank_api:
|
||||
url: "https://mcp.bank.example.com/mcp"
|
||||
client_cert: ["~/secrets/client.crt", "~/secrets/client.key", "my-passphrase"]
|
||||
|
||||
# Custom CA bundle (private CA / self-signed server)
|
||||
lab_api:
|
||||
url: "https://mcp.lab.local/mcp"
|
||||
ssl_verify: "~/secrets/lab-ca.pem"
|
||||
client_cert: "~/secrets/lab-client.pem"
|
||||
```
|
||||
|
||||
Notes:
|
||||
- Paths support `~` expansion. Missing files fail fast at connect time with a server-scoped error message.
|
||||
- `ssl_verify: false` disables server certificate verification entirely. Don't use this with real services.
|
||||
- Works on both Streamable HTTP and SSE transports.
|
||||
|
||||
## Reloading config
|
||||
|
||||
After changing MCP config, reload servers with:
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ Cache location: `~/.hermes/cache/model_catalog.json`.
|
|||
model_catalog:
|
||||
enabled: true
|
||||
url: https://hermes-agent.nousresearch.com/docs/api/model-catalog.json
|
||||
ttl_hours: 24
|
||||
ttl_hours: 1
|
||||
providers: {}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -31,8 +31,11 @@ hermes skills uninstall <skill-name>
|
|||
|
||||
| Skill | Description |
|
||||
|-------|-------------|
|
||||
| [**antigravity-cli**](/docs/user-guide/skills/optional/autonomous-ai-agents/autonomous-ai-agents-antigravity-cli) | Operate the Antigravity CLI (agy): plugins, auth, sandbox. |
|
||||
| [**blackbox**](/docs/user-guide/skills/optional/autonomous-ai-agents/autonomous-ai-agents-blackbox) | Delegate coding tasks to Blackbox AI CLI agent. Multi-model agent with built-in judge that runs tasks through multiple LLMs and picks the best result. Requires the blackbox CLI and a Blackbox AI API key. |
|
||||
| [**grok**](/docs/user-guide/skills/optional/autonomous-ai-agents/autonomous-ai-agents-grok) | Delegate coding to xAI Grok Build CLI (features, PRs). |
|
||||
| [**honcho**](/docs/user-guide/skills/optional/autonomous-ai-agents/autonomous-ai-agents-honcho) | Configure and use Honcho memory with Hermes -- cross-session user modeling, multi-profile peer isolation, observation config, dialectic reasoning, session summaries, and context budget enforcement. Use when setting up Honcho, troubleshoo... |
|
||||
| [**openhands**](/docs/user-guide/skills/optional/autonomous-ai-agents/autonomous-ai-agents-openhands) | Delegate coding to OpenHands CLI (model-agnostic, LiteLLM). |
|
||||
|
||||
## blockchain
|
||||
|
||||
|
|
@ -52,11 +55,15 @@ hermes skills uninstall <skill-name>
|
|||
|
||||
| Skill | Description |
|
||||
|-------|-------------|
|
||||
| [**baoyu-article-illustrator**](/docs/user-guide/skills/optional/creative/creative-baoyu-article-illustrator) | Article illustrations: type × style × palette consistency. |
|
||||
| [**baoyu-comic**](/docs/user-guide/skills/optional/creative/creative-baoyu-comic) | Knowledge comics (知识漫画): educational, biography, tutorial. |
|
||||
| [**blender-mcp**](/docs/user-guide/skills/optional/creative/creative-blender-mcp) | Control Blender directly from Hermes via socket connection to the blender-mcp addon. Create 3D objects, materials, animations, and run arbitrary Blender Python (bpy) code. Use when user wants to create or modify anything in Blender. |
|
||||
| [**concept-diagrams**](/docs/user-guide/skills/optional/creative/creative-concept-diagrams) | Generate flat, minimal light/dark-aware SVG diagrams as standalone HTML files, using a unified educational visual language with 9 semantic color ramps, sentence-case typography, and automatic dark mode. Best suited for educational and no... |
|
||||
| [**ideation**](/docs/user-guide/skills/optional/creative/creative-creative-ideation) | Generate project ideas via creative constraints. |
|
||||
| [**hyperframes**](/docs/user-guide/skills/optional/creative/creative-hyperframes) | Create HTML-based video compositions, animated title cards, social overlays, captioned talking-head videos, audio-reactive visuals, and shader transitions using HyperFrames. HTML is the source of truth for video. Use when the user wants... |
|
||||
| [**kanban-video-orchestrator**](/docs/user-guide/skills/optional/creative/creative-kanban-video-orchestrator) | Plan, set up, and monitor a multi-agent video production pipeline backed by Hermes Kanban. Use when the user wants to make ANY video — narrative film, product/marketing, music video, explainer, ASCII/terminal art, abstract/generative loo... |
|
||||
| [**meme-generation**](/docs/user-guide/skills/optional/creative/creative-meme-generation) | Generate real meme images by picking a template and overlaying text with Pillow. Produces actual .png meme files. |
|
||||
| [**pixel-art**](/docs/user-guide/skills/optional/creative/creative-pixel-art) | Pixel art w/ era palettes (NES, Game Boy, PICO-8). |
|
||||
|
||||
## devops
|
||||
|
||||
|
|
@ -64,6 +71,7 @@ hermes skills uninstall <skill-name>
|
|||
|-------|-------------|
|
||||
| [**inference-sh-cli**](/docs/user-guide/skills/optional/devops/devops-cli) | Run 150+ AI apps via inference.sh CLI (infsh) — image generation, video creation, LLMs, search, 3D, social automation. Uses the terminal tool. Triggers: inference.sh, infsh, ai apps, flux, veo, image generation, video generation, seedrea... |
|
||||
| [**docker-management**](/docs/user-guide/skills/optional/devops/devops-docker-management) | Manage Docker containers, images, volumes, networks, and Compose stacks — lifecycle ops, debugging, cleanup, and Dockerfile optimization. |
|
||||
| [**hermes-s6-container-supervision**](/docs/user-guide/skills/optional/devops/devops-hermes-s6-container-supervision) | Modify, debug, or extend the s6-overlay supervision tree inside the Hermes Agent Docker image — adding new services, debugging profile gateways, understanding the Architecture B main-program pattern. |
|
||||
| [**pinggy-tunnel**](/docs/user-guide/skills/optional/devops/devops-pinggy-tunnel) | Zero-install localhost tunnels over SSH via Pinggy. |
|
||||
| [**watchers**](/docs/user-guide/skills/optional/devops/devops-watchers) | Poll RSS, JSON APIs, and GitHub with watermark dedup. |
|
||||
|
||||
|
|
@ -92,6 +100,13 @@ hermes skills uninstall <skill-name>
|
|||
| [**pptx-author**](/docs/user-guide/skills/optional/finance/finance-pptx-author) | Build PowerPoint decks headless with python-pptx. Pairs with excel-author for model-backed decks where every number traces to a workbook cell. Use for pitch decks, IC memos, earnings notes. |
|
||||
| [**stocks**](/docs/user-guide/skills/optional/finance/finance-stocks) | Stock quotes, history, search, compare, crypto via Yahoo. |
|
||||
|
||||
## gaming
|
||||
|
||||
| Skill | Description |
|
||||
|-------|-------------|
|
||||
| [**minecraft-modpack-server**](/docs/user-guide/skills/optional/gaming/gaming-minecraft-modpack-server) | Host modded Minecraft servers (CurseForge, Modrinth). |
|
||||
| [**pokemon-player**](/docs/user-guide/skills/optional/gaming/gaming-pokemon-player) | Play Pokemon via headless emulator + RAM reads. |
|
||||
|
||||
## health
|
||||
|
||||
| Skill | Description |
|
||||
|
|
@ -120,6 +135,7 @@ hermes skills uninstall <skill-name>
|
|||
| [**axolotl**](/docs/user-guide/skills/optional/mlops/mlops-training-axolotl) | Axolotl: YAML LLM fine-tuning (LoRA, DPO, GRPO). |
|
||||
| [**chroma**](/docs/user-guide/skills/optional/mlops/mlops-chroma) | Open-source embedding database for AI applications. Store embeddings and metadata, perform vector and full-text search, filter by metadata. Simple 4-function API. Scales from notebooks to production clusters. Use for semantic search, RAG... |
|
||||
| [**clip**](/docs/user-guide/skills/optional/mlops/mlops-clip) | OpenAI's model connecting vision and language. Enables zero-shot image classification, image-text matching, and cross-modal retrieval. Trained on 400M image-text pairs. Use for image search, content moderation, or vision-language tasks w... |
|
||||
| [**dspy**](/docs/user-guide/skills/optional/mlops/mlops-research-dspy) | DSPy: declarative LM programs, auto-optimize prompts, RAG. |
|
||||
| [**faiss**](/docs/user-guide/skills/optional/mlops/mlops-faiss) | Facebook's library for efficient similarity search and clustering of dense vectors. Supports billions of vectors, GPU acceleration, and various index types (Flat, IVF, HNSW). Use for fast k-NN search, large-scale vector retrieval, or whe... |
|
||||
| [**optimizing-attention-flash**](/docs/user-guide/skills/optional/mlops/mlops-flash-attention) | Optimizes transformer attention with Flash Attention for 2-4x speedup and 10-20x memory reduction. Use when training/running transformers with long sequences (>512 tokens), encountering GPU memory issues with attention, or need faster in... |
|
||||
| [**guidance**](/docs/user-guide/skills/optional/mlops/mlops-guidance) | Control LLM output with regex and grammars, guarantee valid JSON/XML/code generation, enforce structured formats, and build multi-step workflows with Guidance - Microsoft Research's constrained generation framework |
|
||||
|
|
@ -129,6 +145,7 @@ hermes skills uninstall <skill-name>
|
|||
| [**llava**](/docs/user-guide/skills/optional/mlops/mlops-llava) | Large Language and Vision Assistant. Enables visual instruction tuning and image-based conversations. Combines CLIP vision encoder with Vicuna/LLaMA language models. Supports multi-turn image chat, visual question answering, and instruct... |
|
||||
| [**modal-serverless-gpu**](/docs/user-guide/skills/optional/mlops/mlops-modal) | Serverless GPU cloud platform for running ML workloads. Use when you need on-demand GPU access without infrastructure management, deploying ML models as APIs, or running batch jobs with automatic scaling. |
|
||||
| [**nemo-curator**](/docs/user-guide/skills/optional/mlops/mlops-nemo-curator) | GPU-accelerated data curation for LLM training. Supports text/image/video/audio. Features fuzzy deduplication (16× faster), quality filtering (30+ heuristics), semantic deduplication, PII redaction, NSFW detection. Scales across GPUs wit... |
|
||||
| [**obliteratus**](/docs/user-guide/skills/optional/mlops/mlops-obliteratus) | OBLITERATUS: abliterate LLM refusals (diff-in-means). |
|
||||
| [**outlines**](/docs/user-guide/skills/optional/mlops/mlops-inference-outlines) | Outlines: structured JSON/regex/Pydantic LLM generation. |
|
||||
| [**peft-fine-tuning**](/docs/user-guide/skills/optional/mlops/mlops-peft) | Parameter-efficient fine-tuning for LLMs using LoRA, QLoRA, and 25+ methods. Use when fine-tuning large models (7B-70B) with limited GPU memory, when you need to train <1% of parameters with minimal accuracy loss, or for multi-adapter se... |
|
||||
| [**pinecone**](/docs/user-guide/skills/optional/mlops/mlops-pinecone) | Managed vector database for production AI applications. Fully managed, auto-scaling, with hybrid search (dense + sparse), metadata filtering, and namespaces. Low latency (<100ms p95). Use for production RAG, recommendation systems, or se... |
|
||||
|
|
@ -178,14 +195,18 @@ hermes skills uninstall <skill-name>
|
|||
| Skill | Description |
|
||||
|-------|-------------|
|
||||
| [**1password**](/docs/user-guide/skills/optional/security/security-1password) | Set up and use 1Password CLI (op). Use when installing the CLI, enabling desktop app integration, signing in, and reading/injecting secrets for commands. |
|
||||
| [**godmode**](/docs/user-guide/skills/optional/security/security-godmode) | Jailbreak LLMs: Parseltongue, GODMODE, ULTRAPLINIAN. |
|
||||
| [**oss-forensics**](/docs/user-guide/skills/optional/security/security-oss-forensics) | Supply chain investigation, evidence recovery, and forensic analysis for GitHub repositories. Covers deleted commit recovery, force-push detection, IOC extraction, multi-source evidence collection, hypothesis formation/validation, and st... |
|
||||
| [**sherlock**](/docs/user-guide/skills/optional/security/security-sherlock) | OSINT username search across 400+ social networks. Hunt down social media accounts by username. |
|
||||
| [**web-pentest**](/docs/user-guide/skills/optional/security/security-web-pentest) | Authorized web application penetration testing — reconnaissance, vulnerability analysis, proof-based exploitation, and professional reporting. Adapts Shannon's "No Exploit, No Report" methodology with hard guardrails for scope, authoriza... |
|
||||
|
||||
## software-development
|
||||
|
||||
| Skill | Description |
|
||||
|-------|-------------|
|
||||
| [**code-wiki**](/docs/user-guide/skills/optional/software-development/software-development-code-wiki) | Generate wiki docs + Mermaid diagrams for any codebase. |
|
||||
| [**rest-graphql-debug**](/docs/user-guide/skills/optional/software-development/software-development-rest-graphql-debug) | Debug REST/GraphQL APIs: status codes, auth, schemas, repro. |
|
||||
| [**subagent-driven-development**](/docs/user-guide/skills/optional/software-development/software-development-subagent-driven-development) | Execute plans via delegate_task subagents (2-stage review). |
|
||||
|
||||
## web-development
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ Top-level command for managing profiles. Running `hermes profile` without a subc
|
|||
| `list` | List all profiles. |
|
||||
| `use` | Set the active (default) profile. |
|
||||
| `create` | Create a new profile. |
|
||||
| `describe` | Read or set a profile's description (used by the kanban orchestrator for routing). |
|
||||
| `delete` | Delete a profile. |
|
||||
| `show` | Show details about a profile. |
|
||||
| `alias` | Regenerate the shell alias for a profile. |
|
||||
|
|
@ -84,7 +85,7 @@ Creates a new profile.
|
|||
| `--clone-from <profile>` | Clone from a specific profile instead of the current one. Used with `--clone` or `--clone-all`. |
|
||||
| `--no-alias` | Skip wrapper script creation. |
|
||||
| `--description "<text>"` | One- or two-sentence description of what this profile is good at. Used by the kanban orchestrator to route tasks based on role instead of profile name alone. Skip and add later via `hermes profile describe`. Persisted in `<profile_dir>/profile.yaml`. |
|
||||
| `--no-skills` | Create an **empty** profile with zero bundled skills enabled. Writes a `.no-skills` marker into the profile so future `hermes update` runs won't re-seed the bundled set, and refuses to combine with `--clone` / `--clone-all` (which would copy skills in anyway). Useful for narrow orchestrator profiles or sandbox profiles that should not inherit the full skill catalog. |
|
||||
| `--no-skills` | Create an **empty** profile with zero bundled skills enabled. Writes a `.no-bundled-skills` marker into the profile so future `hermes update` runs won't re-seed the bundled set, and refuses to combine with `--clone` / `--clone-all` (which would copy skills in anyway). Useful for narrow orchestrator profiles or sandbox profiles that should not inherit the full skill catalog. To toggle this on an already-created profile (including the default `~/.hermes`), use `hermes skills opt-out` / `hermes skills opt-in`. |
|
||||
|
||||
Creating a profile does **not** make that profile directory the default project/workspace directory for terminal commands. If you want a profile to start in a specific project, set `terminal.cwd` in that profile's `config.yaml`.
|
||||
|
||||
|
|
|
|||
|
|
@ -38,18 +38,14 @@ If a skill is missing from this list but present in the repo, the catalog is reg
|
|||
| [`architecture-diagram`](/docs/user-guide/skills/bundled/creative/creative-architecture-diagram) | Dark-themed SVG architecture/cloud/infra diagrams as HTML. | `creative/architecture-diagram` |
|
||||
| [`ascii-art`](/docs/user-guide/skills/bundled/creative/creative-ascii-art) | ASCII art: pyfiglet, cowsay, boxes, image-to-ascii. | `creative/ascii-art` |
|
||||
| [`ascii-video`](/docs/user-guide/skills/bundled/creative/creative-ascii-video) | ASCII video: convert video/audio to colored ASCII MP4/GIF. | `creative/ascii-video` |
|
||||
| [`baoyu-article-illustrator`](/docs/user-guide/skills/bundled/creative/creative-baoyu-article-illustrator) | Article illustrations: type × style × palette consistency. | `creative/baoyu-article-illustrator` |
|
||||
| [`baoyu-comic`](/docs/user-guide/skills/bundled/creative/creative-baoyu-comic) | Knowledge comics (知识漫画): educational, biography, tutorial. | `creative/baoyu-comic` |
|
||||
| [`baoyu-infographic`](/docs/user-guide/skills/bundled/creative/creative-baoyu-infographic) | Infographics: 21 layouts x 21 styles (信息图, 可视化). | `creative/baoyu-infographic` |
|
||||
| [`claude-design`](/docs/user-guide/skills/bundled/creative/creative-claude-design) | Design one-off HTML artifacts (landing, deck, prototype). | `creative/claude-design` |
|
||||
| [`comfyui`](/docs/user-guide/skills/bundled/creative/creative-comfyui) | Generate images, video, and audio with ComfyUI — install, launch, manage nodes/models, run workflows with parameter injection. Uses the official comfy-cli for lifecycle and direct REST/WebSocket API for execution. | `creative/comfyui` |
|
||||
| [`ideation`](/docs/user-guide/skills/bundled/creative/creative-creative-ideation) | Generate project ideas via creative constraints. | `creative/creative-ideation` |
|
||||
| [`design-md`](/docs/user-guide/skills/bundled/creative/creative-design-md) | Author/validate/export Google's DESIGN.md token spec files. | `creative/design-md` |
|
||||
| [`excalidraw`](/docs/user-guide/skills/bundled/creative/creative-excalidraw) | Hand-drawn Excalidraw JSON diagrams (arch, flow, seq). | `creative/excalidraw` |
|
||||
| [`humanizer`](/docs/user-guide/skills/bundled/creative/creative-humanizer) | Humanize text: strip AI-isms and add real voice. | `creative/humanizer` |
|
||||
| [`manim-video`](/docs/user-guide/skills/bundled/creative/creative-manim-video) | Manim CE animations: 3Blue1Brown math/algo videos. | `creative/manim-video` |
|
||||
| [`p5js`](/docs/user-guide/skills/bundled/creative/creative-p5js) | p5.js sketches: gen art, shaders, interactive, 3D. | `creative/p5js` |
|
||||
| [`pixel-art`](/docs/user-guide/skills/bundled/creative/creative-pixel-art) | Pixel art w/ era palettes (NES, Game Boy, PICO-8). | `creative/pixel-art` |
|
||||
| [`popular-web-designs`](/docs/user-guide/skills/bundled/creative/creative-popular-web-designs) | 54 real design systems (Stripe, Linear, Vercel) as HTML/CSS. | `creative/popular-web-designs` |
|
||||
| [`pretext`](/docs/user-guide/skills/bundled/creative/creative-pretext) | Use when building creative browser demos with @chenglou/pretext — DOM-free text layout for ASCII art, typographic flow around obstacles, text-as-geometry games, kinetic typography, and text-powered generative art. Produces single-file HT... | `creative/pretext` |
|
||||
| [`sketch`](/docs/user-guide/skills/bundled/creative/creative-sketch) | Throwaway HTML mockups: 2-3 design variants to compare. | `creative/sketch` |
|
||||
|
|
@ -68,7 +64,6 @@ If a skill is missing from this list but present in the repo, the catalog is reg
|
|||
|-------|-------------|------|
|
||||
| [`kanban-orchestrator`](/docs/user-guide/skills/bundled/devops/devops-kanban-orchestrator) | Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill... | `devops/kanban-orchestrator` |
|
||||
| [`kanban-worker`](/docs/user-guide/skills/bundled/devops/devops-kanban-worker) | Pitfalls, examples, and edge cases for Hermes Kanban workers. The lifecycle itself is auto-injected into every worker's system prompt as KANBAN_GUIDANCE (from agent/prompt_builder.py); this skill is what you load when you want deeper det... | `devops/kanban-worker` |
|
||||
| [`webhook-subscriptions`](/docs/user-guide/skills/bundled/devops/devops-webhook-subscriptions) | Webhook subscriptions: event-driven agent runs. | `devops/webhook-subscriptions` |
|
||||
|
||||
## dogfood
|
||||
|
||||
|
|
@ -82,13 +77,6 @@ If a skill is missing from this list but present in the repo, the catalog is reg
|
|||
|-------|-------------|------|
|
||||
| [`himalaya`](/docs/user-guide/skills/bundled/email/email-himalaya) | Himalaya CLI: IMAP/SMTP email from terminal. | `email/himalaya` |
|
||||
|
||||
## gaming
|
||||
|
||||
| Skill | Description | Path |
|
||||
|-------|-------------|------|
|
||||
| [`minecraft-modpack-server`](/docs/user-guide/skills/bundled/gaming/gaming-minecraft-modpack-server) | Host modded Minecraft servers (CurseForge, Modrinth). | `gaming/minecraft-modpack-server` |
|
||||
| [`pokemon-player`](/docs/user-guide/skills/bundled/gaming/gaming-pokemon-player) | Play Pokemon via headless emulator + RAM reads. | `gaming/pokemon-player` |
|
||||
|
||||
## github
|
||||
|
||||
| Skill | Description | Path |
|
||||
|
|
@ -100,12 +88,6 @@ If a skill is missing from this list but present in the repo, the catalog is reg
|
|||
| [`github-pr-workflow`](/docs/user-guide/skills/bundled/github/github-github-pr-workflow) | GitHub PR lifecycle: branch, commit, open, CI, merge. | `github/github-pr-workflow` |
|
||||
| [`github-repo-management`](/docs/user-guide/skills/bundled/github/github-github-repo-management) | Clone/create/fork repos; manage remotes, releases. | `github/github-repo-management` |
|
||||
|
||||
## mcp
|
||||
|
||||
| Skill | Description | Path |
|
||||
|-------|-------------|------|
|
||||
| [`native-mcp`](/docs/user-guide/skills/bundled/mcp/mcp-native-mcp) | MCP client: connect servers, register tools (stdio/HTTP). | `mcp/native-mcp` |
|
||||
|
||||
## media
|
||||
|
||||
| Skill | Description | Path |
|
||||
|
|
@ -113,7 +95,6 @@ If a skill is missing from this list but present in the repo, the catalog is reg
|
|||
| [`gif-search`](/docs/user-guide/skills/bundled/media/media-gif-search) | Search/download GIFs from Tenor via curl + jq. | `media/gif-search` |
|
||||
| [`heartmula`](/docs/user-guide/skills/bundled/media/media-heartmula) | HeartMuLa: Suno-like song generation from lyrics + tags. | `media/heartmula` |
|
||||
| [`songsee`](/docs/user-guide/skills/bundled/media/media-songsee) | Audio spectrograms/features (mel, chroma, MFCC) via CLI. | `media/songsee` |
|
||||
| [`spotify`](/docs/user-guide/skills/bundled/media/media-spotify) | Spotify: play, search, queue, manage playlists and devices. | `media/spotify` |
|
||||
| [`youtube-content`](/docs/user-guide/skills/bundled/media/media-youtube-content) | YouTube transcripts to summaries, threads, blogs. | `media/youtube-content` |
|
||||
|
||||
## mlops
|
||||
|
|
@ -121,11 +102,9 @@ If a skill is missing from this list but present in the repo, the catalog is reg
|
|||
| Skill | Description | Path |
|
||||
|-------|-------------|------|
|
||||
| [`audiocraft-audio-generation`](/docs/user-guide/skills/bundled/mlops/mlops-models-audiocraft) | AudioCraft: MusicGen text-to-music, AudioGen text-to-sound. | `mlops/models/audiocraft` |
|
||||
| [`dspy`](/docs/user-guide/skills/bundled/mlops/mlops-research-dspy) | DSPy: declarative LM programs, auto-optimize prompts, RAG. | `mlops/research/dspy` |
|
||||
| [`huggingface-hub`](/docs/user-guide/skills/bundled/mlops/mlops-huggingface-hub) | HuggingFace hf CLI: search/download/upload models, datasets. | `mlops/huggingface-hub` |
|
||||
| [`llama-cpp`](/docs/user-guide/skills/bundled/mlops/mlops-inference-llama-cpp) | llama.cpp local GGUF inference + HF Hub model discovery. | `mlops/inference/llama-cpp` |
|
||||
| [`evaluating-llms-harness`](/docs/user-guide/skills/bundled/mlops/mlops-evaluation-lm-evaluation-harness) | lm-eval-harness: benchmark LLMs (MMLU, GSM8K, etc.). | `mlops/evaluation/lm-evaluation-harness` |
|
||||
| [`obliteratus`](/docs/user-guide/skills/bundled/mlops/mlops-inference-obliteratus) | OBLITERATUS: abliterate LLM refusals (diff-in-means). | `mlops/inference/obliteratus` |
|
||||
| [`segment-anything-model`](/docs/user-guide/skills/bundled/mlops/mlops-models-segment-anything) | SAM: zero-shot image segmentation via points, boxes, masks. | `mlops/models/segment-anything` |
|
||||
| [`serving-llms-vllm`](/docs/user-guide/skills/bundled/mlops/mlops-inference-vllm) | vLLM: high-throughput LLM serving, OpenAI API, quantization. | `mlops/inference/vllm` |
|
||||
| [`weights-and-biases`](/docs/user-guide/skills/bundled/mlops/mlops-evaluation-weights-and-biases) | W&B: log ML experiments, sweeps, model registry, dashboards. | `mlops/evaluation/weights-and-biases` |
|
||||
|
|
@ -142,7 +121,6 @@ If a skill is missing from this list but present in the repo, the catalog is reg
|
|||
|-------|-------------|------|
|
||||
| [`airtable`](/docs/user-guide/skills/bundled/productivity/productivity-airtable) | Airtable REST API via curl. Records CRUD, filters, upserts. | `productivity/airtable` |
|
||||
| [`google-workspace`](/docs/user-guide/skills/bundled/productivity/productivity-google-workspace) | Gmail, Calendar, Drive, Docs, Sheets via gws CLI or Python. | `productivity/google-workspace` |
|
||||
| [`linear`](/docs/user-guide/skills/bundled/productivity/productivity-linear) | Linear: manage issues, projects, teams via GraphQL + curl. | `productivity/linear` |
|
||||
| [`maps`](/docs/user-guide/skills/bundled/productivity/productivity-maps) | Geocode, POIs, routes, timezones via OpenStreetMap/OSRM. | `productivity/maps` |
|
||||
| [`nano-pdf`](/docs/user-guide/skills/bundled/productivity/productivity-nano-pdf) | Edit PDF text/typos/titles via nano-pdf CLI (NL prompts). | `productivity/nano-pdf` |
|
||||
| [`notion`](/docs/user-guide/skills/bundled/productivity/productivity-notion) | Notion API + ntn CLI: pages, databases, markdown, Workers. | `productivity/notion` |
|
||||
|
|
@ -150,12 +128,6 @@ If a skill is missing from this list but present in the repo, the catalog is reg
|
|||
| [`powerpoint`](/docs/user-guide/skills/bundled/productivity/productivity-powerpoint) | Create, read, edit .pptx decks, slides, notes, templates. | `productivity/powerpoint` |
|
||||
| [`teams-meeting-pipeline`](/docs/user-guide/skills/bundled/productivity/productivity-teams-meeting-pipeline) | Operate the Teams meeting summary pipeline via Hermes CLI — summarize meetings, inspect pipeline status, replay jobs, manage Microsoft Graph subscriptions. | `productivity/teams-meeting-pipeline` |
|
||||
|
||||
## red-teaming
|
||||
|
||||
| Skill | Description | Path |
|
||||
|-------|-------------|------|
|
||||
| [`godmode`](/docs/user-guide/skills/bundled/red-teaming/red-teaming-godmode) | Jailbreak LLMs: Parseltongue, GODMODE, ULTRAPLINIAN. | `red-teaming/godmode` |
|
||||
|
||||
## research
|
||||
|
||||
| Skill | Description | Path |
|
||||
|
|
@ -182,17 +154,15 @@ If a skill is missing from this list but present in the repo, the catalog is reg
|
|||
|
||||
| Skill | Description | Path |
|
||||
|-------|-------------|------|
|
||||
| [`debugging-hermes-tui-commands`](/docs/user-guide/skills/bundled/software-development/software-development-debugging-hermes-tui-commands) | Debug Hermes TUI slash commands: Python, gateway, Ink UI. | `software-development/debugging-hermes-tui-commands` |
|
||||
| [`hermes-agent-skill-authoring`](/docs/user-guide/skills/bundled/software-development/software-development-hermes-agent-skill-authoring) | Author in-repo SKILL.md: frontmatter, validator, structure. | `software-development/hermes-agent-skill-authoring` |
|
||||
| [`node-inspect-debugger`](/docs/user-guide/skills/bundled/software-development/software-development-node-inspect-debugger) | Debug Node.js via --inspect + Chrome DevTools Protocol CLI. | `software-development/node-inspect-debugger` |
|
||||
| [`plan`](/docs/user-guide/skills/bundled/software-development/software-development-plan) | Plan mode: write markdown plan to .hermes/plans/, no exec. | `software-development/plan` |
|
||||
| [`plan`](/docs/user-guide/skills/bundled/software-development/software-development-plan) | Plan mode: write an actionable markdown plan to .hermes/plans/, no execution. Bite-sized tasks, exact paths, complete code. | `software-development/plan` |
|
||||
| [`python-debugpy`](/docs/user-guide/skills/bundled/software-development/software-development-python-debugpy) | Debug Python: pdb REPL + debugpy remote (DAP). | `software-development/python-debugpy` |
|
||||
| [`requesting-code-review`](/docs/user-guide/skills/bundled/software-development/software-development-requesting-code-review) | Pre-commit review: security scan, quality gates, auto-fix. | `software-development/requesting-code-review` |
|
||||
| [`simplify-code`](/docs/user-guide/skills/bundled/software-development/software-development-simplify-code) | Parallel 3-agent cleanup of recent code changes. | `software-development/simplify-code` |
|
||||
| [`spike`](/docs/user-guide/skills/bundled/software-development/software-development-spike) | Throwaway experiments to validate an idea before build. | `software-development/spike` |
|
||||
| [`subagent-driven-development`](/docs/user-guide/skills/bundled/software-development/software-development-subagent-driven-development) | Execute plans via delegate_task subagents (2-stage review). | `software-development/subagent-driven-development` |
|
||||
| [`systematic-debugging`](/docs/user-guide/skills/bundled/software-development/software-development-systematic-debugging) | 4-phase root cause debugging: understand bugs before fixing. | `software-development/systematic-debugging` |
|
||||
| [`test-driven-development`](/docs/user-guide/skills/bundled/software-development/software-development-test-driven-development) | TDD: enforce RED-GREEN-REFACTOR, tests before code. | `software-development/test-driven-development` |
|
||||
| [`writing-plans`](/docs/user-guide/skills/bundled/software-development/software-development-writing-plans) | Write implementation plans: bite-sized tasks, paths, code. | `software-development/writing-plans` |
|
||||
|
||||
## yuanbao
|
||||
|
||||
|
|
|
|||
|
|
@ -36,29 +36,29 @@ Type `/` in the CLI to open the autocomplete menu. Built-in commands are case-in
|
|||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `/new [name]` (alias: `/reset`) | Start a new session (fresh session ID + history). Optional `[name]` sets the initial session title — e.g. `/new my-experiment` opens a fresh session already titled `my-experiment` so it's easy to find later with `/resume` or `/sessions`. |
|
||||
| `/new [name]` (alias: `/reset`) | Start a new session (fresh session ID + history). Optional `[name]` sets the initial session title — e.g. `/new my-experiment` opens a fresh session already titled `my-experiment` so it's easy to find later with `/resume` or `/sessions`. Append `now`, `--yes`, or `-y` to skip the confirmation modal — e.g. `/reset now`, `/new --yes my-experiment`. |
|
||||
| `/clear` | Clear screen and start a new session |
|
||||
| `/history` | Show conversation history |
|
||||
| `/save` | Save the current conversation |
|
||||
| `/retry` | Retry the last message (resend to agent) |
|
||||
| `/undo` | Remove the last user/assistant exchange |
|
||||
| `/title` | Set a title for the current session (usage: /title My Session Name) |
|
||||
| `/compress [focus topic]` | Manually compress conversation context (flush memories + summarize). Optional focus topic narrows what the summary preserves. |
|
||||
| `/compress [here [N] \| focus topic]` | Manually compress conversation context (flush memories + summarize). `/compress here [N]` summarizes everything except the most recent N exchanges (default 2), kept verbatim — pick your own compression boundary. A focus topic narrows what a full summary preserves. |
|
||||
| `/rollback` | List or restore filesystem checkpoints (usage: /rollback [number]) |
|
||||
| `/snapshot [create\|restore <id>\|prune]` (alias: `/snap`) | Create or restore state snapshots of Hermes config/state. `create [label]` saves a snapshot, `restore <id>` reverts to it, `prune [N]` removes old snapshots, or list all with no args. |
|
||||
| `/stop` | Kill all running background processes |
|
||||
| `/queue <prompt>` (alias: `/q`) | Queue a prompt for the next turn (doesn't interrupt the current agent response). |
|
||||
| `/steer <prompt>` | Inject a mid-run note that arrives at the agent **after the next tool call** — no interrupt, no new user turn. The text is appended to the last tool result's content once the current tool completes, giving the agent new context without breaking the current tool-calling loop. Use this to nudge direction mid-task (e.g. "focus on the auth module" while the agent is running tests). |
|
||||
| `/goal <text>` | Set a standing goal Hermes works toward across turns — our take on the Ralph loop. After each turn an auxiliary judge model decides whether the goal is done; if not, Hermes auto-continues. Subcommands: `/goal status`, `/goal pause`, `/goal resume`, `/goal clear`. Budget defaults to 20 turns (`goals.max_turns`); any real user message preempts the continuation loop, and state survives `/resume`. See [Persistent Goals](/docs/user-guide/features/goals) for the full walkthrough. |
|
||||
| `/goal <text>` | Set a standing goal Hermes works toward across turns — our take on the Ralph loop. After each turn an auxiliary judge model decides whether the goal is done; if not, Hermes auto-continues. Subcommands: `/goal status`, `/goal pause`, `/goal resume`, `/goal clear`. Budget defaults to 20 turns (`goals.max_turns`); any real user message preempts the continuation loop, and state survives `/resume`. See [Persistent Goals](/user-guide/features/goals) for the full walkthrough. |
|
||||
| `/subgoal <text>` | Append a user-supplied criterion to the active goal mid-loop. The continuation prompt surfaces all subgoals to the agent verbatim, and the judge factors them into its DONE/CONTINUE verdict — so the goal isn't marked done until the original goal **and** every subgoal are met. Subcommands: `/subgoal` (list), `/subgoal remove <N>`, `/subgoal clear`. Requires an active `/goal`. |
|
||||
| `/resume [name]` | Resume a previously-named session |
|
||||
| `/sessions` | Browse and resume previous sessions in an interactive picker |
|
||||
| `/sessions` (TUI alias: `/switch`) | Classic CLI: browse and resume previous sessions in an interactive picker. TUI: open the live session switcher for currently open TUI sessions. Use `/sessions new` in the TUI to start another live session immediately. |
|
||||
| `/redraw` | Force a full UI repaint (recovers from terminal drift after tmux resize, mouse selection artifacts, etc.) |
|
||||
| `/status` | Show session info — model, provider, profile, session ID, working directory, title, created/updated timestamps, token totals, agent-running state — followed by a local **Session recap** block (recent user/assistant turn counts, tool result count, top tools used, last few files touched, the latest user prompt, and the latest assistant reply). The recap is computed locally from the in-memory conversation; no LLM call, no prompt-cache impact. |
|
||||
| `/agents` (alias: `/tasks`) | Show active agents and running tasks across the current session. |
|
||||
| `/background <prompt>` (alias: `/bg`, `/btw`) | Run a prompt in a separate background session. The agent processes your prompt independently — your current session stays free for other work. Results appear as a panel when the task finishes. See [CLI Background Sessions](/docs/user-guide/cli#background-sessions). |
|
||||
| `/background <prompt>` (alias: `/bg`, `/btw`) | Run a prompt in a separate background session. The agent processes your prompt independently — your current session stays free for other work. Results appear as a panel when the task finishes. See [CLI Background Sessions](/user-guide/cli#background-sessions). |
|
||||
| `/branch [name]` (alias: `/fork`) | Branch the current session (explore a different path) |
|
||||
| `/handoff <platform>` | **CLI only.** Hand the current session off to a messaging platform (Telegram, Discord, Slack, WhatsApp, Signal, Matrix). The gateway picks it up immediately, creates a fresh thread on platforms that support threads (Telegram topics, Discord text-channel threads, Slack message-anchored threads), re-binds the destination to your CLI session_id so the full role-aware transcript replays, and forges a synthetic user turn so the agent confirms it's working in the new place. Your CLI exits cleanly on success with a `/resume` hint; resume locally any time with `/resume <title>`. Refused mid-turn. Requires the gateway to be running and a home channel configured for the target platform (`/sethome` from the destination chat). See [Cross-Platform Handoff](/docs/user-guide/sessions#cross-platform-handoff). |
|
||||
| `/handoff <platform>` | **CLI only.** Hand the current session off to a messaging platform (Telegram, Discord, Slack, WhatsApp, Signal, Matrix). The gateway picks it up immediately, creates a fresh thread on platforms that support threads (Telegram topics, Discord text-channel threads, Slack message-anchored threads), re-binds the destination to your CLI session_id so the full role-aware transcript replays, and forges a synthetic user turn so the agent confirms it's working in the new place. Your CLI exits cleanly on success with a `/resume` hint; resume locally any time with `/resume <title>`. Refused mid-turn. Requires the gateway to be running and a home channel configured for the target platform (`/sethome` from the destination chat). See [Cross-Platform Handoff](/user-guide/sessions#cross-platform-handoff). |
|
||||
|
||||
### Configuration
|
||||
|
||||
|
|
@ -75,7 +75,7 @@ Type `/` in the CLI to open the autocomplete menu. Built-in commands are case-in
|
|||
| `/statusbar` (alias: `/sb`) | Toggle the context/model status bar on or off |
|
||||
| `/voice [on\|off\|tts\|status]` | Toggle CLI voice mode and spoken playback. Recording uses `voice.record_key` (default: `Ctrl+B`). |
|
||||
| `/yolo` | Toggle YOLO mode — skip all dangerous command approval prompts. |
|
||||
| `/footer [on\|off\|status]` | Toggle the gateway runtime-metadata footer on final replies (shows model, tool counts, timing). |
|
||||
| `/footer [on\|off\|status]` | Toggle the gateway runtime-metadata footer on final replies (shows model, context %, and cwd). |
|
||||
| `/busy [queue\|steer\|interrupt\|status]` | CLI-only: control what pressing Enter does while Hermes is working — queue the new message, steer mid-turn, or interrupt immediately. |
|
||||
| `/indicator [kaomoji\|emoji\|unicode\|ascii]` | CLI-only: pick the TUI busy-indicator style. |
|
||||
|
||||
|
|
@ -87,9 +87,10 @@ Type `/` in the CLI to open the autocomplete menu. Built-in commands are case-in
|
|||
| `/toolsets` | List available toolsets |
|
||||
| `/browser [connect\|disconnect\|status]` | Manage a local Chromium-family CDP connection. `connect` attaches browser tools to a running Chrome, Brave, Chromium, or Edge instance (default: `http://127.0.0.1:9222`). `disconnect` detaches. `status` shows current connection. Auto-launches a supported Chromium-family browser if no debugger is detected. |
|
||||
| `/skills` | Search, install, inspect, or manage skills from online registries |
|
||||
| `/bundles` | List configured skill bundles — `/<name>` slash aliases that preload several skills at once. Configure under `bundles:` in `~/.hermes/config.yaml`. See [Skill Bundles](/user-guide/features/skills#skill-bundles). |
|
||||
| `/cron` | Manage scheduled tasks (list, add/create, edit, pause, resume, run, remove) |
|
||||
| `/curator` | Background skill maintenance — `status`, `run`, `pin`, `archive`. See [Curator](/docs/user-guide/features/curator). |
|
||||
| `/kanban <action>` | Drive the multi-profile, multi-project collaboration board without leaving chat. Full `hermes kanban` surface is available: `/kanban list`, `/kanban show t_abc`, `/kanban create "title" --assignee X`, `/kanban comment t_abc "text"`, `/kanban unblock t_abc`, `/kanban dispatch`, etc. Multi-board support included: `/kanban boards list`, `/kanban boards create <slug>`, `/kanban boards switch <slug>`, `/kanban --board <slug> <action>`. See [Kanban slash command](/docs/user-guide/features/kanban#kanban-slash-command). |
|
||||
| `/curator` | Background skill maintenance — `status`, `run`, `pin`, `archive`. See [Curator](/user-guide/features/curator). |
|
||||
| `/kanban <action>` | Drive the multi-profile, multi-project collaboration board without leaving chat. Full `hermes kanban` surface is available: `/kanban list`, `/kanban show t_abc`, `/kanban create "title" --assignee X`, `/kanban comment t_abc "text"`, `/kanban unblock t_abc`, `/kanban dispatch`, etc. Multi-board support included: `/kanban boards list`, `/kanban boards create <slug>`, `/kanban boards switch <slug>`, `/kanban --board <slug> <action>`. See [Kanban slash command](/user-guide/features/kanban#kanban-slash-command). |
|
||||
| `/reload-mcp` (alias: `/reload_mcp`) | Reload MCP servers from config.yaml |
|
||||
| `/reload-skills` (alias: `/reload_skills`) | Re-scan `~/.hermes/skills/` for newly installed or removed skills |
|
||||
| `/reload` | Reload `.env` variables into the running session (picks up new API keys without restarting) |
|
||||
|
|
@ -100,6 +101,7 @@ Type `/` in the CLI to open the autocomplete menu. Built-in commands are case-in
|
|||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `/help` | Show this help message |
|
||||
| `/version` | Show Hermes Agent version, build, and environment info. |
|
||||
| `/usage` | Show token usage, cost breakdown, session duration, and — when available from the active provider — an **Account limits** section with remaining quota / credits / plan usage pulled live from the provider's API. |
|
||||
| `/insights` | Show usage insights and analytics (last 30 days) |
|
||||
| `/platforms` (alias: `/gateway`) | Show gateway/messaging platform status (CLI-only summary view). |
|
||||
|
|
@ -115,7 +117,7 @@ Type `/` in the CLI to open the autocomplete menu. Built-in commands are case-in
|
|||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `/quit` | Exit the CLI (also: `/exit`). See note on `/q` under `/queue` above. Pass `--delete` (or `-d`) — e.g. `/exit --delete` — to also permanently remove the current session's SQLite history and on-disk transcripts before exiting. Useful for privacy-sensitive or one-off tasks. |
|
||||
| `/quit` | Exit the CLI (also: `/exit`). |
|
||||
|
||||
### Dynamic CLI slash commands
|
||||
|
||||
|
|
@ -193,6 +195,7 @@ The messaging gateway supports the following built-in commands inside Telegram,
|
|||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `/start` | Platform-protocol command. Many chat platforms (Telegram, Discord, …) send `/start` automatically the first time a user opens a bot conversation. Hermes acknowledges the ping silently — no agent reply, no session burn — so first-contact handshakes don't waste a turn. You can also send it explicitly to confirm the gateway is reachable. |
|
||||
| `/new` | Start a new conversation. |
|
||||
| `/reset` | Reset conversation history. |
|
||||
| `/status` | Show session info, followed by a local **Session recap** block (recent turn counts, top tools used, files touched, latest prompt + reply). |
|
||||
|
|
@ -204,8 +207,8 @@ The messaging gateway supports the following built-in commands inside Telegram,
|
|||
| `/retry` | Retry the last message. |
|
||||
| `/undo` | Remove the last exchange. |
|
||||
| `/sethome` (alias: `/set-home`) | Mark the current chat as the platform home channel for deliveries. |
|
||||
| `/compress [focus topic]` | Manually compress conversation context. Optional focus topic narrows what the summary preserves. |
|
||||
| `/topic [off\|help\|session-id]` | **Telegram DM only.** Manage user-managed multi-session topic mode. `/topic` enables it or shows status; `/topic off` disables it and clears bindings; `/topic help` shows usage; `/topic <session-id>` inside a topic restores a previous session. See [Multi-session DM mode](/docs/user-guide/messaging/telegram#multi-session-dm-mode-topic). |
|
||||
| `/compress [here [N] \| focus topic]` | Manually compress conversation context. `/compress here [N]` keeps the most recent N exchanges (default 2) verbatim and summarizes the rest. A focus topic narrows what a full summary preserves. |
|
||||
| `/topic [off\|help\|session-id]` | **Telegram DM only.** Manage user-managed multi-session topic mode. `/topic` enables it or shows status; `/topic off` disables it and clears bindings; `/topic help` shows usage; `/topic <session-id>` inside a topic restores a previous session. See [Multi-session DM mode](/user-guide/messaging/telegram#multi-session-dm-mode-topic). |
|
||||
| `/title [name]` | Set or show the session title. |
|
||||
| `/resume [name]` | Resume a previously named session. |
|
||||
| `/usage` | Show token usage, estimated cost breakdown (input/output), context window state, session duration, and — when available from the active provider — an **Account limits** section with remaining quota / credits pulled live from the provider's API. |
|
||||
|
|
@ -213,13 +216,13 @@ The messaging gateway supports the following built-in commands inside Telegram,
|
|||
| `/reasoning [level\|show\|hide]` | Change reasoning effort or toggle reasoning display. |
|
||||
| `/voice [on\|off\|tts\|join\|channel\|leave\|status]` | Control spoken replies in chat. `join`/`channel`/`leave` manage Discord voice-channel mode. |
|
||||
| `/rollback [number]` | List or restore filesystem checkpoints. |
|
||||
| `/background <prompt>` | Run a prompt in a separate background session. Results are delivered back to the same chat when the task finishes. See [Messaging Background Sessions](/docs/user-guide/messaging/#background-sessions). |
|
||||
| `/background <prompt>` | Run a prompt in a separate background session. Results are delivered back to the same chat when the task finishes. See [Messaging Background Sessions](/user-guide/messaging/#background-sessions). |
|
||||
| `/queue <prompt>` (alias: `/q`) | Queue a prompt for the next turn without interrupting the current one. |
|
||||
| `/steer <prompt>` | Inject a message after the next tool call without interrupting — the model picks it up on its next iteration rather than as a new turn. |
|
||||
| `/goal <text>` | Set a standing goal Hermes works toward across turns — our take on the Ralph loop. A judge model checks after each turn; if not done, Hermes auto-continues until it is, you pause/clear it, or the turn budget (default 20) is hit. Subcommands: `/goal status`, `/goal pause`, `/goal resume`, `/goal clear`. Safe to run mid-agent for status/pause/clear; setting a new goal requires `/stop` first. See [Persistent Goals](/docs/user-guide/features/goals). |
|
||||
| `/footer [on\|off\|status]` | Toggle the runtime-metadata footer on final replies (shows model, tool counts, timing). |
|
||||
| `/goal <text>` | Set a standing goal Hermes works toward across turns — our take on the Ralph loop. A judge model checks after each turn; if not done, Hermes auto-continues until it is, you pause/clear it, or the turn budget (default 20) is hit. Subcommands: `/goal status`, `/goal pause`, `/goal resume`, `/goal clear`. Safe to run mid-agent for status/pause/clear; setting a new goal requires `/stop` first. See [Persistent Goals](/user-guide/features/goals). |
|
||||
| `/footer [on\|off\|status]` | Toggle the runtime-metadata footer on final replies (shows model, context %, and cwd). |
|
||||
| `/curator [status\|run\|pin\|archive]` | Background skill maintenance controls. |
|
||||
| `/kanban <action>` | Drive the multi-profile, multi-project collaboration board from chat — identical argument surface to the CLI. Bypasses the running-agent guard, so `/kanban unblock t_abc`, `/kanban comment t_abc "…"`, `/kanban list --mine`, `/kanban boards switch <slug>`, etc. work mid-turn. `/kanban create …` auto-subscribes the originating chat to the new task's terminal events. See [Kanban slash command](/docs/user-guide/features/kanban#kanban-slash-command). |
|
||||
| `/kanban <action>` | Drive the multi-profile, multi-project collaboration board from chat — identical argument surface to the CLI. Bypasses the running-agent guard, so `/kanban unblock t_abc`, `/kanban comment t_abc "…"`, `/kanban list --mine`, `/kanban boards switch <slug>`, etc. work mid-turn. `/kanban create …` auto-subscribes the originating chat to the new task's terminal events. See [Kanban slash command](/user-guide/features/kanban#kanban-slash-command). |
|
||||
| `/reload-mcp` (alias: `/reload_mcp`) | Reload MCP servers from config. |
|
||||
| `/yolo` | Toggle YOLO mode — skip all dangerous command approval prompts. |
|
||||
| `/commands [page]` | Browse all commands and skills (paginated). |
|
||||
|
|
@ -236,8 +239,9 @@ The messaging gateway supports the following built-in commands inside Telegram,
|
|||
- `/skin`, `/snapshot`, `/gquota`, `/reload`, `/tools`, `/toolsets`, `/browser`, `/config`, `/cron`, `/skills`, `/platforms`, `/paste`, `/image`, `/statusbar`, `/plugins`, `/busy`, `/indicator`, `/redraw`, `/clear`, `/history`, `/save`, `/copy`, `/handoff`, and `/quit` are **CLI-only** commands.
|
||||
- `/verbose` is **CLI-only by default**, but can be enabled for messaging platforms by setting `display.tool_progress_command: true` in `config.yaml`. When enabled, it cycles the `display.tool_progress` mode and saves to config.
|
||||
- `/sethome`, `/update`, `/restart`, `/approve`, `/deny`, `/topic`, and `/commands` are **messaging-only** commands.
|
||||
- `/status`, `/background`, `/queue`, `/steer`, `/voice`, `/reload-mcp`, `/reload-skills`, `/rollback`, `/debug`, `/fast`, `/footer`, `/curator`, `/kanban`, `/sessions`, and `/yolo` work in **both** the CLI and the messaging gateway.
|
||||
- `/status`, `/version`, `/background`, `/queue`, `/steer`, `/voice`, `/reload-mcp`, `/reload-skills`, `/rollback`, `/debug`, `/fast`, `/footer`, `/curator`, `/kanban`, `/sessions`, and `/yolo` work in **both** the CLI and the messaging gateway.
|
||||
- `/voice join`, `/voice channel`, and `/voice leave` are only meaningful on Discord.
|
||||
- In the TUI, `/sessions` shows live sessions in the current TUI process. Use `/resume [name]` or `hermes --tui --resume <id-or-title>` for saved or closed transcripts.
|
||||
|
||||
## Confirmation prompts for destructive commands
|
||||
|
||||
|
|
@ -252,4 +256,6 @@ The CLI prompts before running slash commands that throw away unsaved session st
|
|||
|
||||
For each of these the CLI opens a three-choice modal: **Approve Once** (proceed this time), **Always Approve** (proceed and persist `approvals.destructive_slash_confirm: false` so future destructive commands run without prompting), or **Cancel**.
|
||||
|
||||
**Inline skip:** append `now`, `--yes`, or `-y` to bypass the modal for a single invocation — e.g. `/reset now`, `/new --yes my-session`, `/clear -y`, `/undo -y`. Useful when the modal doesn't render correctly on your terminal (see [issue #30768](https://github.com/NousResearch/hermes-agent/issues/30768) for native Windows PowerShell) or when scripting against the CLI.
|
||||
|
||||
Set `approvals.destructive_slash_confirm: false` in `~/.hermes/config.yaml` to disable the prompts globally; set it back to `true` to re-enable. See [Security — Destructive slash command confirmation](../user-guide/security.md#dangerous-command-approval) for context.
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@ description: "Authoritative reference for Hermes built-in tools, grouped by tool
|
|||
|
||||
This page documents Hermes' built-in tools, grouped by toolset. Availability varies by platform, credentials, and enabled toolsets.
|
||||
|
||||
**Quick counts (current registry):** ~70 tools — 10 browser tools (core) + 2 CDP-gated browser tools, 4 file tools, 10 RL tools, 4 Home Assistant tools, 2 terminal tools, 2 web tools, 5 Feishu tools, 7 Spotify tools (registered by the bundled `spotify` plugin), 5 Yuanbao tools, 7 kanban tools (registered when the kanban dispatcher spawns the agent), 2 Discord tools, and a handful of standalone tools (`memory`, `clarify`, `delegate_task`, `execute_code`, `cronjob`, `session_search`, `skill_view`/`skill_manage`/`skills_list`, `text_to_speech`, `image_generate`, `video_generate`, `vision_analyze`, `video_analyze`, `mixture_of_agents`, `send_message`, `todo`, `computer_use`, `process`).
|
||||
**Quick counts (current registry):** ~71 tools — 10 browser tools (core) + 2 CDP-gated browser tools, 4 file tools, 4 Home Assistant tools, 2 terminal tools, 2 web tools, 5 Feishu tools, 7 Spotify tools (registered by the bundled `spotify` plugin), 5 Yuanbao tools, 9 kanban tools (registered when the kanban dispatcher spawns the agent), 2 Discord tools, and a handful of standalone tools (`memory`, `clarify`, `delegate_task`, `execute_code`, `cronjob`, `session_search`, `skill_view`/`skill_manage`/`skills_list`, `text_to_speech`, `image_generate`, `video_generate`, `vision_analyze`, `video_analyze`, `mixture_of_agents`, `send_message`, `todo`, `computer_use`, `process`).
|
||||
|
||||
:::tip MCP Tools
|
||||
In addition to built-in tools, Hermes can load tools dynamically from MCP servers. MCP tools appear with the prefix `mcp_<server>_` (e.g., `mcp_github_create_issue` for the `github` MCP server). See [MCP Integration](/docs/user-guide/features/mcp) for configuration.
|
||||
In addition to built-in tools, Hermes can load tools dynamically from MCP servers. MCP tools appear with the prefix `mcp_<server>_` (e.g., `mcp_github_create_issue` for the `github` MCP server). See [MCP Integration](/user-guide/features/mcp) for configuration.
|
||||
:::
|
||||
|
||||
## `browser` toolset
|
||||
|
|
@ -118,7 +118,7 @@ Scoped to the Feishu document-comment handler. Drives comment read/write operati
|
|||
|
||||
## `kanban` toolset
|
||||
|
||||
Registered when the agent is either (a) spawned by the kanban dispatcher (`HERMES_KANBAN_TASK` env set) or (b) running in a profile that explicitly enables the `kanban` toolset. Task-scoped workers use lifecycle tools for their assigned task; orchestrator profiles additionally get board-routing tools like `kanban_list` and `kanban_unblock`. See [Kanban Multi-Agent](/docs/user-guide/features/kanban) for the full workflow.
|
||||
Registered when the agent is either (a) spawned by the kanban dispatcher (`HERMES_KANBAN_TASK` env set) or (b) running in a profile that explicitly enables the `kanban` toolset. Task-scoped workers use lifecycle tools for their assigned task; orchestrator profiles additionally get board-routing tools like `kanban_list` and `kanban_unblock`. See [Kanban Multi-Agent](/user-guide/features/kanban) for the full workflow.
|
||||
|
||||
| Tool | Description | Requires environment |
|
||||
|------|-------------|----------------------|
|
||||
|
|
@ -200,7 +200,7 @@ Backends ship as plugins under `plugins/video_gen/<name>/`:
|
|||
- **xAI Grok-Imagine** — text-to-video and image-to-video (SuperGrok OAuth or `XAI_API_KEY`).
|
||||
- **FAL.ai** — Veo 3.1, Pixverse v6, Kling O3 (requires `FAL_KEY`).
|
||||
|
||||
The single `video_generate` tool covers both modalities — pass `image_url` to animate a still, omit it to generate from text alone. The active backend auto-routes to the right endpoint. The tool's description is rebuilt at session start to reflect the active backend's actual capabilities (modalities, aspect ratios, resolutions, duration range, max reference images, audio support). See [Video Generation Provider Plugins](/docs/developer-guide/video-gen-provider-plugin) for backend authoring.
|
||||
The single `video_generate` tool covers both modalities — pass `image_url` to animate a still, omit it to generate from text alone. The active backend auto-routes to the right endpoint. The tool's description is rebuilt at session start to reflect the active backend's actual capabilities (modalities, aspect ratios, resolutions, duration range, max reference images, audio support). See [Video Generation Provider Plugins](/developer-guide/video-gen-provider-plugin) for backend authoring.
|
||||
|
||||
| Tool | Description | Requires environment |
|
||||
|------|-------------|----------------------|
|
||||
|
|
@ -217,7 +217,7 @@ The single `video_generate` tool covers both modalities — pass `image_url` to
|
|||
|
||||
| Tool | Description | Requires environment |
|
||||
|------|-------------|----------------------|
|
||||
| `x_search` | Search X (Twitter) posts, profiles, and threads using xAI's built-in `x_search` Responses tool. Use this for current discussion, reactions, or claims on X rather than general web pages. Off by default — opt in via `hermes tools` → 🐦 X (Twitter) Search. Schema is only registered when xAI credentials are configured (check_fn-gated). | XAI_API_KEY **or** xAI Grok OAuth (SuperGrok Subscription) login |
|
||||
| `x_search` | Search X (Twitter) posts, profiles, and threads using xAI's built-in `x_search` Responses tool. Use this for current discussion, reactions, or claims on X rather than general web pages. Off by default — opt in via `hermes tools` → 🐦 X (Twitter) Search. Schema is only registered when xAI credentials are configured (check_fn-gated). | XAI_API_KEY **or** xAI Grok OAuth (SuperGrok / Premium+) login |
|
||||
|
||||
## `tts` toolset
|
||||
|
||||
|
|
|
|||
|
|
@ -65,9 +65,10 @@ Or in-session:
|
|||
| `file` | `patch`, `read_file`, `search_files`, `write_file` | File reading, writing, searching, and editing. |
|
||||
| `homeassistant` | `ha_call_service`, `ha_get_state`, `ha_list_entities`, `ha_list_services` | Smart home control via Home Assistant. Only available when `HASS_TOKEN` is set. |
|
||||
| `computer_use` | `computer_use` | Background macOS desktop control via cua-driver — does not steal cursor/focus. Works with any tool-capable model. macOS only; requires `cua-driver` on `$PATH`. |
|
||||
| `context_engine` | (varies) | Runtime tools exposed by the active context-engine plugin (empty until a plugin populates it). |
|
||||
| `image_gen` | `image_generate` | Text-to-image generation via FAL.ai (with opt-in OpenAI / xAI backends). |
|
||||
| `video_gen` | `video_generate` | Text-to-video and image-to-video via plugin-registered backends (xAI Grok-Imagine, FAL.ai Veo 3.1 / Pixverse v6 / Kling O3). Pass `image_url` to animate an image; omit it for text-to-video. |
|
||||
| `kanban` | `kanban_block`, `kanban_comment`, `kanban_complete`, `kanban_create`, `kanban_heartbeat`, `kanban_link`, `kanban_list`, `kanban_show`, `kanban_unblock` | Multi-agent coordination tools. Registered for dispatcher-spawned task workers (`HERMES_KANBAN_TASK`) and for profiles that explicitly enable the `kanban` toolset. Workers mark tasks done, block, heartbeat, comment, and create/link follow-up tasks; orchestrator profiles additionally get board-routing tools like list/unblock. |
|
||||
| `kanban` | `kanban_block`, `kanban_comment`, `kanban_complete`, `kanban_create`, `kanban_heartbeat`, `kanban_link`, `kanban_list`, `kanban_show`, `kanban_unblock` | Multi-agent coordination tools. Registered for dispatcher-spawned task workers (`HERMES_KANBAN_TASK`) and for profiles that explicitly list the `kanban` toolset by name (the `all`/`*` wildcard does **not** enable it). Workers mark tasks done, block, heartbeat, comment, and create/link follow-up tasks; orchestrator profiles additionally get board-routing tools like list/unblock. |
|
||||
| `memory` | `memory` | Persistent cross-session memory management. |
|
||||
| `messaging` | `send_message` | Send messages to other platforms (Telegram, Discord, etc.) from within a session. |
|
||||
| `moa` | `mixture_of_agents` | Multi-model consensus via Mixture of Agents. |
|
||||
|
|
@ -156,6 +157,11 @@ custom_toolsets:
|
|||
|
||||
- `all` or `*` — expands to every registered toolset (built-in + dynamic + plugin)
|
||||
|
||||
A handful of tools have an additional availability check on top of toolset membership and are **not** turned on by `all`/`*` alone:
|
||||
|
||||
- **Capability-gated** tools (browser, `computer_use`, `code_execution`, Feishu, Home Assistant, cronjob) appear only when their backend/credential prerequisite is configured.
|
||||
- **Workflow-gated** tools — the `kanban` toolset — are deliberately opt-in. `all`/`*` does **not** enable kanban; you must list `kanban` explicitly (or be a dispatcher-spawned worker with `HERMES_KANBAN_TASK` set). Kanban tools mutate shared board state, so they stay off by default even under `all`.
|
||||
|
||||
## Relationship to `hermes tools`
|
||||
|
||||
The `hermes tools` command provides a curses-based UI for toggling individual tools on or off per platform. This operates at the tool level (finer than toolsets) and persists to `config.yaml`. Disabled tools are filtered out even if their toolset is enabled.
|
||||
|
|
|
|||
|
|
@ -8,6 +8,10 @@ description: "Master the Hermes Agent terminal interface — commands, keybindin
|
|||
|
||||
Hermes Agent's CLI is a full terminal user interface (TUI) — not a web UI. It features multiline editing, slash-command autocomplete, conversation history, interrupt-and-redirect, and streaming tool output. Built for people who live in the terminal.
|
||||
|
||||
:::tip First-time setup
|
||||
One command — `hermes setup --portal` — and you're ready to `hermes chat`. See [Nous Portal](/integrations/nous-portal).
|
||||
:::
|
||||
|
||||
:::tip
|
||||
Hermes also ships a modern TUI with modal overlays, mouse selection, and non-blocking input. Launch it with `hermes --tui` — see the [TUI](tui.md) guide.
|
||||
:::
|
||||
|
|
@ -44,12 +48,12 @@ hermes chat --verbose
|
|||
|
||||
# Isolated git worktree (for running multiple agents in parallel)
|
||||
hermes -w # Interactive mode in worktree
|
||||
hermes -w -q "Fix issue #123" # Single query in worktree
|
||||
hermes -w -z "Fix issue #123" # Single query in worktree
|
||||
```
|
||||
|
||||
## Interface Layout
|
||||
|
||||
<img className="docs-terminal-figure" src="/img/docs/cli-layout.svg" alt="Stylized preview of the Hermes CLI layout showing the banner, conversation area, and fixed input prompt." />
|
||||
<img className="docs-terminal-figure" src="/docs/img/docs/cli-layout.svg" alt="Stylized preview of the Hermes CLI layout showing the banner, conversation area, and fixed input prompt." />
|
||||
<p className="docs-figure-caption">The Hermes CLI banner, conversation stream, and fixed input prompt rendered as a stable docs figure instead of fragile text art.</p>
|
||||
|
||||
The welcome banner shows your model, terminal backend, working directory, available tools, and installed skills at a glance.
|
||||
|
|
@ -157,7 +161,7 @@ quick_commands:
|
|||
target: /gateway restart
|
||||
```
|
||||
|
||||
Then type `/status`, `/gpu`, or `/restart` in any chat. See the [Configuration guide](/docs/user-guide/configuration#quick-commands) for more examples.
|
||||
Then type `/status`, `/gpu`, or `/restart` in any chat. See the [Configuration guide](/user-guide/configuration#quick-commands) for more examples.
|
||||
|
||||
## Preloading Skills at Launch
|
||||
|
||||
|
|
@ -305,7 +309,7 @@ The CLI shows animated feedback as the agent works:
|
|||
┊ 📄 web_extract (2.1s)
|
||||
```
|
||||
|
||||
Cycle through display modes with `/verbose`: `off → new → all → verbose`. This command can also be enabled for messaging platforms — see [configuration](/docs/user-guide/configuration#display-settings).
|
||||
Cycle through display modes with `/verbose`: `off → new → all → verbose`. This command can also be enabled for messaging platforms — see [configuration](/user-guide/configuration#display-settings).
|
||||
|
||||
### Tool Preview Length
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,10 @@ description: "Configure Hermes Agent — config.yaml, providers, models, API key
|
|||
|
||||
All settings are stored in the `~/.hermes/` directory for easy access.
|
||||
|
||||
:::tip Easiest path to a working `config.yaml`
|
||||
Run `hermes setup --portal` — one OAuth gets you a model provider and all four Tool Gateway tools without hand-editing YAML. Portal subscribers also get 10% off token-billed providers. See [Nous Portal](/integrations/nous-portal).
|
||||
:::
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```text
|
||||
|
|
@ -71,7 +75,7 @@ delegation:
|
|||
|
||||
Multiple references in a single value work: `url: "${HOST}:${PORT}"`. If a referenced variable is not set, the placeholder is kept verbatim (`${UNDEFINED_VAR}` stays as-is). Only the `${VAR}` syntax is supported — bare `$VAR` is not expanded.
|
||||
|
||||
For AI provider setup (OpenRouter, Anthropic, Copilot, custom endpoints, self-hosted LLMs, fallback models, etc.), see [AI Providers](/docs/integrations/providers).
|
||||
For AI provider setup (OpenRouter, Anthropic, Copilot, custom endpoints, self-hosted LLMs, fallback models, etc.), see [AI Providers](/integrations/providers).
|
||||
|
||||
### Provider Timeouts
|
||||
|
||||
|
|
@ -81,13 +85,28 @@ You can also set `providers.<id>.stale_timeout_seconds` for the non-streaming st
|
|||
|
||||
Leaving these unset keeps the legacy defaults (`HERMES_API_TIMEOUT=1800`s, `HERMES_API_CALL_STALE_TIMEOUT=300`s, native Anthropic 900s). Not currently wired for AWS Bedrock (both `bedrock_converse` and AnthropicBedrock SDK paths use boto3 with its own timeout configuration). See the commented example in [`cli-config.yaml.example`](https://github.com/NousResearch/hermes-agent/blob/main/cli-config.yaml.example).
|
||||
|
||||
## Update Behavior
|
||||
|
||||
`hermes update` settings live under `updates` in `config.yaml`:
|
||||
|
||||
```yaml
|
||||
updates:
|
||||
pre_update_backup: false # Create a full HERMES_HOME zip before every update
|
||||
backup_keep: 5 # Keep this many pre-update backup zips
|
||||
non_interactive_local_changes: stash # stash | discard
|
||||
```
|
||||
|
||||
For git installs, Hermes auto-stashes dirty tracked files and untracked files before checking out the update branch or pulling. Interactive terminal updates prompt before restoring that stash. Non-interactive updates (desktop/chat app, gateway, or `--yes`) use `updates.non_interactive_local_changes`: `stash` restores local source edits after a successful pull, while `discard` drops the update-created stash after a successful pull. Use `discard` only on managed installs where local source edits are never meant to persist.
|
||||
|
||||
Before that stash step, Hermes also restores tracked `package-lock.json` diffs left by npm install/build churn. Commit or manually stash intentional lockfile edits before updating.
|
||||
|
||||
## Terminal Backend Configuration
|
||||
|
||||
Hermes supports seven terminal backends. Each determines where the agent's shell commands actually execute — your local machine, a Docker container, a remote server via SSH, a Modal cloud sandbox (direct or via the Nous-managed gateway), a Daytona workspace, a Vercel Sandbox, or a Singularity/Apptainer container.
|
||||
Hermes supports six terminal backends. Each determines where the agent's shell commands actually execute — your local machine, a Docker container, a remote server via SSH, a Modal cloud sandbox (direct or via the Nous-managed gateway), a Daytona workspace, or a Singularity/Apptainer container.
|
||||
|
||||
```yaml
|
||||
terminal:
|
||||
backend: local # local | docker | ssh | modal | daytona | vercel_sandbox | singularity
|
||||
backend: local # local | docker | ssh | modal | daytona | singularity
|
||||
cwd: "." # Gateway/cron working directory (CLI always uses launch dir)
|
||||
timeout: 180 # Per-command timeout in seconds
|
||||
env_passthrough: [] # Env var names to forward to sandboxed execution (terminal + execute_code)
|
||||
|
|
@ -96,7 +115,7 @@ terminal:
|
|||
daytona_image: "nikolaik/python-nodejs:python3.11-nodejs20" # Container image for Daytona backend
|
||||
```
|
||||
|
||||
For cloud sandboxes such as Modal, Daytona, and Vercel Sandbox, `container_persistent: true` means Hermes will try to preserve filesystem state across sandbox recreation. It does not promise that the same live sandbox, PID space, or background processes will still be running later.
|
||||
For cloud sandboxes such as Modal and Daytona, `container_persistent: true` means Hermes will try to preserve filesystem state across sandbox recreation. It does not promise that the same live sandbox, PID space, or background processes will still be running later.
|
||||
|
||||
### Backend Overview
|
||||
|
||||
|
|
@ -107,7 +126,6 @@ For cloud sandboxes such as Modal, Daytona, and Vercel Sandbox, `container_persi
|
|||
| **ssh** | Remote server via SSH | Network boundary | Remote dev, powerful hardware |
|
||||
| **modal** | Modal cloud sandbox | Full (cloud VM) | Ephemeral cloud compute, evals |
|
||||
| **daytona** | Daytona workspace | Full (cloud container) | Managed cloud dev environments |
|
||||
| **vercel_sandbox** | Vercel Sandbox | Full (cloud microVM) | Cloud execution with snapshot-backed filesystem persistence |
|
||||
| **singularity** | Singularity/Apptainer container | Namespaces (--containall) | HPC clusters, shared machines |
|
||||
|
||||
### Local Backend
|
||||
|
|
@ -127,7 +145,7 @@ The agent has the same filesystem access as your user account. Use `hermes tools
|
|||
|
||||
Runs commands inside a Docker container with security hardening (all capabilities dropped, no privilege escalation, PID limits).
|
||||
|
||||
**Single persistent container, not per-command.** Hermes starts ONE long-lived container on first use and routes every terminal, file, and `execute_code` call through `docker exec` into that same container — across sessions, `/new`, `/reset`, and `delegate_task` subagents — for the lifetime of the Hermes process. Working-directory changes, installed packages, and files in `/workspace` carry over from one tool call to the next, just like a local shell. The container is stopped and removed on shutdown. See **Container lifecycle** below for details.
|
||||
**Single persistent container, shared across Hermes processes.** Hermes starts ONE long-lived container on first use and routes every terminal, file, and `execute_code` call through `docker exec` into that same container — across sessions, `/new`, `/reset`, and `delegate_task` subagents. Working-directory changes, installed packages, files in `/workspace`, and **background processes** all carry over from one tool call to the next, and from one Hermes process to the next. When you close a TUI session, run `/quit`, or start a new `hermes` invocation, the container keeps running and the next Hermes process reuses it via a labeled lookup. See **Container lifecycle** below for the exact teardown rules.
|
||||
|
||||
```yaml
|
||||
terminal:
|
||||
|
|
@ -135,8 +153,11 @@ terminal:
|
|||
docker_image: "nikolaik/python-nodejs:python3.11-nodejs20"
|
||||
docker_mount_cwd_to_workspace: false # Mount launch dir into /workspace
|
||||
docker_run_as_host_user: false # See "Running container as host user" below
|
||||
docker_forward_env: # Env vars to forward into container
|
||||
docker_forward_env: # Host env vars to forward into container
|
||||
- "GITHUB_TOKEN"
|
||||
docker_env: # Literal env vars to inject (KEY=value)
|
||||
DEBUG: "1"
|
||||
PYTHONUNBUFFERED: "1"
|
||||
docker_volumes: # Host directory mounts
|
||||
- "/home/user/projects:/workspace/projects"
|
||||
- "/home/user/data:/data:ro" # :ro for read-only
|
||||
|
|
@ -148,14 +169,49 @@ terminal:
|
|||
container_cpu: 1 # CPU cores (0 = unlimited)
|
||||
container_memory: 5120 # MB (0 = unlimited)
|
||||
container_disk: 51200 # MB (requires overlay2 on XFS+pquota)
|
||||
container_persistent: true # Persist /workspace and /root across sessions
|
||||
container_persistent: true # Persist /workspace and /root bind-mount dirs
|
||||
|
||||
# Cross-process container reuse (defaults match the "one long-lived
|
||||
# container shared across sessions" contract — see Container lifecycle).
|
||||
docker_persist_across_processes: true # Reuse container across Hermes restarts
|
||||
docker_orphan_reaper: true # Sweep abandoned Exited containers at startup
|
||||
|
||||
# Cross-backend lifecycle settings (apply to docker as well)
|
||||
timeout: 180 # Per-command timeout in seconds
|
||||
lifetime_seconds: 300 # Idle-reaper window; also feeds 2× orphan-reaper threshold
|
||||
```
|
||||
|
||||
**`docker_env`** vs **`docker_forward_env`**: the former injects literal `KEY=value` pairs you specify in the config (the values live in your `config.yaml` or are passed as a JSON dict via `TERMINAL_DOCKER_ENV='{"DEBUG":"1"}'`). The latter forwards values from your shell or `~/.hermes/.env`, so the actual secret never appears in the config file. Use `docker_forward_env` for tokens and `docker_env` for static knobs the container needs.
|
||||
|
||||
**`terminal.docker_extra_args`** (also overridable via `TERMINAL_DOCKER_EXTRA_ARGS='["--gpus=all"]'`) lets you pass arbitrary `docker run` flags that Hermes doesn't surface as first-class keys — `--gpus`, `--network`, `--add-host`, alternative `--security-opt` overrides, etc. Each entry must be a string; the list is appended last to the assembled `docker run` invocation so it can override Hermes' defaults if needed. Use sparingly — flags that conflict with the sandbox hardening (capability drops, `--user`, the workspace bind mount) will silently weaken isolation.
|
||||
|
||||
**Requirements:** Docker Desktop or Docker Engine installed and running. Hermes probes `$PATH` plus common macOS install locations (`/usr/local/bin/docker`, `/opt/homebrew/bin/docker`, Docker Desktop app bundle). Podman is supported out of the box: set `HERMES_DOCKER_BINARY=podman` (or the full path) to force it when both are installed.
|
||||
|
||||
**Container lifecycle:** Hermes reuses a single long-lived container (`docker run -d ... sleep 2h`) for every terminal and file-tool call, across sessions, `/new`, `/reset`, and `delegate_task` subagents, for the lifetime of the Hermes process. Commands run via `docker exec` with a login shell, so working-directory changes, installed packages, and files in `/workspace` all persist from one tool call to the next. The container is stopped and removed on Hermes shutdown (or when the idle-sweep reclaims it).
|
||||
#### Container lifecycle
|
||||
|
||||
Every Hermes-managed container is tagged with three labels so subsequent processes (and the orphan reaper) can identify it:
|
||||
|
||||
- `hermes-agent=1` — marks it as Hermes-managed
|
||||
- `hermes-task-id=<sanitized task_id>` — keys the per-task reuse probe
|
||||
- `hermes-profile=<sanitized profile name>` — scopes reuse and reaping to the active Hermes profile
|
||||
|
||||
On startup, Hermes runs `docker ps --filter label=hermes-task-id=<id> --filter label=hermes-profile=<profile>` and **attaches to the existing container** when it finds one. If the container is `exited` (e.g. after a Docker daemon restart), it's `docker start`'d and reused — filesystem state and any installed packages survive, but in-container background processes do not.
|
||||
|
||||
When a Hermes process exits — `/quit`, closing a TUI session, gateway shutdown, even SIGKILL — the cleanup path is a **no-op for the container in default mode**. The container keeps running. The next Hermes process attaches to it in milliseconds via the label probe. This is the behavior the "one long-lived container shared across sessions" contract requires: it's the only way background processes (npm watchers, dev servers, long-running pytest) survive across sessions.
|
||||
|
||||
**The container is only torn down (stopped and `docker rm -f`'d) in these cases:**
|
||||
|
||||
| Trigger | When it fires |
|
||||
|---|---|
|
||||
| `docker_persist_across_processes: false` | Explicit per-process isolation. Every `cleanup()` does `stop` + `rm -f`. Matches pre-issue-#20561 behavior. |
|
||||
| Idle reaper (`lifetime_seconds`, default 300s) | Only when the env is `persist_across_processes=false`. Persist-mode envs are no-op'd; container survives the idle sweep. |
|
||||
| Orphan reaper at next startup | Sweeps **Exited** hermes-labeled containers older than `2 × lifetime_seconds` (default 600s = 10 min), scoped to the current profile. **Running containers are never touched** — sibling-process safety. Set `docker_orphan_reaper: false` to disable. |
|
||||
| Direct user action | `docker rm -f`, `docker system prune`, Docker Desktop restart. We don't set `--restart=always`, so a host reboot leaves the container `Exited` (its CoW layer survives and gets reused on next startup, but bg processes are gone). |
|
||||
|
||||
Edge cases worth knowing:
|
||||
|
||||
- **OOM kill of in-container PID 1** transitions the container to `Exited`. Next reuse will `docker start` it; filesystem state survives, bg processes do not.
|
||||
- **Switching profiles** isolates containers from each other — a container labeled `hermes-profile=work` is invisible to a Hermes process running under `hermes-profile=research`. The orphan reaper is profile-scoped too, so cross-profile containers don't get reaped accidentally, but they also won't get cleaned up automatically until you start Hermes again under their original profile.
|
||||
|
||||
Parallel subagents spawned via `delegate_task(tasks=[...])` share this one container — concurrent `cd`, env mutations, and writes to the same path will collide. If a subagent needs an isolated sandbox, it must register a per-task image override via `register_task_env_overrides()`, which RL and benchmark environments (TerminalBench2, HermesSweEnv, etc.) do automatically for their per-task Docker images.
|
||||
|
||||
|
|
@ -167,6 +223,29 @@ Parallel subagents spawned via `delegate_task(tasks=[...])` share this one conta
|
|||
|
||||
**Credential forwarding:** Env vars listed in `docker_forward_env` are resolved from your shell environment first, then `~/.hermes/.env`. Skills can also declare `required_environment_variables` which are merged automatically.
|
||||
|
||||
#### Environment variable overrides
|
||||
|
||||
Every key under `terminal:` has an env-var override of the form `TERMINAL_<KEY_UPPERCASE>`. The most useful ones for the Docker backend:
|
||||
|
||||
| Env var | Maps to | Notes |
|
||||
|---|---|---|
|
||||
| `TERMINAL_DOCKER_IMAGE` | `docker_image` | Base image |
|
||||
| `TERMINAL_DOCKER_FORWARD_ENV` | `docker_forward_env` | JSON array: `'["GITHUB_TOKEN","OPENAI_API_KEY"]'` |
|
||||
| `TERMINAL_DOCKER_ENV` | `docker_env` | JSON dict: `'{"DEBUG":"1"}'` |
|
||||
| `TERMINAL_DOCKER_VOLUMES` | `docker_volumes` | JSON array of `"host:container[:ro]"` strings |
|
||||
| `TERMINAL_DOCKER_EXTRA_ARGS` | `docker_extra_args` | JSON array |
|
||||
| `TERMINAL_DOCKER_MOUNT_CWD_TO_WORKSPACE` | `docker_mount_cwd_to_workspace` | `true` / `false` |
|
||||
| `TERMINAL_DOCKER_RUN_AS_HOST_USER` | `docker_run_as_host_user` | `true` / `false` |
|
||||
| `TERMINAL_DOCKER_PERSIST_ACROSS_PROCESSES` | `docker_persist_across_processes` | `true` / `false` — default `true` |
|
||||
| `TERMINAL_DOCKER_ORPHAN_REAPER` | `docker_orphan_reaper` | `true` / `false` — default `true` |
|
||||
| `TERMINAL_CONTAINER_CPU` | `container_cpu` | CPU cores |
|
||||
| `TERMINAL_CONTAINER_MEMORY` | `container_memory` | MB |
|
||||
| `TERMINAL_CONTAINER_DISK` | `container_disk` | MB |
|
||||
| `TERMINAL_CONTAINER_PERSISTENT` | `container_persistent` | `true` / `false` — controls the bind-mount workspace dirs, distinct from `docker_persist_across_processes` |
|
||||
| `TERMINAL_LIFETIME_SECONDS` | `lifetime_seconds` | Idle reaper window |
|
||||
| `TERMINAL_TIMEOUT` | `timeout` | Per-command timeout |
|
||||
| `HERMES_DOCKER_BINARY` | _none_ | Force a specific docker/podman binary path |
|
||||
|
||||
### SSH Backend
|
||||
|
||||
Runs commands on a remote server over SSH. Uses ControlMaster for connection reuse (5-minute idle keepalive). Persistent shell is enabled by default — state (cwd, env vars) survives across commands.
|
||||
|
|
@ -232,49 +311,6 @@ terminal:
|
|||
|
||||
**Disk limit:** Daytona enforces a 10 GiB maximum. Requests above this are capped with a warning.
|
||||
|
||||
### Vercel Sandbox Backend
|
||||
|
||||
Runs commands in a [Vercel Sandbox](https://vercel.com/docs/vercel-sandbox) cloud microVM. Hermes uses the normal terminal and file tool surfaces; there are no Vercel-specific model-facing tools.
|
||||
|
||||
```yaml
|
||||
terminal:
|
||||
backend: vercel_sandbox
|
||||
vercel_runtime: node24 # node24 | node22 | python3.13
|
||||
cwd: /vercel/sandbox # default workspace root
|
||||
container_persistent: true # Snapshot/restore filesystem
|
||||
container_disk: 51200 # Shared default only; custom disk is unsupported
|
||||
```
|
||||
|
||||
**Required install:** Install the optional SDK extra:
|
||||
|
||||
```bash
|
||||
pip install 'hermes-agent[vercel]'
|
||||
```
|
||||
|
||||
**Required authentication:** Configure access-token auth with all three of `VERCEL_TOKEN`, `VERCEL_PROJECT_ID`, and `VERCEL_TEAM_ID`. This is the supported setup for deployments and normal long-running Hermes processes on Render, Railway, Docker, and similar hosts.
|
||||
|
||||
For one-off local development, Hermes also accepts short-lived Vercel OIDC tokens:
|
||||
|
||||
```bash
|
||||
VERCEL_OIDC_TOKEN="$(vc project token <project-name>)" hermes chat
|
||||
```
|
||||
|
||||
From a linked Vercel project directory, you can omit the project name:
|
||||
|
||||
```bash
|
||||
VERCEL_OIDC_TOKEN="$(vc project token)" hermes chat
|
||||
```
|
||||
|
||||
OIDC tokens are short-lived and should not be used as the documented deployment path.
|
||||
|
||||
**Runtime:** `terminal.vercel_runtime` supports `node24`, `node22`, and `python3.13`. If unset, Hermes defaults to `node24`.
|
||||
|
||||
**Persistence:** When `container_persistent: true`, Hermes snapshots the sandbox filesystem during cleanup and restores a later sandbox for the same task from that snapshot. Snapshot contents can include Hermes-synced credentials, skills, and cache files that were copied into the sandbox. This preserves filesystem state only; it does not preserve live sandbox identity, PID space, shell state, or running background processes.
|
||||
|
||||
**Background commands:** `terminal(background=true)` uses Hermes' generic non-local background process flow. You can spawn, poll, wait, view logs, and kill processes through the normal process tool while the sandbox is alive. Hermes does not provide native Vercel detached-process recovery after cleanup or restart.
|
||||
|
||||
**Disk sizing:** Vercel Sandbox does not currently support Hermes' `container_disk` resource knob. Leave `container_disk` unset or at the shared default `51200`; non-default values fail diagnostics and backend creation instead of being silently ignored.
|
||||
|
||||
### Singularity/Apptainer Backend
|
||||
|
||||
Runs commands in a [Singularity/Apptainer](https://apptainer.org) container. Designed for HPC clusters and shared machines where Docker isn't available.
|
||||
|
|
@ -484,7 +520,7 @@ skills:
|
|||
hermes config set skills.config.myplugin.path ~/myplugin-data
|
||||
```
|
||||
|
||||
For details on declaring config settings in your own skills, see [Creating Skills — Config Settings](/docs/developer-guide/creating-skills#config-settings-configyaml).
|
||||
For details on declaring config settings in your own skills, see [Creating Skills — Config Settings](/developer-guide/creating-skills#config-settings-configyaml).
|
||||
|
||||
### Guard on agent-created skill writes
|
||||
|
||||
|
|
@ -610,6 +646,7 @@ compression:
|
|||
threshold: 0.50 # Compress at this % of context limit
|
||||
target_ratio: 0.20 # Fraction of threshold to preserve as recent tail
|
||||
protect_last_n: 20 # Min recent messages to keep uncompressed
|
||||
protect_first_n: 3 # Non-system head messages pinned across compactions (0 = pin nothing)
|
||||
hygiene_hard_message_limit: 400 # Gateway safety valve — see below
|
||||
|
||||
# The summarization model/provider is configured under auxiliary:
|
||||
|
|
@ -626,6 +663,8 @@ Older configs with `compression.summary_model`, `compression.summary_provider`,
|
|||
|
||||
`hygiene_hard_message_limit` is a gateway-only **pre-compression safety valve**. Runaway sessions with thousands of messages can hit model context limits before the normal percent-of-context threshold fires; when message count crosses this ceiling, Hermes forces compression regardless of token usage. Default `400` — raise it for platforms where very long sessions are normal, lower it to force more aggressive compression. Editing this value on a running gateway takes effect on the next message (see below).
|
||||
|
||||
`protect_first_n` controls how many **non-system** head messages are pinned across every compaction. Default `3` — the opening user/assistant exchange survives every summarizer pass so the original goal stays visible. On long-running rolling-compaction sessions where the opening turn is no longer relevant, set `protect_first_n: 0` to pin nothing but the system prompt + summary + tail. The system prompt itself is always preserved regardless of this setting.
|
||||
|
||||
:::tip Gateway hot-reload of compression and context length
|
||||
As of recent releases, editing `model.context_length` or any `compression.*` key in `config.yaml` on a running gateway takes effect on the next message — no gateway restart, no `/reset`, no session rotation required. The cached-agent signature includes these keys, so the gateway transparently rebuilds the agent when it sees a change. API keys and tool/skill config still require the usual reload paths.
|
||||
:::
|
||||
|
|
@ -672,7 +711,7 @@ The summary model **must** have a context window at least as large as your main
|
|||
|
||||
## Context Engine
|
||||
|
||||
The context engine controls how conversations are managed when approaching the model's token limit. The built-in `compressor` engine uses lossy summarization (see [Context Compression](/docs/developer-guide/context-compression-and-caching)). Plugin engines can replace it with alternative strategies.
|
||||
The context engine controls how conversations are managed when approaching the model's token limit. The built-in `compressor` engine uses lossy summarization (see [Context Compression](/developer-guide/context-compression-and-caching)). Plugin engines can replace it with alternative strategies.
|
||||
|
||||
```yaml
|
||||
context:
|
||||
|
|
@ -688,7 +727,7 @@ context:
|
|||
|
||||
Plugin engines are **never auto-activated** — you must explicitly set `context.engine` to the plugin name. Available engines can be browsed and selected via `hermes plugins` → Provider Plugins → Context Engine.
|
||||
|
||||
See [Memory Providers](/docs/user-guide/features/memory-providers) for the analogous single-select system for memory plugins.
|
||||
See [Memory Providers](/user-guide/features/memory-providers) for the analogous single-select system for memory plugins.
|
||||
|
||||
## Iteration Budget Pressure
|
||||
|
||||
|
|
@ -711,7 +750,7 @@ Budget pressure is enabled by default. The agent sees warnings naturally as part
|
|||
|
||||
When the iteration budget is fully exhausted, the CLI shows a notification to the user: `⚠ Iteration budget reached (90/90) — response may be incomplete`. If the budget runs out during active work, the agent generates a summary of what was accomplished before stopping.
|
||||
|
||||
`agent.api_max_retries` controls how many times Hermes retries a provider API call on transient errors (rate limits, connection drops, 5xx) **before** fallback-provider switching engages. The default is `3` — four attempts total. If you have [fallback providers](/docs/user-guide/features/fallback-providers) configured and want to fail over faster, drop this to `0` so the first transient error on your primary immediately hands off to the fallback instead of churning retries against the flaky endpoint.
|
||||
`agent.api_max_retries` controls how many times Hermes retries a provider API call on transient errors (rate limits, connection drops, 5xx) **before** fallback-provider switching engages. The default is `3` — four attempts total. If you have [fallback providers](/user-guide/features/fallback-providers) configured and want to fail over faster, drop this to `0` so the first transient error on your primary immediately hands off to the fallback instead of churning retries against the flaky endpoint.
|
||||
|
||||
### API Timeouts
|
||||
|
||||
|
|
@ -765,7 +804,7 @@ credential_pool_strategies:
|
|||
anthropic: least_used # always pick the least-used key
|
||||
```
|
||||
|
||||
Options: `fill_first` (default), `round_robin`, `least_used`, `random`. See [Credential Pools](/docs/user-guide/features/credential-pools) for full documentation.
|
||||
Options: `fill_first` (default), `round_robin`, `least_used`, `random`. See [Credential Pools](/user-guide/features/credential-pools) for full documentation.
|
||||
|
||||
## Prompt caching
|
||||
|
||||
|
|
@ -773,7 +812,7 @@ Hermes turns on cross-session prompt caching automatically when the active provi
|
|||
|
||||
For Claude on **native Anthropic**, **OpenRouter**, and **Nous Portal**, Hermes attaches `cache_control` breakpoints with the 1-hour TTL (`ttl: "1h"`) on the system prompt and skill blocks. The first send within a fresh hour pays full input rates; subsequent sends across any session within the same hour pull from the cache at the discounted cached-read rate. This means the system prompt, loaded skill content, and the early portion of any long-context include get reused across `hermes` sessions and across forked subagents for the first hour.
|
||||
|
||||
The Qwen Cloud (Alibaba DashScope) upstream caps cache TTL at 5 minutes, so Hermes uses the 5-minute breakpoint TTL there instead. Other Claude-via-third-party paths (AWS Bedrock, Azure Foundry) fall back to the provider's own caching defaults. xAI Grok uses a separate session-pinned conversation-id mechanism — see [xAI prompt caching](/docs/integrations/providers#xai-grok--responses-api--prompt-caching).
|
||||
The Qwen Cloud (Alibaba DashScope) upstream caps cache TTL at 5 minutes, so Hermes uses the 5-minute breakpoint TTL there instead. Other Claude-via-third-party paths (AWS Bedrock, Azure Foundry) fall back to the provider's own caching defaults. xAI Grok uses a separate session-pinned conversation-id mechanism — see [xAI prompt caching](/integrations/providers#xai-grok--responses-api--prompt-caching).
|
||||
|
||||
No knob exists to disable this — caching is always-on and saves money even on single-turn conversations because the system prompt alone is a meaningful fraction of the input token count.
|
||||
|
||||
|
|
@ -796,6 +835,7 @@ $ hermes model
|
|||
[ ] vision currently: auto / main model
|
||||
[ ] web_extract currently: auto / main model
|
||||
[ ] title_generation currently: openrouter / google/gemini-3-flash-preview
|
||||
[ ] tts_audio_tags currently: auto / main model
|
||||
[ ] compression currently: auto / main model
|
||||
[ ] approval currently: auto / main model
|
||||
[ ] triage_specifier currently: auto / main model
|
||||
|
|
@ -829,18 +869,18 @@ Every model slot in Hermes — auxiliary tasks, compression, fallback — uses t
|
|||
|
||||
When `base_url` is set, Hermes ignores the provider and calls that endpoint directly (using `api_key` or `OPENAI_API_KEY` for auth). When only `provider` is set, Hermes uses that provider's built-in auth and base URL.
|
||||
|
||||
Available providers for auxiliary tasks: `auto`, `main`, plus any provider in the [provider registry](/docs/reference/environment-variables) — `openrouter`, `nous`, `openai-codex`, `copilot`, `copilot-acp`, `anthropic`, `gemini`, `google-gemini-cli`, `qwen-oauth`, `zai`, `kimi-coding`, `kimi-coding-cn`, `minimax`, `minimax-cn`, `minimax-oauth`, `deepseek`, `nvidia`, `xai`, `xai-oauth`, `ollama-cloud`, `alibaba`, `bedrock`, `huggingface`, `arcee`, `xiaomi`, `kilocode`, `opencode-zen`, `opencode-go`, `ai-gateway`, `azure-foundry` — or any named custom provider from your `custom_providers` list (e.g. `provider: "beans"`).
|
||||
Available providers for auxiliary tasks: `auto`, `main`, plus any provider in the [provider registry](/reference/environment-variables) — `openrouter`, `nous`, `openai-codex`, `copilot`, `copilot-acp`, `anthropic`, `gemini`, `google-gemini-cli`, `qwen-oauth`, `zai`, `kimi-coding`, `kimi-coding-cn`, `minimax`, `minimax-cn`, `minimax-oauth`, `deepseek`, `nvidia`, `xai`, `xai-oauth`, `ollama-cloud`, `alibaba`, `bedrock`, `huggingface`, `arcee`, `xiaomi`, `kilocode`, `opencode-zen`, `opencode-go`, `azure-foundry` — or any named custom provider from your `custom_providers` list (e.g. `provider: "beans"`).
|
||||
|
||||
:::tip MiniMax OAuth
|
||||
`minimax-oauth` logs in via browser OAuth (no API key needed). Run `hermes model` and select **MiniMax (OAuth)** to authenticate. Auxiliary tasks use `MiniMax-M2.7-highspeed` automatically. See the [MiniMax OAuth guide](../guides/minimax-oauth.md).
|
||||
:::
|
||||
|
||||
:::tip xAI Grok OAuth
|
||||
`xai-oauth` logs in via browser OAuth for SuperGrok and X Premium+ subscribers (no API key needed). Run `hermes model` and select **xAI Grok OAuth (SuperGrok Subscription)** to authenticate. The same OAuth token is reused for every direct-to-xAI surface (chat, auxiliary tasks, TTS, image gen, video gen, transcription). See the [xAI Grok OAuth guide](../guides/xai-grok-oauth.md), and if Hermes is on a remote host see [OAuth over SSH / Remote Hosts](../guides/oauth-over-ssh.md).
|
||||
`xai-oauth` logs in via browser OAuth for SuperGrok and X Premium+ subscribers (no API key needed). Run `hermes model` and select **xAI Grok OAuth (SuperGrok / Premium+)** to authenticate. The same OAuth token is reused for every direct-to-xAI surface (chat, auxiliary tasks, TTS, image gen, video gen, transcription). See the [xAI Grok OAuth guide](../guides/xai-grok-oauth.md), and if Hermes is on a remote host see [OAuth over SSH / Remote Hosts](../guides/oauth-over-ssh.md).
|
||||
:::
|
||||
|
||||
:::warning `"main"` is for auxiliary tasks only
|
||||
The `"main"` provider option means "use whatever provider my main agent uses" — it's only valid inside `auxiliary:`, `compression:`, and `fallback_model:` configs. It is **not** a valid value for your top-level `model.provider` setting. If you use a custom OpenAI-compatible endpoint, set `provider: custom` in your `model:` section. See [AI Providers](/docs/integrations/providers) for all main model provider options.
|
||||
The `"main"` provider option means "use whatever provider my main agent uses" — it's only valid inside `auxiliary:`, `compression:`, and primary fallback entries (`fallback_providers:` or legacy `fallback_model:`). It is **not** a valid value for your top-level `model.provider` setting. If you use a custom OpenAI-compatible endpoint, set `provider: custom` in your `model:` section. See [AI Providers](/integrations/providers) for all main model provider options.
|
||||
:::
|
||||
|
||||
### Full auxiliary config reference
|
||||
|
|
@ -872,6 +912,14 @@ auxiliary:
|
|||
api_key: ""
|
||||
timeout: 30 # seconds
|
||||
|
||||
# Gemini 3.1 TTS hidden audio-tag insertion
|
||||
tts_audio_tags:
|
||||
provider: "auto"
|
||||
model: "" # empty = main chat model
|
||||
base_url: ""
|
||||
api_key: ""
|
||||
timeout: 30
|
||||
|
||||
# Context compression timeout (separate from compression.* config)
|
||||
compression:
|
||||
timeout: 120 # seconds — compression summarizes long conversations, needs more time
|
||||
|
|
@ -910,12 +958,12 @@ Each auxiliary task has a configurable `timeout` (in seconds). Defaults: vision
|
|||
:::
|
||||
|
||||
:::info
|
||||
Context compression has its own `compression:` block for thresholds and an `auxiliary.compression:` block for model/provider settings — see [Context Compression](#context-compression) above. The fallback model uses a `fallback_model:` block — see [Fallback Model](/docs/integrations/providers#fallback-model). All three follow the same provider/model/base_url pattern.
|
||||
Context compression has its own `compression:` block for thresholds and an `auxiliary.compression:` block for model/provider settings — see [Context Compression](#context-compression) above. The primary fallback chain uses a top-level `fallback_providers:` list — see [Fallback Providers](/integrations/providers#fallback-providers). All three follow the same provider/model/base_url pattern.
|
||||
:::
|
||||
|
||||
### OpenRouter routing & Pareto Code for auxiliary tasks
|
||||
|
||||
When an auxiliary task resolves to OpenRouter (either explicitly or via `provider: "main"` while your main agent is on OpenRouter), the main agent's `provider_routing` and `openrouter.min_coding_score` settings **do not propagate** — by design, each auxiliary task is independent. To set OpenRouter provider preferences or use the [Pareto Code router](/docs/integrations/providers#openrouter-pareto-code-router) for a specific aux task, set them per-task via `extra_body`:
|
||||
When an auxiliary task resolves to OpenRouter (either explicitly or via `provider: "main"` while your main agent is on OpenRouter), the main agent's `provider_routing` and `openrouter.min_coding_score` settings **do not propagate** — by design, each auxiliary task is independent. To set OpenRouter provider preferences or use the [Pareto Code router](/integrations/providers#openrouter-pareto-code-router) for a specific aux task, set them per-task via `extra_body`:
|
||||
|
||||
```yaml
|
||||
auxiliary:
|
||||
|
|
@ -953,7 +1001,7 @@ AUXILIARY_VISION_MODEL=openai/gpt-4o
|
|||
|
||||
### Provider Options
|
||||
|
||||
These options apply to **auxiliary task configs** (`auxiliary:`, `compression:`, `fallback_model:`), not to your main `model.provider` setting.
|
||||
These options apply to **auxiliary task configs** (`auxiliary:`, `compression:`) and primary fallback entries (`fallback_providers:` or legacy `fallback_model:`), not to your main `model.provider` setting.
|
||||
|
||||
| Provider | Description | Requirements |
|
||||
|----------|-------------|-------------|
|
||||
|
|
@ -962,7 +1010,7 @@ These options apply to **auxiliary task configs** (`auxiliary:`, `compression:`,
|
|||
| `"nous"` | Force Nous Portal | `hermes auth` |
|
||||
| `"codex"` | Force Codex OAuth (ChatGPT account). Supports vision (gpt-5.3-codex). | `hermes model` → Codex |
|
||||
| `"minimax-oauth"` | Force MiniMax OAuth (browser login, no API key). Uses MiniMax-M2.7-highspeed for auxiliary tasks. | `hermes model` → MiniMax (OAuth) |
|
||||
| `"xai-oauth"` | Force xAI Grok OAuth (browser login for SuperGrok or X Premium+ subscribers, no API key). Same OAuth token covers chat, TTS, image, video, and transcription. | `hermes model` → xAI Grok OAuth (SuperGrok Subscription) |
|
||||
| `"xai-oauth"` | Force xAI Grok OAuth (browser login for SuperGrok or X Premium+ subscribers, no API key). Same OAuth token covers chat, TTS, image, video, and transcription. | `hermes model` → xAI Grok OAuth (SuperGrok / Premium+) |
|
||||
| `"main"` | Use your active custom/main endpoint. This can come from `OPENAI_BASE_URL` + `OPENAI_API_KEY` or from a custom endpoint saved via `hermes model` / `config.yaml`. Works with OpenAI, local models, or any OpenAI-compatible API. **Auxiliary tasks only — not valid for `model.provider`.** | Custom endpoint credentials + base URL |
|
||||
|
||||
Direct API-key providers from the main provider catalog also work here when you want side tasks to bypass your default router. `gmi` is valid once `GMI_API_KEY` is configured:
|
||||
|
|
@ -1076,6 +1124,17 @@ agent:
|
|||
|
||||
When unset (default), reasoning effort defaults to "medium" — a balanced level that works well for most tasks. Setting a value overrides it — higher reasoning effort gives better results on complex tasks at the cost of more tokens and latency.
|
||||
|
||||
:::note Adaptive-thinking models (Claude 4.6+, Fable/Mythos-class) over OpenRouter
|
||||
These models use *adaptive* thinking and don't accept the usual `reasoning.effort`
|
||||
field — OpenRouter ignores it for them. Hermes transparently routes your
|
||||
`reasoning_effort` to OpenRouter's `verbosity` parameter instead (which maps to
|
||||
Anthropic's `output_config.effort`), so the same `low`/`medium`/`high`/`xhigh`
|
||||
knob keeps working — no extra configuration needed. `none` (or unset) leaves the
|
||||
model on its own adaptive default. (`max` is accepted on the wire but is not a
|
||||
selectable `reasoning_effort` value; `xhigh` is the configurable ceiling.) The
|
||||
native Anthropic provider already controls effort directly and is unaffected.
|
||||
:::
|
||||
|
||||
You can also change the reasoning effort at runtime with the `/reasoning` command:
|
||||
|
||||
```
|
||||
|
|
@ -1147,8 +1206,10 @@ tts:
|
|||
model: "voxtral-mini-tts-2603"
|
||||
voice_id: "c69964a6-ab8b-4f8a-9465-ec0925096ec8" # Paul - Neutral (default)
|
||||
gemini:
|
||||
model: "gemini-2.5-flash-preview-tts" # or gemini-2.5-pro-preview-tts
|
||||
model: "gemini-2.5-flash-preview-tts" # or gemini-3.1-flash-tts-preview
|
||||
voice: "Kore" # 30 prebuilt voices: Zephyr, Puck, Kore, Enceladus, etc.
|
||||
audio_tags: false # Hidden Gemini 3.1 TTS audio-tag insertion
|
||||
persona_prompt_file: "" # Optional Markdown/text file with Gemini voice direction
|
||||
xai:
|
||||
voice_id: "eve" # xAI TTS voice
|
||||
language: "en" # ISO 639-1
|
||||
|
|
@ -1211,7 +1272,7 @@ Set `file_mutation_verifier: false` (or `HERMES_FILE_MUTATION_VERIFIER=0`) to su
|
|||
|
||||
The `display.language` setting translates a small set of static user-facing messages — the CLI approval prompt, a handful of gateway slash-command replies (e.g. restart-drain notices, "approval expired", "goal cleared"). It does **not** translate agent responses, log lines, tool output, error tracebacks, or slash-command descriptions — those stay in English. If you want the agent itself to reply in another language, just tell it in your prompt or system message.
|
||||
|
||||
Supported values: `en` (default), `zh` (Simplified Chinese), `ja` (Japanese), `de` (German), `es` (Spanish), `fr` (French), `tr` (Turkish), `uk` (Ukrainian). Unknown values fall back to English.
|
||||
Supported values: `en` (default), `zh` (Simplified Chinese), `zh-hant` (Traditional Chinese), `ja` (Japanese), `de` (German), `es` (Spanish), `fr` (French), `tr` (Turkish), `uk` (Ukrainian), `af` (Afrikaans), `ko` (Korean), `it` (Italian), `ga` (Irish), `pt` (Portuguese), `ru` (Russian), `hu` (Hungarian). Unknown values fall back to English.
|
||||
|
||||
You can also set this per-session with the `HERMES_LANGUAGE` env var, which overrides the config value.
|
||||
|
||||
|
|
@ -1229,15 +1290,17 @@ display:
|
|||
|
||||
In the CLI, cycle through these modes with `/verbose`. To use `/verbose` in messaging platforms (Telegram, Discord, Slack, etc.), set `tool_progress_command: true` in the `display` section above. The command will then cycle the mode and save to config.
|
||||
|
||||
Tool progress requires a gateway adapter that can display progress updates safely. Platforms without message editing support, including Signal, suppress tool-progress bubbles even if `/verbose` saves a non-`off` mode.
|
||||
|
||||
### Runtime-metadata footer (gateway only)
|
||||
|
||||
When `display.runtime_footer.enabled: true`, Hermes appends a small runtime-context footer to the **final** message of each gateway turn — same info the CLI shows in its status bar (model, context %, cwd, session duration, tokens, cost). Off by default; opt in per-gateway if your team wants every reply to include the provenance.
|
||||
When `display.runtime_footer.enabled: true`, Hermes appends a small runtime-context footer to the **final** message of each gateway turn. The current footer can show the model, context-window percentage, and current working directory. Off by default; opt in per-gateway if your team wants every reply to include this provenance.
|
||||
|
||||
```yaml
|
||||
display:
|
||||
runtime_footer:
|
||||
enabled: true
|
||||
fields: ["model", "context_pct", "cwd"] # any of: model, context_pct, cwd, duration, tokens, cost
|
||||
fields: ["model", "context_pct", "cwd"] # supported fields: model, context_pct, cwd
|
||||
```
|
||||
|
||||
The `/footer` slash command toggles this at runtime in any session.
|
||||
|
|
@ -1252,14 +1315,14 @@ Only the **final** message of a turn gets the footer; interim updates stay clean
|
|||
|
||||
### Per-platform progress overrides
|
||||
|
||||
Different platforms have different verbosity needs. For example, Signal can't edit messages, so each progress update becomes a separate message — noisy. Use `display.platforms` to set per-platform modes:
|
||||
Different platforms have different verbosity needs. Use `display.platforms` to set per-platform modes:
|
||||
|
||||
```yaml
|
||||
display:
|
||||
tool_progress: all # global default
|
||||
platforms:
|
||||
signal:
|
||||
tool_progress: 'off' # silence progress on Signal
|
||||
tool_progress: 'off' # Signal cannot currently display tool-progress bubbles
|
||||
telegram:
|
||||
tool_progress: verbose # detailed progress on Telegram
|
||||
slack:
|
||||
|
|
@ -1268,6 +1331,8 @@ display:
|
|||
|
||||
Platforms without an override fall back to the global `tool_progress` value. Valid platform keys: `telegram`, `discord`, `slack`, `signal`, `whatsapp`, `matrix`, `mattermost`, `email`, `sms`, `homeassistant`, `dingtalk`, `feishu`, `wecom`, `weixin`, `bluebubbles`, `qqbot`. The legacy `display.tool_progress_overrides` key still loads for backward compatibility but is deprecated and migrated into `display.platforms` on first load.
|
||||
|
||||
Signal is listed as a valid platform key because the setting can be saved per platform, but the current Signal adapter cannot edit sent messages and does not render tool-progress bubbles. Keep Signal `tool_progress` set to `off`; use the CLI or an editing-capable messaging platform if you need to watch each tool call live.
|
||||
|
||||
`interim_assistant_messages` is gateway-only. When enabled, Hermes sends completed mid-turn assistant updates as separate chat messages. This is independent from `tool_progress` and does not require gateway streaming.
|
||||
|
||||
## Privacy
|
||||
|
|
@ -1332,7 +1397,7 @@ voice:
|
|||
silence_duration: 3.0 # Seconds of silence before auto-stop
|
||||
```
|
||||
|
||||
Use `/voice on` in the CLI to enable microphone mode, `record_key` to start/stop recording, and `/voice tts` to toggle spoken replies. See [Voice Mode](/docs/user-guide/features/voice-mode) for end-to-end setup and platform-specific behavior.
|
||||
Use `/voice on` in the CLI to enable microphone mode, `record_key` to start/stop recording, and `/voice tts` to toggle spoken replies. See [Voice Mode](/user-guide/features/voice-mode) for end-to-end setup and platform-specific behavior.
|
||||
|
||||
## Streaming
|
||||
|
||||
|
|
@ -1368,12 +1433,31 @@ For separate natural mid-turn assistant updates without progressive token editin
|
|||
|
||||
**Fresh final (Telegram):** Telegram's `editMessageText` preserves the original message timestamp, so a long-running streamed reply would keep the first-token timestamp even after completion. When `fresh_final_after_seconds > 0` (default `60`), the completed reply is delivered as a brand-new message (with the stale preview best-effort deleted) so Telegram's visible timestamp reflects completion time. Short previews still finalize in place. Set to `0` to always edit in place.
|
||||
|
||||
:::note
|
||||
Streaming is disabled by default. Enable it in `~/.hermes/config.yaml` to try the streaming UX.
|
||||
:::note Per-platform streaming defaults
|
||||
The master `streaming.enabled` switch is `false` by default — nothing streams until you flip it. Once enabled, streaming is decided **per platform**: Telegram ships with `display.platforms.telegram.streaming: true` (streams) and Discord with `display.platforms.discord.streaming: false` (does not). So after enabling streaming, Telegram streams out of the box and Discord stays on whole-message replies until you change its toggle. You can adjust these per-platform switches from the dashboard's **Channels** toggles or directly in `~/.hermes/config.yaml`.
|
||||
:::
|
||||
|
||||
## Group Chat Session Isolation
|
||||
|
||||
Limit how many chat sessions can actively be open across CLI, TUI/dashboard,
|
||||
and messaging gateway:
|
||||
|
||||
```yaml
|
||||
max_concurrent_sessions: null # null/0 = unlimited; positive integer = active session cap
|
||||
```
|
||||
|
||||
When the cap is reached, Hermes returns a direct limit message for new sessions.
|
||||
Existing active sessions keep their normal behavior.
|
||||
|
||||
The canonical key is top-level `max_concurrent_sessions`. Hermes also accepts
|
||||
`gateway.max_concurrent_sessions` as a fallback, but the top-level key wins when
|
||||
both are set.
|
||||
|
||||
The cap is enforced with a local runtime lease file and is best-effort: Hermes
|
||||
fails open if the registry cannot be read or locked so users are not stranded.
|
||||
It is intended for a single host/profile runtime, not a shared `$HERMES_HOME`
|
||||
mounted across multiple machines.
|
||||
|
||||
Control whether shared chats keep one conversation per room or one conversation per participant:
|
||||
|
||||
```yaml
|
||||
|
|
@ -1385,7 +1469,7 @@ group_sessions_per_user: true # true = per-user isolation in groups/channels, f
|
|||
- Direct messages are unaffected. Hermes still keys DMs by chat/DM ID as usual.
|
||||
- Threads stay isolated from their parent channel either way; with `true`, each participant also gets their own session inside the thread.
|
||||
|
||||
For the behavior details and examples, see [Sessions](/docs/user-guide/sessions) and the [Discord guide](/docs/user-guide/messaging/discord).
|
||||
For the behavior details and examples, see [Sessions](/user-guide/sessions) and the [Discord guide](/user-guide/messaging/discord).
|
||||
|
||||
## Unauthorized DM Behavior
|
||||
|
||||
|
|
@ -1466,7 +1550,7 @@ Environment scrubbing (strips `*_API_KEY`, `*_TOKEN`, `*_SECRET`, `*_PASSWORD`,
|
|||
|
||||
## Web Search Backends
|
||||
|
||||
The `web_search`, `web_extract`, and `web_crawl` tools support five backend providers. Configure the backend in `config.yaml` or via `hermes tools`:
|
||||
The `web_search` and `web_extract` tools support five backend providers. Configure the backend in `config.yaml` or via `hermes tools`:
|
||||
|
||||
```yaml
|
||||
web:
|
||||
|
|
@ -1477,17 +1561,17 @@ web:
|
|||
extract_backend: "firecrawl"
|
||||
```
|
||||
|
||||
| Backend | Env Var | Search | Extract | Crawl |
|
||||
|---------|---------|--------|---------|-------|
|
||||
| **Firecrawl** (default) | `FIRECRAWL_API_KEY` | ✔ | ✔ | ✔ |
|
||||
| **SearXNG** | `SEARXNG_URL` | ✔ | — | — |
|
||||
| **Parallel** | `PARALLEL_API_KEY` | ✔ | ✔ | — |
|
||||
| **Tavily** | `TAVILY_API_KEY` | ✔ | ✔ | ✔ |
|
||||
| **Exa** | `EXA_API_KEY` | ✔ | ✔ | — |
|
||||
| Backend | Env Var | Search | Extract |
|
||||
|---------|---------|--------|---------|
|
||||
| **Firecrawl** (default) | `FIRECRAWL_API_KEY` | ✔ | ✔ |
|
||||
| **SearXNG** | `SEARXNG_URL` | ✔ | — |
|
||||
| **Parallel** | `PARALLEL_API_KEY` | ✔ | ✔ |
|
||||
| **Tavily** | `TAVILY_API_KEY` | ✔ | ✔ |
|
||||
| **Exa** | `EXA_API_KEY` | ✔ | ✔ |
|
||||
|
||||
**Backend selection:** If `web.backend` is not set, the backend is auto-detected from available API keys. If only `SEARXNG_URL` is set, SearXNG is used. If only `EXA_API_KEY` is set, Exa is used. If only `TAVILY_API_KEY` is set, Tavily is used. If only `PARALLEL_API_KEY` is set, Parallel is used. Otherwise Firecrawl is the default.
|
||||
|
||||
**SearXNG** is a free, self-hosted, privacy-respecting metasearch engine that queries 70+ search engines. No API key needed — just set `SEARXNG_URL` to your instance (e.g., `http://localhost:8080`). SearXNG is search-only; `web_extract` and `web_crawl` require a separate extract provider (set `web.extract_backend`). See the [Web Search setup guide](/docs/user-guide/features/web-search) for Docker setup instructions.
|
||||
**SearXNG** is a free, self-hosted, privacy-respecting metasearch engine that queries 70+ search engines. No API key needed — just set `SEARXNG_URL` to your instance (e.g., `http://localhost:8080`). SearXNG is search-only; `web_extract` requires a separate extract provider (set `web.extract_backend`). See the [Web Search setup guide](/user-guide/features/web-search) for Docker setup instructions.
|
||||
|
||||
**Self-hosted Firecrawl:** Set `FIRECRAWL_API_URL` to point at your own instance. When a custom URL is set, the API key becomes optional (set `USE_DB_AUTHENTICATION=*** on the server to disable auth).
|
||||
|
||||
|
|
@ -1527,7 +1611,7 @@ browser:
|
|||
|
||||
See the [browser feature page](./features/browser.md#browser_dialog) for the full dialog workflow.
|
||||
|
||||
The browser toolset supports multiple providers. See the [Browser feature page](/docs/user-guide/features/browser) for details on Browserbase, Browser Use, and local Chromium-family CDP setup.
|
||||
The browser toolset supports multiple providers. See the [Browser feature page](/user-guide/features/browser) for details on Browserbase, Browser Use, and local Chromium-family CDP setup.
|
||||
|
||||
## Timezone
|
||||
|
||||
|
|
@ -1560,7 +1644,7 @@ Pre-execution security scanning and secret redaction:
|
|||
|
||||
```yaml
|
||||
security:
|
||||
redact_secrets: false # Redact API key patterns in tool output and logs (off by default)
|
||||
redact_secrets: true # Redact API key patterns in tool output and logs (on by default)
|
||||
tirith_enabled: true # Enable Tirith security scanning for terminal commands
|
||||
tirith_path: "tirith" # Path to tirith binary (default: "tirith" in $PATH)
|
||||
tirith_timeout: 5 # Seconds to wait for tirith scan before timing out
|
||||
|
|
@ -1571,7 +1655,7 @@ security:
|
|||
shared_files: []
|
||||
```
|
||||
|
||||
- `redact_secrets` — when `true`, automatically detects and redacts patterns that look like API keys, tokens, and passwords in tool output before it enters the conversation context and logs. **Off by default** — enable if you commonly work with real credentials in tool output and want a safety net. Set to `true` explicitly to turn on.
|
||||
- `redact_secrets` — when `true`, automatically detects and redacts patterns that look like API keys, tokens, and passwords in tool output before it enters the conversation context and logs. **On by default**. Set to `false` explicitly only when you need raw credential-like strings for debugging or redactor development.
|
||||
- `tirith_enabled` — when `true`, terminal commands are scanned by [Tirith](https://github.com/sheeki03/tirith) before execution to detect potentially dangerous operations.
|
||||
- `tirith_path` — path to the tirith binary. Set this if tirith is installed in a non-standard location.
|
||||
- `tirith_timeout` — maximum seconds to wait for a tirith scan. Commands proceed if the scan times out.
|
||||
|
|
@ -1627,7 +1711,7 @@ Setting `approvals.mode: off` disables all safety checks for terminal commands.
|
|||
|
||||
## Checkpoints
|
||||
|
||||
Automatic filesystem snapshots before destructive file operations. See the [Checkpoints & Rollback](/docs/user-guide/checkpoints-and-rollback) for details.
|
||||
Automatic filesystem snapshots before destructive file operations. See the [Checkpoints & Rollback](/user-guide/checkpoints-and-rollback) for details.
|
||||
|
||||
```yaml
|
||||
checkpoints:
|
||||
|
|
@ -1694,20 +1778,22 @@ Hermes uses two different context scopes:
|
|||
- All loaded context files are capped at 20,000 characters with smart truncation.
|
||||
|
||||
See also:
|
||||
- [Personality & SOUL.md](/docs/user-guide/features/personality)
|
||||
- [Context Files](/docs/user-guide/features/context-files)
|
||||
- [Personality & SOUL.md](/user-guide/features/personality)
|
||||
- [Context Files](/user-guide/features/context-files)
|
||||
|
||||
## Working Directory
|
||||
|
||||
| Context | Default |
|
||||
|---------|---------|
|
||||
| **CLI (`hermes`)** | Current directory where you run the command |
|
||||
| **Messaging gateway** | Home directory `~` (override with `MESSAGING_CWD`) |
|
||||
| **Messaging gateway** | `terminal.cwd` from `~/.hermes/config.yaml`; if unset, home directory `~` |
|
||||
| **Docker / Singularity / Modal / SSH** | User's home directory inside the container or remote machine |
|
||||
|
||||
Override the working directory:
|
||||
```bash
|
||||
# In ~/.hermes/.env or ~/.hermes/config.yaml:
|
||||
MESSAGING_CWD=/home/myuser/projects # Gateway sessions
|
||||
TERMINAL_CWD=/workspace # All terminal sessions
|
||||
```yaml
|
||||
# In ~/.hermes/config.yaml:
|
||||
terminal:
|
||||
cwd: /home/myuser/projects
|
||||
```
|
||||
|
||||
`MESSAGING_CWD` and direct `TERMINAL_CWD` entries in `~/.hermes/.env` are legacy compatibility fallbacks. New configurations should use `terminal.cwd`.
|
||||
|
|
|
|||
|
|
@ -11,6 +11,16 @@ Hermes uses two kinds of model slots:
|
|||
|
||||
This page covers configuring both from the dashboard. If you prefer config files or the CLI, jump to [Alternative methods](#alternative-methods) at the bottom.
|
||||
|
||||
:::tip Fastest path: Nous Portal
|
||||
[Nous Portal](/user-guide/features/tool-gateway) provides 300+ models under one subscription. On a fresh install, run `hermes setup --portal` to log in and set Nous as your provider in one command. Inspect what's wired up with `hermes portal info`.
|
||||
|
||||
- Portal subscribers also get **10% off token-billed providers**.
|
||||
:::
|
||||
|
||||
:::note `model:` schema — empty string vs. mapping
|
||||
On a brand-new install the bundled default config has `model: ""` (an empty string sentinel meaning "not configured yet"). The first time you run `hermes setup` or `hermes model`, that key is upgraded in-place to a mapping with `provider`, `default`, `base_url`, and `api_mode` sub-keys — the shape shown throughout this page and in [`profiles.md`](./profiles.md) / [`configuration.md`](./configuration.md). If you ever see an empty string in `config.yaml`, run `hermes model` (or click **Change** in the dashboard) and Hermes will write the dict form for you.
|
||||
:::
|
||||
|
||||
## The Models page
|
||||
|
||||
Open the dashboard and click **Models** in the sidebar. You get two sections:
|
||||
|
|
@ -39,7 +49,7 @@ Pick a model, hit **Switch**, and Hermes writes it to `~/.hermes/config.yaml` un
|
|||
|
||||
## Setting auxiliary models
|
||||
|
||||
Click **Show auxiliary** to reveal the eight task slots:
|
||||
Click **Show auxiliary** to reveal the 11 task slots:
|
||||
|
||||

|
||||
|
||||
|
|
@ -50,12 +60,16 @@ Every auxiliary task defaults to `auto` — meaning Hermes uses your main model
|
|||
| Task | When to override |
|
||||
|---|---|
|
||||
| **Title Gen** | Almost always. A $0.10/M flash model writes session titles as well as Opus. Default config sets this to `google/gemini-3-flash-preview` on OpenRouter. |
|
||||
| **Vision** | When your main model is a coding model without vision (e.g. Kimi, DeepSeek). Point it at `google/gemini-2.5-flash` or `gpt-4o-mini`. |
|
||||
| **Vision** | When your main model lacks vision support. Point it at `google/gemini-2.5-flash` or `gpt-4o-mini`. |
|
||||
| **Compression** | When you're burning reasoning tokens on Opus/M2.7 just to summarize context. A fast chat model does the job at 1/50th the cost. |
|
||||
| **Approval** | For `approval_mode: smart` — a fast/cheap model (haiku, flash, gpt-5-mini) decides whether to auto-approve low-risk commands. Expensive models here are waste. |
|
||||
| **Web Extract** | When you use `web_extract` heavily. Same logic as compression — summarization doesn't need reasoning. |
|
||||
| **Skills Hub** | `hermes skills search` uses this. Usually fine at `auto`. |
|
||||
| **MCP** | MCP tool routing. Usually fine at `auto`. |
|
||||
| **Triage Specifier** | Routes the Kanban triage specifier (`hermes kanban specify`) that expands a rough one-liner into a concrete spec. A cheap, capable model works well. |
|
||||
| **Kanban Decomposer** | Routes Kanban task decomposition — splits a triage task into a graph of child tasks for specialist profiles. |
|
||||
| **Profile Describer** | Routes profile-description generation (`hermes profile describe --auto` / the dashboard auto-generate button). Short, cheap call. |
|
||||
| **Curator** | Routes the curator skill-usage review pass. Can run for minutes on reasoning models, so a cheaper aux model is often worthwhile. |
|
||||
|
||||
### Per-task override
|
||||
|
||||
|
|
@ -74,7 +88,7 @@ Every model card on the page has a **Use as** dropdown. This is the fast path
|
|||
The dropdown has:
|
||||
|
||||
- **Main model** — same as clicking Change on the main row.
|
||||
- **All auxiliary tasks** — assigns this model to all 8 aux slots at once. Useful when you just want every side-job on a cheap flash model.
|
||||
- **All auxiliary tasks** — assigns this model to all 11 aux slots at once. Useful when you just want every side-job on a cheap flash model.
|
||||
- **Individual task options** — Vision, Web Extract, Compression, etc. The currently-assigned model for each task is marked `current`.
|
||||
|
||||
Cards are badged with `main` or `aux · <task>` when they're currently assigned to something — so you can see at a glance which of your historical models are wired in where.
|
||||
|
|
@ -162,7 +176,9 @@ Inside any `hermes chat` session:
|
|||
|
||||
### Custom aliases
|
||||
|
||||
Define your own short names for models you reach for often, then use `/model <alias>` in the CLI or any messaging platform:
|
||||
Define your own short names for models you reach for often, then use `/model <alias>` in the CLI or any messaging platform. There are two equivalent formats — pick whichever fits your workflow.
|
||||
|
||||
**Canonical (top-level `model_aliases:`)** — full control over provider + base_url:
|
||||
|
||||
```yaml
|
||||
# ~/.hermes/config.yaml
|
||||
|
|
@ -175,14 +191,16 @@ model_aliases:
|
|||
provider: x-ai
|
||||
```
|
||||
|
||||
Or from the shell (short form, `provider/model`):
|
||||
**Short string form (`model.aliases.<name>: provider/model`)** — convenient from the shell because `hermes config set` only writes scalar values, but it can't carry a custom `base_url`:
|
||||
|
||||
```bash
|
||||
hermes config set model.aliases.fav anthropic/claude-opus-4.6
|
||||
hermes config set model.aliases.grok x-ai/grok-4
|
||||
```
|
||||
|
||||
Then `/model fav` or `/model grok` in chat. User aliases shadow built-in short names (`sonnet`, `kimi`, `opus`, etc.). See [Custom model aliases](/docs/reference/slash-commands#custom-model-aliases) for the full reference.
|
||||
Both paths feed the same loader (`hermes_cli/model_switch.py`). Entries declared in `model_aliases:` take precedence over `model.aliases:` entries with the same name.
|
||||
|
||||
Then `/model fav` or `/model grok` in chat. User aliases shadow built-in short names (`sonnet`, `kimi`, `opus`, etc.). See [Custom model aliases](/reference/slash-commands#custom-model-aliases) for the full reference.
|
||||
|
||||
### `hermes model` subcommand
|
||||
|
||||
|
|
@ -192,7 +210,7 @@ hermes model # Interactive provider + model picker (the canonical way
|
|||
|
||||
`hermes model` walks you through picking a provider, authenticating (OAuth flows open a browser; API-key providers prompt for the key), and then choosing a specific model from that provider's curated catalog. The choice is written to `model.provider` and `model.model` in `~/.hermes/config.yaml`.
|
||||
|
||||
To list providers/models without launching the picker, use the dashboard or the REST endpoints below. To inspect what the CLI will actually use right now: `hermes config get model` and `hermes status`.
|
||||
To list providers/models without launching the picker, use the dashboard or the REST endpoints below. To inspect what the CLI will actually use right now: `hermes config show | grep '^model\.'` and `hermes status`.
|
||||
|
||||
### Direct config edit
|
||||
|
||||
|
|
|
|||
291
website/docs/user-guide/desktop.md
Normal file
291
website/docs/user-guide/desktop.md
Normal file
|
|
@ -0,0 +1,291 @@
|
|||
---
|
||||
sidebar_position: 3
|
||||
title: "Desktop App"
|
||||
description: "The native Hermes desktop app — a polished experience for chatting with Hermes, with streaming tool output, side-by-side previews, a file browser, voice, cron, profiles, skills, and settings. macOS, Windows, and Linux."
|
||||
---
|
||||
|
||||
# Desktop App
|
||||
|
||||
The Hermes desktop app is a native app built around the **same** agent you get from the CLI and the gateway — same config, same API keys, same sessions, same skills, same memory. It is not a separate product or a lightweight clone; it uses the same Hermes Agent core and settings, and drives it through a modern & thoughtfully designed UI. If you have used `hermes` in a terminal, everything you set up there is already here, and anything you do here shows up there.
|
||||
|
||||
It runs on **macOS, Windows, and Linux**.
|
||||
|
||||
:::tip Which interface is which?
|
||||
Hermes has several front ends that all talk to the same agent:
|
||||
|
||||
- **Desktop App** (this page) — a native application with a purpose-built UI for chat, configuration, and management.
|
||||
- **CLI** (`hermes`) and **[TUI](./tui.md)** (`hermes --tui`) — terminal interfaces.
|
||||
- **[Web Dashboard](./features/web-dashboard.md)** (`hermes dashboard`) — a browser admin panel; its optional **Chat** tab embeds the TUI through a pseudo-terminal.
|
||||
|
||||
Pick whichever fits the moment. They share state, so you can start a session in one and resume it in another.
|
||||
:::
|
||||
|
||||
## Install
|
||||
|
||||
Follow the [installation instructions for Hermes Desktop](../getting-started/installation.md).
|
||||
|
||||
If you already have Hermes installed, simply run
|
||||
|
||||
```bash
|
||||
hermes desktop
|
||||
```
|
||||
|
||||
That uses your current config, keys, sessions, and skills.
|
||||
|
||||
## What's in the app
|
||||
|
||||
The desktop app is organized as a chat-first window with a left sidebar for navigation. It's built to allow managing multiple simultaneous agent conversations, configuring messaging providers, creating artifacts, browsing projects' folder structures, and working on multiple projects at once.
|
||||
|
||||
### Chat
|
||||
|
||||
The center of the app. You get:
|
||||
|
||||
- **Streaming responses** with live tool activity and structured tool-call summaries as the agent works.
|
||||
- **The same conversation history** as every other Hermes surface — sessions started here resume in the CLI/TUI and vice versa.
|
||||
- **Drag-and-drop files** anywhere in the chat area to attach them to your next message.
|
||||
- **A right-hand preview rail** — render web pages, files, and tool outputs side by side while you keep chatting.
|
||||
- **Composer history and queue editing** — press the up/down arrow keys in an empty composer to recall and reuse previous prompts, and edit messages you've queued up before they're sent.
|
||||
|
||||
#### Status bar
|
||||
|
||||
The bar along the bottom of the chat shows live session state and exposes quick controls without opening Settings:
|
||||
|
||||
- **Inline model picker** — switch the model for the active session straight from the status bar.
|
||||
- **Per-session YOLO toggle** — flip YOLO on or off for just this session (matching the TUI). YOLO bypasses the dangerous-command approval prompts, so know what you're turning off — see [Security → YOLO Mode](./security.md#yolo-mode).
|
||||
|
||||
Chatting against a Hermes instance on another machine instead of the bundled local backend? See [Connecting to a remote backend](#connecting-to-a-remote-backend) below — and for the full picture of how the remote-hosted dashboard connection works (the auth gate, the `/api/ws` chat socket, and WebSocket close-code triage), see [Web Dashboard → Connecting Hermes Desktop to a remote backend](./features/web-dashboard.md#connecting-hermes-desktop-to-a-remote-backend).
|
||||
|
||||
### File browser
|
||||
|
||||
Explore and preview the working directory without leaving the app — useful for following along as the agent reads, writes, and edits files. Set the initial project directory with `hermes desktop --cwd <path>` (or the `HERMES_DESKTOP_CWD` environment variable).
|
||||
|
||||
### Voice
|
||||
|
||||
Talk to Hermes and hear it back, the same [voice mode](./features/voice-mode.md) available elsewhere. On macOS the OS will prompt once for microphone access.
|
||||
|
||||
### Settings & onboarding
|
||||
|
||||
Manage providers, models, tools, and credentials from a real UI instead of editing YAML. First-run onboarding gets you to your first message in seconds. The settings panes cover providers/keys, model selection, toolset configuration, MCP servers, the gateway, and session management.
|
||||
|
||||
- **Providers settings pane** — a dedicated place to manage inference providers, with an Accounts / API-keys UX for signing in and storing credentials per provider.
|
||||
- **Every provider and model in the menus** — the GUI surfaces the full provider list and every model that `hermes model` knows about, so you pick from the same catalog the CLI sees rather than a curated subset.
|
||||
- **xAI Grok OAuth** — Grok is a first-class OAuth provider in the launcher; sign in through the browser flow like the other OAuth providers.
|
||||
- **Tool-backend installs from the GUI** — run a tool backend's post-setup install steps directly from the app instead of dropping to a terminal.
|
||||
- **Auxiliary-model warning** — if you switch the main model to a new provider while auxiliary tasks (titling, summarization, and similar helpers) are still pinned to another provider, the app warns you so you don't unknowingly split work across two providers.
|
||||
|
||||
First-run onboarding has been redesigned on a unified overlay design system, and you can pick **Choose provider later** to skip provider setup and get into the app first.
|
||||
|
||||
### Management panes
|
||||
|
||||
The app also surfaces the broader Hermes management surface so you don't have to drop to a terminal:
|
||||
|
||||
- **Skills** — browse, install, and manage [skills](./features/skills.md).
|
||||
- **Cron** — view and manage [scheduled jobs](../reference/cli-commands.md#hermes-cron).
|
||||
- **Profiles** — switch between [Hermes profiles](./profiles.md) (isolated config/skills/sessions).
|
||||
- **Messaging** — set up gateway channels.
|
||||
- **Agents** and **Command Center** — orchestration surfaces for multi-agent work.
|
||||
|
||||
### Keyboard & navigation
|
||||
|
||||
- **Command palette** — press **Cmd+K** (Ctrl+K on Windows/Linux) to jump to actions and navigate the app from the keyboard.
|
||||
- **Rebindable shortcuts** — a shortcuts panel in Settings lets you remap the app's keyboard shortcuts to your own keys.
|
||||
- **Custom zoom shortcuts** — zoom the interface in half-step increments for finer control over text size.
|
||||
- **UI language switcher** — change the app's interface language in-app, including Simplified Chinese (zh-Hans).
|
||||
|
||||
### Sessions & profiles
|
||||
|
||||
- **Session-list overhaul** — a reworked session list with archiving and general session hygiene to keep the list manageable as it grows.
|
||||
- **Search sessions by id** — find a specific session directly by its id.
|
||||
- **Concurrent multi-profile sessions** — run sessions across multiple [profiles](./profiles.md) at the same time, and reference a session in another profile with cross-profile `@session` links.
|
||||
|
||||
## Updating
|
||||
|
||||
The app checks for updates in the background and offers a one-click update when one is ready.
|
||||
|
||||
The [manual update process](https://hermes-agent.nousresearch.com/docs/getting-started/updating) also works with the GUI.
|
||||
|
||||
## Uninstalling
|
||||
|
||||
Open **Settings → About → Danger zone** and pick how much to remove:
|
||||
|
||||
- **Uninstall Chat GUI only** — removes the desktop app and its data; the Hermes agent, your config, and your chats stay. (Same as `hermes uninstall --gui`.)
|
||||
- **Uninstall GUI + agent, keep my data** — removes the app and the agent but keeps config, chats, and secrets for a future reinstall. (Same as `hermes uninstall`.)
|
||||
- **Uninstall everything** — removes the app, the agent, and all user data. (Same as `hermes uninstall --full`.)
|
||||
|
||||
The app closes to finish the job (the cleanup runs after it exits so it can remove the running app bundle and its own venv). The agent-removing options are hidden automatically when no local agent is installed (for example, a GUI-only "lite" client connected to a remote backend).
|
||||
|
||||
You can do the same from the terminal — `hermes uninstall --gui` for the GUI alone, or `hermes uninstall` / `hermes uninstall --full` for the agent too.
|
||||
|
||||
:::note
|
||||
Running `hermes uninstall --gui` from a **source checkout** (a `hermes desktop` dev build) also removes the workspace `node_modules` and `apps/desktop/{dist,release}` build output, since those are GUI build artifacts. They're recoverable with `hermes desktop` (or `npm install` + a rebuild) — but if you're actively hacking on the desktop app, expect to reinstall dependencies afterward.
|
||||
:::
|
||||
|
||||
## CLI reference: `hermes desktop`
|
||||
|
||||
To launch via the CLI, simply run `hermes desktop`. By default it installs workspace Node dependencies, builds the current OS's unpacked Electron app, then launches that packaged artifact.
|
||||
|
||||
| Flag | Description |
|
||||
| -------------------- | ----------------------------------------------------------------------------------------- |
|
||||
| `--skip-build` | Skip npm install/package and launch the existing unpacked app from `apps/desktop/release` |
|
||||
| `--force-build` | Force a full rebuild even if the content stamp matches |
|
||||
| `--build-only` | Build the desktop app but do not launch it (used by `hermes update`) |
|
||||
| `--source` | Launch via `electron .` against `apps/desktop/dist` instead of the packaged app |
|
||||
| `--cwd PATH` | Initial project directory for desktop chat sessions (sets `HERMES_DESKTOP_CWD`) |
|
||||
| `--hermes-root PATH` | Override the Hermes source root the app uses (sets `HERMES_DESKTOP_HERMES_ROOT`) |
|
||||
| `--ignore-existing` | Force the app to ignore any `hermes` CLI already on `PATH` during backend resolution |
|
||||
| `--fake-boot` | Enable deterministic boot delays for validating the startup UI |
|
||||
|
||||
## How it works
|
||||
|
||||
The packaged app ships only the Electron shell. On first launch it installs the Hermes Agent runtime into `HERMES_HOME` (`~/.hermes`, or `%LOCALAPPDATA%\hermes` on Windows) — **the same layout a CLI install uses**, which is why the two are interchangeable. The React renderer talks to a `hermes dashboard` backend over the standard gateway APIs and reuses the agent rather than reimplementing it. Install, backend-resolution, and self-update logic live in the Electron main process.
|
||||
|
||||
## Connecting to a remote backend
|
||||
|
||||
By default the app starts and manages its own **local** backend. You can instead point it at a Hermes backend running on another machine — a VPS, a home server, or a Mini behind Tailscale.
|
||||
|
||||
:::info The remote backend is a running `hermes dashboard` process
|
||||
"Remote backend" means a **`hermes dashboard`** server running on the remote machine — that is the process the desktop app connects to. Nothing in this section works unless that dashboard is actually up and reachable. The desktop app does not start it for you; you (or a `systemd` service) keep `hermes dashboard` running on the remote host, and the app attaches to it. If you also use messaging channels (Telegram, Discord, etc.), the **gateway** is a *separate* long-running process you start independently — see the note after the setup steps.
|
||||
:::
|
||||
|
||||
The connection has two halves: on the backend you protect the dashboard with an **auth provider**, and in the app you enter the backend's URL and sign in. Binding the dashboard to a non-loopback address automatically engages its auth gate, and the provider you configure is what lets the desktop app through.
|
||||
|
||||
**Pick a provider based on where the backend lives:**
|
||||
|
||||
- **OAuth (Nous Portal) — preferred for anything reachable beyond your own machine.** Logins are verified against your Nous account, so this is the option suitable for a VPS, a public host, or any remote backend. Register the dashboard with `hermes dashboard register` (or the Portal [`/local-dashboards`](https://portal.nousresearch.com/local-dashboards) page) to provision its OAuth client, then sign in from the app with **Sign in with Nous Research**. A self-hosted OIDC provider works the same way if you run your own identity provider.
|
||||
- **Username/password — local / trusted-network use only.** The simplest option when the backend is on the same trusted LAN or reachable only over a VPN (e.g. Tailscale). It protects a single shared credential with no external identity provider, so **do not use it for a dashboard exposed to the public internet** — reach for OAuth there instead.
|
||||
|
||||
The rest of this section shows the username/password path because it's the quickest to stand up on a trusted network; for the OAuth path see [Web Dashboard → Default provider: Nous Research](./features/web-dashboard.md#default-provider-nous-research).
|
||||
|
||||
### On the backend (the remote machine)
|
||||
|
||||
Set a username and password, then start the dashboard bound to a reachable address. The credentials live in `~/.hermes/.env` (the secrets file, mode 0600):
|
||||
|
||||
```bash
|
||||
# 1. Set the dashboard login credentials.
|
||||
cat >> ~/.hermes/.env <<'EOF'
|
||||
HERMES_DASHBOARD_BASIC_AUTH_USERNAME=admin
|
||||
HERMES_DASHBOARD_BASIC_AUTH_PASSWORD=choose-a-strong-password
|
||||
# Recommended: a stable signing secret so sessions survive restarts.
|
||||
# Without it a random key is generated per boot and you'll be logged out
|
||||
# on every restart.
|
||||
HERMES_DASHBOARD_BASIC_AUTH_SECRET=$(openssl rand -base64 32)
|
||||
EOF
|
||||
chmod 600 ~/.hermes/.env
|
||||
|
||||
# 2. Run the dashboard bound to a reachable address. The non-loopback bind
|
||||
# engages the auth gate; the username/password provider handles login.
|
||||
hermes dashboard --no-open --host 0.0.0.0 --port 9119
|
||||
```
|
||||
|
||||
Keep that `hermes dashboard` process running for as long as you want the desktop app to be able to connect — if it stops, the app can no longer reach the backend. Run it under `systemd`, `tmux`, or your process manager of choice so it survives logout and reboots.
|
||||
|
||||
Separately, make sure the **gateway is running** on the remote host if you rely on messaging channels — the dashboard backend is what the desktop app talks to, but your Telegram/Discord/Slack gateway sessions are a different process that you start and keep running on their own. See [Messaging](./messaging/index.md) for gateway setup.
|
||||
|
||||
Prefer not to keep a plaintext password at rest? Set `HERMES_DASHBOARD_BASIC_AUTH_PASSWORD_HASH` to a scrypt hash instead — compute it with `python -c "from plugins.dashboard_auth.basic import hash_password; print(hash_password('PW'))"`. Full configuration surface (config.yaml keys, every env var, the rate limiter): [Web Dashboard → Username/password provider](./features/web-dashboard.md#usernamepassword-provider-no-oauth-idp).
|
||||
|
||||
Running the dashboard as a systemd service? Give the unit `EnvironmentFile=%h/.hermes/.env` so the credentials are in the environment at boot.
|
||||
|
||||
:::warning
|
||||
The dashboard reads and writes your `.env` (API keys, secrets) and can run agent commands. The **username/password** setup shown above is for a trusted network — never expose a password-protected dashboard directly to the open internet; put it behind a VPN. [Tailscale](https://tailscale.com/) is the clean option: bind to the machine's tailscale IP (`--host <tailscale-ip>`) and use `http://<tailscale-ip>:9119` as the Remote URL so only your tailnet can reach it. To reach a backend over the public internet, use the **OAuth (Nous Portal)** provider instead.
|
||||
:::
|
||||
|
||||
### In the app
|
||||
|
||||
**Settings → Gateway → Remote gateway:**
|
||||
|
||||
1. **Remote URL** — `http://<backend-host>:9119` (path prefixes like `/hermes` work if you front it with a reverse proxy)
|
||||
2. **Sign in** — the app detects which provider the backend advertises and adapts the button. For a username/password backend it shows a **Sign in** button that opens a credential form (enter the credentials from step 1). For an OAuth backend it shows **Sign in with `<provider>`** (e.g. *Sign in with Nous Research*), which runs the provider's browser sign-in. Either way the app ends up with an authenticated session against the backend.
|
||||
3. **Save and reconnect** — switches the desktop shell onto the remote backend. The session refreshes automatically; you stay signed in across restarts when `HERMES_DASHBOARD_BASIC_AUTH_SECRET` is set.
|
||||
|
||||
You can also set the backend URL without the UI via the `HERMES_DESKTOP_REMOTE_URL` environment variable before launching the app (it overrides the in-app setting); you still sign in from the Gateway settings panel.
|
||||
|
||||
:::note Per-profile remote hosts
|
||||
The remote gateway host is configured per [profile](./profiles.md), so each profile can point at its own remote backend (or stay on its local one). Switching profiles switches which remote host the app connects to.
|
||||
:::
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
- **Sign-in fails with 401 / "Invalid credentials"** — the username or password doesn't match the backend's `HERMES_DASHBOARD_BASIC_AUTH_USERNAME` / `HERMES_DASHBOARD_BASIC_AUTH_PASSWORD`. The backend returns the same generic error for an unknown user and a wrong password (no enumeration oracle), so double-check both. Confirm the gate is on with `curl -s http://<host>:9119/api/status | jq '.auth_required, .auth_providers'` — it should report `true` and include `"basic"`.
|
||||
- **No "Sign in" button — it asks for a session token instead** — the backend's username/password provider isn't active. `/api/status` won't list `"basic"` in `auth_providers`. Make sure both the username and a password (or password hash) are set in `~/.hermes/.env` and that the dashboard process actually loaded them.
|
||||
- **Signed out on every restart** — set `HERMES_DASHBOARD_BASIC_AUTH_SECRET` to a stable value. Without it the token-signing key is regenerated per boot, invalidating all sessions.
|
||||
- **Connection refused / times out** — the backend bound to `127.0.0.1` (the default) or a firewall/VPN is blocking the port. Bind to `0.0.0.0` or the tailscale IP and open the port to your trusted network.
|
||||
|
||||
For the same setup from the web-dashboard angle, see [Web Dashboard → Connecting Hermes Desktop to a remote backend](./features/web-dashboard.md#connecting-hermes-desktop-to-a-remote-backend); the env vars are catalogued under [Environment Variables → Web Dashboard & Hermes Desktop](../reference/environment-variables.md#web-dashboard--hermes-desktop).
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
Boot logs land in `HERMES_HOME/logs/desktop.log` (it includes backend output and recent Python tracebacks) — check it first if the app reports a boot failure. You can also tail it from the CLI:
|
||||
|
||||
```bash
|
||||
hermes logs gui -f
|
||||
```
|
||||
|
||||
Common resets:
|
||||
|
||||
```bash
|
||||
# Force a clean first-launch setup (macOS/Linux)
|
||||
rm "$HOME/.hermes/hermes-agent/.hermes-bootstrap-complete"
|
||||
|
||||
# Rebuild a broken Python venv (macOS/Linux)
|
||||
rm -rf "$HOME/.hermes/hermes-agent/venv"
|
||||
|
||||
# Reset a stuck macOS microphone prompt
|
||||
tccutil reset Microphone com.nousresearch.hermes
|
||||
```
|
||||
|
||||
### "Build desktop app" stuck on Electron download
|
||||
|
||||
The build downloads the Electron runtime (~114 MB) from `github.com/electron/electron/releases`. If the installer hangs on the **Build desktop app** step with the live output repeating `retrying attempt=…`, GitHub is being blocked or throttled on your network (firewall, proxy, or region).
|
||||
|
||||
The installer self-heals this automatically: on a failed build it (1) clears a corrupt cached Electron zip and retries, then (2) if it still fails and you haven't set `ELECTRON_MIRROR`, retries once more through `npmmirror.com`, the de-facto Electron community mirror. `@electron/get` SHASUM-checks the download, but the checksums come from the same mirror — that catches a corrupt or partial download, not a compromised mirror. If you'd rather not trust a third-party host, pin your own `ELECTRON_MIRROR` (below); the build never overrides one you've set.
|
||||
|
||||
To **choose your own mirror** (e.g. a corporate/trusted one), set `ELECTRON_MIRROR` before installing or rebuild manually — the build honors it and won't override it:
|
||||
|
||||
```bash
|
||||
ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/ \
|
||||
bash -c 'cd "$HOME/.hermes/hermes-agent/apps/desktop" && CSC_IDENTITY_AUTO_DISCOVERY=false npm run pack'
|
||||
```
|
||||
|
||||
To clear a corrupt cached zip by hand:
|
||||
|
||||
```bash
|
||||
rm -f "$HOME/Library/Caches/electron"/electron-*.zip # macOS
|
||||
rm -f "$HOME/.cache/electron"/electron-*.zip # Linux
|
||||
```
|
||||
|
||||
## Building from source
|
||||
|
||||
If you want to hack on the app itself, install workspace deps from the repo root once, then run the dev server from `apps/desktop`:
|
||||
|
||||
```bash
|
||||
npm install # from repo root — links apps/desktop, web, apps/shared
|
||||
cd apps/desktop
|
||||
npm run dev # Vite renderer + Electron, which boots the Python backend
|
||||
```
|
||||
|
||||
Point the app at a specific checkout, or sandbox it from your real config:
|
||||
|
||||
```bash
|
||||
HERMES_DESKTOP_HERMES_ROOT=/path/to/clone npm run dev
|
||||
HERMES_HOME=/tmp/throwaway npm run dev
|
||||
npm run dev:fake-boot # exercise the startup overlay with deterministic delays
|
||||
```
|
||||
|
||||
Build installers:
|
||||
|
||||
```bash
|
||||
npm run dist:mac # DMG + zip
|
||||
npm run dist:win # NSIS + MSI
|
||||
npm run dist:linux # AppImage + deb + rpm
|
||||
npm run pack # unpacked app under release/ (no installer)
|
||||
```
|
||||
|
||||
macOS/Windows signing and notarization run automatically when the relevant credentials are present in the environment (`CSC_LINK` / `CSC_KEY_PASSWORD` / `APPLE_*` for macOS, `WIN_CSC_*` for Windows).
|
||||
|
||||
## See also
|
||||
|
||||
- [CLI Guide](./cli.md) — the terminal interface
|
||||
- [TUI](./tui.md) — the modern terminal UI the desktop backend reuses
|
||||
- [Web Dashboard](./features/web-dashboard.md) — browser admin panel with an embedded chat tab
|
||||
- [Configuration](./configuration.md) — config that the desktop app reads and writes
|
||||
- [Windows (Native)](./windows-native.md) — native Windows install path
|
||||
|
|
@ -17,6 +17,19 @@ This page covers option 1. The container stores all user data (config, API keys,
|
|||
|
||||
If this is your first time running Hermes Agent, create a data directory on the host and start the container interactively to run the setup wizard:
|
||||
|
||||
:::caution Avoid browser-based VPS consoles for the install commands
|
||||
Some VPS providers (Hetzner Cloud, and several others) offer a browser-based
|
||||
console for managing hosts. These consoles transmit special characters
|
||||
incorrectly — `:` may arrive as `;`, `@` may be mis-rendered, and non-English
|
||||
keyboard layouts fare worse — which silently corrupts `docker run` arguments
|
||||
like `-v ~/.hermes:/opt/data`, `-e KEY=value`, and pasted API keys / tokens.
|
||||
|
||||
**Connect over SSH instead** (`ssh root@<host>`) for copy-paste-safe command
|
||||
entry. If you must use the browser console, type the commands manually
|
||||
instead of pasting, and double-check every `:`, `@`, `=`, and `/` in the
|
||||
result before hitting Enter.
|
||||
:::
|
||||
|
||||
```sh
|
||||
mkdir -p ~/.hermes
|
||||
docker run -it --rm \
|
||||
|
|
@ -26,6 +39,10 @@ docker run -it --rm \
|
|||
|
||||
This drops you into the setup wizard, which will prompt you for your API keys and write them to `~/.hermes/.env`. You only need to do this once. It is highly recommended to set up a chat system for the gateway to work with at this point.
|
||||
|
||||
:::tip
|
||||
Inside the container, run `hermes setup --portal` once — the refresh token persists in the mounted `~/.hermes` volume. See [Nous Portal](/integrations/nous-portal).
|
||||
:::
|
||||
|
||||
## Running in gateway mode
|
||||
|
||||
Once configured, run the container in the background as a persistent gateway (Telegram, Discord, Slack, WhatsApp, etc.):
|
||||
|
|
@ -41,6 +58,18 @@ docker run -d \
|
|||
|
||||
Port 8642 exposes the gateway's [OpenAI-compatible API server](./features/api-server.md) and health endpoint. It's optional if you only use chat platforms (Telegram, Discord, etc.), but required if you want the dashboard or external tools to reach the gateway.
|
||||
|
||||
:::tip Gateway runs supervised
|
||||
Inside the official Docker image, `gateway run` is **automatically supervised by s6-overlay**: if the gateway process crashes it's restarted within a couple of seconds without losing the container, and the dashboard (when `HERMES_DASHBOARD=1` is set) is supervised alongside it. The `gateway run` CMD process itself is a `sleep infinity` heartbeat that keeps the container alive while s6 manages the actual gateway process — so `docker stop` still shuts everything down cleanly, but `docker logs` shows the supervised gateway's output.
|
||||
|
||||
You'll see a one-line breadcrumb in `docker logs` confirming the upgrade. To opt out — and get the historical "gateway is the container's main process, container exit = gateway exit" semantics — pass `--no-supervise` or set `HERMES_GATEWAY_NO_SUPERVISE=1`. The opt-out is useful for CI smoke tests that want the container to exit with the gateway's status code; for production deployments the supervised default is strictly better.
|
||||
|
||||
This behavior applies to the s6-based image only. Earlier (tini-based) images still run `gateway run` as the foreground main process.
|
||||
:::
|
||||
|
||||
:::note Where gateway logs go
|
||||
See the [Where the logs go](#where-the-logs-go) section below for the full routing map (per-profile gateways, dashboard, boot reconciler, container-wide `docker logs`).
|
||||
:::
|
||||
|
||||
Note: the API server is gated on `API_SERVER_ENABLED=true`. To expose it beyond `127.0.0.1` inside the container, also set `API_SERVER_HOST=0.0.0.0` and an `API_SERVER_KEY` (minimum 8 characters — generate one with `openssl rand -hex 32`). Example:
|
||||
|
||||
```sh
|
||||
|
|
@ -51,7 +80,7 @@ docker run -d \
|
|||
-p 8642:8642 \
|
||||
-e API_SERVER_ENABLED=true \
|
||||
-e API_SERVER_HOST=0.0.0.0 \
|
||||
-e API_SERVER_KEY=your_api_key_here \
|
||||
-e API_SERVER_KEY="$(openssl rand -hex 32)" \
|
||||
-e API_SERVER_CORS_ORIGINS='*' \
|
||||
nousresearch/hermes-agent gateway run
|
||||
```
|
||||
|
|
@ -60,7 +89,7 @@ Opening any port on an internet facing machine is a security risk. You should no
|
|||
|
||||
## Running the dashboard
|
||||
|
||||
The built-in web dashboard runs as an optional side-process inside the same container as the gateway. Set `HERMES_DASHBOARD=1` and expose port `9119` alongside the gateway's `8642`:
|
||||
The built-in web dashboard runs as a supervised s6-rc service alongside the gateway in the same container. Set `HERMES_DASHBOARD=1` to bring it up:
|
||||
|
||||
```sh
|
||||
docker run -d \
|
||||
|
|
@ -73,21 +102,38 @@ docker run -d \
|
|||
nousresearch/hermes-agent gateway run
|
||||
```
|
||||
|
||||
The entrypoint starts `hermes dashboard` in the background (running as the non-root `hermes` user) before `exec`-ing the main command. Dashboard output is prefixed with `[dashboard]` in `docker logs` so it's easy to separate from gateway logs.
|
||||
The dashboard is supervised by s6 — if it crashes, `s6-supervise` restarts it automatically after a short backoff. Dashboard stdout/stderr is forwarded to `docker logs <container>` (no prefix; the gateway's own output now lives in a per-profile s6-log file — see [Where the logs go](#where-the-logs-go) below — so the two streams don't clash).
|
||||
|
||||
| Environment variable | Description | Default |
|
||||
|---------------------|-------------|---------|
|
||||
| `HERMES_DASHBOARD` | Set to `1` (or `true` / `yes`) to launch the dashboard alongside the main command | *(unset — dashboard not started)* |
|
||||
| `HERMES_DASHBOARD` | Set to `1` (or `true` / `yes`) to enable the supervised dashboard service | *(unset — service is registered but stays down)* |
|
||||
| `HERMES_DASHBOARD_HOST` | Bind address for the dashboard HTTP server | `0.0.0.0` |
|
||||
| `HERMES_DASHBOARD_PORT` | Port for the dashboard HTTP server | `9119` |
|
||||
| `HERMES_DASHBOARD_TUI` | Set to `1` to expose the in-browser Chat tab (embedded `hermes --tui` via PTY/WebSocket) | *(unset)* |
|
||||
| `HERMES_DASHBOARD_INSECURE` | Set to `1` (or `true` / `yes`) to bind without the OAuth auth gate. Only use on trusted networks behind a reverse proxy without the OAuth contract — the dashboard exposes API keys and session data | *(unset — gate enforced when a `DashboardAuthProvider` is registered)* |
|
||||
|
||||
The default `HERMES_DASHBOARD_HOST=0.0.0.0` is required for the host to reach the dashboard through the published port; the entrypoint automatically passes `--insecure` to `hermes dashboard` in that case. Override to `127.0.0.1` if you want to restrict the dashboard to in-container access only (e.g. behind a reverse proxy in a sidecar).
|
||||
The dashboard inside the container defaults to binding `0.0.0.0` — without it, the published `-p 9119:9119` port would not be reachable from the host. To restrict the bind to container loopback (for sidecar / reverse-proxy setups), set `HERMES_DASHBOARD_HOST=127.0.0.1`.
|
||||
|
||||
:::note
|
||||
The dashboard side-process is **not supervised** — if it crashes, it stays down until the container restarts. Running it as a separate container is not supported: the dashboard's gateway-liveness detection requires a shared PID namespace with the gateway process.
|
||||
The dashboard's auth gate engages automatically when both of the following are true:
|
||||
|
||||
1. The bind host is non-loopback (e.g. the default `0.0.0.0` inside the container), **and**
|
||||
2. A `DashboardAuthProvider` plugin is registered.
|
||||
|
||||
There are three bundled ways to satisfy the second condition:
|
||||
|
||||
- **Username/password** — the simplest for a self-hosted / on-prem / homelab container on a trusted network or behind a VPN: set `HERMES_DASHBOARD_BASIC_AUTH_USERNAME` + `HERMES_DASHBOARD_BASIC_AUTH_PASSWORD` (and `HERMES_DASHBOARD_BASIC_AUTH_SECRET` for restart-stable sessions). Not suitable for direct public-internet exposure.
|
||||
- **OAuth (Nous Portal)** — for hosted/public deploys: the `dashboard_auth/nous` provider activates whenever `HERMES_DASHBOARD_OAUTH_CLIENT_ID` is set.
|
||||
- **Self-hosted OIDC** — to authenticate against your own identity provider via standard OpenID Connect: the `dashboard_auth/self_hosted` provider activates when `HERMES_DASHBOARD_OIDC_ISSUER` + `HERMES_DASHBOARD_OIDC_CLIENT_ID` are set.
|
||||
|
||||
Whichever you choose, the gate redirects callers to a login page before they can reach any protected route. See [Web Dashboard → Authentication](features/web-dashboard.md#authentication-gated-mode) for all three providers.
|
||||
|
||||
If no provider is registered and the bind is non-loopback, the dashboard **fails closed at startup** with a specific error pointing at the missing env var. The `HERMES_DASHBOARD_INSECURE=1` escape hatch disables the gate entirely (the bind host alone never implies `--insecure`), but it serves an unauthenticated dashboard — configure a provider instead unless you have your own auth layer in front.
|
||||
|
||||
:::warning `HERMES_DASHBOARD_INSECURE=1` exposes API keys
|
||||
Opting out of the OAuth gate serves the dashboard's API surface (including model keys and session data) to anyone who can reach the published port. Only enable it when you have your own auth layer in front, or on a trusted LAN you fully control.
|
||||
:::
|
||||
|
||||
Running the dashboard as a separate container **is** supported when that container shares the host PID and network namespace (e.g. `network_mode: host`, as the repo's own `docker-compose.yml` does — see its `dashboard` service). Its gateway-liveness detection requires a shared PID namespace with the gateway process, so the limitation only applies to dashboards run in isolated bridge-network containers without a shared PID namespace.
|
||||
|
||||
## Running interactively (CLI chat)
|
||||
|
||||
To open an interactive chat session against a running data directory:
|
||||
|
|
@ -116,48 +162,74 @@ The `/opt/data` volume is the single source of truth for all Hermes state. It ma
|
|||
| `sessions/` | Conversation history |
|
||||
| `memories/` | Persistent memory store |
|
||||
| `skills/` | Installed skills |
|
||||
| `home/` | Per-profile HOME for Hermes tool subprocesses (`git`, `ssh`, `gh`, `npm`, and skill CLIs) |
|
||||
| `cron/` | Scheduled job definitions |
|
||||
| `hooks/` | Event hooks |
|
||||
| `logs/` | Runtime logs |
|
||||
| `skins/` | Custom CLI skins |
|
||||
|
||||
Skill CLIs that store credentials under `~` must be initialized against the subprocess HOME, not just the data-volume root. For example, the [xurl skill](./skills/bundled/social-media/social-media-xurl.md) stores OAuth state in `~/.xurl`; in the official Docker layout, Hermes tool calls read that as `/opt/data/home/.xurl`, so run manual xurl auth with `HOME=/opt/data/home` and verify with `HOME=/opt/data/home xurl auth status`.
|
||||
|
||||
:::warning
|
||||
Never run two Hermes **gateway** containers against the same data directory simultaneously — session files and memory stores are not designed for concurrent write access.
|
||||
:::
|
||||
|
||||
## Multi-profile support
|
||||
|
||||
Hermes supports [multiple profiles](../reference/profile-commands.md) — separate `~/.hermes/` directories that let you run independent agents (different SOUL, skills, memory, sessions, credentials) from a single installation. **When running under Docker, using Hermes' built-in multi-profile feature is not recommended.**
|
||||
Hermes supports [multiple profiles](../reference/profile-commands.md) — separate `~/.hermes/` subdirectories that let you run independent agents (different SOUL, skills, memory, sessions, credentials) from a single installation. **Inside the official Docker image, the s6 supervision tree treats each profile as a first-class supervised service**, so the recommended deployment is **one container hosting all profiles**.
|
||||
|
||||
Instead, the recommended pattern is **one container per profile**, with each container bind-mounting its own host directory as `/opt/data`:
|
||||
Each profile created with `hermes profile create <name>` gets:
|
||||
|
||||
- A dedicated s6 service slot at `/run/service/gateway-<name>/`, registered dynamically by the runtime — no container rebuild required.
|
||||
- Auto-restart on crash, backoff-managed by `s6-supervise`.
|
||||
- Per-profile rotated logs at `${HERMES_HOME}/logs/gateways/<name>/current` (10 archives × 1 MB each).
|
||||
- State persistence across container restarts: the boot-time reconciler reads `gateway_state.json` from each profile directory and brings the slot back up only for profiles whose last recorded state was `running`. Only a gateway you explicitly stopped (`hermes gateway stop`) stays down across a restart — a container restart, image upgrade, or unexpected exit leaves the recorded state as `running`, so the gateway auto-starts on the next boot.
|
||||
|
||||
The lifecycle commands you'd run on the host work the same way from inside the container:
|
||||
|
||||
```sh
|
||||
# Work profile
|
||||
docker run -d \
|
||||
--name hermes-work \
|
||||
--restart unless-stopped \
|
||||
-v ~/.hermes-work:/opt/data \
|
||||
-p 8642:8642 \
|
||||
nousresearch/hermes-agent gateway run
|
||||
# Create a profile — registers the gateway-<name> s6 slot.
|
||||
docker exec hermes hermes profile create coder
|
||||
|
||||
# Personal profile
|
||||
docker run -d \
|
||||
--name hermes-personal \
|
||||
--restart unless-stopped \
|
||||
-v ~/.hermes-personal:/opt/data \
|
||||
-p 8643:8642 \
|
||||
nousresearch/hermes-agent gateway run
|
||||
# Start / stop / restart — dispatches s6-svc; the gateway lifecycle survives docker restart.
|
||||
docker exec hermes hermes -p coder gateway start
|
||||
docker exec hermes hermes -p coder gateway stop
|
||||
docker exec hermes hermes -p coder gateway restart
|
||||
|
||||
# Status — reports `Manager: s6 (container supervisor)` inside the container.
|
||||
docker exec hermes hermes -p coder gateway status
|
||||
|
||||
# Remove a profile — tears down the s6 slot too.
|
||||
docker exec hermes hermes profile delete coder
|
||||
```
|
||||
|
||||
Why separate containers over profiles in Docker:
|
||||
Under the hood, `hermes gateway start/stop/restart` inside the container is intercepted and routed to `s6-svc` against the right service directory; you don't need to learn the s6 commands directly. For raw supervisor state, use `/command/s6-svstat /run/service/gateway-<name>` (note `/command/` is on PATH only for processes spawned by the supervision tree — when calling from `docker exec`, pass the absolute path).
|
||||
|
||||
- **Isolation** — each container has its own filesystem, process table, and resource limits. A crash, dependency change, or runaway session in one profile can't affect another.
|
||||
- **Independent lifecycle** — upgrade, restart, pause, or roll back each agent separately (`docker restart hermes-work` leaves `hermes-personal` untouched).
|
||||
- **Clean port and network separation** — each gateway binds its own host port; there's no risk of cross-talk between chat platforms or API servers.
|
||||
- **Simpler mental model** — the container *is* the profile. Backups, migrations, and permissions all follow the bind-mounted directory, with no extra `--profile` flags to remember.
|
||||
- **Avoids concurrent-write risk** — the warning above about never running two gateways against the same data directory still applies to profiles within a single container.
|
||||
### Why one container with many profiles, not many containers
|
||||
|
||||
In Docker Compose, this just means declaring one service per profile with distinct `container_name`, `volumes`, and `ports`:
|
||||
Before the s6 migration, "one container per profile" was the recommended pattern because there was no in-container supervisor to manage multiple gateways. With s6 as PID 1, that's no longer necessary, and the single-container layout is simpler in almost every dimension:
|
||||
|
||||
| | One container, many profiles | One container per profile |
|
||||
|---|---|---|
|
||||
| Disk overhead | One image, one bundled venv, one Playwright cache | N images / N caches |
|
||||
| Memory overhead | Shared Python interpreter cache, shared node_modules | Duplicated per container |
|
||||
| Profile creation | `docker exec ... hermes profile create <name>` (seconds) | New `docker run` invocation + port allocation + bind-mount config |
|
||||
| Per-profile crash recovery | `s6-supervise` auto-restart | Docker's `--restart unless-stopped` (slower, kills sibling work) |
|
||||
| Logs | Per-profile rotated file via `s6-log`, plus container-boot audit log | `docker logs <name>` per container — no built-in rotation |
|
||||
| Backup | One `~/.hermes` directory | N directories to coordinate |
|
||||
|
||||
The default profile (`default`) is always registered on first boot, so a fresh container ships with one supervised gateway out of the box. Additional profiles are pure runtime adds.
|
||||
|
||||
### When you DO want a separate container
|
||||
|
||||
Profile-in-container is the default. Run a separate container per profile only when you have a specific reason:
|
||||
|
||||
- **Resource isolation per workload** — e.g. a runaway browser-tool session in profile A shouldn't be able to OOM profile B. Containers give you `--memory` / `--cpus` per profile.
|
||||
- **Independent image pinning** — different upstream image tags per workload.
|
||||
- **Network segmentation** — distinct Docker networks per profile (e.g. one customer-facing, one internal).
|
||||
- **Compliance / blast radius** — distinct credentials never share an OS-level process tree.
|
||||
|
||||
In those cases, declare one service per profile with distinct `container_name`, `volumes`, and `ports`:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
|
|
@ -182,6 +254,24 @@ services:
|
|||
- ~/.hermes-personal:/opt/data
|
||||
```
|
||||
|
||||
The warning from [Persistent volumes](#persistent-volumes) still applies: never point two containers at the same `~/.hermes` directory simultaneously. The s6 supervisor inside each container manages its own profile set; cross-container sharing of a data volume corrupts session files and memory stores.
|
||||
|
||||
## Where the logs go
|
||||
|
||||
The s6 container has four distinct log surfaces, and "why isn't my gateway showing anything in `docker logs`" is a common surprise. Cheatsheet:
|
||||
|
||||
| Source | Where it lands | How to read it |
|
||||
|---|---|---|
|
||||
| **Per-profile gateway** (`hermes gateway run` and per-profile gateways under s6) | Tee'd to two places: `docker logs <container>` (real time, no extra prefix) **and** `${HERMES_HOME}/logs/gateways/<profile>/current` (rotated, ISO-8601 timestamped, 10 archives × 1 MB each) | `docker logs -f hermes` or `tail -F ~/.hermes/logs/gateways/default/current` on the host |
|
||||
| **Dashboard** (when `HERMES_DASHBOARD=1`) | `docker logs <container>` (no prefix) | `docker logs -f hermes` — interleaved with gateway lines |
|
||||
| **Boot reconciler** (records which profile gateways were restored on each container start) | `${HERMES_HOME}/logs/container-boot.log` (append-only audit log) | `tail -F ~/.hermes/logs/container-boot.log` |
|
||||
| **Generic Hermes logs** (`agent.log`, `errors.log`) | `${HERMES_HOME}/logs/` (profile-aware) | `docker exec hermes hermes logs --follow [--level WARNING] [--session <id>]` |
|
||||
|
||||
Two practical consequences worth knowing:
|
||||
|
||||
- The file copy at `logs/gateways/<profile>/current` is what survives container restarts. `docker logs` only retains output from the current container's lifetime (and is wiped on `docker rm`); the rotated files persist on the bind-mounted volume.
|
||||
- The boot reconciler's audit line shape is `<iso-timestamp> profile=<name> prior_state=<state> action=<registered|started>`, so a quick `grep profile=coder ~/.hermes/logs/container-boot.log` reveals when a given profile was last restored and whether s6 auto-started it.
|
||||
|
||||
## Environment variable forwarding
|
||||
|
||||
API keys are read from `/opt/data/.env` inside the container. You can also pass environment variables directly:
|
||||
|
|
@ -197,7 +287,7 @@ docker run -it --rm \
|
|||
Direct `-e` flags override values from `.env`. This is useful for CI/CD or secrets-manager integrations where you don't want keys on disk.
|
||||
|
||||
:::note Looking for Docker as the **terminal backend**?
|
||||
This page covers running Hermes itself inside Docker. If you want Hermes to execute the agent's `terminal` / `execute_code` calls inside a Docker sandbox container (one persistent container per Hermes process), that's a separate config block — `terminal.backend: docker` plus `terminal.docker_image`, `terminal.docker_volumes`, `terminal.docker_forward_env`, `terminal.docker_run_as_host_user`, and `terminal.docker_extra_args`. See [Configuration → Docker Backend](configuration.md#docker-backend) for the full set.
|
||||
This page covers running Hermes itself inside Docker. If you want Hermes to execute the agent's `terminal` / `execute_code` calls inside a Docker sandbox container (one long-lived container shared across Hermes processes — see issue #20561), that's a separate config block — `terminal.backend: docker` plus `terminal.docker_image`, `terminal.docker_volumes`, `terminal.docker_forward_env`, `terminal.docker_env`, `terminal.docker_run_as_host_user`, `terminal.docker_extra_args`, `terminal.docker_persist_across_processes`, and `terminal.docker_orphan_reaper`. See [Configuration → Docker Backend](configuration.md#docker-backend) for the full set including container-lifecycle rules.
|
||||
:::
|
||||
|
||||
## Docker Compose example
|
||||
|
|
@ -229,7 +319,85 @@ services:
|
|||
cpus: "2.0"
|
||||
```
|
||||
|
||||
Start with `docker compose up -d` and view logs with `docker compose logs -f`. Dashboard output is prefixed with `[dashboard]` so it's easy to filter from gateway logs.
|
||||
Start with `docker compose up -d` and view logs with `docker compose logs -f`. The supervised gateway's stdout is also tee'd to `${HERMES_HOME}/logs/gateways/<profile>/current` on the volume — see [Where the logs go](#where-the-logs-go) for the full routing map.
|
||||
|
||||
## Optional: Linux desktop audio bridge
|
||||
|
||||
Voice mode in Docker needs two separate things to work: Hermes must be allowed to probe audio devices inside the container, and the container must be able to reach your host audio server. The setup below covers the host audio plumbing for Linux desktops that expose a PulseAudio-compatible socket, including many PipeWire setups.
|
||||
|
||||
:::caution
|
||||
This is a Linux desktop workaround, not a general Docker Desktop feature. It is useful when you already have host audio working and want CLI voice mode inside the Hermes container. If Hermes still reports `Running inside Docker container -- no audio devices`, use a build that includes Docker audio probing support for `PULSE_SERVER` / `PIPEWIRE_REMOTE`.
|
||||
:::
|
||||
|
||||
First, create an ALSA config next to your Compose file:
|
||||
|
||||
```conf title="asound.conf"
|
||||
pcm.!default {
|
||||
type pulse
|
||||
hint {
|
||||
show on
|
||||
description "Default ALSA Output (PulseAudio)"
|
||||
}
|
||||
}
|
||||
|
||||
pcm.pulse {
|
||||
type pulse
|
||||
}
|
||||
|
||||
ctl.!default {
|
||||
type pulse
|
||||
}
|
||||
```
|
||||
|
||||
Then build a small derived image with the ALSA PulseAudio plugin installed:
|
||||
|
||||
```dockerfile title="Dockerfile.audio"
|
||||
FROM nousresearch/hermes-agent:latest
|
||||
|
||||
USER root
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends libasound2-plugins \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
```
|
||||
|
||||
Use that image in Compose and pass through the host user's PulseAudio socket and cookie:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
hermes:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.audio
|
||||
image: hermes-agent-audio
|
||||
container_name: hermes
|
||||
restart: unless-stopped
|
||||
command: gateway run
|
||||
volumes:
|
||||
- ~/.hermes:/opt/data
|
||||
- /run/user/${HERMES_UID}/pulse:/run/user/${HERMES_UID}/pulse
|
||||
- ~/.config/pulse/cookie:/tmp/pulse-cookie:ro
|
||||
- ./asound.conf:/etc/asound.conf:ro
|
||||
environment:
|
||||
- HERMES_UID=${HERMES_UID}
|
||||
- HERMES_GID=${HERMES_GID}
|
||||
- XDG_RUNTIME_DIR=/run/user/${HERMES_UID}
|
||||
- PULSE_SERVER=unix:/run/user/${HERMES_UID}/pulse/native
|
||||
- PULSE_COOKIE=/tmp/pulse-cookie
|
||||
```
|
||||
|
||||
Start it with your host UID/GID so the container process can access the per-user audio socket:
|
||||
|
||||
```sh
|
||||
export HERMES_UID="$(id -u)"
|
||||
export HERMES_GID="$(id -g)"
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
To verify what PortAudio sees inside the container:
|
||||
|
||||
```sh
|
||||
docker exec hermes /opt/hermes/.venv/bin/python -c "import sounddevice as sd; print(sd.query_devices())"
|
||||
```
|
||||
|
||||
## Resource limits
|
||||
|
||||
|
|
@ -261,27 +429,62 @@ The official image is based on `debian:13.4` and includes:
|
|||
- Python 3 with all Hermes dependencies (`uv pip install -e ".[all]"`)
|
||||
- Node.js + npm (for browser automation and WhatsApp bridge)
|
||||
- Playwright with Chromium (`npx playwright install --with-deps chromium --only-shell`)
|
||||
- ripgrep, ffmpeg, git, and tini as system utilities
|
||||
- ripgrep, ffmpeg, git, and `xz-utils` as system utilities
|
||||
- **`docker-cli`** — so agents running inside the container can drive the host's Docker daemon (bind-mount `/var/run/docker.sock` to opt in) for `docker build`, `docker run`, container inspection, etc.
|
||||
- **`openssh-client`** — enables the [SSH terminal backend](/docs/user-guide/configuration#ssh-backend) from inside the container. The SSH backend shells out to the system `ssh` binary; without this, it failed silently in containerized installs.
|
||||
- **`openssh-client`** — enables the [SSH terminal backend](/user-guide/configuration#ssh-backend) from inside the container. The SSH backend shells out to the system `ssh` binary; without this, it failed silently in containerized installs.
|
||||
- The WhatsApp bridge (`scripts/whatsapp-bridge/`)
|
||||
- **[`s6-overlay`](https://github.com/just-containers/s6-overlay) v3** as PID 1 (replaces the older `tini`) — supervises the dashboard and per-profile gateways with auto-restart on crash, reaps zombie subprocesses, and forwards signals.
|
||||
|
||||
The entrypoint script (`docker/entrypoint.sh`) bootstraps the data volume on first run:
|
||||
- Creates the directory structure (`sessions/`, `memories/`, `skills/`, etc.)
|
||||
- Copies `.env.example` → `.env` if no `.env` exists
|
||||
- Copies default `config.yaml` if missing
|
||||
- Copies default `SOUL.md` if missing
|
||||
- Syncs bundled skills using a manifest-based approach (preserves user edits)
|
||||
- Optionally launches `hermes dashboard` as a background side-process when `HERMES_DASHBOARD=1` (see [Running the dashboard](#running-the-dashboard))
|
||||
- Then runs `hermes` with whatever arguments you pass
|
||||
The container's `ENTRYPOINT` is s6-overlay's `/init`. On boot it:
|
||||
1. Runs `/etc/cont-init.d/01-hermes-setup` (= `docker/stage2-hook.sh`) as root: optional UID/GID remap, fixes volume ownership, seeds `.env` / `config.yaml` / `SOUL.md` on first boot, runs non-interactive config-schema migrations unless `HERMES_SKIP_CONFIG_MIGRATION=1`, syncs bundled skills.
|
||||
2. Runs `/etc/cont-init.d/02-reconcile-profiles` (= `hermes_cli.container_boot`): walks `$HERMES_HOME/profiles/<name>/`, recreates the per-profile gateway s6 service slot under `/run/service/gateway-<profile>/`, and auto-starts only those whose last recorded state was `running` (see [Per-profile gateway supervision](#per-profile-gateway-supervision)).
|
||||
3. Starts the static `main-hermes` and `dashboard` s6-rc services.
|
||||
4. Exec's the container's CMD as the main program (`/opt/hermes/docker/main-wrapper.sh`), which routes the arguments the user passed to `docker run`:
|
||||
- no args → `hermes` (the default)
|
||||
- first arg is an executable on PATH (e.g. `sleep`, `bash`) → exec it directly
|
||||
- anything else → `hermes <args>` (subcommand passthrough)
|
||||
The container exits when this main program exits, with its exit code.
|
||||
|
||||
:::warning
|
||||
Do not override the image entrypoint unless you keep `/opt/hermes/docker/entrypoint.sh` in the command chain. The entrypoint drops root privileges to the `hermes` user before gateway state files are created. Starting `hermes gateway run` as root inside the official image is refused by default because it can leave root-owned files in `/opt/data` and break later dashboard or gateway starts. Set `HERMES_ALLOW_ROOT_GATEWAY=1` only when you intentionally accept that risk.
|
||||
:::warning Breaking change vs. pre-s6 images
|
||||
The container ENTRYPOINT is now `/init` (s6-overlay), not `/usr/bin/tini`. All five documented `docker run` invocation patterns (no args, `chat -q "…"`, `sleep infinity`, `bash`, `--tui`) behave identically to the tini-based image. If you have a downstream wrapper that depended on tini-specific signal behavior or hard-coded `/usr/bin/tini --` invocation, pin to the previous image tag.
|
||||
:::
|
||||
|
||||
:::warning Privilege model
|
||||
Do not override the image entrypoint unless you keep `/init` (or, equivalently, the legacy `docker/entrypoint.sh` shim that forwards to the stage2 hook) in the command chain. s6-overlay's `/init` runs as root so it can chown the volume on first boot, then drops to the `hermes` user via `s6-setuidgid` for every supervised service AND for the main program. Starting `hermes gateway run` as root inside the official image is refused by default because it can leave root-owned files in `/opt/data` and break later dashboard or gateway starts. Set `HERMES_ALLOW_ROOT_GATEWAY=1` only when you intentionally accept that risk.
|
||||
:::
|
||||
|
||||
### `docker exec` automatically drops to the `hermes` user
|
||||
|
||||
`docker exec hermes <cmd>` defaults to running as root inside the container, but the image ships a thin shim at `/opt/hermes/bin/hermes` (earliest on PATH) that detects root callers and transparently re-execs through `s6-setuidgid hermes`. So `docker exec hermes login`, `docker exec hermes profile create …`, `docker exec hermes setup`, etc. all write files owned by UID 10000 — i.e. readable by the supervised gateway — with no extra `--user` flag needed. Non-root callers (the supervised processes themselves, `docker exec --user hermes`, kanban subagents inside the container) hit a short-circuit that exec's the venv binary directly, so there's no overhead on the hot paths.
|
||||
|
||||
If you specifically need a `docker exec` that retains root semantics (diagnostic sessions, inspecting root-only state, files outside `/opt/data` that root happens to own), opt out per invocation:
|
||||
|
||||
```sh
|
||||
docker exec -e HERMES_DOCKER_EXEC_AS_ROOT=1 hermes <cmd>
|
||||
```
|
||||
|
||||
The shim accepts `1` / `true` / `yes` (case-insensitive). Anything else — including typos like `=0` — falls through to the drop, so silent opt-outs aren't possible. If `s6-setuidgid` isn't available (custom builds that stripped s6-overlay), the shim refuses to run as root and exits 126 instead, surfacing the broken privilege model loudly rather than regressing to the historical footgun where `docker exec hermes login` would write `auth.json` as `root:root` and break the supervised gateway's auth on every chat platform message.
|
||||
|
||||
### Per-profile gateway supervision
|
||||
|
||||
Each profile created with `hermes profile create <name>` automatically gets an s6-supervised gateway service registered at `/run/service/gateway-<name>/`, with state-persistent auto-restart across container restarts. See [Multi-profile support](#multi-profile-support) above for the user-facing workflow and the lifecycle commands.
|
||||
|
||||
**Supervision benefits over the pre-s6 image:**
|
||||
|
||||
- Gateway crashes are auto-restarted by `s6-supervise` after a ~1s backoff.
|
||||
- Dashboard, when enabled with `HERMES_DASHBOARD=1`, is supervised on the same supervision tree and gets the same auto-restart treatment.
|
||||
- `docker restart`, image upgrades (`docker compose up -d --force-recreate`), and unexpected exits preserve running gateways: the cont-init reconciler reads `$HERMES_HOME/profiles/<name>/gateway_state.json` and brings the slot back up if the last recorded state was `running`. Only an explicit `hermes gateway stop` records `stopped` and keeps the gateway down across the restart; the container/s6 SIGTERM sent on a restart or upgrade is treated as "still running" and auto-starts.
|
||||
- Per-profile gateway logs persist under `$HERMES_HOME/logs/gateways/<profile>/current` (rotated by `s6-log`), and the reconciler's actions are appended to `$HERMES_HOME/logs/container-boot.log` per boot. See [Where the logs go](#where-the-logs-go) for the full routing map.
|
||||
|
||||
`hermes status` inside the container reports `Manager: s6 (container supervisor)`. Use `/command/s6-svstat /run/service/gateway-<name>` for the raw supervisor view (note `/command/` is on PATH for supervision-tree processes only; pass the absolute path when calling from `docker exec`).
|
||||
|
||||
## Upgrading
|
||||
|
||||
Pull the latest image and recreate the container. Your data directory is untouched.
|
||||
Pull the latest image and recreate the container. Your data directory is
|
||||
preserved, and the container runs non-interactive config-schema migrations
|
||||
against the mounted `$HERMES_HOME/config.yaml` before starting the gateway.
|
||||
When a migration is needed, Hermes writes timestamped backups next to
|
||||
`config.yaml` and `.env` first.
|
||||
|
||||
```sh
|
||||
docker pull nousresearch/hermes-agent:latest
|
||||
|
|
@ -300,12 +503,95 @@ docker compose pull
|
|||
docker compose up -d
|
||||
```
|
||||
|
||||
Set `HERMES_SKIP_CONFIG_MIGRATION=1` only if you need to inspect or migrate the
|
||||
persisted config manually before letting the new image rewrite it.
|
||||
|
||||
## Skills and credential files
|
||||
|
||||
When using Docker as the execution environment (not the methods above, but when the agent runs commands inside a Docker sandbox — see [Configuration → Docker Backend](./configuration.md#docker-backend)), Hermes reuses a single long-lived container for all tool calls and automatically bind-mounts the skills directory (`~/.hermes/skills/`) and any credential files declared by skills into that container as read-only volumes. Skill scripts, templates, and references are available inside the sandbox without manual configuration, and because the container persists for the life of the Hermes process, any dependencies you install or files you write stay around for the next tool call.
|
||||
|
||||
The same syncing happens for SSH and Modal backends — skills and credential files are uploaded via rsync or the Modal mount API before each command.
|
||||
|
||||
## Installing more tools in the container
|
||||
|
||||
The official image ships with a curated set of utilities (see [What the Dockerfile does](#what-the-dockerfile-does)), but not every tool an agent might want is preinstalled. There are five recommended approaches, in increasing order of effort and durability.
|
||||
|
||||
### npm or Python tools — use `npx` or `uvx`
|
||||
|
||||
For any tool published to npm or PyPI, instruct Hermes to run it via `npx` (npm) or `uvx` (Python) and to remember that command in its persistent memory. If the tool needs a config file or credentials, instruct it to drop those under `/opt/data` (e.g. `/opt/data/<tool>/config.yaml`).
|
||||
|
||||
Dependencies are fetched on demand and cached for the life of the container. Configuration written under `/opt/data` survives container restarts because it lives on the bind-mounted host directory. The package cache itself is rebuilt after a `docker rm`, but `npx` and `uvx` re-fetch transparently the next time the tool runs.
|
||||
|
||||
### Other tools (apt packages, binaries) — install and remember
|
||||
|
||||
For anything outside npm or PyPI — `apt` packages, prebuilt binaries, language runtimes not already in the image — instruct Hermes how to install it (e.g. `apt-get update && apt-get install -y <package>`) and tell it to remember the install command. The tool persists for the rest of the container's lifetime, and Hermes will re-run the install command after a container restart when it next needs the tool.
|
||||
|
||||
This is a good fit for tools that are quick to install and used occasionally. For tools used constantly, prefer the next approach.
|
||||
|
||||
### Durable installs — build a derived image
|
||||
|
||||
When a tool must be available immediately on every container start with no re-install delay, build a new image that inherits from `nousresearch/hermes-agent` and installs the tool in a layer:
|
||||
|
||||
```dockerfile
|
||||
FROM nousresearch/hermes-agent:latest
|
||||
|
||||
USER root
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends <your-package> \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
USER hermes
|
||||
```
|
||||
|
||||
Build it and use it in place of the official image:
|
||||
|
||||
```sh
|
||||
docker build -t my-hermes:latest .
|
||||
docker run -d \
|
||||
--name hermes \
|
||||
--restart unless-stopped \
|
||||
-v ~/.hermes:/opt/data \
|
||||
-p 8642:8642 \
|
||||
my-hermes:latest gateway run
|
||||
```
|
||||
|
||||
The entrypoint script and `/opt/data` semantics are inherited unchanged, so the rest of this page still applies. Remember to rebuild the image when pulling a newer upstream `nousresearch/hermes-agent`.
|
||||
|
||||
### Complex tools or multi-service stacks — run a sidecar container
|
||||
|
||||
For tools that bring their own service (a database, a web server, a queue, a headless browser farm) or that are too heavy to live inside the Hermes container, run them as a separate container on a shared Docker network. Hermes reaches the sidecar by container name, the same way it reaches a local inference server (see [Connecting to local inference servers](#connecting-to-local-inference-servers-vllm-ollama-etc)).
|
||||
|
||||
```yaml
|
||||
services:
|
||||
hermes:
|
||||
image: nousresearch/hermes-agent:latest
|
||||
container_name: hermes
|
||||
restart: unless-stopped
|
||||
command: gateway run
|
||||
ports:
|
||||
- "8642:8642"
|
||||
volumes:
|
||||
- ~/.hermes:/opt/data
|
||||
networks:
|
||||
- hermes-net
|
||||
|
||||
my-tool:
|
||||
image: example/my-tool:latest
|
||||
container_name: my-tool
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- hermes-net
|
||||
|
||||
networks:
|
||||
hermes-net:
|
||||
driver: bridge
|
||||
```
|
||||
|
||||
From inside the Hermes container, the sidecar is reachable at `http://my-tool:<port>` (or whatever protocol it serves). This pattern keeps each service's lifecycle, resource limits, and upgrade cadence independent, and avoids bloating the Hermes image with dependencies that are only needed by one tool.
|
||||
|
||||
### Broadly useful tools — open an issue or pull request
|
||||
|
||||
If a tool is likely to be useful to most Hermes Agent users, consider contributing it upstream rather than carrying it in a private derived image. Open an issue or pull request on the [hermes-agent repository](https://github.com/NousResearch/hermes-agent) describing the tool and its use case. Tools that get bundled into the official image benefit every user and avoid the maintenance overhead of a downstream fork.
|
||||
|
||||
## Connecting to local inference servers (vLLM, Ollama, etc.)
|
||||
|
||||
When running Hermes in Docker and your inference server (vLLM, Ollama, text-generation-inference, etc.) is also running on the host or in another container, networking requires extra attention.
|
||||
|
|
@ -449,12 +735,24 @@ Check logs: `docker logs hermes`. Common causes:
|
|||
|
||||
### "Permission denied" errors
|
||||
|
||||
The container's entrypoint drops privileges to the non-root `hermes` user (UID 10000) via `gosu`. If your host `~/.hermes/` is owned by a different UID, set `HERMES_UID`/`HERMES_GID` to match your host user, or ensure the data directory is writable:
|
||||
The container's stage2 hook drops privileges to the non-root `hermes` user (UID 10000) via `s6-setuidgid` inside each supervised service. If your host `~/.hermes/` is owned by a different UID, set `HERMES_UID`/`HERMES_GID` — or their `PUID`/`PGID` aliases, for parity with LinuxServer.io and NAS images — to match your host user, or ensure the data directory is writable:
|
||||
|
||||
```sh
|
||||
chmod -R 755 ~/.hermes
|
||||
```
|
||||
|
||||
On a NAS (UGOS, Synology, unRAID) the data directory is typically a **bind mount** owned by a host UID the container cannot `chown`. Set `PUID`/`PGID` (or `HERMES_UID`/`HERMES_GID`) to that host user so the runtime runs as the owner of the mount rather than UID 10000:
|
||||
|
||||
```sh
|
||||
docker run -d \
|
||||
--name hermes \
|
||||
-e PUID=1000 -e PGID=10 \
|
||||
-v /volume1/docker/hermes:/opt/data \
|
||||
nousresearch/hermes-agent gateway run
|
||||
```
|
||||
|
||||
`docker exec hermes <cmd>` automatically drops to UID 10000 too — see [`docker exec` automatically drops to the `hermes` user](#docker-exec-automatically-drops-to-the-hermes-user) for details and the per-invocation opt-out.
|
||||
|
||||
### Browser tools not working
|
||||
|
||||
Playwright needs shared memory. Add `--shm-size=1g` to your Docker run command:
|
||||
|
|
|
|||
|
|
@ -10,6 +10,10 @@ The API server exposes hermes-agent as an OpenAI-compatible HTTP endpoint. Any f
|
|||
|
||||
Your agent handles requests with its full toolset (terminal, file operations, web search, memory, skills) and returns the final response. When streaming, tool progress indicators appear inline so frontends can show what the agent is doing.
|
||||
|
||||
:::tip One backend covers models + tools
|
||||
Hermes itself needs a configured provider and tool backends for the API server to be useful. A [Nous Portal](/user-guide/features/tool-gateway) subscription handles both — 300+ models plus web/image/TTS/browser via the Tool Gateway. Run `hermes setup --portal` once before starting the API server and frontends like Open WebUI or LobeChat get a fully tool-equipped backend.
|
||||
:::
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 1. Enable the API server
|
||||
|
|
@ -47,7 +51,7 @@ curl http://localhost:8642/v1/chat/completions \
|
|||
-d '{"model": "hermes-agent", "messages": [{"role": "user", "content": "Hello!"}]}'
|
||||
```
|
||||
|
||||
Or connect Open WebUI, LobeChat, or any other frontend — see the [Open WebUI integration guide](/docs/user-guide/messaging/open-webui) for step-by-step instructions.
|
||||
Or connect Open WebUI, LobeChat, or any other frontend — see the [Open WebUI integration guide](/user-guide/messaging/open-webui) for step-by-step instructions.
|
||||
|
||||
## Endpoints
|
||||
|
||||
|
|
@ -192,7 +196,7 @@ Delete a stored response.
|
|||
|
||||
### GET /v1/models
|
||||
|
||||
Lists the agent as an available model. The advertised model name defaults to the [profile](/docs/user-guide/profiles) name (or `hermes-agent` for the default profile). Required by most frontends for model discovery.
|
||||
Lists the agent as an available model. The advertised model name defaults to the [profile](/user-guide/profiles) name (or `hermes-agent` for the default profile). Required by most frontends for model discovery.
|
||||
|
||||
### GET /v1/capabilities
|
||||
|
||||
|
|
@ -268,6 +272,10 @@ Server-Sent Events stream of the run's tool-call progress, token deltas, and lif
|
|||
|
||||
Interrupt a running agent turn. The endpoint returns immediately with `{"status": "stopping"}` while Hermes asks the active agent to stop at the next safe interruption point.
|
||||
|
||||
### POST /v1/runs/\{run_id\}/approval
|
||||
|
||||
Resolve a pending approval for a run that is waiting on a human decision (for example, a tool call gated behind an approval policy). The body carries the approval decision; the run resumes once the decision is recorded. This endpoint is advertised in `/v1/capabilities` as the `run_approval` feature so external UIs can detect support before surfacing an approval prompt.
|
||||
|
||||
## Jobs API (background scheduled work)
|
||||
|
||||
The server exposes a lightweight jobs CRUD surface for managing scheduled / background agent runs from a remote client. All endpoints are gated behind the same bearer auth.
|
||||
|
|
@ -304,6 +312,66 @@ Resume a previously paused job.
|
|||
|
||||
Trigger the job to run immediately, out of schedule.
|
||||
|
||||
## Sessions API (session control over REST)
|
||||
|
||||
External UIs can manage Hermes sessions over REST without standing up the dashboard. All endpoints are gated by `API_SERVER_KEY` and live under `/api/sessions/*`.
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| `GET` | `/api/sessions` | List sessions (paginated — `limit`, `offset`, `source`, `include_children`) |
|
||||
| `POST` | `/api/sessions` | Create an empty session |
|
||||
| `GET` | `/api/sessions/{id}` | Read session metadata |
|
||||
| `PATCH` | `/api/sessions/{id}` | Update title or `end_reason` |
|
||||
| `DELETE` | `/api/sessions/{id}` | Delete a session |
|
||||
| `GET` | `/api/sessions/{id}/messages` | Message history for a session |
|
||||
| `POST` | `/api/sessions/{id}/fork` | Branch the session via `SessionDB` lineage (matches CLI `/branch` semantics) |
|
||||
| `POST` | `/api/sessions/{id}/chat` | Run one synchronous agent turn |
|
||||
| `POST` | `/api/sessions/{id}/chat/stream` | SSE wrapper over a single turn — emits `assistant.delta`, `tool.started`, `tool.completed`, `run.completed` events |
|
||||
|
||||
`/v1/capabilities` advertises the full surface via `session_*` feature flags and `endpoints.session_*` entries so external UIs can detect support and fall back safely. Inline images are supported in `chat` and `chat/stream` payloads (multimodal-aware path).
|
||||
|
||||
```bash
|
||||
# fork a session and run one turn
|
||||
curl -X POST http://localhost:8642/api/sessions/$ID/fork \
|
||||
-H "Authorization: Bearer $API_SERVER_KEY" \
|
||||
-d '{"title": "explore alt path"}'
|
||||
|
||||
# stream a turn over SSE
|
||||
curl -N -X POST http://localhost:8642/api/sessions/$ID/chat/stream \
|
||||
-H "Authorization: Bearer $API_SERVER_KEY" \
|
||||
-d '{"input": "what files changed in the last hour?"}'
|
||||
```
|
||||
|
||||
## Skills and toolsets discovery
|
||||
|
||||
`GET /v1/skills` and `GET /v1/toolsets` let external clients enumerate the agent's capabilities deterministically over REST instead of asking the model. Both are read-only and gated by `API_SERVER_KEY`.
|
||||
|
||||
```bash
|
||||
curl http://localhost:8642/v1/skills \
|
||||
-H "Authorization: Bearer $API_SERVER_KEY"
|
||||
# → [{"name": "github-pr-workflow", "description": "...", "category": "..."}, ...]
|
||||
|
||||
curl http://localhost:8642/v1/toolsets \
|
||||
-H "Authorization: Bearer $API_SERVER_KEY"
|
||||
# → [{"name": "core", "label": "...", "description": "...", "enabled": true,
|
||||
# "configured": true, "tools": ["read_file", "write_file", ...]}, ...]
|
||||
```
|
||||
|
||||
`/v1/skills` returns the same metadata the skills hub uses internally. `/v1/toolsets` returns toolsets resolved for the `api_server` platform with the concrete `tools` list each one expands to. Both are advertised under `endpoints.*` in `/v1/capabilities`.
|
||||
|
||||
## Long-term memory scoping (`X-Hermes-Session-Key`)
|
||||
|
||||
Multi-user frontends like Open WebUI need a stable per-channel identifier for long-term memory (Honcho, etc.) that is **independent** of the transcript-scoped `X-Hermes-Session-Id` (which rotates on `/new`). Pass `X-Hermes-Session-Key` on `/v1/chat/completions`, `/v1/responses`, or `/v1/runs` and Hermes threads it through to `AIAgent(gateway_session_key=...)`, where the Honcho memory provider uses it to derive a stable scope.
|
||||
|
||||
```http
|
||||
POST /v1/chat/completions HTTP/1.1
|
||||
Authorization: Bearer ***
|
||||
X-Hermes-Session-Id: transcript-alpha
|
||||
X-Hermes-Session-Key: agent:main:webui:dm:user-42
|
||||
```
|
||||
|
||||
Rules: max 256 chars, control characters (`\r`, `\n`, `\x00`) are rejected, and the value is echoed back on responses (JSON + SSE). `/v1/capabilities` advertises support via `"session_key_header": "X-Hermes-Session-Key"`. Without the key, Honcho's `per-session` strategy produces a different scope per `session_id` — exactly the behavior Hermes had before.
|
||||
|
||||
## System Prompt Handling
|
||||
|
||||
When a frontend sends a `system` message (Chat Completions) or `instructions` field (Responses API), hermes-agent **layers it on top** of its core system prompt. Your agent keeps all its tools, memory, and skills — the frontend's system prompt adds extra instructions.
|
||||
|
|
@ -323,9 +391,7 @@ Authorization: Bearer ***
|
|||
Configure the key via `API_SERVER_KEY` env var. If you need a browser to call Hermes directly, also set `API_SERVER_CORS_ORIGINS` to an explicit allowlist.
|
||||
|
||||
:::warning Security
|
||||
The API server gives full access to hermes-agent's toolset, **including terminal commands**. When binding to a non-loopback address like `0.0.0.0`, `API_SERVER_KEY` is **required**. Also keep `API_SERVER_CORS_ORIGINS` narrow to control browser access.
|
||||
|
||||
The default bind address (`127.0.0.1`) is for local-only use. Browser access is disabled by default; enable it only for explicit trusted origins.
|
||||
The API server gives full access to hermes-agent's toolset, **including terminal commands**. `API_SERVER_KEY` is **required for every deployment**, including the default loopback bind on `127.0.0.1`. Keep `API_SERVER_CORS_ORIGINS` narrow to control browser access when you explicitly allow browser callers.
|
||||
:::
|
||||
|
||||
## Configuration
|
||||
|
|
@ -337,7 +403,7 @@ The default bind address (`127.0.0.1`) is for local-only use. Browser access is
|
|||
| `API_SERVER_ENABLED` | `false` | Enable the API server |
|
||||
| `API_SERVER_PORT` | `8642` | HTTP server port |
|
||||
| `API_SERVER_HOST` | `127.0.0.1` | Bind address (localhost only by default) |
|
||||
| `API_SERVER_KEY` | _(none)_ | Bearer token for auth |
|
||||
| `API_SERVER_KEY` | _(required)_ | Bearer token for auth |
|
||||
| `API_SERVER_CORS_ORIGINS` | _(none)_ | Comma-separated allowed browser origins |
|
||||
| `API_SERVER_MODEL_NAME` | _(profile name)_ | Model name on `/v1/models`. Defaults to profile name, or `hermes-agent` for default profile. |
|
||||
|
||||
|
|
@ -377,7 +443,7 @@ Any frontend that supports the OpenAI API format works. Tested/documented integr
|
|||
|
||||
| Frontend | Stars | Connection |
|
||||
|----------|-------|------------|
|
||||
| [Open WebUI](/docs/user-guide/messaging/open-webui) | 126k | Full guide available |
|
||||
| [Open WebUI](/user-guide/messaging/open-webui) | 126k | Full guide available |
|
||||
| LobeChat | 73k | Custom provider endpoint |
|
||||
| LibreChat | 34k | Custom endpoint in librechat.yaml |
|
||||
| AnythingLLM | 56k | Generic OpenAI provider |
|
||||
|
|
@ -391,7 +457,7 @@ Any frontend that supports the OpenAI API format works. Tested/documented integr
|
|||
|
||||
## Multi-User Setup with Profiles
|
||||
|
||||
To give multiple users their own isolated Hermes instance (separate config, memory, skills), use [profiles](/docs/user-guide/profiles):
|
||||
To give multiple users their own isolated Hermes instance (separate config, memory, skills), use [profiles](/user-guide/profiles):
|
||||
|
||||
```bash
|
||||
# Create a profile per user
|
||||
|
|
@ -422,7 +488,7 @@ Each profile's API server automatically advertises the profile name as the model
|
|||
- `http://localhost:8643/v1/models` → model `alice`
|
||||
- `http://localhost:8644/v1/models` → model `bob`
|
||||
|
||||
In Open WebUI, add each as a separate connection. The model dropdown shows `alice` and `bob` as distinct models, each backed by a fully isolated Hermes instance. See the [Open WebUI guide](/docs/user-guide/messaging/open-webui#multi-user-setup-with-profiles) for details.
|
||||
In Open WebUI, add each as a separate connection. The model dropdown shows `alice` and `bob` as distinct models, each backed by a fully isolated Hermes instance. See the [Open WebUI guide](/user-guide/messaging/open-webui#multi-user-setup-with-profiles) for details.
|
||||
|
||||
## Limitations
|
||||
|
||||
|
|
@ -434,4 +500,4 @@ In Open WebUI, add each as a separate connection. The model dropdown shows `alic
|
|||
|
||||
The API server also serves as the backend for **gateway proxy mode**. When another Hermes gateway instance is configured with `GATEWAY_PROXY_URL` pointing at this API server, it forwards all messages here instead of running its own agent. This enables split deployments — for example, a Docker container handling Matrix E2EE that relays to a host-side agent.
|
||||
|
||||
See [Matrix Proxy Mode](/docs/user-guide/messaging/matrix#proxy-mode-e2ee-on-macos) for the full setup guide.
|
||||
See [Matrix Proxy Mode](/user-guide/messaging/matrix#proxy-mode-e2ee-on-macos) for the full setup guide.
|
||||
|
|
|
|||
|
|
@ -34,6 +34,10 @@ python batch_runner.py \
|
|||
python batch_runner.py --list_distributions
|
||||
```
|
||||
|
||||
:::tip Predictable cost at scale
|
||||
Batch runs spin up many concurrent agent sessions, each making model calls and tool calls. A [Nous Portal](/user-guide/features/tool-gateway) subscription bundles model access plus web search, image gen, TTS, and cloud browsers under one bill — useful when you want stable cost-per-trajectory without juggling rate limits across five vendor accounts. Set up with `hermes setup --portal`, then point `--model` at a Nous model.
|
||||
:::
|
||||
|
||||
## Dataset Format
|
||||
|
||||
The input dataset is a JSONL file (one JSON object per line). Each entry must have a `prompt` field:
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ Key capabilities:
|
|||
## Setup
|
||||
|
||||
:::tip Nous Subscribers
|
||||
If you have a paid [Nous Portal](https://portal.nousresearch.com) subscription, you can use browser automation through the **[Tool Gateway](tool-gateway.md)** without any separate API keys. Run `hermes model` or `hermes tools` to enable it.
|
||||
If you have a paid [Nous Portal](https://portal.nousresearch.com) subscription, you can use browser automation through the **[Tool Gateway](tool-gateway.md)** without any separate API keys. New installs can run `hermes setup --portal` to log in and turn on every gateway tool at once; existing installs can pick **Nous Subscription** as the browser provider via `hermes model` or `hermes tools`.
|
||||
:::
|
||||
|
||||
### Browserbase cloud mode
|
||||
|
|
@ -185,6 +185,25 @@ Then set in `~/.hermes/.env`:
|
|||
CAMOFOX_URL=http://localhost:9377
|
||||
```
|
||||
|
||||
If Camofox is running in Docker and you want it to open web apps served from the host machine, enable loopback rewriting. `CAMOFOX_URL` should still point at the host-published control API, but page URLs such as `http://127.0.0.1:3000` must be opened from inside the container as `http://host.docker.internal:3000`:
|
||||
|
||||
```yaml
|
||||
# ~/.hermes/config.yaml
|
||||
browser:
|
||||
camofox:
|
||||
rewrite_loopback_urls: true
|
||||
loopback_host_alias: host.docker.internal # default; use a LAN IP if needed
|
||||
```
|
||||
|
||||
Equivalent env vars:
|
||||
|
||||
```bash
|
||||
CAMOFOX_REWRITE_LOOPBACK_URLS=true
|
||||
CAMOFOX_LOOPBACK_HOST_ALIAS=host.docker.internal
|
||||
```
|
||||
|
||||
The rewrite only applies to page navigation URLs with loopback hosts (`localhost`, `127.0.0.1`, `::1`). It does not change `CAMOFOX_URL`. Leave it disabled for non-Docker Camofox installs, where the browser already runs on the host and loopback URLs are correct.
|
||||
|
||||
Or configure via `hermes tools` → Browser Automation → Camofox.
|
||||
|
||||
When `CAMOFOX_URL` is set, all browser tools automatically route through Camofox instead of Browserbase or agent-browser.
|
||||
|
|
@ -376,9 +395,9 @@ BROWSERBASE_ADVANCED_STEALTH=false
|
|||
# Session reconnection after disconnects — requires paid plan (default: "true")
|
||||
BROWSERBASE_KEEP_ALIVE=true
|
||||
|
||||
# Custom session timeout in milliseconds (default: project default)
|
||||
# Examples: 600000 (10min), 1800000 (30min)
|
||||
BROWSERBASE_SESSION_TIMEOUT=600000
|
||||
# Custom session timeout in seconds (max 21600 = 6 hours) (default: project default)
|
||||
# Examples: 600 (10min), 1800 (30min), 21600 (6h max)
|
||||
BROWSERBASE_SESSION_TIMEOUT=1800
|
||||
|
||||
# Inactivity timeout before auto-cleanup in seconds (default: 120)
|
||||
BROWSER_INACTIVITY_TIMEOUT=120
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ description: "Plugins shipped with Hermes Agent that run automatically via lifec
|
|||
|
||||
Hermes ships a small set of plugins bundled with the repository. They live under `<repo>/plugins/<name>/` and load automatically alongside user-installed plugins in `~/.hermes/plugins/`. They use the same plugin surface as third-party plugins — hooks, tools, slash commands — just maintained in-tree.
|
||||
|
||||
See the [Plugins](/docs/user-guide/features/plugins) page for the general plugin system, and [Build a Hermes Plugin](/docs/guides/build-a-hermes-plugin) to write your own.
|
||||
See the [Plugins](/user-guide/features/plugins) page for the general plugin system, and [Build a Hermes Plugin](/guides/build-a-hermes-plugin) to write your own.
|
||||
|
||||
## How discovery works
|
||||
|
||||
|
|
@ -56,7 +56,10 @@ The repo ships these bundled plugins under `plugins/`. All are opt-in — enable
|
|||
| Plugin | Kind | Purpose |
|
||||
|---|---|---|
|
||||
| `disk-cleanup` | hooks + slash command | Auto-track ephemeral files and clean them on session end |
|
||||
| `security-guidance` | hooks | Pattern-match dangerous code on `write_file`/`patch` and append a security warning (or block) — 25 rules (Apache-2.0 fork of Anthropic's `claude-plugins-official` patterns) |
|
||||
| `observability/langfuse` | hooks | Trace turns / LLM calls / tools to [Langfuse](https://langfuse.com) |
|
||||
| `observability/nemo_relay` | hooks | Relay observability events (turns / LLM calls / tools) to an NVIDIA NeMo endpoint |
|
||||
| `teams_pipeline` | standalone | Microsoft Teams meeting pipeline — Graph-backed, transcript-first meeting summaries |
|
||||
| `spotify` | backend (7 tools) | Native Spotify playback, queue, search, playlists, albums, library |
|
||||
| `google_meet` | standalone | Join Meet calls, live-caption transcription, optional realtime duplex audio |
|
||||
| `image_gen/openai` | image backend | OpenAI `gpt-image-2` image generation backend (alternative to FAL) |
|
||||
|
|
@ -115,20 +118,50 @@ Auto-tracks and removes ephemeral files created during sessions — test scripts
|
|||
|
||||
**Disabling again:** `hermes plugins disable disk-cleanup`.
|
||||
|
||||
### security-guidance
|
||||
|
||||
Fast pattern-matched security warnings on file writes. When the agent's `write_file` / `patch` / `skill_manage` calls carry content matching a known-dangerous code pattern — `pickle.load`, `yaml.load` without `SafeLoader`, `eval(`, `os.system`, `subprocess(..., shell=True)`, JS `child_process.exec`, React `dangerouslySetInnerHTML`, raw `.innerHTML =` / `.outerHTML =` / `document.write`, Node `crypto.createCipher`, AES ECB mode, TLS verification disabled, XXE-prone `xml.etree` / `minidom` parsers, `<script src="//..." >` without SRI, `torch.load` without `weights_only=True`, GitHub Actions `${{ github.event.* }}` injection — the plugin appends a `⚠️ Security guidance` block to the tool's result.
|
||||
|
||||
The file is still written. The model reads the warning in the next turn's tool message and can either fix the code or document why the construct is safe in this context. Pattern matching has a non-trivial false-positive rate, which is why warn (not block) is the default.
|
||||
|
||||
**Coverage:** 25 rules total, covering unsafe deserialization, command injection, XSS sinks, crypto footguns, XXE, supply-chain (SRI), and CI/CD workflow injection. The pattern data is a verbatim Apache-2.0 fork of [Anthropic's `claude-plugins-official`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/security-guidance/hooks) — see the plugin's `LICENSE` and `NOTICE` files for attribution.
|
||||
|
||||
**Modes:**
|
||||
|
||||
| Env var | Effect |
|
||||
|---|---|
|
||||
| (unset) | **warn mode** (default) — file is written, warning appended to result |
|
||||
| `SECURITY_GUIDANCE_BLOCK=1` | **block mode** — write refused, warning returned as the block reason |
|
||||
| `SECURITY_GUIDANCE_DISABLE=1` | kill switch — plugin loads but does nothing |
|
||||
|
||||
**Enabling:** `hermes plugins enable security-guidance` (or check the box in `hermes plugins`).
|
||||
|
||||
**Disabling again:** `hermes plugins disable security-guidance`.
|
||||
|
||||
**What it does not do (yet):** the upstream Anthropic plugin has two more layers — an LLM diff review on each agent turn that touched files, and an agentic commit-time review that traces data flow across files. Neither is ported. The agent can already run those reviews on demand via `delegate_task`.
|
||||
|
||||
### observability/langfuse
|
||||
|
||||
Traces Hermes turns, LLM calls, and tool invocations to [Langfuse](https://langfuse.com) — an open-source LLM observability platform. One span per turn, one generation per API call, one tool observation per tool call. Usage totals, per-type token counts, and cost estimates come out of Hermes' canonical `agent.usage_pricing` numbers, so the Langfuse dashboard sees the same breakdown (input / output / `cache_read_input_tokens` / `cache_creation_input_tokens` / `reasoning_tokens`) that appears in `hermes logs`.
|
||||
|
||||
The plugin is fail-open: no SDK installed, no credentials, or a transient Langfuse error — all turn into a silent no-op in the hook. The agent loop is never impacted.
|
||||
|
||||
**Setup:**
|
||||
**Setup (interactive — recommended):**
|
||||
|
||||
```bash
|
||||
hermes tools # → Langfuse Observability → Cloud or Self-Hosted
|
||||
```
|
||||
|
||||
The wizard collects your keys, `pip install`s the `langfuse` SDK, and adds `observability/langfuse` to `plugins.enabled` for you. Restart Hermes and the next turn ships a trace.
|
||||
|
||||
**Setup (manual):**
|
||||
|
||||
```bash
|
||||
pip install langfuse
|
||||
hermes plugins enable observability/langfuse
|
||||
```
|
||||
|
||||
Or check the box in the interactive `hermes plugins` UI. Then put the credentials in `~/.hermes/.env`:
|
||||
Then put the credentials in `~/.hermes/.env`:
|
||||
|
||||
```bash
|
||||
HERMES_LANGFUSE_PUBLIC_KEY=pk-lf-...
|
||||
|
|
@ -253,7 +286,7 @@ Adds a **Steam-style achievements tab to the dashboard** — 60+ collectible, ti
|
|||
|
||||
## Adding a bundled plugin
|
||||
|
||||
Bundled plugins are written exactly like any other Hermes plugin — see [Build a Hermes Plugin](/docs/guides/build-a-hermes-plugin). The only differences are:
|
||||
Bundled plugins are written exactly like any other Hermes plugin — see [Build a Hermes Plugin](/guides/build-a-hermes-plugin). The only differences are:
|
||||
|
||||
- Directory lives at `<repo>/plugins/<name>/` instead of `~/.hermes/plugins/<name>/`
|
||||
- Manifest source is reported as `bundled` in `hermes plugins list`
|
||||
|
|
|
|||
|
|
@ -217,7 +217,63 @@ terminal:
|
|||
- ANOTHER_TOKEN
|
||||
```
|
||||
|
||||
See the [Security guide](/docs/user-guide/security#environment-variable-passthrough) for full details.
|
||||
See the [Security guide](/user-guide/security#environment-variable-passthrough) for full details.
|
||||
|
||||
### `HERMES_*` variables in the child
|
||||
|
||||
The child process receives only a small, fixed set of operational `HERMES_*`
|
||||
variables by exact name:
|
||||
|
||||
- `HERMES_HOME`
|
||||
- `HERMES_PROFILE`
|
||||
- `HERMES_CONFIG`
|
||||
- `HERMES_ENV`
|
||||
|
||||
(plus `HERMES_RPC_DIR` / `HERMES_RPC_SOCKET` / `TZ` / `HOME`, which Hermes
|
||||
injects explicitly so the RPC channel works).
|
||||
|
||||
:::note Behavior change
|
||||
Earlier versions passed **any** variable whose name began with `HERMES_`
|
||||
through to the child. That broad prefix was removed for security hardening: it
|
||||
could leak `HERMES_*`-named configuration that doesn't match a secret substring
|
||||
(for example `HERMES_BASE_URL`, `HERMES_KANBAN_DB`, or a `HERMES_*_WEBHOOK`
|
||||
endpoint) into arbitrary sandboxed code.
|
||||
|
||||
If an `execute_code` script — or a repo/plugin module it imports at import time
|
||||
— relied on a `HERMES_*` variable outside the four operational names above, it
|
||||
will now find that variable **unset** in the child. The drop is intentional,
|
||||
not a bug.
|
||||
:::
|
||||
|
||||
**Workaround — opt the variable back in explicitly.** Both routes pass the
|
||||
variable through `execute_code` *and* `terminal` children, and neither weakens
|
||||
the secret-stripping guarantee (Hermes-managed provider credentials can never
|
||||
be re-allowed this way):
|
||||
|
||||
1. **Per-machine, in `config.yaml`** — add the exact variable name to the
|
||||
passthrough allowlist:
|
||||
|
||||
```yaml
|
||||
terminal:
|
||||
env_passthrough:
|
||||
- HERMES_KANBAN_DB
|
||||
- HERMES_BASE_URL
|
||||
```
|
||||
|
||||
2. **Per-skill, in the skill's frontmatter** — declare it so it is registered
|
||||
automatically whenever that skill is loaded:
|
||||
|
||||
```yaml
|
||||
required_environment_variables:
|
||||
- HERMES_KANBAN_DB
|
||||
```
|
||||
|
||||
**Diagnosing it.** When the child drops one or more non-allowlisted `HERMES_*`
|
||||
variables, Hermes emits a one-line `debug` log naming them and pointing at the
|
||||
`env_passthrough` escape hatch. Run with debug logging (`hermes logs --level
|
||||
DEBUG`, or check `~/.hermes/logs/agent.log`) and look for
|
||||
`execute_code: dropped N non-allowlisted HERMES_* var(s)` if a script behaves
|
||||
as though a `HERMES_*` variable is missing.
|
||||
|
||||
Hermes always writes the script and the auto-generated `hermes_tools.py` RPC stub into a temp staging directory that is cleaned up after execution. In `strict` mode the script also *runs* there; in `project` mode it runs in the session's working directory (the staging directory stays on `PYTHONPATH` so imports still resolve). The child process runs in its own process group so it can be cleanly killed on timeout or interruption.
|
||||
|
||||
|
|
@ -231,7 +287,7 @@ Hermes always writes the script and the auto-generated `hermes_tools.py` RPC stu
|
|||
| Running a build or test suite | ❌ | ✅ |
|
||||
| Looping over search results | ✅ | ❌ |
|
||||
| Interactive/background processes | ❌ | ✅ |
|
||||
| Needs API keys in environment | ⚠️ Only via [passthrough](/docs/user-guide/security#environment-variable-passthrough) | ✅ (most pass through) |
|
||||
| Needs API keys in environment | ⚠️ Only via [passthrough](/user-guide/security#environment-variable-passthrough) | ✅ (most pass through) |
|
||||
|
||||
**Rule of thumb:** Use `execute_code` when you need to call Hermes tools programmatically with logic between calls. Use `terminal` for running shell commands, builds, and processes.
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,10 @@ Hermes can optionally hand `openai/*` and `openai-codex/*` turns to the [Codex C
|
|||
|
||||
This is **opt-in only**. Default Hermes behavior is unchanged unless you flip the flag. Hermes never auto-routes you onto this runtime.
|
||||
|
||||
:::tip
|
||||
Not using OpenAI Codex? `hermes setup --portal` configures a non-Codex backend with Claude/Gemini/etc. in one step. See [Nous Portal](/integrations/nous-portal).
|
||||
:::
|
||||
|
||||
## Why
|
||||
|
||||
- Run OpenAI agent turns against your **ChatGPT subscription** (no API key required) using the same auth flow Codex CLI uses.
|
||||
|
|
@ -253,10 +257,10 @@ auxiliary:
|
|||
title_generation:
|
||||
provider: openrouter
|
||||
model: google/gemini-3-flash-preview
|
||||
context_compression:
|
||||
compression:
|
||||
provider: openrouter
|
||||
model: google/gemini-3-flash-preview
|
||||
vision_detect:
|
||||
vision:
|
||||
provider: openrouter
|
||||
model: google/gemini-3-flash-preview
|
||||
goal_judge:
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
---
|
||||
title: Computer Use
|
||||
sidebar_position: 16
|
||||
---
|
||||
|
||||
# Computer Use (macOS)
|
||||
|
||||
Hermes Agent can drive your Mac's desktop — clicking, typing, scrolling,
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ This is a Next.js 14 web application with a Python FastAPI backend.
|
|||
|
||||
## SOUL.md
|
||||
|
||||
`SOUL.md` controls the agent's personality, tone, and communication style. See the [Personality](/docs/user-guide/features/personality) page for full details.
|
||||
`SOUL.md` controls the agent's personality, tone, and communication style. See the [Personality](/user-guide/features/personality) page for full details.
|
||||
|
||||
**Location:**
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,10 @@ Credential pools let you register multiple API keys or OAuth tokens for the same
|
|||
|
||||
This is different from [fallback providers](./fallback-providers.md), which switch to a *different* provider entirely. Credential pools are same-provider rotation; fallback providers are cross-provider failover. Pools are tried first — if all pool keys are exhausted, *then* the fallback provider activates.
|
||||
|
||||
:::tip
|
||||
Credential pools are mainly for API-key providers (OpenRouter, Anthropic). A single [Nous Portal](/integrations/nous-portal) OAuth covers 300+ models, so most users don't need a pool when on Portal.
|
||||
:::
|
||||
|
||||
## How It Works
|
||||
|
||||
```
|
||||
|
|
@ -18,8 +22,11 @@ Your request
|
|||
→ Pick key from pool (round_robin / least_used / fill_first / random)
|
||||
→ Send to provider
|
||||
→ 429 rate limit?
|
||||
→ Retry same key once (transient blip)
|
||||
→ Second 429 → rotate to next pool key
|
||||
→ Plan/usage limit reached (e.g. ChatGPT/Codex "usage limit reached")?
|
||||
→ Rotate to next pool key immediately (no retry — the cap won't clear on retry)
|
||||
→ Generic / transient 429?
|
||||
→ Retry same key once (transient blip)
|
||||
→ Second 429 → rotate to next pool key
|
||||
→ All keys exhausted → fallback_model (different provider)
|
||||
→ 402 billing error?
|
||||
→ Immediately rotate to next pool key (24h cooldown)
|
||||
|
|
@ -179,6 +186,8 @@ Hermes automatically discovers credentials from multiple sources and seeds the p
|
|||
|
||||
Auto-seeded entries are updated on each pool load — if you remove an env var, its pool entry is automatically pruned. Manual entries (added via `hermes auth add`) are never auto-pruned.
|
||||
|
||||
Borrowed runtime secrets (for example env vars, Bitwarden/Vault/keyring/systemd references, and custom config values) are reference-only at the `auth.json` boundary. Hermes can use the resolved value in memory for the current run, but it persists only metadata such as the source ref, label, status, request counters, and a non-reversible fingerprint. Manual entries and Hermes-owned OAuth/device-code state keep the durable tokens they need to refresh.
|
||||
|
||||
## Delegation & Subagent Sharing
|
||||
|
||||
When the agent spawns subagents via `delegate_task`, the parent's credential pool is automatically shared with children:
|
||||
|
|
@ -219,15 +228,28 @@ Pool state is stored in `~/.hermes/auth.json` under the `credential_pool` key:
|
|||
"auth_type": "api_key",
|
||||
"priority": 0,
|
||||
"source": "env:OPENROUTER_API_KEY",
|
||||
"access_token": "sk-or-v1-...",
|
||||
"secret_source": "bitwarden",
|
||||
"secret_fingerprint": "sha256:12ab34cd56ef7890",
|
||||
"last_status": "ok",
|
||||
"request_count": 142
|
||||
}
|
||||
],
|
||||
"anthropic": [
|
||||
{
|
||||
"id": "manual1",
|
||||
"label": "personal-api-key",
|
||||
"auth_type": "api_key",
|
||||
"priority": 0,
|
||||
"source": "manual",
|
||||
"access_token": "sk-ant-api03-..."
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The OpenRouter entry above was borrowed from an external source, so the raw key is not stored in `auth.json`. The manual Anthropic entry was intentionally added to Hermes' credential store, so its token remains persistable.
|
||||
|
||||
Strategies are stored in `config.yaml` (not `auth.json`):
|
||||
|
||||
```yaml
|
||||
|
|
|
|||
|
|
@ -21,6 +21,10 @@ Cron jobs can:
|
|||
|
||||
All of this is available to Hermes itself through the `cronjob` tool, so you can create, pause, edit, and remove jobs by asking in plain language — no CLI required.
|
||||
|
||||
:::tip
|
||||
Cron jobs use whatever provider `hermes model` selected. `hermes setup --portal` is the lowest-friction option for unattended runs since OAuth refresh is automatic. See [Nous Portal](/integrations/nous-portal).
|
||||
:::
|
||||
|
||||
:::warning
|
||||
Cron-run sessions cannot recursively create more cron jobs. Hermes disables cron management tools inside cron executions to prevent runaway scheduling loops.
|
||||
:::
|
||||
|
|
@ -113,12 +117,12 @@ cronjob(
|
|||
When `workdir` is set:
|
||||
|
||||
- `AGENTS.md`, `CLAUDE.md`, and `.cursorrules` from that directory are injected into the system prompt (same discovery order as the interactive CLI)
|
||||
- `terminal`, `read_file`, `write_file`, `patch`, `search_files`, and `execute_code` all use that directory as their working directory (via `TERMINAL_CWD`)
|
||||
- `terminal`, `read_file`, `write_file`, `patch`, `search_files`, and `execute_code` all use that directory as their working directory
|
||||
- The path must be an absolute directory that exists — relative paths and missing directories are rejected at create / update time
|
||||
- Pass `--workdir ""` (or `workdir=""` via the tool) on edit to clear it and restore the old behaviour
|
||||
|
||||
:::note Serialization
|
||||
Jobs with a `workdir` run sequentially on the scheduler tick, not in the parallel pool. This is deliberate — `TERMINAL_CWD` is process-global, so two workdir jobs running at the same time would corrupt each other's cwd. Workdir-less jobs still run in parallel as before.
|
||||
Jobs with a `workdir` run sequentially on the scheduler tick, not in the parallel pool. This is deliberate: the cron worker applies the job workdir through process-global terminal state, so two workdir jobs running at the same time would corrupt each other's cwd. Workdir-less jobs still run in parallel as before.
|
||||
:::
|
||||
|
||||
## Running cron jobs in a specific profile
|
||||
|
|
@ -204,10 +208,11 @@ Cron jobs now have a fuller lifecycle than just create/remove.
|
|||
|
||||
```bash
|
||||
hermes cron list
|
||||
hermes cron pause <job_id>
|
||||
hermes cron resume <job_id>
|
||||
hermes cron run <job_id>
|
||||
hermes cron remove <job_id>
|
||||
hermes cron pause <job_id_or_name>
|
||||
hermes cron resume <job_id_or_name>
|
||||
hermes cron run <job_id_or_name>
|
||||
hermes cron remove <job_id_or_name>
|
||||
hermes cron edit <job_id_or_name> [...flags]
|
||||
hermes cron status
|
||||
hermes cron tick
|
||||
```
|
||||
|
|
@ -218,6 +223,9 @@ What they do:
|
|||
- `resume` — re-enable the job and compute the next future run
|
||||
- `run` — trigger the job on the next scheduler tick
|
||||
- `remove` — delete it entirely
|
||||
- `edit` — modify schedule, prompt, profile, delivery, etc.
|
||||
|
||||
**Name-based lookup.** All four mutating verbs (`pause`, `resume`, `run`, `remove`, `edit`) plus the agent's `cronjob` tool now accept a job **name** (case-insensitive) in place of the hex ID. The agent and CLI both prefer an exact ID match if one exists; ambiguous name matches (multiple jobs sharing the same name) are refused with the full list of candidate IDs so you can pick one explicitly. Names are not unique, so this guard is load-bearing — it prevents silently mutating the wrong job when two share a name.
|
||||
|
||||
## How it works
|
||||
|
||||
|
|
@ -384,7 +392,7 @@ cronjob(action="create", schedule="every 5m",
|
|||
|
||||
It picks `no_agent=True` automatically when the message content is fully determined by the script (watchdogs, threshold alerts, heartbeats). The same tool also lets the agent pause, resume, edit, and remove jobs — so the whole lifecycle is chat-driven without anyone touching the CLI.
|
||||
|
||||
See the [Script-Only Cron Jobs guide](/docs/guides/cron-script-only) for worked examples.
|
||||
See the [Script-Only Cron Jobs guide](/guides/cron-script-only) for worked examples.
|
||||
|
||||
## Chaining jobs with `context_from`
|
||||
|
||||
|
|
@ -446,7 +454,7 @@ Outputs are concatenated in the order listed.
|
|||
Cron jobs inherit your configured fallback providers and credential pool rotation. If the primary API key is rate-limited or the provider returns an error, the cron agent can:
|
||||
|
||||
- **Fall back to an alternate provider** if you have `fallback_providers` (or the legacy `fallback_model`) configured in `config.yaml`
|
||||
- **Rotate to the next credential** in your [credential pool](/docs/user-guide/configuration#credential-pool-strategies) for the same provider
|
||||
- **Rotate to the next credential** in your [credential pool](/user-guide/configuration#credential-pool-strategies) for the same provider
|
||||
|
||||
This means cron jobs that run at high frequency or during peak hours are more resilient — a single rate-limited key won't fail the entire run.
|
||||
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ description: "Background maintenance for agent-created skills — usage tracking
|
|||
|
||||
The curator is a background maintenance pass for **agent-created skills**. It tracks how often each skill is viewed, used, and patched, moves long-unused skills through `active → stale → archived` states, and periodically spawns a short auxiliary-model review that proposes consolidations or patches drift.
|
||||
|
||||
It exists so that skills created via the [self-improvement loop](/docs/user-guide/features/skills#agent-managed-skills-skill_manage-tool) don't pile up forever. Every time the agent solves a novel problem and saves a skill, that skill lands in `~/.hermes/skills/`. Without maintenance, you end up with dozens of narrow near-duplicates that pollute the catalog and waste tokens.
|
||||
It exists so that skills created via the [self-improvement loop](/user-guide/features/skills#agent-managed-skills-skill_manage-tool) don't pile up forever. Every time the agent solves a novel problem and saves a skill, that skill lands in `~/.hermes/skills/`. Without maintenance, you end up with dozens of narrow near-duplicates that pollute the catalog and waste tokens.
|
||||
|
||||
The curator **never touches** bundled skills (shipped with the repo) or hub-installed skills (from [agentskills.io](https://agentskills.io)). It only reviews skills the agent itself authored. It also **never auto-deletes** — the worst outcome is archival into `~/.hermes/skills/.archive/`, which is recoverable.
|
||||
By default (`prune_builtins: true`) the curator can archive **unused bundled built-in skills** (shipped with the repo) after `archive_after_days` of non-use, alongside the agent-created skills it primarily manages. Hub-installed skills (from [agentskills.io](https://agentskills.io)) are always off-limits. Set `curator.prune_builtins: false` to restore the old agent-created-only behavior, where bundled skills are never touched. The curator also **never auto-deletes** — the worst outcome is archival into `~/.hermes/skills/.archive/`, which is recoverable.
|
||||
|
||||
Tracks [issue #7816](https://github.com/NousResearch/hermes-agent/issues/7816).
|
||||
|
||||
|
|
@ -32,7 +32,7 @@ If you want to see what the curator *would* do before it runs for real, run `her
|
|||
A run has two phases:
|
||||
|
||||
1. **Automatic transitions** (deterministic, no LLM). Skills unused for `stale_after_days` (30) become `stale`; skills unused for `archive_after_days` (90) are moved to `~/.hermes/skills/.archive/`.
|
||||
2. **LLM review** (single aux-model pass, `max_iterations=8`). The forked agent surveys the agent-created skills, can read any of them with `skill_view`, and decides per-skill whether to keep, patch (via `skill_manage`), consolidate overlapping ones, or archive via the terminal tool.
|
||||
2. **LLM review** (single aux-model pass, `max_iterations=8`). The forked agent surveys the agent-created skills, can read any of them with `skill_view`, and decides per-skill whether to keep, patch (via `skill_manage`), consolidate overlapping ones, or archive via the terminal tool. Consolidation treats a skill as a full package: if a skill has `references/`, `templates/`, `scripts/`, `assets/`, or relative links to those paths, the curator must either keep it standalone, re-home the needed support files and rewrite paths, or archive the entire package unchanged — not flatten only `SKILL.md` into another skill's `references/` file.
|
||||
|
||||
Pinned skills are off-limits to both the curator's auto-transitions and the agent's own `skill_manage` tool. See [Pinning a skill](#pinning-a-skill) below.
|
||||
|
||||
|
|
@ -47,6 +47,7 @@ curator:
|
|||
min_idle_hours: 2
|
||||
stale_after_days: 30
|
||||
archive_after_days: 90
|
||||
prune_builtins: true # archive unused bundled built-in skills too (hub skills always exempt)
|
||||
```
|
||||
|
||||
To disable entirely, set `curator.enabled: false`.
|
||||
|
|
@ -97,6 +98,9 @@ hermes curator resume
|
|||
hermes curator pin <skill> # never auto-transition this skill
|
||||
hermes curator unpin <skill>
|
||||
hermes curator restore <skill> # move an archived skill back to active
|
||||
hermes curator list-archived # list skills currently in ~/.hermes/skills/.archive/
|
||||
hermes curator archive <skill> # manually archive a single skill now
|
||||
hermes curator prune [--days N] # bulk-archive agent-created skills idle >= N days (default 90)
|
||||
```
|
||||
|
||||
## Backups and rollback
|
||||
|
|
@ -130,30 +134,45 @@ The same subcommands are available as the `/curator` slash command inside a runn
|
|||
|
||||
## What "agent-created" means
|
||||
|
||||
A skill is considered agent-created if its name is **not** in:
|
||||
The curator only manages skills explicitly marked as **agent-created** in
|
||||
`~/.hermes/skills/.usage.json`. A skill qualifies when ALL of the following
|
||||
are true:
|
||||
|
||||
- `~/.hermes/skills/.bundled_manifest` (skills copied from the repo on install), and
|
||||
- `~/.hermes/skills/.hub/lock.json` (skills installed via `hermes skills install`).
|
||||
1. Its name is **not** in `~/.hermes/skills/.bundled_manifest` (bundled skills shipped with the repo).
|
||||
2. Its name is **not** in `~/.hermes/skills/.hub/lock.json` (hub-installed skills).
|
||||
3. Its `.usage.json` entry has `"created_by": "agent"` or `"agent_created": true`.
|
||||
|
||||
Everything else in `~/.hermes/skills/` is fair game for the curator. This includes:
|
||||
Currently, only the **background self-improvement review fork** sets this marker
|
||||
— when it creates a new umbrella skill during its periodic review pass (~every 10
|
||||
agent turns). The background fork runs with a write origin of `"background_review"`
|
||||
(via `tools/skill_provenance.py`), which is the only path that triggers the
|
||||
`mark_agent_created()` call in `skill_manage`.
|
||||
|
||||
- Skills the agent saved via `skill_manage(action="create")` during a conversation.
|
||||
- Skills you created manually with a hand-written `SKILL.md`.
|
||||
- Skills added via external skill directories you've pointed Hermes at.
|
||||
Skills the foreground agent creates via `skill_manage(action="create")` during a
|
||||
conversation are **not** marked as agent-created — they are considered
|
||||
user-directed and the curator intentionally leaves them alone.
|
||||
|
||||
:::warning Your hand-written skills look the same as agent-saved ones
|
||||
Provenance here is **binary** (bundled/hub vs. everything else). The curator cannot tell a hand-authored skill you rely on for private workflows apart from a skill the self-improvement loop saved mid-session. Both land in the "agent-created" bucket.
|
||||
:::warning Your hand-written skills are NOT curated
|
||||
If you manually created a `SKILL.md` or pointed Hermes at an external skill
|
||||
directory, that skill will have a `.usage.json` entry with `created_by: null`
|
||||
(or the field absent). The curator will not touch it. The same applies to
|
||||
skills the foreground agent created at your request.
|
||||
|
||||
Before the first real pass (7 days after installation by default), take a moment to:
|
||||
|
||||
1. Run `hermes curator run --dry-run` to see exactly what the curator would propose.
|
||||
2. Use `hermes curator pin <name>` to fence off anything you don't want touched.
|
||||
3. Or set `curator.enabled: false` in `config.yaml` if you'd rather manage the library yourself.
|
||||
|
||||
Archives are always recoverable via `hermes curator restore <name>`, but it's easier to pin up-front than to chase down a consolidation after the fact.
|
||||
**To see which skills the curator actually manages**, run `hermes curator status`.
|
||||
If the agent-created count is 0, no skills are currently in the curator's
|
||||
jurisdiction — the LLM review pass is skipped and the report will show
|
||||
`Model: (not resolved) via (not resolved)` with `Duration: 0s`.
|
||||
:::
|
||||
|
||||
If you want to protect a specific skill from ever being touched — for example a hand-authored skill you rely on — use `hermes curator pin <name>`. See the next section.
|
||||
Skills that ARE agent-created follow the full lifecycle:
|
||||
|
||||
- `active` → (30d unused) `stale` → (90d unused) `archived`
|
||||
- Pinned skills bypass all auto-transitions
|
||||
- Archives are recoverable via `hermes curator restore <name>`
|
||||
|
||||
If you want to protect a specific skill from ever being touched — for example a
|
||||
hand-authored skill you rely on — use `hermes curator pin <name>`. See the next
|
||||
section.
|
||||
|
||||
## Pinning a skill
|
||||
|
||||
|
|
@ -171,7 +190,9 @@ hermes curator unpin <skill>
|
|||
|
||||
The flag is stored as `"pinned": true` on the skill's entry in `~/.hermes/skills/.usage.json`, so it survives across sessions.
|
||||
|
||||
Only **agent-created** skills can be pinned — bundled and hub-installed skills are never subject to curator mutation in the first place, and `hermes curator pin` will refuse with an explanatory message if you try.
|
||||
Only **agent-created** skills can be pinned — `hermes curator pin` refuses on bundled and hub-installed skills with an explanatory message if you try. Hub-installed skills are never subject to curator mutation. Bundled built-in skills are only touched when `curator.prune_builtins: true` (the default), and even then only archived after `archive_after_days` of non-use — never patched, consolidated, or deleted. Set `curator.prune_builtins: false` to exempt bundled skills entirely.
|
||||
|
||||
A small set of **protected built-ins** is hardcoded as never-archivable and never-consolidatable, regardless of `curator.prune_builtins`, pin state, or LLM judgment. These back load-bearing UX — for example, `plan` powers the `/plan` slash-command flow — so silently archiving one would turn its slash command into an "Unknown command" error with no signal to you. Protected built-ins are filtered out of the curator's candidate list entirely, so the consolidation pass never sees them.
|
||||
|
||||
If you want a stronger guarantee than "no deletion" — for instance, freezing a skill's content entirely while the agent still reads it — edit `~/.hermes/skills/<name>/SKILL.md` directly with your editor. The pin guards tool-driven deletion, not your own filesystem access.
|
||||
|
||||
|
|
@ -217,6 +238,15 @@ Every curator run writes a timestamped directory under `~/.hermes/logs/curator/`
|
|||
|
||||
`REPORT.md` is a quick way to see what a given run did — which skills transitioned, what the LLM reviewer said, which skills it patched. Good for auditing without having to grep `agent.log`.
|
||||
|
||||
:::note No candidates? Report shows `(not resolved)`
|
||||
When the curator has **no agent-created skills** to review, the LLM review pass
|
||||
is skipped entirely. The report header will show
|
||||
`Model: (not resolved) via (not resolved)` with `Duration: 0s` — this does **not**
|
||||
indicate a configuration error or model resolution failure. It simply means there
|
||||
were no candidates, so no model was ever invoked. The auto-transition phase still
|
||||
runs and reports its counts normally.
|
||||
:::
|
||||
|
||||
### Rename map in the summary
|
||||
|
||||
If a run consolidated multiple skills under an umbrella (or merged near-duplicates), the user-visible summary printed at the end of the run includes an explicit rename map showing every `old-name → new-name` pair the curator applied. This is in addition to per-skill transition lines, so when a wave of renames lands you can spot them at a glance without diffing the JSON report. The hint also surfaces under `hermes curator pin` so you can pin the umbrella name immediately if you want to lock the new label in.
|
||||
|
|
@ -242,7 +272,7 @@ The curator also refuses to run if `min_idle_hours` hasn't elapsed, so on an act
|
|||
|
||||
## See also
|
||||
|
||||
- [Skills System](/docs/user-guide/features/skills) — how skills work in general and the self-improvement loop that creates them
|
||||
- [Memory](/docs/user-guide/features/memory) — a parallel background review that maintains long-term memory
|
||||
- [Bundled Skills Catalog](/docs/reference/skills-catalog)
|
||||
- [Skills System](/user-guide/features/skills) — how skills work in general and the self-improvement loop that creates them
|
||||
- [Memory](/user-guide/features/memory) — a parallel background review that maintains long-term memory
|
||||
- [Bundled Skills Catalog](/reference/skills-catalog)
|
||||
- [Issue #7816](https://github.com/NousResearch/hermes-agent/issues/7816) — original proposal and design discussion
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ The TUI ships a `/agents` overlay (alias `/tasks`) that turns recursive `delegat
|
|||
- Kill and pause controls — cancel a specific subagent mid-flight without interrupting its siblings
|
||||
- Post-hoc review: step through each subagent's turn-by-turn history even after they've returned to the parent
|
||||
|
||||
The classic CLI just prints `/agents` as a text summary; the TUI is where the overlay shines. See [TUI — Slash commands](/docs/user-guide/tui#slash-commands).
|
||||
The classic CLI just prints `/agents` as a text summary; the TUI is where the overlay shines. See [TUI — Slash commands](/user-guide/tui#slash-commands).
|
||||
|
||||
## Depth Limit and Nested Orchestration
|
||||
|
||||
|
|
@ -214,7 +214,7 @@ delegate_task(
|
|||
```
|
||||
|
||||
- `role="leaf"` (default): child cannot delegate further — identical to the flat-delegation behavior.
|
||||
- `role="orchestrator"`: child retains the `delegation` toolset. Gated by `delegation.max_spawn_depth` (default **1** = flat, so `role="orchestrator"` is a no-op at defaults). Raise `max_spawn_depth` to 2 to allow orchestrator children to spawn leaf grandchildren; 3 for three levels (cap).
|
||||
- `role="orchestrator"`: child retains the `delegation` toolset. Gated by `delegation.max_spawn_depth` (default **1** = flat, so `role="orchestrator"` is a no-op at defaults). Raise `max_spawn_depth` to 2 to allow orchestrator children to spawn leaf grandchildren; 3+ for deeper trees. There is no upper ceiling — cost is the practical limit.
|
||||
- `delegation.orchestrator_enabled: false`: global kill switch that forces every child to `leaf` regardless of the `role` parameter.
|
||||
|
||||
**Cost warning:** With `max_spawn_depth: 3` and `max_concurrent_children: 3`, the tree can reach 3×3×3 = 27 concurrent leaf agents. Each extra level multiplies spend — raise `max_spawn_depth` intentionally.
|
||||
|
|
@ -264,7 +264,7 @@ For **durable long-running work** that must survive interrupts or outlive the cu
|
|||
delegation:
|
||||
max_iterations: 50 # Max turns per child (default: 50)
|
||||
# max_concurrent_children: 3 # Parallel children per batch (default: 3)
|
||||
# max_spawn_depth: 1 # Tree depth (1-3, default 1 = flat). Raise to 2 to allow orchestrator children to spawn leaves; 3 for three levels.
|
||||
# max_spawn_depth: 1 # Tree depth (floor 1, no ceiling, default 1 = flat). Raise to 2 to allow orchestrator children to spawn leaves; 3+ for deeper trees.
|
||||
# orchestrator_enabled: true # Disable to force all children to leaf role.
|
||||
model: "google/gemini-3-flash-preview" # Optional provider/model override
|
||||
provider: "openrouter" # Optional built-in provider
|
||||
|
|
|
|||
|
|
@ -63,8 +63,10 @@ personality entry that biases toward artifact-style replies on
|
|||
messaging platforms.
|
||||
|
||||
**Project-level:** add the bias to `AGENTS.md` / `CLAUDE.md` /
|
||||
`.cursorrules` in a project the agent works from, or to your global
|
||||
custom instructions in `~/.hermes/config.yaml` under `agent.custom_instructions`.
|
||||
`.cursorrules` in a project the agent works from, to your global
|
||||
persona in `~/.hermes/SOUL.md`, or as a named preset under
|
||||
`agent.personalities` in `~/.hermes/config.yaml` (switchable per session
|
||||
via `/personality`).
|
||||
|
||||
The mechanic the agent has to use is simple: render the file to an
|
||||
absolute path (e.g. `/tmp/q3-revenue.png`) and mention that path as
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ All three are **drop-in at runtime**: no repo clone, no `npm run build`, no patc
|
|||
If you just want to use the dashboard, see [Web Dashboard](./web-dashboard). If you want to reskin the terminal CLI (not the web dashboard), see [Skins & Themes](./skins) — the CLI skin system is unrelated to dashboard themes.
|
||||
|
||||
:::note How the pieces compose
|
||||
Themes and plugins are independent but synergistic. A theme can stand alone (just a YAML file). A plugin can stand alone (just a tab). Together they let you build a complete visual reskin with custom HUDs — the bundled `strike-freedom-cockpit` demo does exactly that. See [Combined theme + plugin demo](#combined-theme--plugin-demo).
|
||||
Themes and plugins are independent but synergistic. A theme can stand alone (just a YAML file). A plugin can stand alone (just a tab). Together they let you build a complete visual reskin with custom HUDs — the example `strike-freedom-cockpit` demo (lives in the `hermes-example-plugins` companion repo — see [Combined theme + plugin demo](#combined-theme--plugin-demo) for install steps) does exactly that.
|
||||
:::
|
||||
|
||||
---
|
||||
|
|
@ -131,6 +131,22 @@ typography:
|
|||
letterSpacing: "0.04em"
|
||||
```
|
||||
|
||||
##### Changing the font from the UI (no YAML)
|
||||
|
||||
The theme picker in the dashboard header has a **Font** section below the
|
||||
theme list. Pick any font there and it overrides the body font of whatever
|
||||
theme is active — the choice is independent of the theme and persists across
|
||||
theme switches (stored in `config.yaml` under `dashboard.font`). Choose
|
||||
**Theme default** to clear the override and fall back to the active theme's
|
||||
own `fontSans`.
|
||||
|
||||
The picker offers a curated catalog (system stacks plus a set of Google-Fonts
|
||||
families across sans / serif / mono). It deliberately does **not** accept a
|
||||
free-text font URL — the font's stylesheet is injected as a `<link>`, so the
|
||||
catalog keeps the injected origins fixed. For a fully custom face, set
|
||||
`fontSans` + `fontUrl` in a theme YAML as shown above. The theme's `fontMono`
|
||||
(code blocks, terminal) is always left untouched by the UI override.
|
||||
|
||||
#### Layout
|
||||
|
||||
| Key | Values | Description |
|
||||
|
|
|
|||
|
|
@ -29,27 +29,26 @@ hermes fallback
|
|||
|
||||
`hermes fallback` reuses the provider picker from `hermes model` — same provider list, same credential prompts, same validation. Use the subcommands `add`, `list` (alias `ls`), `remove` (alias `rm`), and `clear` to manage the chain. Changes persist under the top-level `fallback_providers:` list in `config.yaml`.
|
||||
|
||||
If you'd rather edit the YAML directly, add a `fallback_model` section to `~/.hermes/config.yaml`:
|
||||
If you'd rather edit the YAML directly, add a top-level `fallback_providers` list to `~/.hermes/config.yaml`:
|
||||
|
||||
```yaml
|
||||
fallback_model:
|
||||
provider: openrouter
|
||||
model: anthropic/claude-sonnet-4
|
||||
fallback_providers:
|
||||
- provider: openrouter
|
||||
model: anthropic/claude-sonnet-4
|
||||
```
|
||||
|
||||
Both `provider` and `model` are **required**. If either is missing, the fallback is disabled.
|
||||
Each entry requires both `provider` and `model`. Entries missing either field are ignored.
|
||||
|
||||
:::note `fallback_model` vs `fallback_providers`
|
||||
`fallback_model` (singular) is the legacy single-fallback key — Hermes still honors it for back-compat. `fallback_providers` (plural, list) supports multiple fallbacks tried in order; `hermes fallback` writes to this key. When both are set, Hermes merges them with `fallback_providers` taking priority.
|
||||
`fallback_providers` (plural, list) is the current config shape and supports multiple fallbacks tried in order. `fallback_model` (singular) is the legacy single-fallback key — Hermes still honors it for back-compat, but `hermes fallback` writes the current `fallback_providers` key and migrates legacy config on write. When both are set, `fallback_providers` takes priority.
|
||||
:::
|
||||
|
||||
### Supported Providers
|
||||
|
||||
| Provider | Value | Requirements |
|
||||
|----------|-------|-------------|
|
||||
| AI Gateway | `ai-gateway` | `AI_GATEWAY_API_KEY` |
|
||||
| OpenRouter | `openrouter` | `OPENROUTER_API_KEY` |
|
||||
| Nous Portal | `nous` | `hermes auth` (OAuth) |
|
||||
| Nous Portal | `nous` | `hermes setup --portal` (fresh) or `hermes auth add nous` (OAuth) |
|
||||
| OpenAI Codex | `openai-codex` | `hermes model` (ChatGPT OAuth) |
|
||||
| GitHub Copilot | `copilot` | `COPILOT_GITHUB_TOKEN`, `GH_TOKEN`, or `GITHUB_TOKEN` |
|
||||
| GitHub Copilot ACP | `copilot-acp` | External process (editor integration) |
|
||||
|
|
@ -91,11 +90,11 @@ Both `provider` and `model` are **required**. If either is missing, the fallback
|
|||
For a custom OpenAI-compatible endpoint, add `base_url` and optionally `key_env`:
|
||||
|
||||
```yaml
|
||||
fallback_model:
|
||||
provider: custom
|
||||
model: my-local-model
|
||||
base_url: http://localhost:8000/v1
|
||||
key_env: MY_LOCAL_KEY # env var name containing the API key
|
||||
fallback_providers:
|
||||
- provider: custom
|
||||
model: my-local-model
|
||||
base_url: http://localhost:8000/v1
|
||||
key_env: MY_LOCAL_KEY # env var name containing the API key
|
||||
```
|
||||
|
||||
### When Fallback Triggers
|
||||
|
|
@ -129,9 +128,9 @@ model:
|
|||
provider: anthropic
|
||||
default: claude-sonnet-4-6
|
||||
|
||||
fallback_model:
|
||||
provider: openrouter
|
||||
model: anthropic/claude-sonnet-4
|
||||
fallback_providers:
|
||||
- provider: openrouter
|
||||
model: anthropic/claude-sonnet-4
|
||||
```
|
||||
|
||||
**Nous Portal as fallback for OpenRouter:**
|
||||
|
|
@ -140,25 +139,25 @@ model:
|
|||
provider: openrouter
|
||||
default: anthropic/claude-opus-4
|
||||
|
||||
fallback_model:
|
||||
provider: nous
|
||||
model: nous-hermes-3
|
||||
fallback_providers:
|
||||
- provider: nous
|
||||
model: nous-hermes-3
|
||||
```
|
||||
|
||||
**Local model as fallback for cloud:**
|
||||
```yaml
|
||||
fallback_model:
|
||||
provider: custom
|
||||
model: llama-3.1-70b
|
||||
base_url: http://localhost:8000/v1
|
||||
key_env: LOCAL_API_KEY
|
||||
fallback_providers:
|
||||
- provider: custom
|
||||
model: llama-3.1-70b
|
||||
base_url: http://localhost:8000/v1
|
||||
key_env: LOCAL_API_KEY
|
||||
```
|
||||
|
||||
**Codex OAuth as fallback:**
|
||||
```yaml
|
||||
fallback_model:
|
||||
provider: openai-codex
|
||||
model: gpt-5.3-codex
|
||||
fallback_providers:
|
||||
- provider: openai-codex
|
||||
model: gpt-5.3-codex
|
||||
```
|
||||
|
||||
### Where Fallback Works
|
||||
|
|
@ -167,12 +166,12 @@ fallback_model:
|
|||
|---------|-------------------|
|
||||
| CLI sessions | ✔ |
|
||||
| Messaging gateway (Telegram, Discord, etc.) | ✔ |
|
||||
| Subagent delegation | ✘ (subagents do not inherit fallback config) |
|
||||
| Cron jobs | ✘ (run with a fixed provider) |
|
||||
| Subagent delegation | ✔ (subagents inherit the parent fallback chain) |
|
||||
| Cron jobs | ✔ (cron agents inherit configured fallback providers) |
|
||||
| Auxiliary tasks (vision, compression) | ✘ (use their own provider chain — see below) |
|
||||
|
||||
:::tip
|
||||
There are no environment variables for `fallback_model` — it is configured exclusively through `config.yaml`. This is intentional: fallback configuration is a deliberate choice, not something a stale shell export should override.
|
||||
There are no environment variables for the primary fallback chain — configure it exclusively through `config.yaml` or `hermes fallback`. This is intentional: fallback configuration is a deliberate choice, not something a stale shell export should override.
|
||||
:::
|
||||
|
||||
---
|
||||
|
|
@ -253,20 +252,20 @@ auxiliary:
|
|||
base_url: null # Custom OpenAI-compatible endpoint
|
||||
```
|
||||
|
||||
And the fallback model uses:
|
||||
And the primary fallback chain uses:
|
||||
|
||||
```yaml
|
||||
fallback_model:
|
||||
provider: openrouter
|
||||
model: anthropic/claude-sonnet-4
|
||||
# base_url: http://localhost:8000/v1 # Optional custom endpoint
|
||||
fallback_providers:
|
||||
- provider: openrouter
|
||||
model: anthropic/claude-sonnet-4
|
||||
# base_url: http://localhost:8000/v1 # Optional custom endpoint
|
||||
```
|
||||
|
||||
All three — auxiliary, compression, fallback — work the same way: set `provider` to pick who handles the request, `model` to pick which model, and `base_url` to point at a custom endpoint (overrides provider).
|
||||
|
||||
### Provider Options for Auxiliary Tasks
|
||||
|
||||
These options apply to `auxiliary:`, `compression:`, and `fallback_model:` configs only — `"main"` is **not** a valid value for your top-level `model.provider`. For custom endpoints, use `provider: custom` in your `model:` section (see [AI Providers](/docs/integrations/providers)).
|
||||
These options apply to `auxiliary:`, `compression:`, and `fallback_providers:` entries only — `"main"` is **not** a valid value for your top-level `model.provider`. For custom endpoints, use `provider: custom` in your `model:` section (see [AI Providers](/integrations/providers)).
|
||||
|
||||
| Provider | Description | Requirements |
|
||||
|----------|-------------|-------------|
|
||||
|
|
@ -363,7 +362,7 @@ If no provider is available for compression, Hermes drops middle conversation tu
|
|||
|
||||
## Delegation Provider Override
|
||||
|
||||
Subagents spawned by `delegate_task` do **not** use the primary fallback model. However, they can be routed to a different provider:model pair for cost optimization:
|
||||
Subagents spawned by `delegate_task` inherit the parent agent's primary fallback chain. You can still route subagents to a different primary provider:model pair for cost optimization:
|
||||
|
||||
```yaml
|
||||
delegation:
|
||||
|
|
@ -373,13 +372,13 @@ delegation:
|
|||
# api_key: "local-key"
|
||||
```
|
||||
|
||||
See [Subagent Delegation](/docs/user-guide/features/delegation) for full configuration details.
|
||||
See [Subagent Delegation](/user-guide/features/delegation) for full configuration details.
|
||||
|
||||
---
|
||||
|
||||
## Cron Job Providers
|
||||
|
||||
Cron jobs run with whatever provider is configured at execution time. They do not support a fallback model. To use a different provider for cron jobs, configure `provider` and `model` overrides on the cron job itself:
|
||||
Cron jobs inherit your configured `fallback_providers` chain (or legacy `fallback_model`) when they create an agent. To use a different primary provider for a cron job, configure `provider` and `model` overrides on the cron job itself:
|
||||
|
||||
```python
|
||||
cronjob(
|
||||
|
|
@ -391,7 +390,7 @@ cronjob(
|
|||
)
|
||||
```
|
||||
|
||||
See [Scheduled Tasks (Cron)](/docs/user-guide/features/cron) for full configuration details.
|
||||
See [Scheduled Tasks (Cron)](/user-guide/features/cron) for full configuration details.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -399,7 +398,7 @@ See [Scheduled Tasks (Cron)](/docs/user-guide/features/cron) for full configurat
|
|||
|
||||
| Feature | Fallback Mechanism | Config Location |
|
||||
|---------|-------------------|----------------|
|
||||
| Main agent model | `fallback_model` in config.yaml — per-turn failover on errors (primary restored each turn) | `fallback_model:` (top-level) |
|
||||
| Main agent model | `fallback_providers` in config.yaml — per-turn failover on errors (primary restored each turn) | `fallback_providers:` (top-level list) |
|
||||
| Auxiliary tasks (any) — auto users | Full auto-detection chain (main agent model first, then provider chain) on capacity errors | `auxiliary.<task>.provider: auto` |
|
||||
| Auxiliary tasks (any) — explicit provider | `fallback_chain` (if set) → main agent model → warn + raise, on capacity errors only | `auxiliary.<task>.fallback_chain` |
|
||||
| Vision | Layered (see above) + internal OpenRouter retry | `auxiliary.vision` |
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ goals:
|
|||
|
||||
### Choosing the judge model
|
||||
|
||||
The judge uses the `goal_judge` auxiliary task. By default it resolves to your main model (see [Auxiliary Models](/docs/user-guide/configuration#auxiliary-models)). If you want to route the judge to a cheap fast model to keep costs down, add an override:
|
||||
The judge uses the `goal_judge` auxiliary task. By default it resolves to your main model (see [Auxiliary Models](/user-guide/configuration#auxiliary-models)). If you want to route the judge to a cheap fast model to keep costs down, add an override:
|
||||
|
||||
```yaml
|
||||
auxiliary:
|
||||
|
|
|
|||
|
|
@ -106,6 +106,10 @@ The auto-injected dialectic scales `dialecticReasoningLevel` by query length: +1
|
|||
|
||||
Honcho is configured in `~/.honcho/config.json` (global) or `$HERMES_HOME/honcho.json` (profile-local). The setup wizard handles this for you.
|
||||
|
||||
### Self-Hosted Honcho with Authentication
|
||||
|
||||
When pointing Hermes at a self-hosted Honcho server, `hermes honcho setup` (and `hermes memory setup`) ask for a **local JWT / bearer token** after the base URL. Paste a JWT signed with the server's `AUTH_JWT_SECRET` (the Honcho compose env var) to enable authenticated access; leave it blank for servers running with `AUTH_USE_AUTH=false`. The local token is stored under the host block (`hosts.<host>.apiKey` in `honcho.json`), separate from any cloud `apiKey`, so you can flip the `Cloud or local?` prompt back to `cloud` later without losing either credential.
|
||||
|
||||
### Full Config Reference
|
||||
|
||||
| Key | Default | Description |
|
||||
|
|
@ -199,11 +203,12 @@ When Honcho is active as the memory provider, five tools become available:
|
|||
|
||||
## CLI Commands
|
||||
|
||||
The `hermes honcho` subcommand is **only registered when Honcho is the active memory provider** (`memory.provider: honcho` in `config.yaml`). Run `hermes memory setup` and pick Honcho first; the subcommand appears on the next invocation.
|
||||
The `hermes honcho` subcommand is **only registered when Honcho is the active memory provider** (`memory.provider: honcho` in `config.yaml`). On a fresh install, configure Honcho directly with `hermes memory setup honcho` (or run `hermes memory setup` and pick it from the list); the `hermes honcho` subcommand then appears on the next invocation.
|
||||
|
||||
```bash
|
||||
hermes memory setup honcho # Configure Honcho directly (works before activation)
|
||||
hermes honcho status # Connection status, config, and key settings
|
||||
hermes honcho setup # Redirects to `hermes memory setup`
|
||||
hermes honcho setup # Redirects to `hermes memory setup` (post-activation alias)
|
||||
hermes honcho strategy # Show or set session strategy (per-session/per-directory/per-repo/global)
|
||||
hermes honcho peer # Show or update peer names + dialectic reasoning level
|
||||
hermes honcho mode # Show or set recall mode (hybrid/context/tools)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ Hermes has three hook systems that run custom code at key lifecycle points:
|
|||
| System | Registered via | Runs in | Use case |
|
||||
|--------|---------------|---------|----------|
|
||||
| **[Gateway hooks](#gateway-event-hooks)** | `HOOK.yaml` + `handler.py` in `~/.hermes/hooks/` | Gateway only | Logging, alerts, webhooks |
|
||||
| **[Plugin hooks](#plugin-hooks)** | `ctx.register_hook()` in a [plugin](/docs/user-guide/features/plugins) | CLI + Gateway | Tool interception, metrics, guardrails |
|
||||
| **[Plugin hooks](#plugin-hooks)** | `ctx.register_hook()` in a [plugin](/user-guide/features/plugins) | CLI + Gateway | Tool interception, metrics, guardrails |
|
||||
| **[Shell hooks](#shell-hooks)** | `hooks:` block in `~/.hermes/config.yaml` pointing at shell scripts | CLI + Gateway | Drop-in scripts for blocking, auto-formatting, context injection |
|
||||
|
||||
All three systems are non-blocking — errors in any hook are caught and logged, never crashing the agent.
|
||||
|
|
@ -351,7 +351,10 @@ Gateway hooks only fire in the **gateway** (Telegram, Discord, Slack, WhatsApp,
|
|||
|
||||
## Plugin Hooks
|
||||
|
||||
[Plugins](/docs/user-guide/features/plugins) can register hooks that fire in **both CLI and gateway** sessions. These are registered programmatically via `ctx.register_hook()` in your plugin's `register()` function.
|
||||
[Plugins](/user-guide/features/plugins) can register hooks that fire in **both CLI and gateway** sessions. These are registered programmatically via `ctx.register_hook()` in your plugin's `register()` function.
|
||||
|
||||
For plugin packaging and registration details, see
|
||||
the [Plugins guide](/docs/user-guide/features/plugins).
|
||||
|
||||
```python
|
||||
def register(ctx):
|
||||
|
|
@ -368,6 +371,7 @@ def register(ctx):
|
|||
- Callbacks receive **keyword arguments**. Always accept `**kwargs` for forward compatibility — new parameters may be added in future versions without breaking your plugin.
|
||||
- If a callback **crashes**, it's logged and skipped. Other hooks and the agent continue normally. A misbehaving plugin can never break the agent.
|
||||
- Two hooks' return values affect behavior: [`pre_tool_call`](#pre_tool_call) can **block** the tool, and [`pre_llm_call`](#pre_llm_call) can **inject context** into the LLM call. All other hooks are fire-and-forget observers.
|
||||
- Observer callbacks receive `telemetry_schema_version` automatically. When present, `turn_id`, `api_request_id`, `task_id`, `session_id`, and `api_call_count` are separate correlation fields. Treat `api_request_id` as an opaque identifier; do not parse its string format.
|
||||
|
||||
### Quick reference
|
||||
|
||||
|
|
@ -801,7 +805,7 @@ def my_callback(session_id: str, platform: str, **kwargs):
|
|||
|
||||
---
|
||||
|
||||
See the **[Build a Plugin guide](/docs/guides/build-a-hermes-plugin)** for the full walkthrough including tool schemas, handlers, and advanced hook patterns.
|
||||
See the **[Build a Plugin guide](/guides/build-a-hermes-plugin)** for the full walkthrough including tool schemas, handlers, and advanced hook patterns.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
---
|
||||
title: Image Generation
|
||||
description: Generate images via FAL.ai — 9 models including FLUX 2, GPT Image (1.5 & 2), Nano Banana Pro, Ideogram, Recraft V4 Pro, and more, selectable via `hermes tools`.
|
||||
description: Generate images via FAL.ai — 11 models including FLUX 2, GPT Image (1.5 & 2), Nano Banana Pro, Ideogram, Recraft V4 Pro, Krea 2, and more, selectable via `hermes tools`.
|
||||
sidebar_label: Image Generation
|
||||
sidebar_position: 6
|
||||
---
|
||||
|
||||
# Image Generation
|
||||
|
||||
Hermes Agent generates images from text prompts via FAL.ai. Nine models are supported out of the box, each with different speed, quality, and cost tradeoffs. The active model is user-configurable via `hermes tools` and persists in `config.yaml`.
|
||||
Hermes Agent generates images from text prompts via FAL.ai. Eleven models are supported out of the box, each with different speed, quality, and cost tradeoffs. The active model is user-configurable via `hermes tools` and persists in `config.yaml`.
|
||||
|
||||
## Supported Models
|
||||
|
||||
|
|
@ -22,13 +22,15 @@ Hermes Agent generates images from text prompts via FAL.ai. Nine models are supp
|
|||
| `fal-ai/ideogram/v3` | ~5s | Best typography | $0.03–0.09/image |
|
||||
| `fal-ai/recraft/v4/pro/text-to-image` | ~8s | Design, brand systems, production-ready | $0.25/image |
|
||||
| `fal-ai/qwen-image` | ~12s | LLM-based, complex text | $0.02/MP |
|
||||
| `fal-ai/krea/v2/medium/text-to-image` | ~15-25s | Illustration, anime, painting, expressive/artistic styles | $0.030–0.035/image |
|
||||
| `fal-ai/krea/v2/large/text-to-image` | ~25-60s | Photorealism, raw textured looks (motion blur, grain, film) | $0.060–0.065/image |
|
||||
|
||||
Prices are FAL's pricing at time of writing; check [fal.ai](https://fal.ai/) for current numbers.
|
||||
|
||||
## Setup
|
||||
|
||||
:::tip Nous Subscribers
|
||||
If you have a paid [Nous Portal](https://portal.nousresearch.com) subscription, you can use image generation through the **[Tool Gateway](tool-gateway.md)** without a FAL API key. Your model selection persists across both paths.
|
||||
If you have a paid [Nous Portal](https://portal.nousresearch.com) subscription, you can use image generation through the **[Tool Gateway](tool-gateway.md)** without a FAL API key. Your model selection persists across both paths. New installs can run `hermes setup --portal` to log in and turn on every gateway tool at once; existing installs can pick **Nous Subscription** as the image-gen backend via `hermes tools`.
|
||||
|
||||
If the managed gateway returns `HTTP 4xx` for a specific model, that model isn't yet proxied on the portal side — the agent will tell you so, with remediation steps (set `FAL_KEY` for direct access, or pick a different model).
|
||||
:::
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ Throughout the tutorial, **code blocks labelled `bash` are commands *you* run.**
|
|||
|
||||
Six columns, left to right:
|
||||
|
||||
- **Triage** — raw ideas. By default the dispatcher auto-runs the **decomposer** (orchestrator-driven fan-out) on tasks here: it reads your profile roster + descriptions and produces a graph of child tasks routed to the best-fit specialists, with the original task held alive as the parent so the orchestrator wakes back up to judge completion when everything finishes. Flip the **Orchestration: Auto/Manual** pill at the top of the kanban page to switch modes. In Manual mode (or for setups without an orchestrator profile) click **⚗ Decompose** on a card, or run `hermes kanban decompose <id>` / `/kanban decompose <id>`. For single tasks that don't need fan-out, **✨ Specify** does a one-shot spec rewrite (goal, approach, acceptance criteria) and promotes to `todo`. Configure the models under `auxiliary.kanban_decomposer` and `auxiliary.triage_specifier` in `config.yaml`. See [Auto vs Manual orchestration](./kanban#auto-vs-manual-orchestration) in the main Kanban guide.
|
||||
- **Triage** — raw ideas. By default the dispatcher auto-runs the **decomposer** on tasks here: the built-in decomposer uses `auxiliary.kanban_decomposer`, reads your profile roster + descriptions, and produces a graph of child tasks routed to the best-fit specialists. The original task is held alive as the parent so its assignee (`kanban.orchestrator_profile`, or the active default profile when unset) wakes back up to judge completion when everything finishes. Flip the **Orchestration: Auto/Manual** pill at the top of the kanban page to switch modes. In Manual mode click **⚗ Decompose** on a card, or run `hermes kanban decompose <id>` / `/kanban decompose <id>`. For single tasks that don't need fan-out, **✨ Specify** does a one-shot spec rewrite (goal, approach, acceptance criteria) and promotes to `todo`. Configure the models under `auxiliary.kanban_decomposer` and `auxiliary.triage_specifier` in `config.yaml`. See [Auto vs Manual orchestration](./kanban#auto-vs-manual-orchestration) in the main Kanban guide.
|
||||
- **Todo** — created but waiting on dependencies, or not yet assigned.
|
||||
- **Ready** — assigned and waiting for the dispatcher to claim.
|
||||
- **In progress** — a worker is actively running the task. With "Lanes by profile" on (the default), this column sub-groups by assignee so you can see at a glance what each worker is doing.
|
||||
|
|
|
|||
|
|
@ -63,9 +63,9 @@ They coexist: a kanban worker may call `delegate_task` internally during its run
|
|||
- **Link** — `task_links` row recording a parent → child dependency. The dispatcher promotes `todo → ready` when all parents are `done`.
|
||||
- **Comment** — the inter-agent protocol. Agents and humans append comments; when a worker is (re-)spawned it reads the full comment thread as part of its context.
|
||||
- **Workspace** — the directory a worker operates in. Three kinds:
|
||||
- `scratch` (default) — fresh tmp dir under `~/.hermes/kanban/workspaces/<id>/` (or `~/.hermes/kanban/boards/<slug>/workspaces/<id>/` on non-default boards).
|
||||
- `dir:<path>` — an existing shared directory (Obsidian vault, mail ops dir, per-account folder). **Must be an absolute path.** Relative paths like `dir:../tenants/foo/` are rejected at dispatch because they'd resolve against whatever CWD the dispatcher happens to be in, which is ambiguous and a confused-deputy escape vector. The path is otherwise trusted — it's your box, your filesystem, the worker runs with your uid. This is the trusted-local-user threat model; kanban is single-host by design.
|
||||
- `worktree` — a git worktree under `.worktrees/<id>/` for coding tasks. Use `worktree:<path>` to pin the exact target path. Worker-side `git worktree add` creates it, using `--branch` when provided.
|
||||
- `scratch` (default) — fresh tmp dir under `~/.hermes/kanban/workspaces/<id>/` (or `~/.hermes/kanban/boards/<slug>/workspaces/<id>/` on non-default boards). **Deleted when the task completes** — scratch is ephemeral by design, so the dir is wiped the moment the worker (or `hermes kanban complete <id>`) marks the task done. If you want to keep the worker's output, use `worktree:` or `dir:<path>` instead. The first time a scratch workspace is created on an install, the dispatcher logs a warning and emits a `tip_scratch_workspace` event on the task (visible via `hermes kanban show <id>`).
|
||||
- `dir:<path>` — an existing shared directory (Obsidian vault, mail ops dir, per-account folder). **Must be an absolute path.** Relative paths like `dir:../tenants/foo/` are rejected at dispatch because they'd resolve against whatever CWD the dispatcher happens to be in, which is ambiguous and a confused-deputy escape vector. The path is otherwise trusted — it's your box, your filesystem, the worker runs with your uid. This is the trusted-local-user threat model; kanban is single-host by design. **Preserved on completion.**
|
||||
- `worktree` — a git worktree under `.worktrees/<id>/` for coding tasks. Use `worktree:<path>` to pin the exact target path. Worker-side `git worktree add` creates it, using `--branch` when provided. **Preserved on completion.**
|
||||
- **Dispatcher** — a long-lived loop that, every N seconds (default 60): reclaims stale claims, reclaims crashed workers (PID gone but TTL not yet expired), promotes ready tasks, atomically claims, spawns assigned profiles. Runs **inside the gateway** by default (`kanban.dispatch_in_gateway: true`). One dispatcher sweeps all boards per tick; workers are spawned with `HERMES_KANBAN_BOARD` pinned so they can't see other boards. After `kanban.failure_limit` consecutive spawn failures on the same task (default: 2) the dispatcher auto-blocks it with the last error as the reason — prevents thrashing on tasks whose profile doesn't exist, workspace can't mount, etc.
|
||||
- **Tenant** — optional string namespace *within* a board. One specialist fleet can serve multiple businesses (`--tenant business-a`) with data isolation by workspace path and memory key prefix. Tenants are a soft filter; boards are the hard isolation boundary.
|
||||
|
||||
|
|
@ -155,6 +155,36 @@ events WebSocket is pinned to a board at connection time; switching in
|
|||
the UI opens a fresh WS against the new board.
|
||||
|
||||
|
||||
## File attachments
|
||||
|
||||
Tasks can carry file attachments — PDFs, images, source documents — so a
|
||||
worker has the source material it needs without you pasting paths into the
|
||||
body and hoping it finds them.
|
||||
|
||||
- **Upload** — open a task in the dashboard drawer and use the
|
||||
**Attachments** section's *Upload file* button (multiple files at once
|
||||
are fine). Each upload is capped at 25 MB.
|
||||
- **Storage** — files land under
|
||||
`<hermes-home>/kanban/attachments/<task_id>/` for the default board, or
|
||||
`<hermes-home>/kanban/boards/<slug>/attachments/<task_id>/` for a named
|
||||
board. Set `HERMES_KANBAN_ATTACHMENTS_ROOT` to pin a custom location.
|
||||
- **What the worker sees** — when the dispatcher hands a task to a worker,
|
||||
the worker's context includes an **Attachments** section listing each
|
||||
file's name and its **absolute path**. The worker has full file/terminal
|
||||
tool access, so it reads attachments directly (`read_file`, or shell
|
||||
tools like `pdftotext`).
|
||||
- **Download / remove** — the drawer lists each attachment with a download
|
||||
link and a remove (×) control. Removing an attachment deletes both the
|
||||
metadata row and the on-disk file.
|
||||
|
||||
:::note Remote terminal backends
|
||||
Attachment paths resolve directly on the **local** terminal backend, which
|
||||
is the default for Kanban workers. If you run workers on a remote backend
|
||||
(Docker, Modal), mount the board's `attachments/` directory into the
|
||||
sandbox so the absolute paths in the worker context are reachable.
|
||||
:::
|
||||
|
||||
|
||||
## Quick start
|
||||
|
||||
The commands below are **you** (the human) setting up the board and creating tasks. Once a task is assigned, the dispatcher spawns the assigned profile as a worker, and from there **the model drives the task through `kanban_*` tool calls, not CLI commands** — see [How workers interact with the board](#how-workers-interact-with-the-board).
|
||||
|
|
@ -398,6 +428,20 @@ hermes kanban create "audit auth flow" \
|
|||
|
||||
These skills are **additive** to the built-in `kanban-worker` — the dispatcher emits one `--skills <name>` flag for each (and for the built-in), so the worker spawns with all of them loaded. The skill names must match skills that are actually installed on the assignee's profile (run `hermes skills list` to see what's available); there's no runtime install.
|
||||
|
||||
### Goal-mode cards (`--goal`)
|
||||
|
||||
By default each worker gets **one shot** at its card — do the work, call `kanban_complete`/`kanban_block`, exit. Pass `--goal` (CLI) or `goal_mode=True` (the `kanban_create` tool / dashboard) to instead run that worker in a **goal loop**, the same Ralph-style engine behind the `/goal` slash command: after every turn an auxiliary judge checks the worker's output against the card's title + body (treated as the acceptance criteria), and if the work isn't done — and the turn budget remains — the worker keeps going **in the same session** until the judge agrees, the worker terminates the task itself, or the budget runs out (which **blocks** the card for human review rather than exiting silently).
|
||||
|
||||
```bash
|
||||
hermes kanban create "Translate the docs site to French" \
|
||||
--body "Acceptance: every page translated, no English left, links intact." \
|
||||
--assignee linguist \
|
||||
--goal \
|
||||
--goal-max-turns 15 # optional; default 20
|
||||
```
|
||||
|
||||
Use it for open-ended, multi-step, or "keep going until X is true" cards. Skip it for cheap one-shot work — the per-turn judge overhead isn't worth it, and the dispatcher's existing retry/circuit-breaker already handles transient worker failures. The judge is only as good as your goal text, so write the body as **explicit acceptance criteria**.
|
||||
|
||||
### The orchestrator skill
|
||||
|
||||
A **well-behaved orchestrator does not do the work itself.** It decomposes the user's goal into tasks, links them, assigns each to one of the profiles you've set up, and steps back. The `kanban-orchestrator` skill encodes this as tool-call patterns: anti-temptation rules, a Step-0 profile-discovery prompt (the dispatcher silently fails on unknown assignee names, so the orchestrator must ground every card in profiles that actually exist on your machine), and a decomposition playbook keyed on `kanban_create` / `kanban_link` / `kanban_comment`.
|
||||
|
|
@ -451,7 +495,7 @@ hermes dashboard # "Kanban" tab appears in the nav, after "Skills"
|
|||
### What the plugin gives you
|
||||
|
||||
- A **Kanban** tab showing one column per status: `triage`, `todo`, `ready`, `running`, `blocked`, `done` (plus `archived` when the toggle is on).
|
||||
- `triage` is the parking column for rough ideas. By default (`kanban.auto_decompose: true`), the dispatcher auto-runs the **decomposer** on tasks that land here — the orchestrator profile reads the rough idea, looks at your profile roster (with descriptions), and fans the task out into a small graph of child tasks routed to the best-fit specialists. The original task stays alive as the parent of every child so the orchestrator wakes back up to judge completion when everything finishes. Flip the **Orchestration: Auto/Manual** pill at the top of the page (or set `kanban.auto_decompose: false`) to switch to manual mode, where triage tasks stay put until you click **⚗ Decompose** on a card or run `hermes kanban decompose <id>`. For tasks that don't need fan-out (or for setups without an orchestrator profile), the **✨ Specify** button does a single-task spec rewrite (title + body with goal, approach, acceptance criteria) via the same LLM machinery. See [Auto vs Manual orchestration](#auto-vs-manual-orchestration) below.
|
||||
- `triage` is the parking column for rough ideas. By default (`kanban.auto_decompose: true`), the dispatcher auto-runs the **decomposer** on tasks that land here. The built-in decomposer uses the `auxiliary.kanban_decomposer` model path, reads your profile roster (with descriptions), and fans the task out into a small graph of child tasks routed to the best-fit specialists. The original task stays alive as the parent of every child so its assignee (`kanban.orchestrator_profile`, or the active default profile when unset) wakes back up to judge completion when everything finishes. Flip the **Orchestration: Auto/Manual** pill at the top of the page (emerald = Auto, muted gray = Manual), or by editing `config.yaml` directly. Both modes coexist with `hermes kanban specify` - that's still available as a single-task spec rewrite when you don't want fan-out.
|
||||
- Cards show the task id, title, priority badge, tenant tag, assigned profile, comment/link counts, a **progress pill** (`N/M` children done when the task has dependents), and "created N ago". A per-card checkbox enables multi-select.
|
||||
- **Per-profile lanes inside Running** — toolbar checkbox toggles sub-grouping of the Running column by assignee.
|
||||
- **Live updates via WebSocket** — the plugin tails the append-only `task_events` table on a short poll interval; the board reflects changes the instant any profile (CLI, gateway, or another dashboard tab) acts. Reloads are debounced so a burst of events triggers a single refetch.
|
||||
|
|
@ -463,7 +507,7 @@ hermes dashboard # "Kanban" tab appears in the nav, after "Skills"
|
|||
- **Editable assignee / priority** — click the meta row to rewrite.
|
||||
- **Editable description** — markdown-rendered by default (headings, bold, italic, inline code, fenced code, `http(s)` / `mailto:` links, bullet lists), with an "edit" button that swaps in a textarea. Markdown rendering is a tiny, XSS-safe renderer — every substitution runs on HTML-escaped input, only `http(s)` / `mailto:` links pass through, and `target="_blank"` + `rel="noopener noreferrer"` are always set.
|
||||
- **Dependency editor** — chip list of parents and children, each with an `×` to unlink, plus dropdowns over every other task to add a new parent or child. Cycle attempts are rejected server-side with a clear message.
|
||||
- **Status action row** (→ triage / → ready / → running / block / unblock / complete / archive) with confirm prompts for destructive transitions. For cards in the **Triage** column the row also exposes two LLM-driven actions: **⚗ Decompose** fans the task out into a graph of child tasks routed to specialist profiles by description (the orchestrator-driven path), and **✨ Specify** does a single-task spec rewrite. Decompose falls back to specify-style promotion when the LLM decides the task doesn't benefit from fan-out, so it's a strict superset. Both are reachable from the CLI (`hermes kanban decompose <id>` / `specify <id>` / `--all`), from any gateway platform (`/kanban decompose <id>`), and programmatically via `POST /api/plugins/kanban/tasks/:id/decompose` and `…/specify`. Configure the models under `auxiliary.kanban_decomposer` and `auxiliary.triage_specifier` in `config.yaml`.
|
||||
- **Status action row** (→ triage / → ready / → running / block / unblock / complete / archive) with confirm prompts for destructive transitions. For cards in the **Triage** column the row also exposes two LLM-driven actions: **⚗ Decompose** fans the task out into a graph of child tasks routed to specialist profiles by description, and **✨ Specify** does a single-task spec rewrite. Decompose falls back to specify-style promotion when the LLM decides the task doesn't benefit from fan-out, so it's a strict superset. Both are reachable from the CLI (`hermes kanban decompose <id>` / `specify <id>` / `--all`), from any gateway platform (`/kanban decompose <id>`), and programmatically via `POST /api/plugins/kanban/tasks/:id/decompose` and `…/specify`. Configure the models under `auxiliary.kanban_decomposer` and `auxiliary.triage_specifier` in `config.yaml`.
|
||||
- Result section (also markdown-rendered), comment thread with Enter-to-submit, the last 20 events.
|
||||
- **Toolbar filters** — free-text search, tenant dropdown (defaults to `dashboard.kanban.default_tenant` from `config.yaml`), assignee dropdown, "show archived" toggle, "lanes by profile" toggle, and a **Nudge dispatcher** button so you don't have to wait for the next 60 s tick.
|
||||
|
||||
|
|
@ -473,7 +517,7 @@ Visually the target is the familiar Linear / Fusion layout: dark theme, column h
|
|||
|
||||
The kanban board has two ways to handle a task you drop into the Triage column:
|
||||
|
||||
**Auto (default)** — `kanban.auto_decompose: true`. The gateway-embedded dispatcher runs the **decomposer** on each tick, capped by `kanban.auto_decompose_per_tick` (default 3 tasks per tick) so a bulk-load of triage tasks doesn't burst-spend the auxiliary LLM. The decomposer reads the rough idea, looks at your installed profiles + their descriptions, and asks the LLM to produce a JSON task graph: which tasks to spawn, who they go to, and which depend on which. The original triage task becomes the parent of every leaf in the graph, so it stays alive until the whole graph completes — and then promotes back to `ready` so its assignee (the orchestrator profile) can judge completion and add more tasks if the work isn't done. This is the "drop a one-liner, walk away" flow.
|
||||
**Auto (default)** — `kanban.auto_decompose: true`. The gateway-embedded dispatcher runs the **decomposer** on each tick, capped by `kanban.auto_decompose_per_tick` (default 3 tasks per tick) so a bulk-load of triage tasks doesn't burst-spend the auxiliary LLM. The decomposer uses the built-in decomposition prompt plus the `auxiliary.kanban_decomposer` model path, reads your installed profiles + their descriptions, and asks the LLM to produce a JSON task graph: which tasks to spawn, who they go to, and which depend on which. The original triage task becomes the parent of every leaf in the graph, so it stays alive until the whole graph completes - and then promotes back to `ready` so its assignee (`kanban.orchestrator_profile`, or the active default profile when unset) can judge completion and add more tasks if the work isn't done. This is the "drop a one-liner, walk away" flow.
|
||||
|
||||
**Manual** — `kanban.auto_decompose: false`. Triage tasks stay in triage until you act. Click the **⚗ Decompose** button on a card, run `hermes kanban decompose <id>` (or `--all`), or use `/kanban decompose <id>` from a chat. This matches the pre-decomposer behavior of the board, useful when you want full control over what runs when.
|
||||
|
||||
|
|
@ -481,13 +525,15 @@ Flip between the two modes from the **Orchestration: Auto/Manual** pill at the t
|
|||
|
||||
The decomposer's routing decisions depend on profile descriptions, which is a per-profile labeling primitive you set with `hermes profile create --description "..."`, `hermes profile describe <name> --text "..."`, `hermes profile describe <name> --auto` (LLM-generates from the profile's installed skills + model), or the dashboard's per-profile editor in the expanded **Orchestration settings** panel. Profiles without a description still appear in the roster — they're routable by name, just less precisely. The decomposer NEVER lands a child task with `assignee=None`: when the LLM picks an unknown profile, the child gets routed to `kanban.default_assignee` (or the active default profile if that's unset).
|
||||
|
||||
`kanban.orchestrator_profile` does not load that profile's prompt, skills, or custom logic into the decomposition call. It controls who owns the root/orchestration task after fan-out. To change the decomposer's model/provider, configure `auxiliary.kanban_decomposer`. To use a profile's custom task-splitting logic instead of the built-in decomposer, switch to Manual mode and have that profile create or decompose tasks explicitly.
|
||||
|
||||
Config knobs (all under `kanban:` in `~/.hermes/config.yaml`):
|
||||
|
||||
| Key | Default | Purpose |
|
||||
|---|---|---|
|
||||
| `auto_decompose` | `true` | Dispatcher auto-runs the decomposer every tick. |
|
||||
| `auto_decompose_per_tick` | `3` | Cap on decompositions per dispatcher tick. Excess defers to the next tick. |
|
||||
| `orchestrator_profile` | `""` | Profile that owns decomposition. Empty = fall back to active default profile. |
|
||||
| `orchestrator_profile` | `""` | Profile assigned to the root/orchestration task after decomposition. Empty = fall back to active default profile. |
|
||||
| `default_assignee` | `""` | Where a child task lands when the LLM picks an unknown profile. Empty = fall back to active default. |
|
||||
|
||||
And the two auxiliary LLM slots:
|
||||
|
|
@ -602,11 +648,21 @@ hermes kanban create "<title>" [--body ...] [--assignee <profile>]
|
|||
[--priority N] [--triage] [--idempotency-key KEY]
|
||||
[--max-runtime 30m|2h|1d|<seconds>]
|
||||
[--max-retries N]
|
||||
[--goal] [--goal-max-turns N]
|
||||
[--skill <name>]...
|
||||
[--json]
|
||||
hermes kanban list [--mine] [--assignee P] [--status S] [--tenant T] [--archived] [--json]
|
||||
hermes kanban list [--mine] [--assignee P] [--status S] [--tenant T] [--archived]
|
||||
[--workflow-template-id <id>] [--current-step-key <key>]
|
||||
[--sort created|created-desc|priority|priority-desc|status|assignee|title|updated]
|
||||
[--json]
|
||||
hermes kanban show <id> [--json]
|
||||
hermes kanban assign <id> <profile> # or 'none' to unassign
|
||||
hermes kanban reassign <id>... <profile> # bulk re-assign tasks to a profile
|
||||
hermes kanban edit <id> [--title ...] [--body ...] # edit task title / body / priority in place
|
||||
[--priority N]
|
||||
hermes kanban promote <id>... # move todo/blocked tasks to ready (recovery)
|
||||
hermes kanban schedule <id> --at <ISO8601> # set/clear a task's scheduled_at start time
|
||||
hermes kanban diagnostics [--json] # board health snapshot (alias: diag)
|
||||
hermes kanban link <parent_id> <child_id>
|
||||
hermes kanban unlink <parent_id> <child_id>
|
||||
hermes kanban claim <id> [--ttl SECONDS]
|
||||
|
|
@ -646,6 +702,64 @@ All commands are also available as a slash command in the interactive CLI and in
|
|||
|
||||
`--max-retries` is a per-task circuit-breaker override for the dispatcher. `--max-retries 1` blocks the task on the first non-successful attempt, while `--max-retries 3` allows two retries and blocks on the third failure. Omit it to use `kanban.failure_limit` from `config.yaml`, then the built-in default.
|
||||
|
||||
### Concurrency, scheduling, and child promotion config
|
||||
|
||||
| Config key | Default | What it does |
|
||||
|------------|---------|--------------|
|
||||
| `kanban.max_in_progress` | unset (unlimited) | Caps the number of simultaneously running tasks. When the board already has N running, the dispatcher skips spawning more — useful for slow workers (local LLMs, resource-constrained hosts) so they finish what they have before more pile up and time out. Invalid or below-1 values log a warning and behave as unlimited. |
|
||||
| `kanban.max_in_progress_per_profile` | unset (unlimited) | Per-profile variant of `max_in_progress` — caps how many tasks any single assignee profile may run concurrently. Useful when one profile is slow or rate-limited but others should keep flowing. Applies alongside the board-wide `max_in_progress`; both must allow a spawn for it to proceed. |
|
||||
| `kanban.auto_promote_children` | `true` | After `decompose_triage_task()` produces children with no parent-blocker dependencies, they're automatically promoted to `ready` so the dispatcher can pick them up. Set to `false` to require manual review — children stay in `todo` until you promote them. |
|
||||
| `kanban.default_workdir` | unset | Board-level default working directory applied to new tasks when neither `--workspace` nor the task itself overrides it. Per-task `workspace:` still wins. |
|
||||
|
||||
```yaml
|
||||
kanban:
|
||||
max_in_progress: 2
|
||||
auto_promote_children: false
|
||||
default_workdir: ~/work/active-project
|
||||
```
|
||||
|
||||
### Scheduled task starts (`scheduled_at`)
|
||||
|
||||
Set `scheduled_at` on a task to delay dispatch until a specific time. The dispatcher skips ready tasks whose `scheduled_at` is in the future and picks them up on the first tick after that timestamp.
|
||||
|
||||
```bash
|
||||
hermes kanban create "nightly backup audit" \
|
||||
--assignee ops --scheduled-at "2026-06-01T03:00:00Z"
|
||||
```
|
||||
|
||||
### Respawn guard
|
||||
|
||||
The dispatcher refuses to re-spawn a ready task when it hit a quota/auth/429 error on the previous run (`blocker_auth`), or completed a run successfully within the guard window (`recent_success`), or a recent task comment links to a GitHub PR (`active_pr`). This prevents repeat worker storms on the same bug or task while a human catches up. See the `respawn_guarded` row in the [event reference](#event-reference).
|
||||
|
||||
### Drag-to-delete and bulk delete (dashboard)
|
||||
|
||||
The dashboard exposes a **trash drop zone** on the kanban page — drag any card into it to delete the task (cascades through `task_events`, child links, and subscriptions). A confirmation prompt protects against accidents. Bulk delete is also reachable via `DELETE /api/plugins/kanban/tasks` with a JSON body `{"ids": ["t_abc", "t_def", ...]}`.
|
||||
|
||||
### Worker visibility endpoints
|
||||
|
||||
The dashboard plugin API now exposes these read-only endpoints (plus a run-control verb) for external monitors:
|
||||
|
||||
| Endpoint | Returns |
|
||||
|----------|---------|
|
||||
| `GET /api/plugins/kanban/workers/active` | Currently spawned workers with PID, profile, task id, started-at, last heartbeat |
|
||||
| `GET /api/plugins/kanban/runs/{id}` | Single-run detail — task id, status, started/ended, exit code, log path |
|
||||
| `POST /api/plugins/kanban/runs/{run_id}/terminate` | Terminate a reclaimable run — stops the worker and frees the task for re-dispatch |
|
||||
| `GET /api/plugins/kanban/inspect` | Combined dispatcher snapshot — backlog, in-progress count vs. `max_in_progress`, recent events |
|
||||
|
||||
All of these are gated by the same dashboard plugin auth as the rest of the kanban plugin API.
|
||||
|
||||
### Kanban Swarm topology helper
|
||||
|
||||
`hermes kanban swarm` creates a durable **Kanban Swarm v1** graph in one shot: a completed root/blackboard card, N parallel worker cards, a verifier card gated on all workers, and a synthesizer card gated on the verifier. Shared swarm context (the "blackboard") is stored as structured JSON comments on the root card so any worker can read it.
|
||||
|
||||
```bash
|
||||
hermes kanban swarm "Design a multi-region failover plan" \
|
||||
--workers researcher,architect,sre \
|
||||
--verifier reviewer --synthesizer writer
|
||||
```
|
||||
|
||||
The resulting graph dispatches normally — workers run in parallel, the verifier wakes after they all finish, the synthesizer wakes after the verifier marks the work clean.
|
||||
|
||||
## `/kanban` slash command {#kanban-slash-command}
|
||||
|
||||
Every `hermes kanban <action>` verb is also reachable as `/kanban <action>` — from inside an interactive `hermes chat` session **and** from any gateway platform (Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Mattermost, email, SMS). Both surfaces call the exact same `hermes_cli.kanban.run_slash()` entry point that reuses the `hermes kanban` argparse tree, so the argument surface, flags, and output format are identical across CLI, `/kanban`, and `hermes kanban`. You don't have to leave the chat to drive the board.
|
||||
|
|
|
|||
|
|
@ -52,6 +52,126 @@ List the files in /home/user/projects and summarize the repo structure.
|
|||
|
||||
Hermes will discover the MCP server's tools and use them like any other tool.
|
||||
|
||||
## Catalog: one-click install for Nous-approved MCPs
|
||||
|
||||
Hermes ships a curated catalog of MCP servers that Nous staff has reviewed
|
||||
and merged. They're disabled by default — install only what you actually
|
||||
want.
|
||||
|
||||
```bash
|
||||
hermes mcp # interactive picker (default)
|
||||
hermes mcp catalog # plain-text list, scriptable
|
||||
hermes mcp install n8n # install a catalog entry by name
|
||||
```
|
||||
|
||||
The picker shows each entry with its current status:
|
||||
|
||||
```
|
||||
n8n available Manage and inspect n8n workflows from Hermes
|
||||
linear enabled Linear issue/project management (remote OAuth)
|
||||
github installed (disabled) GitHub repo + PR tools
|
||||
```
|
||||
|
||||
Hit `Enter` on a row to install (and walk through any required credentials),
|
||||
enable, disable, or uninstall. Catalog entries are stored under
|
||||
`optional-mcps/` in the hermes-agent repo — presence in that directory means
|
||||
Nous approval. There is no community submission tier; entries are added by
|
||||
merging a PR.
|
||||
|
||||
Catalog entries can require:
|
||||
|
||||
- **API key** — Hermes prompts at install time and writes the value to
|
||||
`~/.hermes/.env`. Non-secret values (base URLs) go to the same file.
|
||||
- **OAuth** (remote MCP) — written as `auth: oauth` in your config; the MCP
|
||||
client opens a browser on first connection.
|
||||
- **OAuth** (third-party provider like Google/GitHub) — Hermes points you at
|
||||
`hermes auth <provider>` if you haven't authenticated already.
|
||||
|
||||
### Tool selection at install time
|
||||
|
||||
After credentials are configured, Hermes probes the MCP server to list every
|
||||
tool it exposes and presents a checklist:
|
||||
|
||||
```
|
||||
Select tools for 'linear' (SPACE toggle, ENTER confirm)
|
||||
[x] find_issues Find issues matching a query
|
||||
[x] get_issue Get a single issue
|
||||
[x] create_issue Create a new issue
|
||||
[ ] delete_workspace Delete a Linear workspace
|
||||
...
|
||||
```
|
||||
|
||||
The pre-checked rows come from:
|
||||
|
||||
1. **Your prior selection** if you've installed this entry before (reinstalls
|
||||
preserve what you had — the manifest's defaults don't override it)
|
||||
2. **The manifest's `tools.default_enabled`** if the entry declares one (some
|
||||
catalog entries pre-prune mutating or rarely-useful tools)
|
||||
3. **Everything** if neither applies
|
||||
|
||||
Submit the checklist with ENTER. Only the checked tools end up in
|
||||
`mcp_servers.<name>.tools.include`. If you select everything, no filter is
|
||||
written (cleanest config shape, identical behavior).
|
||||
|
||||
**If the probe fails** (server unreachable, OAuth not yet completed,
|
||||
backing service not running), the install still succeeds: the manifest's
|
||||
`tools.default_enabled` is applied directly (if declared), or no filter is
|
||||
written (if not). Re-run `hermes mcp configure <name>` once the server is
|
||||
reachable to refine.
|
||||
|
||||
### Trust model
|
||||
|
||||
Installing a catalog entry runs whatever the manifest specifies — `git clone`,
|
||||
the entry's `bootstrap` commands (`pip install`, `npm install`, etc.), and
|
||||
ultimately the MCP server's own code. Manifests are gated by PR review into
|
||||
the hermes-agent repo, so Nous has reviewed each entry before it shipped —
|
||||
**but you should still read the manifest before installing**, especially the
|
||||
`source:` field's repository, the `install.bootstrap:` commands, and any
|
||||
`transport.command:` invocation.
|
||||
|
||||
Manifests live at
|
||||
[`optional-mcps/<name>/manifest.yaml`](https://github.com/NousResearch/hermes-agent/tree/main/optional-mcps)
|
||||
on GitHub. The picker also prints the manifest's `source:` URL at install
|
||||
time so you can quickly verify the upstream repo.
|
||||
|
||||
### Manifest version compatibility
|
||||
|
||||
Manifests pin a `manifest_version`. The catalog is forward-compatible: if a
|
||||
PR adds an entry with a newer `manifest_version` than your installed Hermes
|
||||
understands, the picker will surface a warning (`⚠ '<name>' requires a newer
|
||||
Hermes`) for that entry instead of silently hiding it. Run `hermes update`
|
||||
to install the latest Hermes when you see that.
|
||||
|
||||
### Runtime `${ENV_VAR}` substitution
|
||||
|
||||
Inside an entry's `transport.command`, `transport.args`, `transport.url`,
|
||||
and `headers`, `${VAR}` placeholders are resolved at server-connect time
|
||||
from environment variables (which include everything in `~/.hermes/.env`).
|
||||
This is useful when a catalog entry wants to reference a value the user
|
||||
configured elsewhere — e.g. `${HOME}/foo` or `${MY_PROVIDER_TOKEN}`.
|
||||
|
||||
Note this is distinct from `${INSTALL_DIR}` in catalog manifests, which is
|
||||
substituted at install-time with the path the catalog cloned the entry's
|
||||
repo into.
|
||||
|
||||
### Updating tool selection later
|
||||
|
||||
```bash
|
||||
hermes mcp configure linear
|
||||
```
|
||||
|
||||
Reopens the same checklist with your current selection pre-checked. Use this
|
||||
when you want more tools enabled, or when the server has added new tools that
|
||||
you want to opt into.
|
||||
|
||||
### Updating the catalog manifest
|
||||
|
||||
MCPs are never auto-updated. Re-run `hermes mcp install <name>` to refresh
|
||||
after a Hermes update if a manifest version changed.
|
||||
|
||||
To add an MCP to the catalog, open a PR against
|
||||
[`optional-mcps/`](https://github.com/NousResearch/hermes-agent/tree/main/optional-mcps).
|
||||
|
||||
## Two kinds of MCP servers
|
||||
|
||||
### Stdio servers
|
||||
|
|
@ -89,6 +209,77 @@ Use HTTP servers when:
|
|||
- your organization exposes internal MCP endpoints
|
||||
- you do not want Hermes spawning a local subprocess for that integration
|
||||
|
||||
### OAuth-authenticated HTTP servers
|
||||
|
||||
Most hosted MCP servers (Linear, Sentry, Atlassian, Asana, Figma, Stripe, …) require OAuth 2.1 instead of a static bearer token. Set `auth: oauth` and Hermes handles discovery, dynamic client registration, PKCE, token exchange, refresh, and step-up auth via the MCP Python SDK.
|
||||
|
||||
```yaml
|
||||
mcp_servers:
|
||||
linear:
|
||||
url: "https://mcp.linear.app/mcp"
|
||||
auth: oauth
|
||||
```
|
||||
|
||||
On first connect, Hermes prints an authorize URL, opens your browser when possible, and waits for the OAuth callback on a local loopback port. Tokens are cached at `~/.hermes/mcp-tokens/<server>.json` with 0o600 perms; subsequent runs reuse them silently until refresh fails.
|
||||
|
||||
**Remote / headless hosts.** When Hermes runs on a different machine than your browser, the loopback callback can't reach your laptop. Two ways to complete the flow:
|
||||
|
||||
- **Paste-back (no setup):** on an interactive terminal Hermes prints "Or paste the redirect URL here…" alongside the authorize URL. Open the URL in your browser, approve, copy the full URL the browser ends up on (the redirect will show a connection error — that's expected), paste it at the prompt. Bare `?code=…&state=…` query strings work too.
|
||||
- **SSH port forward:** `ssh -N -L <port>:127.0.0.1:<port> user@host` in a separate terminal, then let the redirect flow normally.
|
||||
|
||||
See [OAuth over SSH / Remote Hosts](../../guides/oauth-over-ssh.md#mcp-servers) for the full walkthrough, including DCR-less servers (e.g. Slack), pre-registered `client_id`/`client_secret`, scope customization, and re-auth via `hermes mcp login <server>`.
|
||||
|
||||
**Pitfall — providers that don't support automatic registration (Google Drive, Atlassian).** Some servers reject the dynamic client registration step (RFC 7591) that bare `auth: oauth` relies on — Google's official Drive server (`https://drivemcp.googleapis.com/mcp/v1`) returns a `400 Bad Request`, so no OAuth client is created and no token is acquired. The symptom is subtle: these servers also serve `tools/list` *without* auth, so `hermes mcp login` can list the tools and look like it worked, but every real tool call later times out. `hermes mcp login` now detects this (it checks that a token actually landed on disk) and tells you to supply your own OAuth client. Create one in the provider's console and add it to config:
|
||||
|
||||
```yaml
|
||||
mcp_servers:
|
||||
googledrive:
|
||||
url: "https://drivemcp.googleapis.com/mcp/v1"
|
||||
auth: oauth
|
||||
oauth:
|
||||
client_id: "<your-oauth-client-id>"
|
||||
client_secret: "<your-oauth-client-secret>"
|
||||
```
|
||||
|
||||
Then run `hermes mcp login googledrive` — with the pre-registered client, Hermes skips registration and runs the normal browser authorization flow.
|
||||
|
||||
**Pitfall — config auto-reload race.** When you edit `~/.hermes/config.yaml` from inside a running Hermes session, the CLI auto-reloads MCP connections with a 30s timeout. That's not enough for an interactive OAuth flow. Add the entry, then run `hermes mcp login <server>` from a fresh terminal — it waits the full 5 minutes for you to complete auth.
|
||||
|
||||
## mTLS / client certificates
|
||||
|
||||
Remote HTTP MCP servers that require mutual TLS (client-certificate authentication) are supported via `client_cert` / `client_key`. Hermes passes the resolved certificate to the underlying HTTP client for the TLS handshake.
|
||||
|
||||
`client_cert` accepts three shapes:
|
||||
|
||||
- **A single combined PEM path** — one file holding both the certificate and the private key:
|
||||
|
||||
```yaml
|
||||
mcp_servers:
|
||||
internal_api:
|
||||
url: "https://mcp.internal.example.com/mcp"
|
||||
client_cert: "~/.certs/mcp-client.pem"
|
||||
```
|
||||
|
||||
- **A `[cert, key]` 2-tuple** — certificate and key in separate files (equivalent to setting `client_cert` + `client_key`):
|
||||
|
||||
```yaml
|
||||
mcp_servers:
|
||||
internal_api:
|
||||
url: "https://mcp.internal.example.com/mcp"
|
||||
client_cert: ["~/.certs/mcp-client.crt", "~/.certs/mcp-client.key"]
|
||||
```
|
||||
|
||||
- **A `[cert, key, password]` 3-tuple** — when the private key is encrypted, the third element is the key passphrase:
|
||||
|
||||
```yaml
|
||||
mcp_servers:
|
||||
internal_api:
|
||||
url: "https://mcp.internal.example.com/mcp"
|
||||
client_cert: ["~/.certs/mcp-client.crt", "~/.certs/mcp-client.key", "${MCP_KEY_PASSWORD}"]
|
||||
```
|
||||
|
||||
You can also keep the cert and key fully separate via `client_cert` (combined PEM) plus an explicit `client_key`. Paths support `~` expansion; a missing file raises a clear, server-scoped error rather than an opaque TLS handshake failure.
|
||||
|
||||
## Basic configuration reference
|
||||
|
||||
Hermes reads MCP config from `~/.hermes/config.yaml` under `mcp_servers`.
|
||||
|
|
@ -102,6 +293,8 @@ Hermes reads MCP config from `~/.hermes/config.yaml` under `mcp_servers`.
|
|||
| `env` | mapping | Environment variables passed to the stdio server |
|
||||
| `url` | string | HTTP MCP endpoint |
|
||||
| `headers` | mapping | HTTP headers for remote servers |
|
||||
| `client_cert` | string \| list | Client certificate for mTLS — a combined PEM path, or `[cert, key]` / `[cert, key, password]` |
|
||||
| `client_key` | string | Client private-key PEM path (when separate from `client_cert`) |
|
||||
| `timeout` | number | Tool call timeout |
|
||||
| `connect_timeout` | number | Initial connection timeout |
|
||||
| `enabled` | bool | If `false`, Hermes skips the server entirely |
|
||||
|
|
@ -585,7 +778,7 @@ The gateway does NOT need to be running for read operations (listing conversatio
|
|||
|
||||
## Related docs
|
||||
|
||||
- [Use MCP with Hermes](/docs/guides/use-mcp-with-hermes)
|
||||
- [CLI Commands](/docs/reference/cli-commands)
|
||||
- [Slash Commands](/docs/reference/slash-commands)
|
||||
- [FAQ](/docs/reference/faq)
|
||||
- [Use MCP with Hermes](/guides/use-mcp-with-hermes)
|
||||
- [CLI Commands](/reference/cli-commands)
|
||||
- [Slash Commands](/reference/slash-commands)
|
||||
- [FAQ](/reference/faq)
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ hermes memory setup # select "honcho" — runs the Honcho-specific post-s
|
|||
|
||||
The legacy `hermes honcho setup` command still works (it now redirects to `hermes memory setup`), but is only registered after Honcho is selected as the active memory provider.
|
||||
|
||||
**Config:** `$HERMES_HOME/honcho.json` (profile-local) or `~/.honcho/config.json` (global). Resolution order: `$HERMES_HOME/honcho.json` > `~/.hermes/honcho.json` > `~/.honcho/config.json`. See the [config reference](https://github.com/hermes-ai/hermes-agent/blob/main/plugins/memory/honcho/README.md) and the [Honcho integration guide](https://docs.honcho.dev/v3/guides/integrations/hermes).
|
||||
**Config:** `$HERMES_HOME/honcho.json` (profile-local) or `~/.honcho/config.json` (global). Resolution order: `$HERMES_HOME/honcho.json` > `~/.hermes/honcho.json` > `~/.honcho/config.json`. See the [config reference](https://github.com/NousResearch/hermes-agent/blob/main/plugins/memory/honcho/README.md) and the [Honcho integration guide](https://docs.honcho.dev/v3/guides/integrations/hermes).
|
||||
|
||||
<details>
|
||||
<summary>Full config reference</summary>
|
||||
|
|
@ -255,7 +255,7 @@ See the [Honcho page](./honcho.md#observation-directional-vs-unified) for the fu
|
|||
|
||||
</details>
|
||||
|
||||
See the [config reference](https://github.com/hermes-ai/hermes-agent/blob/main/plugins/memory/honcho/README.md) and [Honcho integration guide](https://docs.honcho.dev/v3/guides/integrations/hermes).
|
||||
See the [config reference](https://github.com/NousResearch/hermes-agent/blob/main/plugins/memory/honcho/README.md) and [Honcho integration guide](https://docs.honcho.dev/v3/guides/integrations/hermes).
|
||||
|
||||
|
||||
---
|
||||
|
|
@ -498,11 +498,11 @@ echo 'SUPERMEMORY_API_KEY=***' >> ~/.hermes/.env
|
|||
|
||||
**Key features:**
|
||||
- Automatic context fencing — strips recalled memories from captured turns to prevent recursive memory pollution
|
||||
- Session-end conversation ingest for richer graph-level knowledge building
|
||||
- Full-session ingest — the entire conversation is sent once at session boundaries
|
||||
- Session-end conversation ingest (to `/v4/conversations`) for richer profile + graph building in Supermemory
|
||||
- Profile facts injected on first turn and at configurable intervals
|
||||
- Trivial message filtering (skips "ok", "thanks", etc.)
|
||||
- **Profile-scoped containers** — use `{identity}` in `container_tag` (e.g. `hermes-{identity}` → `hermes-coder`) to isolate memories per Hermes profile
|
||||
- **Multi-container mode** — enable `enable_custom_container_tags` with a `custom_containers` list to let the agent read/write across named containers. Automatic operations (sync, prefetch) stay on the primary container.
|
||||
- **Multi-container mode** — enable `enable_custom_container_tags` with a `custom_containers` list to let the agent read/write across named containers. Automatic operations stay on the primary container.
|
||||
|
||||
<details>
|
||||
<summary>Multi-container example</summary>
|
||||
|
|
@ -520,6 +520,27 @@ echo 'SUPERMEMORY_API_KEY=***' >> ~/.hermes/.env
|
|||
|
||||
**Support:** [Discord](https://supermemory.link/discord) · [support@supermemory.com](mailto:support@supermemory.com)
|
||||
|
||||
### Memori
|
||||
|
||||
Structured long-term memory using Memori Cloud, with background completed-turn capture, tool-aware turn context, and explicit recall tools for facts, summaries, quota, signup, and feedback.
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| **Best for** | Agent-controlled recall with structured project and session attribution |
|
||||
| **Requires** | `pip install hermes-memori` + `hermes-memori install` + [Memori API key](https://app.memorilabs.ai/signup) |
|
||||
| **Data storage** | Memori Cloud |
|
||||
| **Cost** | Memori pricing |
|
||||
|
||||
**Tools:** `memori_recall` (search long-term memory), `memori_recall_summary` (summarized context), `memori_quota` (usage/quota), `memori_signup` (request signup email), `memori_feedback` (send integration feedback)
|
||||
|
||||
**Setup:**
|
||||
```bash
|
||||
pip install hermes-memori
|
||||
hermes-memori install
|
||||
hermes config set memory.provider memori
|
||||
hermes memory setup
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Provider Comparison
|
||||
|
|
@ -534,10 +555,11 @@ echo 'SUPERMEMORY_API_KEY=***' >> ~/.hermes/.env
|
|||
| **RetainDB** | Cloud | $20/mo | 5 | `requests` | Delta compression |
|
||||
| **ByteRover** | Local/Cloud | Free/Paid | 3 | `brv` CLI | Pre-compression extraction |
|
||||
| **Supermemory** | Cloud | Paid | 4 | `supermemory` | Context fencing + session graph ingest + multi-container |
|
||||
| **Memori** | Cloud | Free/Paid | 5 | `hermes-memori` | Tool-aware memory + structured recall |
|
||||
|
||||
## Profile Isolation
|
||||
|
||||
Each provider's data is isolated per [profile](/docs/user-guide/profiles):
|
||||
Each provider's data is isolated per [profile](/user-guide/profiles):
|
||||
|
||||
- **Local storage providers** (Holographic, ByteRover) use `$HERMES_HOME/` paths which differ per profile
|
||||
- **Config file providers** (Honcho, Mem0, Hindsight, Supermemory) store config in `$HERMES_HOME/` so each profile has its own credentials
|
||||
|
|
@ -546,4 +568,4 @@ Each provider's data is isolated per [profile](/docs/user-guide/profiles):
|
|||
|
||||
## Building a Memory Provider
|
||||
|
||||
See the [Developer Guide: Memory Provider Plugins](/docs/developer-guide/memory-provider-plugin) for how to create your own.
|
||||
See the [Developer Guide: Memory Provider Plugins](/developer-guide/memory-provider-plugin) for how to create your own.
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue