# NousResearch/hermes-agent · OpenRouter credential not detected or sent in requests

## Open now

- 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.

## TL;DR

- 3 member(s): 0 open issue(s), 1 closed issue(s), 0 open PR(s), 1 merged PR(s), 1 PR(s) closed without merging.
- A fix was merged to main in PR #42263. Verify it addresses your case.
- **Recommended:** read PR #42263 (and any competing PRs below) before filing. Confirm the merged change covers your symptom.

## Maintainer resolution verdict

- Internal-tracker verdict over this cluster's issue members: `resolved` · deciding PR(s): `pr-42263`. This is distinct from the fix status above. Weigh it yourself.

## How this cluster was grouped

- Link evidence (`STRUCTURAL_SPANNING`): every member is connected by structural evidence: shared changed files, or a closing/superseded reference.
- Pairwise link density `0.67`: the share of member pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. `1.00` means every pair is linked.

## Closed / duplicate issues

- #42130: \[Setup\]: OpenRouter credential configured but Hermes sends requests without Authentication header

## Prior & competing PRs

- **#42263: fix(auth): auto-detect OpenRouter credential from the pool, not just env**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`
  - files: `hermes_cli/auth.py`, `hermes_cli/dump.py`, `tests/hermes_cli/test_resolve_provider_openrouter_pool.py`
  - fix hunks:
  - `hermes_cli/auth.py`

    ```diff
    @@ -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`

    ```diff
    @@ -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`

    ```diff
    @@ -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")
    ```
- **#42183: fix(runtime-provider): check ~/.hermes/.env for OpenRouter API keys**. closed without merge
  - maintainer direction: category `implemented_elsewhere`; implication `superseded`; refs `f538470cf4afddb9ae6cc476c4f71b671f5a8420`

## Fix status

- Merged to main in PR #42263 (cited above). No release data is tracked. Verify downstream.
- Fix last verified (merged) `2026-06-08`.
- Subsystem: `hermes_cli`
