Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion website/docs/developer-guide/adding-platform-adapters.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
17 changes: 4 additions & 13 deletions website/docs/guides/cron-script-only.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,10 @@ Sometimes you already know exactly what message you want to send. You don't need

Hermes calls this **no-agent mode**. It's the cron system minus the LLM.

```
┌──────────────────┐ ┌──────────────────┐
│ scheduler tick │ every │ run script │
│ (every N minutes)│ ──────▶ │ (bash or python) │
└──────────────────┘ └──────────────────┘
│ stdout
┌──────────────────┐
│ delivery router │
│ (telegram/disc…) │
└──────────────────┘
```mermaid
flowchart LR
tick["scheduler tick<br/>(every N minutes)"] -->|every| script["run script<br/>(bash or python)"]
script -->|stdout| router["delivery router<br/>(telegram / discord / ...)"]
```

- **No LLM call.** Zero tokens, zero agent loop, zero model spend.
Expand Down Expand Up @@ -242,5 +234,4 @@ For critical system-health watchdogs that must fire *even when the gateway is do

- [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.
- [Pipe Script Output with `hermes send`](/docs/guides/pipe-script-output) — the one-shot counterpart for ad-hoc scripts.
- [Gateway Internals](/docs/developer-guide/gateway-internals) — delivery-router internals.
18 changes: 9 additions & 9 deletions website/docs/integrations/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -1372,24 +1372,24 @@ provider_routing:

**Shortcuts:** Append `:nitro` to any model name for throughput sorting (e.g., `anthropic/claude-sonnet-4:nitro`), or `:floor` for price sorting.

## Fallback Model
## Fallback Providers

Configure a backup provider:model that Hermes switches to automatically when your primary model fails (rate limits, server errors, auth failures):
Configure a backup provider:model chain that Hermes switches to automatically when your primary model fails (rate limits, server errors, auth failures):

```yaml
fallback_model:
provider: openrouter # required
model: anthropic/claude-sonnet-4 # required
# base_url: http://localhost:8000/v1 # optional, for custom endpoints
# key_env: MY_CUSTOM_KEY # optional, env var name for custom endpoint API key
fallback_providers:
- provider: openrouter # required
model: anthropic/claude-sonnet-4 # required
# base_url: http://localhost:8000/v1 # optional, for custom endpoints
# key_env: MY_CUSTOM_KEY # optional, env var name for custom endpoint API key
```

When activated, the fallback swaps the model and provider mid-session without losing your conversation. It fires **at most once** per session.
When activated, the fallback swaps the model and provider mid-turn without losing your conversation. The primary model is restored for the next user message.

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`, `ollama-cloud`, `bedrock`, `ai-gateway`, `opencode-zen`, `opencode-go`, `kilocode`, `xiaomi`, `arcee`, `gmi`, `stepfun`, `alibaba`, `tencent-tokenhub`, `custom`.

:::tip
Fallback is configured exclusively through `config.yaml` — there are no environment variables for it. For full details on when it triggers, supported providers, 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` — there are no environment variables for it. The older top-level `fallback_model` object is still read for backward compatibility, but new configs should use `fallback_providers`. For full details on when it triggers, supported providers, and how it interacts with auxiliary tasks and delegation, see [Fallback Providers](/docs/user-guide/features/fallback-providers).
:::

---
Expand Down
6 changes: 3 additions & 3 deletions website/docs/user-guide/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -819,7 +819,7 @@ Available providers for auxiliary tasks: `auto`, `main`, plus any provider in th
:::

:::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 fallback-provider entries. 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.
:::

### Full auxiliary config reference
Expand Down Expand Up @@ -887,7 +887,7 @@ 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 top-level `fallback_providers:` — see [Fallback Providers](/docs/integrations/providers#fallback-providers). All three follow the same provider/model/base_url pattern.
:::

### Session Search Tuning
Expand Down Expand Up @@ -936,7 +936,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 fallback-provider entries, not to your main `model.provider` setting.

| Provider | Description | Requirements |
|----------|-------------|-------------|
Expand Down
70 changes: 35 additions & 35 deletions website/docs/user-guide/features/fallback-providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,20 @@ The easiest path is the interactive manager:
hermes fallback
```

