OpenRouter credential not detected or sent in requests
Cluster 42130 · hermes cli. Data as of
Nothing open on GitHub. Fix merged in #42263 on 8 Jun 2026. Check it covers your case.
The short answer
- Known?
- Yes. 3 related items grouped here, 1 issue already closed.
- Fix event
- A fix was merged to main in PR #42263. Check it covers your case. No release data is tracked.
- Tracker
- The maintainers' tracker marks this
resolved, deciding PR #42263. That is separate from the fix event. - Still open
- Nothing open on GitHub.
The members concern OpenRouter API credentials not being picked up by Hermes: one setup issue reports requests going out without an Authentication header despite a configured credential, and two fix-oriented PRs address detecting keys from ~/.hermes/.env and from the credential pool rather than only environment variables. Whether these changes address the reported issue is not established by the titles.
Open issues0
Open PRs0
Fixes on record
-
#42263 fix(auth): auto-detect OpenRouter credential from the pool, not just env
files:
hermes_cli/auth.py,hermes_cli/dump.py,tests/hermes_cli/test_resolve_provider_openrouter_pool.pyShow the diff
-
hermes_cli/auth.py@@ -1561,6 +1561,21 @@ def resolve_provider( if has_usable_secret(os.getenv("OPENAI_API_KEY")) or has_usable_secret(os.getenv("OPENROUTER_API_KEY")): return "openrouter" + # Auto-detect an OpenRouter credential added via `hermes auth add openrouter` + # (manual pool entry, no env var). Without this, a key that only lives in + # the credential pool is invisible to auto-detection — the user sees + # `hermes auth list` showing the credential while requests go out with no + # Authorization header ("HTTP 401: Missing Authentication header"). The + # env-var check above only covers keys exported as OPENROUTER_API_KEY / + # OPENAI_API_KEY. See issue #42130. + try: + from agent.credential_pool import load_pool as _load_pool + + if _load_pool("openrouter").has_credentials(): + return "openrouter" + except Exception as e: + logger.debug("Could not check OpenRouter credential pool: %s", e) + # Auto-detect API-key providers by checking their env vars for pid, pconfig in PROVIDER_REGISTRY.items(): if pconfig.auth_type != "api_key": -
hermes_cli/dump.py@@ -318,6 +318,17 @@ def run_dump(args): display = _redact(val) else: display = "set" if val else "not set" + # A credential added via `hermes auth add openrouter` lives in the + # credential pool, not as an env var — surface it so the dump doesn't + # misleadingly read "not set" while `hermes auth list` shows it (#42130). + if not val and label == "openrouter": + try: + from agent.credential_pool import load_pool as _load_pool + + if _load_pool("openrouter").has_credentials(): + display = "set (auth pool)" + except Exception: + pass lines.append(f" {label:<20} {display}") # Features summary -
tests/hermes_cli/test_resolve_provider_openrouter_pool.py@@ -0,0 +1,76 @@ +"""Regression tests for issue #42130. + +A credential added via `hermes auth add openrouter` lives in the credential +pool, NOT as an OPENROUTER_API_KEY env var. Before the fix, resolve_provider() +auto-detection only checked env vars, so such a credential was invisible: +the provider failed to resolve (AuthError) or resolved without a key, and +requests went out with no Authorization header — OpenRouter's +"HTTP 401: Missing Authentication header". + +These tests lock in that auto-detection consults the OpenRouter pool. +""" + +import uuid + +import pytest + + [redacted:email](autouse=True) +def _clean_inference_env(monkeypatch): + """Strip credential-shaped env vars so the pool is the only source.""" + for key in ( + "OPENROUTER_API_KEY", + "OPENAI_API_KEY", + "ANTHROPIC_API_KEY", + "ANTHROPIC_TOKEN", + "CLAUDE_CODE_OAUTH_TOKEN", + "NOUS_API_KEY", + "HERMES_INFERENCE_PROVIDER", + ): + monkeypatch.delenv(key, raising=False) + + +def _seed_openrouter_pool(token: str = "sk-or-FAKEKEY123") -> None: + """Mimic `hermes auth add openrouter <token>` — a manual pool entry.""" + from agent.credential_pool import ( + AUTH_TYPE_API_KEY, + SOURCE_MANUAL, + PooledCredential, + load_pool, + ) + + pool = load_pool("openrouter") + pool.add_entry( + PooledCredential( + provider="openrouter", + id=uuid.uuid4().hex[:6], + label="api-key-1", + auth_type=AUTH_TYPE_API_KEY, + priority=0, + source=SOURCE_MANUAL, + access_token=[redacted:secret-assignment] + base_url="https://openrouter.ai/api/v1", + ) + ) + + +def test_auto_detects_openrouter_from_pool(tmp_path, monkeypatch): + """With only a pool credential (no env var), auto-detection finds it.""" + monkeypatch.setenv("HERMES_HOME", str(tmp_path / "hermes")) + (tmp_path / "hermes").mkdir(parents=True, exist_ok=True) + _seed_openrouter_pool() + + from hermes_cli.auth import resolve_provider + + assert resolve_provider("auto") == "openrouter" + + +def test_no_credentials_still_raises(tmp_path, monkeypatch): + """Empty pool + no env var must still fail to resolve — no false positive.""" + monkeypatch.setenv("HERMES_HOME", str(tmp_path / "hermes")) + (tmp_path / "hermes").mkdir(parents=True, exist_ok=True) + + from hermes_cli.auth import AuthError, resolve_provider + + with pytest.raises(AuthError): + resolve_provider("auto")
-
1 PR closed without merging
From the close comments: done elsewhere 1
-
#42183 fix(runtime-provider): check ~/.hermes/.env for OpenRouter API keys · done elsewhere →
f538470
Closed issues · 1
- Closed#42130[Setup]: OpenRouter credential configured but Hermes sends requests without Authentication header
How this cluster was grouped
-
Link evidence (
structural links throughout): every member is connected by structural evidence: shared changed files, or a closing/superseded reference. -
Pairwise link density
0.67: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36.1.00means every pair is linked.
Pick up a Lab task
Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.
Open the LabAt a glance
- Subsystem
- hermes cli
- Merged PRs
- #42263
- Closed issues
- 1
- Attempts
- 1 PR closed without merging
- Fix link checked
- 8 Jun 2026