{"repo":"NousResearch/hermes-agent","public_id":"19691","display_label":"Fallback provider docs config path corrections","summary":"Multiple issues and PRs addressing incorrect or stale configuration paths in documentation for fallback providers. The work centers on aligning docs with the actual top-level `fallback_providers` config shape and precedence behavior.","subsystem":"docs","counts":{"members":9,"open_issues":0,"open_issues_distinct":0,"open_prs":1,"closed_issues":1,"merged_prs":2,"attempt_prs":6},"landed_fix":{"status":"merged_to_main","basis":"structural","pr":34781,"merged_at":"2026-05-29T19:06:23+00:00"},"resolution":{"state":"unresolved","by":null},"freshness":{"state":"verified","last_verified_at":"2026-05-29T19:06:23+00:00","is_stale":false},"grouping":{"backbone":"STRUCTURAL_SPANNING","link_density":0.2222222222222222},"fix_edges":[{"issue_number":19691,"pr_number":20382,"tier":"verified","basis":"superseded_ref","confidence":0.9,"recoverable_from_timeline":false,"pr_merged_at":"2026-05-05T20:24:53+00:00"},{"issue_number":19691,"pr_number":34781,"tier":"verified","basis":"superseded_ref","confidence":0.9,"recoverable_from_timeline":false,"pr_merged_at":"2026-05-29T19:06:23+00:00"}],"members":[{"kind":"issue","number":19691,"title":"Fallback provider docs show stale/incorrect config paths for fallback_providers","url":null,"state":"closed"},{"kind":"pr","number":20033,"title":"docs(config): fix fallback provider config paths","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#19790","number":19790}],"category":"duplicate_of","implication":"duplicate"},"merged":false},{"kind":"pr","number":20382,"title":"docs(config): fix fallback provider config paths (salvage #20033)","url":null,"state":"merged","close_reason":{"category":"merged"},"merged":true,"is_fix_pr":true,"fix_tier":"verified","files_changed":["website/docs/reference/cli-commands.md","website/docs/reference/environment-variables.md"],"fix_hunks":[{"file":"website/docs/reference/cli-commands.md","hunks":["@@ -1093,7 +1093,7 @@ Typical session:\n 2. Use `↑`/`↓` to reorder fallbacks (first-in-list is tried first).\n 3. Press `d` to remove one.\n \n-All changes persist to `fallback_providers:` under `model:` in `config.yaml`. Interacts with [Credential Pools](/docs/user-guide/features/credential-pools): pools rotate keys *within* a provider, fallbacks switch to a *different* provider entirely.\n+All changes persist to the top-level `fallback_providers:` list in `config.yaml`. Interacts with [Credential Pools](/docs/user-guide/features/credential-pools): pools rotate keys *within* a provider, fallbacks switch to a *different* provider entirely.\n \n See [Fallback Providers](/docs/user-guide/features/fallback-providers) for behavior details and interaction with `fallback_model` (legacy single-fallback key).\n "]},{"file":"website/docs/reference/environment-variables.md","hunks":["@@ -514,16 +514,18 @@ Older configs with `compression.summary_model`, `compression.summary_provider`,\n \n For task-specific direct endpoints, Hermes uses the task's configured API key or `OPENAI_API_KEY`. It does not reuse `OPENROUTER_API_KEY` for those custom endpoints.\n \n-## Fallback Model (config.yaml only)\n+## Fallback Providers (config.yaml only)\n \n-The primary model fallback is configured exclusively through `config.yaml` — there are no environment variables for it. Add a `fallback_model` section with `provider` and `model` keys to enable automatic failover when your main model encounters errors.\n+The primary model fallback chain is configured exclusively through `config.yaml` — there are no environment variables for it. Add a top-level `fallback_providers` list with `provider` and `model` keys to enable automatic failover when your main model encounters errors.\n \n ```yaml\n-fallback_model:\n-  provider: openrouter\n-  model: anthropic/claude-sonnet-4\n+fallback_providers:\n+  - provider: openrouter\n+    model: anthropic/claude-sonnet-4\n ```\n \n+The older top-level `fallback_model` single-provider shape is still read for backward compatibility, but new configuration should use `fallback_providers`.\n+\n See [Fallback Providers](/docs/user-guide/features/fallback-providers) for full details.\n \n ## Provider Routing (config.yaml only)\n"]}]},{"kind":"pr","number":20516,"title":"docs(fallback): document the actual config shape (top-level fallback_providers) (#19691)","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#19790","number":19790},{"kind":"pr","value":"#19691","number":19691},{"kind":"pr","value":"#20382","number":20382}],"category":"implemented_elsewhere","implication":"superseded"},"merged":false},{"kind":"pr","number":23163,"title":"docs(fallback): align feature guide with fallback_providers","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#26017","number":26017},{"kind":"pr","value":"#34781","number":34781}],"category":"superseded_by_pr","implication":"superseded"},"merged":false},{"kind":"pr","number":23164,"title":"docs(config): align fallback config references with fallback_providers","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#26017","number":26017},{"kind":"pr","value":"#34781","number":34781}],"category":"superseded_by_pr","implication":"superseded"},"merged":false},{"kind":"pr","number":23165,"title":"docs(runtime): document fallback_providers precedence","url":null,"state":"open","close_reason":{"category":"silent_close","implication":"active"},"merged":false},{"kind":"pr","number":26017,"title":"fix(docs): align fallback provider config examples","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#23163","number":23163},{"kind":"pr","value":"#23164","number":23164},{"kind":"pr","value":"#19691","number":19691}],"category":"duplicate_of","implication":"duplicate"},"merged":false},{"kind":"pr","number":34781,"title":"docs: correctness sweep — 15 verified fixes (Bucket 1)","url":null,"state":"merged","close_reason":{"category":"merged"},"merged":true,"is_fix_pr":true,"fix_tier":"verified","files_changed":["CONTRIBUTING.md","agent/redact.py","cli-config.yaml.example","nix/nixosModules.nix","optional-skills/migration/openclaw-migration/SKILL.md","plugins/browser/browserbase/provider.py","scripts/release.py","skills/autonomous-ai-agents/hermes-agent/SKILL.md","skills/research/research-paper-writing/templates/acl/acl_lualatex.tex","tools/browser_tool.py","website/docs/developer-guide/architecture.md","website/docs/developer-guide/creating-skills.md","website/docs/developer-guide/prompt-assembly.md","website/docs/getting-started/nix-setup.md","website/docs/getting-started/quickstart.md","website/docs/guides/build-a-hermes-plugin.md","website/docs/guides/migrate-from-openclaw.md","website/docs/guides/work-with-skills.md","website/docs/reference/cli-commands.md","website/docs/reference/environment-variables.md","website/docs/user-guide/cli.md","website/docs/user-guide/configuration.md","website/docs/user-guide/configuring-models.md","website/docs/user-guide/features/browser.md","website/docs/user-guide/features/cron.md","website/docs/user-guide/features/curator.md","website/docs/user-guide/features/fallback-providers.md","website/docs/user-guide/features/memory-providers.md","website/docs/user-guide/features/skills.md","website/docs/user-guide/git-worktrees.md","website/docs/user-guide/messaging/simplex.md","website/docs/user-guide/security.md","website/docs/user-guide/sessions.md","website/docs/user-guide/skills/bundled/autonomous-ai-agents/autonomous-ai-agents-hermes-agent.md","website/docs/user-guide/skills/google-workspace.md","website/docs/user-guide/skills/optional/migration/migration-openclaw-migration.md"],"fix_hunks":[{"file":"CONTRIBUTING.md","hunks":["@@ -43,7 +43,7 @@ Bundled skills (in `skills/`) ship with every Hermes install. They should be **b\n - Document handling, web research, common dev workflows, system administration\n - Used regularly by a wide range of people\n \n-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 but isn't activated by default. Users can discover it via `hermes skills browse` (labeled \"official\") and install it with `hermes skills install` (no third-party warning, builtin trust).\n+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 but isn't activated by default. Users can discover it via `hermes skills browse` (labeled \"official\") and install it with `hermes skills install` (no third-party warning, built-in trust).\n \n If your skill is specialized, community-contributed, or niche, it's better suited for a **Skills Hub** — upload it to a skills registry and share it in the [Nous Research Discord](https://discord.gg/NousResearch). Users can install it with `hermes skills install`.\n "]},{"file":"agent/redact.py","hunks":["@@ -331,7 +331,7 @@ def redact_sensitive_text(text: str, *, force: bool = False, code_file: bool = F\n     \"\"\"Apply all redaction patterns to a block of text.\n \n     Safe to call on any string -- non-matching text passes through unchanged.\n-    Disabled by default — enable via security.redact_secrets: true in config.yaml.\n+    Enabled by default. Disable via security.redact_secrets: false in config.yaml.\n     Set force=True for safety boundaries that must never return raw secrets\n     regardless of the user's global logging redaction preference.\n "]},{"file":"cli-config.yaml.example","hunks":["@@ -163,7 +163,7 @@ model:\n # -----------------------------------------------------------------------------\n # Working directory behavior:\n #   - CLI (`hermes` command): Uses \".\" (current directory where you run hermes)\n-#   - Messaging (Telegram/Discord): Uses MESSAGING_CWD from .env (default: home)\n+#   - Gateway/messaging/cron: Uses terminal.cwd here; legacy .env cwd values are deprecated\n terminal:\n   backend: \"local\"\n   cwd: \".\"  # For local backend: \".\" = current directory. Ignored for remote backends unless a backend documents otherwise."]},{"file":"nix/nixosModules.nix","hunks":["@@ -242,7 +242,7 @@\n         type = types.str;\n         default = \"${cfg.stateDir}/workspace\";\n         defaultText = literalExpression ''\"''${cfg.stateDir}/workspace\"'';\n-        description = \"Working directory for the agent (MESSAGING_CWD).\";\n+        description = \"Working directory for the agent.\";\n       };\n \n       # ── Declarative config ───────────────────────────────────────────────"]},{"file":"optional-skills/migration/openclaw-migration/SKILL.md","hunks":["@@ -38,7 +38,7 @@ It uses `scripts/openclaw_to_hermes.py` to:\n - import `SOUL.md` into the Hermes home directory as `SOUL.md`\n - transform OpenClaw `MEMORY.md` and `USER.md` into Hermes memory entries\n - merge OpenClaw command approval patterns into Hermes `command_allowlist`\n-- migrate Hermes-compatible messaging settings such as `TELEGRAM_ALLOWED_USERS` and `MESSAGING_CWD`\n+- migrate Hermes-compatible messaging settings such as `TELEGRAM_ALLOWED_USERS`, and map OpenClaw workspace settings to Hermes working-directory configuration\n - copy OpenClaw skills into `~/.hermes/skills/openclaw-imports/`\n - optionally copy the OpenClaw workspace instructions file into a chosen Hermes workspace\n - mirror compatible workspace assets such as `workspace/tts/` into `~/.hermes/tts/`"]},{"file":"plugins/browser/browserbase/provider.py","hunks":["@@ -26,7 +26,7 @@\n     BROWSERBASE_PROXIES=true      # default true\n     BROWSERBASE_ADVANCED_STEALTH=false\n     BROWSERBASE_KEEP_ALIVE=true   # default true\n-    BROWSERBASE_SESSION_TIMEOUT=... (ms, integer)\n+    BROWSERBASE_SESSION_TIMEOUT=... (seconds, integer, max 21600 = 6h)\n \"\"\"\n \n from __future__ import annotations"]},{"file":"scripts/release.py","hunks":["@@ -45,6 +45,14 @@\n \n # Auto-extracted from noreply emails + manual overrides\n AUTHOR_MAP = {\n+    \"[redacted:email]\": \"HashClawAI\",\n+    \"[redacted:email]\": \"TonyPepeBear\",\n+    \"[redacted:email]\": \"nielskaspers\",\n+    \"[redacted:email]\": \"kurobaryo\",\n+    \"155192176+alelpoan@users.noreply.github.com\": \"alelpoan\",\n+    \"[redacted:email]\": \"Aman113114-IITD\",\n+    \"[redacted:email]\": \"octavioturra\",\n+    \"524706+Twanislas@users.noreply.github.com\": \"Twanislas\",\n     \"9592417+adam91holt@users.noreply.github.com\": \"adam91holt\",\n     \"kchuang1015@users.noreply.github.com\": \"kchuang1015\",\n     \"45688690+fujinice@users.noreply.github.com\": \"fujinice\","]},{"file":"skills/autonomous-ai-agents/hermes-agent/SKILL.md","hunks":["@@ -446,15 +446,15 @@ Common \"why is Hermes doing X to my output / tool calls / commands?\" toggles —\n \n ### Secret redaction in tool output\n \n-Secret redaction is **off by default** — tool output (terminal stdout, `read_file`, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:\n+Secret redaction is **on by default** — tool output (terminal stdout, `read_file`, web content, subagent summaries, etc.) is scanned for strings that look like API keys, tokens, and secrets before it enters the conversation context and logs. Leave it enabled for normal use:\n \n ```bash\n-hermes config set security.redact_secrets true       # enable globally\n+hermes config set security.redact_secrets true       # keep enabled globally\n ```\n \n-**Restart required.** `security.redact_secrets` is snapshotted at import time — toggling it mid-session (e.g. via `export HERMES_REDACT_SECRETS=true` from a tool call) will NOT take effect for the running process. Tell the user to run `hermes config set security.redact_secrets true` in a terminal, then start a new session. This is deliberate — it prevents an LLM from flipping the toggle on itself mid-task.\n+**Restart required.** `security.redact_secrets` is snapshotted at import time — toggling it mid-session (e.g. via `export HERMES_REDACT_SECRETS=false` from a tool call) will NOT take effect for the running process. Tell the user to change it in config from a terminal, then start a new session. This is deliberate — it prevents an LLM from flipping the toggle on itself mid-task.\n \n-Disable again with:\n+Disable only when you deliberately need raw credential-like strings for debugging or redactor development:\n ```bash\n hermes config set security.redact_secrets false\n ```"]},{"file":"skills/research/research-paper-writing/templates/acl/acl_lualatex.tex","hunks":["@@ -46,7 +46,7 @@\n % \\author{Author 1 \\\\ Address line \\\\  ... \\\\ Address line\n %         \\And  ... \\And\n %         Author n \\\\ Address line \\\\ ... \\\\ Address line}\n-% To start a seperate ``row'' of authors use \\AND, as in\n+% To start a separate ``row'' of authors use \\AND, as in\n % \\author{Author 1 \\\\ Address line \\\\  ... \\\\ Address line\n %         \\AND\n %         Author 2 \\\\ Address line \\\\ ... \\\\ Address line \\And"]},{"file":"tools/browser_tool.py","hunks":["@@ -33,8 +33,8 @@\n   requires Scale Plan (default: \"false\")\n - BROWSERBASE_KEEP_ALIVE: Enable keepAlive for session reconnection after disconnects,\n   requires paid plan (default: \"true\")\n-- BROWSERBASE_SESSION_TIMEOUT: Custom session timeout in milliseconds. Set to extend\n-  beyond project default. Common values: 600000 (10min), 1800000 (30min) (default: none)\n+- BROWSERBASE_SESSION_TIMEOUT: Custom session timeout in seconds (max 21600 = 6h).\n+  Set to extend beyond project default. Common values: 600 (10min), 1800 (30min) (default: none)\n \n Usage:\n     from tools.browser_tool import browser_navigate, browser_snapshot, browser_click"]},{"file":"website/docs/developer-guide/architecture.md","hunks":["@@ -197,7 +197,7 @@ The synchronous orchestration engine (`AIAgent` in `run_agent.py`). Handles prov\n \n Prompt construction and maintenance across the conversation lifecycle:\n \n-- **`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\n+- **`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\n - **`prompt_caching.py`** — Applies Anthropic cache breakpoints for prefix caching\n - **`context_compressor.py`** — Summarizes middle conversation turns when context exceeds thresholds\n "]},{"file":"website/docs/developer-guide/creating-skills.md","hunks":["@@ -330,7 +330,7 @@ Bundled skills (in `skills/`) ship with every Hermes install. They should be **b\n - Document handling, web research, common dev workflows, system administration\n - Used regularly by a wide range of people\n \n-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.\n+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.\n \n 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`.\n ","@@ -363,7 +363,7 @@ All hub-installed skills go through a security scanner that checks for:\n \n Trust levels:\n - `builtin` — ships with Hermes (always trusted)\n-- `official` — from `optional-skills/` in the repo (builtin trust, no third-party warning)\n+- `official` — from `optional-skills/` in the repo (built-in trust, no third-party warning)\n - `trusted` — from openai/skills, anthropics/skills, huggingface/skills\n - `community` — non-dangerous findings can be overridden with `--force`; `dangerous` verdicts remain blocked\n "]},{"file":"website/docs/developer-guide/prompt-assembly.md","hunks":["@@ -26,18 +26,18 @@ Primary files:\n \n ## Cached system prompt layers\n \n-The cached system prompt is assembled in roughly this order:\n-\n-1. agent identity — `SOUL.md` from `HERMES_HOME` when available, otherwise falls back to `DEFAULT_AGENT_IDENTITY` in `prompt_builder.py`\n-2. tool-aware behavior guidance\n-3. Honcho static block (when active)\n-4. optional system message\n-5. frozen MEMORY snapshot\n-6. frozen USER profile snapshot\n-7. skills index\n-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\n-9. timestamp / optional session ID\n-10. platform hint\n+The cached system prompt is assembled as three ordered tiers (see `agent/system_prompt.py`):\n+\n+1. **stable** — identity (`SOUL.md` or fallback), tool/model guidance, skills prompt, environment hints, platform hints\n+2. **context** — caller-supplied `system_message` plus project context files (`.hermes.md` / `AGENTS.md` / `CLAUDE.md` / `.cursorrules`)\n+3. **volatile** — built-in memory snapshot (`MEMORY.md`), user profile snapshot (`USER.md`), external memory-provider block, timestamp/session/model/provider line\n+\n+The final system prompt is then joined as: `stable` → `context` → `volatile`.\n+\n+This ordering matters for precedence discussions:\n+- skills are part of the **stable** tier\n+- memory/profile snapshots are part of the **volatile** tier\n+- both are still in the cached system prompt (they are not injected as ad-hoc mid-turn overlays)\n \n When `skip_context_files` is set (e.g., subagent delegation), SOUL.md is not loaded and the hardcoded `DEFAULT_AGENT_IDENTITY` is used instead.\n ","@@ -205,13 +205,15 @@ These are intentionally *not* persisted as part of the cached system prompt:\n - `ephemeral_system_prompt`\n - prefill messages\n - gateway-derived session context overlays\n-- later-turn Honcho recall injected into the current-turn user message\n+- later-turn Honcho/external recall injected into the current-turn user message\n+\n+`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)).\n \n This separation keeps the stable prefix stable for caching.\n \n ## Memory snapshots\n \n-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.\n+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).\n \n ## Context files\n "]},{"file":"website/docs/getting-started/nix-setup.md","hunks":["@@ -583,7 +583,7 @@ Host                                    Container\n   │   ├── state.db, sessions/, memories/   (runtime state)\n   │   └── mcp-tokens/                      (OAuth tokens for MCP servers)\n   ├── home/                                ──►  /home/hermes    (rw)\n-  └── workspace/                           (MESSAGING_CWD)\n+  └── workspace/                           (agent working directory)\n       ├── SOUL.md                          (from documents option)\n       └── (agent-created files)\n ","@@ -831,7 +831,7 @@ nix build .#checks.x86_64-linux.config-roundtrip    # merge script preserves use\n | `group` | `str` | `\"hermes\"` | System group |\n | `createUser` | `bool` | `true` | Auto-create user/group |\n | `stateDir` | `str` | `\"/var/lib/hermes\"` | State directory (`HERMES_HOME` parent) |\n-| `workingDirectory` | `str` | `\"${stateDir}/workspace\"` | Agent working directory (`MESSAGING_CWD`) |\n+| `workingDirectory` | `str` | `\"${stateDir}/workspace\"` | Agent working directory |\n | `addToSystemPackages` | `bool` | `false` | Add `hermes` CLI to system PATH and set `HERMES_HOME` system-wide |\n \n ### Configuration","@@ -918,7 +918,7 @@ nix build .#checks.x86_64-linux.config-roundtrip    # merge script preserves use\n │   ├── cron/\n │   └── logs/\n ├── home/                            # Agent HOME\n-└── workspace/                       # MESSAGING_CWD\n+└── workspace/                       # Agent working directory\n     ├── SOUL.md                      # From documents option\n     └── (agent-created files)\n ```"]},{"file":"website/docs/getting-started/quickstart.md","hunks":["@@ -10,7 +10,7 @@ This guide gets you from zero to a working Hermes setup that survives real use.\n \n ## Prefer to watch?\n \n-**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.\n+**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.\n \n <div style={{position: 'relative', paddingBottom: '56.25%', height: 0, overflow: 'hidden', maxWidth: '100%', marginBottom: '1.5rem'}}>\n   <iframe"]},{"file":"website/docs/guides/build-a-hermes-plugin.md","hunks":["@@ -770,7 +770,7 @@ def register(ctx):\n **Runtime behavior:**\n \n - **CLI mode:** `parent_agent` is resolved from the active CLI agent so workspace hints, spinner, and model selection inherit as expected.\n-- **Gateway mode:** There is no CLI agent, so tools degrade gracefully — workspace is read from `TERMINAL_CWD` and no spinner is shown.\n+- **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.\n - **Explicit override:** If the caller passes `parent_agent=` explicitly, it is respected and not overwritten.\n \n 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."]},{"file":"website/docs/guides/migrate-from-openclaw.md","hunks":["@@ -160,7 +160,7 @@ TTS settings are read from **two** OpenClaw config locations with this priority:\n | Browser headless | `browser.headless` | `config.yaml` → `browser.headless` | |\n | Brave search key | `tools.web.search.brave.apiKey` | `.env` → `BRAVE_API_KEY` | Requires `--migrate-secrets` |\n | Gateway auth token | `gateway.auth.token` | `.env` → `HERMES_GATEWAY_TOKEN` | Requires `--migrate-secrets` |\n-| Working directory | `agents.defaults.workspace` | `.env` → `MESSAGING_CWD` | |\n+| Working directory | `agents.defaults.workspace` | `config.yaml` → `terminal.cwd` | Legacy migrations may still emit `MESSAGING_CWD` as a compatibility fallback |\n \n ### Archived (no direct Hermes equivalent)\n ","@@ -229,7 +229,7 @@ The migration resolves all three formats. For env templates and SecretRef object\n \n 5. **Test messaging** — if you migrated platform tokens, restart the gateway: `systemctl --user restart hermes-gateway`\n \n-6. **Check session policies** — verify `hermes config get session_reset` matches your expectations.\n+6. **Check session policies** — run `hermes config show` and verify the `session_reset` value matches your expectations.\n \n 7. **Re-pair WhatsApp** — WhatsApp uses QR code pairing (Baileys), not token migration. Run `hermes whatsapp` to pair.\n "]},{"file":"website/docs/guides/work-with-skills.md","hunks":["@@ -162,7 +162,7 @@ Manage skill config from the CLI:\n hermes skills config gif-search\n \n # View all skill config\n-hermes config get skills.config\n+hermes config show | grep '^skills\\.config'\n ```\n \n ---"]},{"file":"website/docs/reference/cli-commands.md","hunks":["@@ -1373,7 +1373,7 @@ hermes completion fish > ~/.config/fish/completions/hermes.fish\n ## `hermes update`\n \n ```bash\n-hermes update [--check] [--backup] [--restart-gateway]\n+hermes update [--gateway] [--check] [--no-backup] [--backup] [--yes]\n ```\n \n 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.","@@ -1382,12 +1382,15 @@ Pulls the latest `hermes-agent` code and reinstalls dependencies in your venv, t\n \n | Option | Description |\n |--------|-------------|\n-| `--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. |\n-| `--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`. |\n-| `--restart-gateway` | After a successful update, restart the running gateway service. Implies `--all` semantics if multiple profiles are installed. |\n+| `--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. |\n+| `--check` | Check whether an update is available without pulling, installing dependencies, or restarting anything. |\n+| `--no-backup` | Skip the pre-update backup for this run, even if `updates.pre_update_backup` is enabled in `config.yaml`. |\n+| `--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`. |\n+| `--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. |\n \n Additional behavior:\n \n+- **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.\n - **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.\n - **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.\n - **Exit codes.** `0` on success, `1` on pull/install/post-install errors, `2` on unexpected working-tree changes that block `git pull`."]},{"file":"website/docs/reference/environment-variables.md","hunks":["@@ -197,7 +197,7 @@ These variables configure the [Tool Gateway](/user-guide/features/tool-gateway)\n | `TERMINAL_DAYTONA_IMAGE` | Daytona sandbox image |\n | `TERMINAL_TIMEOUT` | Command timeout in seconds |\n | `TERMINAL_LIFETIME_SECONDS` | Max lifetime for terminal sessions in seconds |\n-| `TERMINAL_CWD` | Working directory for terminal sessions (gateway/cron only; CLI uses launch dir) |\n+| `TERMINAL_CWD` | Deprecated direct override for gateway/cron terminal sessions. Prefer `terminal.cwd` in `config.yaml`; CLI still uses the launch directory. |\n | `SUDO_PASSWORD` | Enable sudo without interactive prompt |\n \n 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.","@@ -412,7 +412,7 @@ For cloud sandbox backends, persistence is filesystem-oriented. `TERMINAL_LIFETI\n | `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. |\n | `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`. |\n | `GATEWAY_PROXY_KEY` | Bearer token for authenticating with the remote API server in proxy mode. Must match `API_SERVER_KEY` on the remote host. |\n-| `MESSAGING_CWD` | Working directory for terminal commands in messaging mode (default: `~`) |\n+| `MESSAGING_CWD` | Deprecated compatibility fallback for gateway working directory. Prefer `terminal.cwd` in `config.yaml`. |\n | `GATEWAY_ALLOWED_USERS` | Comma-separated user IDs allowed across all platforms |\n | `GATEWAY_ALLOW_ALL_USERS` | Allow all users without allowlists (`true`/`false`, default: `false`) |\n "]},{"file":"website/docs/user-guide/cli.md","hunks":["@@ -53,7 +53,7 @@ hermes -w -q \"Fix issue #123\"     # Single query in worktree\n \n ## Interface Layout\n \n-<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.\" />\n+<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.\" />\n <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>\n \n The welcome banner shows your model, terminal backend, working directory, available tools, and installed skills at a glance."]},{"file":"website/docs/user-guide/configuration.md","hunks":["@@ -864,7 +864,7 @@ Available providers for auxiliary tasks: `auto`, `main`, plus any provider in th\n :::\n \n :::warning `\"main\"` is for auxiliary tasks only\n-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](/integrations/providers) for all main model provider options.\n+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.\n :::\n \n ### Full auxiliary config reference","@@ -934,7 +934,7 @@ Each auxiliary task has a configurable `timeout` (in seconds). Defaults: vision\n :::\n \n :::info\n-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](/integrations/providers#fallback-providers). All three follow the same provider/model/base_url pattern.\n+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.\n :::\n \n ### OpenRouter routing & Pareto Code for auxiliary tasks","@@ -977,7 +977,7 @@ AUXILIARY_VISION_MODEL=openai/gpt-4o\n \n ### Provider Options\n \n-These options apply to **auxiliary task configs** (`auxiliary:`, `compression:`, `fallback_model:`), not to your main `model.provider` setting.\n+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.\n \n | Provider | Description | Requirements |\n |----------|-------------|-------------|","@@ -1584,7 +1584,7 @@ Pre-execution security scanning and secret redaction:\n \n ```yaml\n security:\n-  redact_secrets: false          # Redact API key patterns in tool output and logs (off by default)\n+  redact_secrets: true           # Redact API key patterns in tool output and logs (on by default)\n   tirith_enabled: true           # Enable Tirith security scanning for terminal commands\n   tirith_path: \"tirith\"          # Path to tirith binary (default: \"tirith\" in $PATH)\n   tirith_timeout: 5              # Seconds to wait for tirith scan before timing out","@@ -1595,7 +1595,7 @@ security:\n     shared_files: []\n ```\n \n-- `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.\n+- `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.\n - `tirith_enabled` — when `true`, terminal commands are scanned by [Tirith](https://github.com/sheeki03/tirith) before execution to detect potentially dangerous operations.\n - `tirith_path` — path to the tirith binary. Set this if tirith is installed in a non-standard location.\n - `tirith_timeout` — maximum seconds to wait for a tirith scan. Commands proceed if the scan times out.","@@ -1726,12 +1726,14 @@ See also:\n | Context | Default |\n |---------|---------|\n | **CLI (`hermes`)** | Current directory where you run the command |\n-| **Messaging gateway** | Home directory `~` (override with `MESSAGING_CWD`) |\n+| **Messaging gateway** | `terminal.cwd` from `~/.hermes/config.yaml`; if unset, home directory `~` |\n | **Docker / Singularity / Modal / SSH** | User's home directory inside the container or remote machine |\n \n Override the working directory:\n-```bash\n-# In ~/.hermes/.env or ~/.hermes/config.yaml:\n-MESSAGING_CWD=/home/myuser/projects    # Gateway sessions\n-TERMINAL_CWD=/workspace                # All terminal sessions\n+```yaml\n+# In ~/.hermes/config.yaml:\n+terminal:\n+  cwd: /home/myuser/projects\n ```\n+\n+`MESSAGING_CWD` and direct `TERMINAL_CWD` entries in `~/.hermes/.env` are legacy compatibility fallbacks. New configurations should use `terminal.cwd`."]},{"file":"website/docs/user-guide/configuring-models.md","hunks":["@@ -206,7 +206,7 @@ hermes model            # Interactive provider + model picker (the canonical way\n \n `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`.\n \n-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`.\n+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`.\n \n ### Direct config edit\n "]},{"file":"website/docs/user-guide/features/browser.md","hunks":["@@ -395,9 +395,9 @@ BROWSERBASE_ADVANCED_STEALTH=false\n # Session reconnection after disconnects — requires paid plan (default: \"true\")\n BROWSERBASE_KEEP_ALIVE=true\n \n-# Custom session timeout in milliseconds (default: project default)\n-# Examples: 600000 (10min), 1800000 (30min)\n-BROWSERBASE_SESSION_TIMEOUT=600000\n+# Custom session timeout in seconds (max 21600 = 6 hours) (default: project default)\n+# Examples: 600 (10min), 1800 (30min), 21600 (6h max)\n+BROWSERBASE_SESSION_TIMEOUT=1800\n \n # Inactivity timeout before auto-cleanup in seconds (default: 120)\n BROWSER_INACTIVITY_TIMEOUT=120"]},{"file":"website/docs/user-guide/features/cron.md","hunks":["@@ -117,12 +117,12 @@ cronjob(\n When `workdir` is set:\n \n - `AGENTS.md`, `CLAUDE.md`, and `.cursorrules` from that directory are injected into the system prompt (same discovery order as the interactive CLI)\n-- `terminal`, `read_file`, `write_file`, `patch`, `search_files`, and `execute_code` all use that directory as their working directory (via `TERMINAL_CWD`)\n+- `terminal`, `read_file`, `write_file`, `patch`, `search_files`, and `execute_code` all use that directory as their working directory\n - The path must be an absolute directory that exists — relative paths and missing directories are rejected at create / update time\n - Pass `--workdir \"\"` (or `workdir=\"\"` via the tool) on edit to clear it and restore the old behaviour\n \n :::note Serialization\n-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.\n+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.\n :::\n \n ## Running cron jobs in a specific profile"]},{"file":"website/docs/user-guide/features/curator.md","hunks":["@@ -130,30 +130,45 @@ The same subcommands are available as the `/curator` slash command inside a runn\n \n ## What \"agent-created\" means\n \n-A skill is considered agent-created if its name is **not** in:\n-\n-- `~/.hermes/skills/.bundled_manifest` (skills copied from the repo on install), and\n-- `~/.hermes/skills/.hub/lock.json` (skills installed via `hermes skills install`).\n-\n-Everything else in `~/.hermes/skills/` is fair game for the curator. This includes:\n-\n-- Skills the agent saved via `skill_manage(action=\"create\")` during a conversation.\n-- Skills you created manually with a hand-written `SKILL.md`.\n-- Skills added via external skill directories you've pointed Hermes at.\n-\n-:::warning Your hand-written skills look the same as agent-saved ones\n-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.\n-\n-Before the first real pass (7 days after installation by default), take a moment to:\n+The curator only manages skills explicitly marked as **agent-created** in\n+`~/.hermes/skills/.usage.json`. A skill qualifies when ALL of the following\n+are true:\n+\n+1. Its name is **not** in `~/.hermes/skills/.bundled_manifest` (bundled skills shipped with the repo).\n+2. Its name is **not** in `~/.hermes/skills/.hub/lock.json` (hub-installed skills).\n+3. Its `.usage.json` entry has `\"created_by\": \"agent\"` or `\"agent_created\": true`.\n+\n+Currently, only the **background self-improvement review fork** sets this marker\n+— when it creates a new umbrella skill during its periodic review pass (~every 10\n+agent turns). The background fork runs with a write origin of `\"background_review\"`\n+(via `tools/skill_provenance.py`), which is the only path that triggers the\n+`mark_agent_created()` call in `skill_manage`.\n+\n+Skills the foreground agent creates via `skill_manage(action=\"create\")` during a\n+conversation are **not** marked as agent-created — they are considered\n+user-directed and the curator intentionally leaves them alone.\n+\n+:::warning Your hand-written skills are NOT curated\n+If you manually created a `SKILL.md` or pointed Hermes at an external skill\n+directory, that skill will have a `.usage.json` entry with `created_by: null`\n+(or the field absent). The curator will not touch it. The same applies to\n+skills the foreground agent created at your request.\n+\n+**To see which skills the curator actually manages**, run `hermes curator status`.\n+If the agent-created count is 0, no skills are currently in the curator's\n+jurisdiction — the LLM review pass is skipped and the report will show\n+`Model: (not resolved) via (not resolved)` with `Duration: 0s`.\n+:::\n \n-1. Run `hermes curator run --dry-run` to see exactly what the curator would propose.\n-2. Use `hermes curator pin <name>` to fence off anything you don't want touched.\n-3. Or set `curator.enabled: false` in `config.yaml` if you'd rather manage the library yourself.\n+Skills that ARE agent-created follow the full lifecycle:\n \n-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.\n-:::\n+- `active` → (30d unused) `stale` → (90d unused) `archived`\n+- Pinned skills bypass all auto-transitions\n+- Archives are recoverable via `hermes curator restore <name>`\n \n-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.\n+If you want to protect a specific skill from ever being touched — for example a\n+hand-authored skill you rely on — use `hermes curator pin <name>`. See the next\n+section.\n \n ## Pinning a skill\n ","@@ -217,6 +232,15 @@ Every curator run writes a timestamped directory under `~/.hermes/logs/curator/`\n \n `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`.\n \n+:::note No candidates? Report shows `(not resolved)`\n+When the curator has **no agent-created skills** to review, the LLM review pass\n+is skipped entirely. The report header will show\n+`Model: (not resolved) via (not resolved)` with `Duration: 0s` — this does **not**\n+indicate a configuration error or model resolution failure. It simply means there\n+were no candidates, so no model was ever invoked. The auto-transition phase still\n+runs and reports its counts normally.\n+:::\n+\n ### Rename map in the summary\n \n 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."]},{"file":"website/docs/user-guide/features/fallback-providers.md","hunks":["@@ -29,18 +29,18 @@ hermes fallback\n \n `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`.\n \n-If you'd rather edit the YAML directly, add a `fallback_model` section to `~/.hermes/config.yaml`:\n+If you'd rather edit the YAML directly, add a top-level `fallback_providers` list to `~/.hermes/config.yaml`:\n \n ```yaml\n-fallback_model:\n-  provider: openrouter\n-  model: anthropic/claude-sonnet-4\n+fallback_providers:\n+  - provider: openrouter\n+    model: anthropic/claude-sonnet-4\n ```\n \n-Both `provider` and `model` are **required**. If either is missing, the fallback is disabled.\n+Each entry requires both `provider` and `model`. Entries missing either field are ignored.\n \n :::note `fallback_model` vs `fallback_providers`\n-`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.\n+`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.\n :::\n \n ### Supported Providers","@@ -90,11 +90,11 @@ Both `provider` and `model` are **required**. If either is missing, the fallback\n For a custom OpenAI-compatible endpoint, add `base_url` and optionally `key_env`:\n \n ```yaml\n-fallback_model:\n-  provider: custom\n-  model: my-local-model\n-  base_url: http://localhost:8000/v1\n-  key_env: MY_LOCAL_KEY              # env var name containing the API key\n+fallback_providers:\n+  - provider: custom\n+    model: my-local-model\n+    base_url: http://localhost:8000/v1\n+    key_env: MY_LOCAL_KEY            # env var name containing the API key\n ```\n \n ### When Fallback Triggers","@@ -128,9 +128,9 @@ model:\n   provider: anthropic\n   default: claude-sonnet-4-6\n \n-fallback_model:\n-  provider: openrouter\n-  model: anthropic/claude-sonnet-4\n+fallback_providers:\n+  - provider: openrouter\n+    model: anthropic/claude-sonnet-4\n ```\n \n **Nous Portal as fallback for OpenRouter:**","@@ -139,25 +139,25 @@ model:\n   provider: openrouter\n   default: anthropic/claude-opus-4\n \n-fallback_model:\n-  provider: nous\n-  model: nous-hermes-3\n+fallback_providers:\n+  - provider: nous\n+    model: nous-hermes-3\n ```\n \n **Local model as fallback for cloud:**\n ```yaml\n-fallback_model:\n-  provider: custom\n-  model: llama-3.1-70b\n-  base_url: http://localhost:8000/v1\n-  key_env: LOCAL_API_KEY\n+fallback_providers:\n+  - provider: custom\n+    model: llama-3.1-70b\n+    base_url: http://localhost:8000/v1\n+    key_env: LOCAL_API_KEY\n ```\n \n **Codex OAuth as fallback:**\n ```yaml\n-fallback_model:\n-  provider: openai-codex\n-  model: gpt-5.3-codex\n+fallback_providers:\n+  - provider: openai-codex\n+    model: gpt-5.3-codex\n ```\n \n ### Where Fallback Works","@@ -166,12 +166,12 @@ fallback_model:\n |---------|-------------------|\n | CLI sessions | ✔ |\n | Messaging gateway (Telegram, Discord, etc.) | ✔ |\n-| Subagent delegation | ✘ (subagents do not inherit fallback config) |\n-| Cron jobs | ✘ (run with a fixed provider) |\n+| Subagent delegation | ✔ (subagents inherit the parent fallback chain) |\n+| Cron jobs | ✔ (cron agents inherit configured fallback providers) |\n | Auxiliary tasks (vision, compression) | ✘ (use their own provider chain — see below) |\n \n :::tip\n-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.\n+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.\n :::\n \n ---","@@ -252,20 +252,20 @@ auxiliary:\n     base_url: null                                    # Custom OpenAI-compatible endpoint\n ```\n \n-And the fallback model uses:\n+And the primary fallback chain uses:\n \n ```yaml\n-fallback_model:\n-  provider: openrouter\n-  model: anthropic/claude-sonnet-4\n-  # base_url: http://localhost:8000/v1               # Optional custom endpoint\n+fallback_providers:\n+  - provider: openrouter\n+    model: anthropic/claude-sonnet-4\n+    # base_url: http://localhost:8000/v1             # Optional custom endpoint\n ```\n \n 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).\n \n ### Provider Options for Auxiliary Tasks\n \n-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](/integrations/providers)).\n+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)).\n \n | Provider | Description | Requirements |\n |----------|-------------|-------------|","@@ -362,7 +362,7 @@ If no provider is available for compression, Hermes drops middle conversation tu\n \n ## Delegation Provider Override\n \n-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:\n+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:\n \n ```yaml\n delegation:","@@ -378,7 +378,7 @@ See [Subagent Delegation](/user-guide/features/delegation) for full configuratio\n \n ## Cron Job Providers\n \n-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:\n+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:\n \n ```python\n cronjob(","@@ -398,7 +398,7 @@ See [Scheduled Tasks (Cron)](/user-guide/features/cron) for full configuration d\n \n | Feature | Fallback Mechanism | Config Location |\n |---------|-------------------|----------------|\n-| Main agent model | `fallback_model` in config.yaml — per-turn failover on errors (primary restored each turn) | `fallback_model:` (top-level) |\n+| Main agent model | `fallback_providers` in config.yaml — per-turn failover on errors (primary restored each turn) | `fallback_providers:` (top-level list) |\n | Auxiliary tasks (any) — auto users | Full auto-detection chain (main agent model first, then provider chain) on capacity errors | `auxiliary.<task>.provider: auto` |\n | Auxiliary tasks (any) — explicit provider | `fallback_chain` (if set) → main agent model → warn + raise, on capacity errors only | `auxiliary.<task>.fallback_chain` |\n | Vision | Layered (see above) + internal OpenRouter retry | `auxiliary.vision` |"]},{"file":"website/docs/user-guide/features/memory-providers.md","hunks":["@@ -68,7 +68,7 @@ hermes memory setup        # select \"honcho\" — runs the Honcho-specific post-s\n \n 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.\n \n-**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).\n+**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).\n \n <details>\n <summary>Full config reference</summary>","@@ -255,7 +255,7 @@ See the [Honcho page](./honcho.md#observation-directional-vs-unified) for the fu\n \n </details>\n \n-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).\n+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).\n \n \n ---"]},{"file":"website/docs/user-guide/features/skills.md","hunks":["@@ -419,7 +419,7 @@ Hermes currently integrates with these skills ecosystems and discovery sources:\n \n #### 1. Official optional skills (`official`)\n \n-These are maintained in the Hermes repository itself and install with builtin trust.\n+These are maintained in the Hermes repository itself and install with built-in trust.\n \n - Catalog: [Official Optional Skills Catalog](../../reference/optional-skills-catalog)\n - Source in repo: `optional-skills/`","@@ -569,14 +569,14 @@ hermes skills install skills-sh/anthropics/skills/pdf --force\n Important behavior:\n - `--force` can override policy blocks for caution/warn-style findings.\n - `--force` does **not** override a `dangerous` scan verdict.\n-- Official optional skills (`official/...`) are treated as builtin trust and do not show the third-party warning panel.\n+- Official optional skills (`official/...`) are treated as built-in trust and do not show the third-party warning panel.\n \n ### Trust levels\n \n | Level | Source | Policy |\n |-------|--------|--------|\n | `builtin` | Ships with Hermes | Always trusted |\n-| `official` | `optional-skills/` in the repo | Builtin trust, no third-party warning |\n+| `official` | `optional-skills/` in the repo | Built-in trust, no third-party warning |\n | `trusted` | Trusted registries/repos such as `openai/skills`, `anthropics/skills`, `huggingface/skills` | More permissive policy than community sources |\n | `community` | Everything else (`skills.sh`, well-known endpoints, custom GitHub repos, most marketplaces) | Non-dangerous findings can be overridden with `--force`; `dangerous` verdicts stay blocked |\n "]},{"file":"website/docs/user-guide/git-worktrees.md","hunks":["@@ -21,7 +21,7 @@ This page shows how to combine worktrees with Hermes so each session has a clean\n Hermes treats the **current working directory** as the project root:\n \n - CLI: the directory where you run `hermes` or `hermes chat`\n-- Messaging gateways: the directory set by `MESSAGING_CWD`\n+- Messaging gateways: the directory set by `terminal.cwd` in `~/.hermes/config.yaml`\n \n If you run multiple agents in the **same checkout**, their changes can interfere with each other:\n ","@@ -171,4 +171,3 @@ This combination gives you:\n - Strong guarantees that different agents and experiments do not step on each other.\n - Fast iteration cycles with easy recovery from bad edits.\n - Clean, reviewable pull requests.\n-"]},{"file":"website/docs/user-guide/messaging/simplex.md","hunks":["@@ -15,7 +15,7 @@ Download the latest release from the [simplex-chat GitHub releases](https://gith\n \n ```bash\n # Linux / macOS binary\n-curl -L https://github.com/simplex-chat/simplex-chat/releases/latest/download/simplex-chat-ubuntu-22_04-x86-64 -o simplex-chat\n+curl -L https://github.com/simplex-chat/simplex-chat/releases/latest/download/simplex-chat-ubuntu-22_04-x86_64 -o simplex-chat\n chmod +x simplex-chat\n ```\n "]},{"file":"website/docs/user-guide/security.md","hunks":["@@ -586,7 +586,7 @@ Blocked files show a warning:\n 4. **Store secrets securely** — keep API keys in `~/.hermes/.env` with proper file permissions\n 5. **Enable DM pairing** — use pairing codes instead of hardcoding user IDs when possible\n 6. **Review command allowlist** — periodically audit `command_allowlist` in config.yaml\n-7. **Set `MESSAGING_CWD`** — don't let the agent operate from sensitive directories\n+7. **Set `terminal.cwd`** — don't let the agent operate from sensitive directories\n 8. **Run as non-root** — never run the gateway as root\n 9. **Monitor logs** — check `~/.hermes/logs/` for unauthorized access attempts\n 10. **Keep updated** — run `hermes update` regularly for security patches"]},{"file":"website/docs/user-guide/sessions.md","hunks":["@@ -4,6 +4,8 @@ title: \"Sessions\"\n description: \"Session persistence, resume, search, management, and per-platform session tracking\"\n ---\n \n+import useBaseUrl from '@docusaurus/useBaseUrl';\n+\n # Sessions\n \n Hermes Agent automatically saves every conversation as a session. Sessions enable conversation resume, cross-session search, and full conversation history management.","@@ -144,7 +146,7 @@ Session IDs are shown when you exit a CLI session, and can be found with `hermes\n \n When you resume a session, Hermes displays a compact recap of the previous conversation in a styled panel before the input prompt:\n \n-<img className=\"docs-terminal-figure\" src=\"/img/docs/session-recap.svg\" alt=\"Stylized preview of the Previous Conversation recap panel shown when resuming a Hermes session.\" />\n+<img className=\"docs-terminal-figure\" src={useBaseUrl('/img/docs/session-recap.svg')} alt=\"Stylized preview of the Previous Conversation recap panel shown when resuming a Hermes session.\" />\n <p className=\"docs-figure-caption\">Resume mode shows a compact recap panel with recent user and assistant turns before returning you to the live prompt.</p>\n \n The recap:"]},{"file":"website/docs/user-guide/skills/bundled/autonomous-ai-agents/autonomous-ai-agents-hermes-agent.md","hunks":["@@ -463,15 +463,15 @@ Common \"why is Hermes doing X to my output / tool calls / commands?\" toggles —\n \n ### Secret redaction in tool output\n \n-Secret redaction is **off by default** — tool output (terminal stdout, `read_file`, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:\n+Secret redaction is **on by default** — tool output (terminal stdout, `read_file`, web content, subagent summaries, etc.) is scanned for strings that look like API keys, tokens, and secrets before it enters the conversation context and logs. Leave it enabled for normal use:\n \n ```bash\n-hermes config set security.redact_secrets true       # enable globally\n+hermes config set security.redact_secrets true       # keep enabled globally\n ```\n \n-**Restart required.** `security.redact_secrets` is snapshotted at import time — toggling it mid-session (e.g. via `export HERMES_REDACT_SECRETS=true` from a tool call) will NOT take effect for the running process. Tell the user to run `hermes config set security.redact_secrets true` in a terminal, then start a new session. This is deliberate — it prevents an LLM from flipping the toggle on itself mid-task.\n+**Restart required.** `security.redact_secrets` is snapshotted at import time — toggling it mid-session (e.g. via `export HERMES_REDACT_SECRETS=false` from a tool call) will NOT take effect for the running process. Tell the user to change it in config from a terminal, then start a new session. This is deliberate — it prevents an LLM from flipping the toggle on itself mid-task.\n \n-Disable again with:\n+Disable only when you deliberately need raw credential-like strings for debugging or redactor development:\n ```bash\n hermes config set security.redact_secrets false\n ```"]},{"file":"website/docs/user-guide/skills/google-workspace.md","hunks":["@@ -7,7 +7,7 @@ description: \"Send email, manage calendar events, search Drive, read/write Sheet\n \n # Google Workspace Skill\n \n-Gmail, Calendar, Drive, Contacts, Sheets, and Docs integration for Hermes. Uses OAuth2 with automatic token refresh. Prefers the [Google Workspace CLI (`gws`)](https://github.com/nicholasgasior/gws) when available for broader coverage, and falls back to Google's Python client libraries otherwise.\n+Gmail, Calendar, Drive, Contacts, Sheets, and Docs integration for Hermes. Uses OAuth2 with automatic token refresh. Prefers the [Google Workspace CLI (`gws`)](https://github.com/googleworkspace/cli) when available for broader coverage, and falls back to Google's Python client libraries otherwise.\n \n **Skill path:** `skills/productivity/google-workspace/`\n "]},{"file":"website/docs/user-guide/skills/optional/migration/migration-openclaw-migration.md","hunks":["@@ -56,7 +56,7 @@ It uses `scripts/openclaw_to_hermes.py` to:\n - import `SOUL.md` into the Hermes home directory as `SOUL.md`\n - transform OpenClaw `MEMORY.md` and `USER.md` into Hermes memory entries\n - merge OpenClaw command approval patterns into Hermes `command_allowlist`\n-- migrate Hermes-compatible messaging settings such as `TELEGRAM_ALLOWED_USERS` and `MESSAGING_CWD`\n+- migrate Hermes-compatible messaging settings such as `TELEGRAM_ALLOWED_USERS`, and map OpenClaw workspace settings to Hermes working-directory configuration\n - copy OpenClaw skills into `~/.hermes/skills/openclaw-imports/`\n - optionally copy the OpenClaw workspace instructions file into a chosen Hermes workspace\n - mirror compatible workspace assets such as `workspace/tts/` into `~/.hermes/tts/`\n"]}]}],"trust":{"default_tier":"verified","includes_suggested":false}}