`hermes fallback` reuses the provider picker from `hermes model` — same provider list, same credential prompts, same validation. Press `a` to add a fallback, `↑`/`↓` to reorder, `d` to remove, `q` to save and exit. Changes persist under `model.fallback_providers` in `config.yaml`.
`hermes fallback` reuses the provider picker from `hermes model` — same provider list, same credential prompts, same validation. Press `a` to add a fallback, `↑`/`↓` to reorder, `d` to remove, `q` to save and exit. Changes persist under top-level `fallback_providers` 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 value 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_model` (singular) is the legacy single-fallback key — Hermes still honors it for back-compat. `fallback_providers` (plural, list) is the current format and supports multiple fallbacks tried in order; `hermes fallback` writes to this top-level key. When both are set, `fallback_providers` takes priority.
:::

### Supported Providers
Expand Down Expand Up @@ -90,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
Expand Down Expand Up @@ -128,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:**
Expand All @@ -139,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
Expand All @@ -171,7 +171,7 @@ fallback_model:
| 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 `fallback_providers` — it is configured exclusively through `config.yaml`. This is intentional: fallback configuration is a deliberate choice, not something a stale shell export should override.
:::

---
Expand Down Expand Up @@ -259,13 +259,13 @@ 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
```

For `auxiliary.session_search`, Hermes also supports:
Expand All @@ -287,11 +287,11 @@ auxiliary:

If your provider does not support a native OpenAI-compatible reasoning-control field, `extra_body` will not help for that part; in that case `max_concurrency` is still useful for reducing request-burst 429s.

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).
Auxiliary, compression, and each fallback entry use the same provider fields: 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-provider 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](/docs/integrations/providers)).

| Provider | Description | Requirements |
|----------|-------------|-------------|
Expand Down Expand Up @@ -375,7 +375,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) |
| Vision | Auto-detection chain + internal OpenRouter retry | `auxiliary.vision` |
| Web extraction | Auto-detection chain + internal OpenRouter retry | `auxiliary.web_extract` |
| Context compression | Auto-detection chain, degrades to no-summary if unavailable | `auxiliary.compression` |
Expand Down
28 changes: 10 additions & 18 deletions website/docs/user-guide/features/kanban.md
Original file line number Diff line number Diff line change
Expand Up @@ -447,25 +447,17 @@ Visually the target is the familiar Linear / Fusion layout: dark theme, column h

The GUI is strictly a **read-through-the-DB + write-through-kanban_db** layer with no domain logic of its own:

```mermaid
flowchart TD
UI["React SPA plugin<br/>HTML5 drag-and-drop"]
API["FastAPI router<br/>plugins/kanban/dashboard/plugin_api.py"]
DB["~/.hermes/kanban.db<br/>WAL, shared"]

UI -->|REST over fetchJSON| API
API -->|writes call kanban_db.*<br/>same code path CLI /kanban verbs use| DB
DB -->|append task_events| UI
```
┌────────────────────────┐ WebSocket (tails task_events)
│ React SPA (plugin) │ ◀──────────────────────────────────┐
│ HTML5 drag-and-drop │ │
└──────────┬─────────────┘ │
│ REST over fetchJSON │
▼ │
┌────────────────────────┐ writes call kanban_db.* │
│ FastAPI router │ directly — same code path │
│ plugins/kanban/ │ the CLI /kanban verbs use │
│ dashboard/plugin_api.py │
└──────────┬─────────────┘ │
│ │
▼ │
┌────────────────────────┐ │
│ ~/.hermes/kanban.db │ ───── append task_events ──────────┘
│ (WAL, shared) │
└────────────────────────┘
```


### REST surface

Expand Down
Loading