# Hermes Configuration Discipline

Do not modify Hermes config.yaml by adding keys you guessed or assumed existed.
Always verify before applying.

## The Rule

**You must verify every config key exists in official Hermes documentation before adding it to config.yaml.**

Hermes config keys are not arbitrary YAML — they are read by specific code paths in the Hermes runtime. A made-up key is silently ignored, not validated, and leaves you thinking a feature was configured when it wasn't.

## Verification Sources (in priority order)

1. **The `hermes config` CLI** — `hermes config set KEY VAL` validates the key path before applying. If `hermes config set` accepts it, it's a real key.
2. **The official docs** — https://hermes-agent.nousresearch.com/docs/user-guide/configuration
3. **The `hermes-agent` skill** — loaded with `skill_view(name='hermes-agent')`, it documents known config sections.
4. **The source code** — `hermes_cli/config.py` contains DEFAULT_CONFIG which enumerates every recognized top-level key.
5. **The internal help** — `hermes config --help`, `hermes config check`, `hermes config show`

## What NOT to do

- **Do not assume patterns from other tools carry over.** Just because some other tool uses `fallback_providers` doesn't mean Hermes reads them.
- **Do not write a key + value into config.yaml that you haven't seen in the docs, the skill, or the source.** Writing and testing is not the right order — verify first, then write.
- **Do not patch config.yaml by hand with arbitrary YAML when `hermes config set` exists.** The CLI is the safe path. Use it.

## What config changes look like for Hermes

If the user wants automatic fallback to a local model, verify the installed Hermes schema first. Current Hermes uses `model.fallbacks` for the main agent and `delegation.fallback` for child agents. Do not substitute guessed names such as `fallback_providers`, `fallback_chain`, or `fallback_order`.

Example shape (verify against the installed version before applying):

```yaml
model:
  fallbacks: '[{"model":"llama3.2:3b","provider":"ollama-local"}]'

delegation:
  fallback: '[{"model":"llama3.2:3b","provider":"ollama-local"}]'

providers:
  ollama-local:
    base_url: http://localhost:11434/v1
```

### Verify a custom OpenAI-compatible provider

A provider is active only if it is represented in current `config.yaml` under `providers` or the active `model` block. A stale `auth.json` record containing only a label, URL, status, or secret fingerprint is metadata -- it does not prove the credential still exists or that Hermes can use it.

1. Parse `config.yaml`; inspect `model`, `providers`, `delegation`, and `auxiliary` without printing secrets.
2. Check `.env` for the expected named variable; report only presence and length.
3. Treat `auth.json` fingerprints as clues, not usable credentials.
4. Call `<base_url>/models` with the actual credential and verify the requested model ID appears.
5. Send a minimal chat completion using that exact model.
6. Only after both calls succeed report the provider and model as functional.

### Verify Ollama as a fallback

1. Confirm the binary, service, and listener. Keep it local-only unless remote access was explicitly requested.
2. Pull the exact configured model.
3. Verify both `/api/tags` and OpenAI-compatible `/v1/models` list it.
4. Send a deterministic `/v1/chat/completions` probe and verify returned content.
5. Confirm `model.fallbacks` and, when required, `delegation.fallback` reference the same provider/model.

Installing a model is not complete until inference succeeds. A configured provider with an empty model list is not operational.

## Config change workflow

```text
User request → check docs/skill/source for real key →
  if EXISTS → use `hermes config set` or edit via `hermes config edit`
  if NOT FOUND → tell user it doesn't exist, suggest alternatives
```

## When the user corrects you

If the user calls out a made-up config key:
- Acknowledge immediately — don't deflect
- Remove the invalid key from config.yaml via the proper CLI or a direct edit
- Document the lesson

## Known missing features (as of 2026-07-05)

| User wants | Hermes has | Workaround |
|---|---|---|
| Automatic provider failover | `fallback_providers` does NOT exist | Manual provider switch via CLI, or local ollama for maintenance tasks |
| Multiple fallback providers | Not supported | N/A |
| Provider priority list | Not supported | N/A |

## Web tools `use_gateway` pitfall

Hermes has two config knobs for web tools:

```yaml
web:
  backend: firecrawl        # Which web backend to use
  use_gateway: false         # true = route through Nous Portal gateway
```

**The trap:** When `web.use_gateway: true` (the default or a previously-set value), Hermes routes Firecrawl requests through **Nous Portal's gateway** — it ignores your `FIRECRAWL_API_KEY` from `.env` entirely. If you're not logged into Nous Portal (no OAuth session), `web_search` and `web_extract` fail with:

> "Web tools are not configured. Set FIRECRAWL_API_KEY for cloud Firecrawl..."

Even though the key IS set and valid. The fix is:

```bash
hermes config set web.use_gateway false
```

Then a new session (`/reset`) picks up the change. **Note:** `/reset` itself does NOT fix this — the problem is the config value, not the session state. Multiple resets without changing the config value will all fail the same way.

**Verification:** Test the key directly against Firecrawl's API before and after:

```bash
source ~/.hermes/.env 2>/dev/null
curl -s -X POST "https://api.firecrawl.dev/v1/search" \
  -H "Authorization: Bearer $FIRECRAWL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query":"test","limit":1}'
# Expected: HTTP 200, {"success": true, "data": [...]}
```

**Key learning:** `web.use_gateway: true` is NOT a fallback or override layer — it *replaces* the local key. If you're self-hosting the Firecrawl key in `.env`, this must be `false`. Setting it back to `true` after switching to Nous Portal OAuth would be correct for that auth mode.

### Debugging flow for "web tools not configured"

```
1. Check .env:  grep FIRECRAWL_API_KEY ~/.hermes/.env
   → If missing, add key. If present, proceed.
2. Check config: grep -A2 '^web:' ~/.hermes/config.yaml
   → If use_gateway: true, flip to false via:
       hermes config set web.use_gateway false
   → Then /reset or start new session.
3. Test key: direct curl to api.firecrawl.dev (see above)
   → 200 = key valid. Non-200 = key expired/wrong.
4. Verify tools: try web_search or web_extract
```
