The HTTP 401 error in Hermes Agent comes from the LLM provider rejecting your API key. The error text varies by provider but means the same thing: the agent sent a request, the provider didn't recognise the credentials, request rejected.
Most 401 cases I help debug are not wrong keys. They are config loading issues. The key is fine, Hermes just isn't sending the right one.
Common 401 error messages
You may see any of these variants depending on which provider you use:
HTTP 401: invalid x-api-key(Anthropic)AuthenticationError [HTTP 401](OpenAI library)Error code: 401 - {'type': 'authentication_error', 'message': 'invalid api key'}(OpenRouter, MiniMax)⚠️ API call failed (attempt 1/3): AuthenticationError [HTTP 401]in Hermes logs
All of these mean: provider rejected the credentials.
Step 1: Verify your key works in curl
Before touching Hermes config, prove the key authenticates against the raw provider API. This isolates if the key itself is broken or if Hermes is sending the wrong one.
Test an Anthropic key
curl -s -H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
https://api.anthropic.com/v1/messages \
-d '{"model":"claude-haiku-4-5","max_tokens":10,"messages":[{"role":"user","content":"hi"}]}'
Test an OpenRouter key
curl -s -H "Authorization: Bearer $OPENROUTER_API_KEY" \
https://openrouter.ai/api/v1/models | head -c 200
If raw curl fails, your key is wrong. Regenerate it in the provider dashboard. If curl succeeds, the key is fine and Hermes is loading the wrong one. Move on to step 2.
Step 2: Check which key Hermes loads at runtime
Hermes pulls credentials from two sources: ~/.hermes/auth.json and environment variables. Look at both:
cat ~/.hermes/auth.json
env | grep -i -E "ANTHROPIC|OPENAI|OPENROUTER|MINIMAX|NOUS|GEMINI"
You're looking for two things. First, that exactly one source has the key. Second, that the key matches the one you tested in step 1.
Duplicated or concatenated keys
The most common bug: someone pastes a new key into auth.json without removing the old one. You end up with two keys mashed together as one string. Provider rejects malformed key as 401.
Stale env var
If you exported the key twice in different terminals with different values, the one that loaded last wins. If your gateway runs in a third terminal, it might have neither.
Step 3: Fix the key through the CLI
Don't hand-edit auth.json. The format has changed between Hermes versions. Use the CLI:
hermes auth set anthropic
Paste the verified key directly when prompted. Don't echo from a shell variable, since long keys can get truncated or wrapped in some shells.
Step 4: Check the credential source
Each provider in Hermes has a credential_source field. It is either file (read from auth.json) or env:VAR_NAME (read from env variable). If the source says env:ANTHROPIC_API_KEY but you saved the key to auth.json instead, Hermes will look at the empty env var, send no key, and you get 401.
Fix one of two ways:
# Option A: export the env var the source expects
export ANTHROPIC_API_KEY="sk-ant-..."
echo 'export ANTHROPIC_API_KEY="sk-ant-..."' >> ~/.bashrc
# Option B: change the source to use auth.json
hermes provider set anthropic --credential-source file
Option A is better if you run Hermes in Docker or under systemd. Option B is better for desktop use where you want the auth CLI to manage everything.
Provider-specific 401 quirks
MiniMax and GLM
MiniMax and Chinese provider endpoints sometimes throw 401s that are not auth failures. They are rate-limit or quota errors that the provider chose to return with the wrong status code. If your key works in curl but Hermes throws intermittent 401s only against MiniMax or GLM, this is likely it.
The fix isn't more auth debugging. Configure a fallback provider so Hermes routes around the flaky one. Our fallback providers guide covers the setup.
OpenAI
OpenAI returns 429 (not 401) when the account is out of credits. If your fallback is configured only for 401, you won't fall through on an OpenAI quota error. Add 429 to your fallback statuses too.
401 inside Docker
When Hermes runs in a container, env vars on the host are not inherited unless you explicitly pass them through. Common bug.
services:
hermes:
image: hermes-agent:latest
environment:
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- OPENROUTER_API_KEY=${OPENROUTER_API_KEY}
You still need to export the variables on the host before docker compose up. The compose interpolation reads from the host environment, not from a .env file unless you point it there explicitly. Full production-grade Docker Compose setup in our Hermes Docker Compose tutorial.
If the gateway crashes on a single 401
Older Hermes versions treated a single 401 as fatal and killed the gateway. Newer versions retry and surface a cleaner error. Check your version:
hermes --version
hermes upgrade
If your gateway still dies after upgrade, check the systemd restart policy. A unit with Restart=on-failure and a reasonable RestartSec will bounce the gateway back up. Details in our production hardening guide.
The diagnostic sequence I run
When a 401 hits, the four commands I run first:
hermes doctor
hermes auth status
hermes provider show
hermes chat -q "hello"
Doctor catches config bugs. Auth status shows which providers have keys saved. Provider show tells me which credential source each uses. Chat smoke test confirms the round trip. If all four pass and a real prompt still 401s, open an issue on the Hermes GitHub repo. But thats a tiny minority of cases.
The LumaDock template skips most auth setup
If you'd rather not debug provider auth on a fresh install, the LumaDock Hermes Agent template includes a guided provider setup that validates your key before you reach the workspace. So a typo or wrong credential source never reaches chat. Unmetered bandwidth and no setup fees on every plan. Setup process is in our Hermes Agent complete guide.

