NousResearch/hermes-agent

Auxiliary LLM provider fallback and warning fixes

Cluster 10149 · agent. Data as of

Nothing open on GitHub. Fix merged in #53906 on 28 Jun 2026. Check it covers your case.

The short answer

0open issues
0open PRs
4items grouped
Known?
Yes. 4 related items grouped here, 1 issue already closed.
Fix event
A fix was merged to main in PR #53906. Check it covers your case. No release data is tracked.
Tracker
The maintainers' tracker marks this unresolved. That is separate from the fix event.
Still open
Nothing open on GitHub.

These issues and PRs address bugs around missing auxiliary LLM provider configuration, improving warning messages and adding fallback behavior to OPENROUTER_API_KEY when the credential pool is missing or exhausted.

Open issues0

No open issues.

Open PRs0

No open pull requests.

Fixes on record

Merged to main. A stamp counts the issues a fix is linked to.

  • #53906 fix(auxiliary): fall back to OPENROUTER_API_KEY when credential pool exhausted

    merged to main

    files: agent/auxiliary_client.py, tests/agent/test_auxiliary_client.py

    Show the diff
    • agent/auxiliary_client.py
      @@ -1669,13 +1669,14 @@ def _try_openrouter(explicit_api_key: str = None, model: str = None) -> Tuple[Op
           pool_present, entry = _select_pool_entry("openrouter")
           if pool_present:
               or_key = explicit_api_key or _pool_runtime_api_key(entry)
      -        if not or_key:
      -            _mark_provider_unhealthy("openrouter", ttl=60)
      -            return None, None
      -        base_url = _pool_runtime_base_url(entry, OPENROUTER_BASE_URL) or OPENROUTER_BASE_URL
      -        logger.debug("Auxiliary client: OpenRouter via pool")
      -        return OpenAI(api_key=[redacted:secret-assignment] base_url=base_url,
      -                       default_headers=build_or_headers()), model or _OPENROUTER_MODEL
      +        if or_key:
      +            base_url = _pool_runtime_base_url(entry, OPENROUTER_BASE_URL) or OPENROUTER_BASE_URL
      +            logger.debug("Auxiliary client: OpenRouter via pool")
      +            return OpenAI(api_key=[redacted:secret-assignment] base_url=base_url,
      +                           default_headers=build_or_headers()), model or _OPENROUTER_MODEL
      +        # Pool exists but is exhausted (no usable runtime key) — fall through to
      +        # the OPENROUTER_API_KEY env-var path rather than failing outright.
      +        logger.debug("Auxiliary client: OpenRouter pool exhausted, trying OPENROUTER_API_KEY")
       
           or_key = explicit_api_key or os.getenv("OPENROUTER_API_KEY")
           if not or_key:
    • tests/agent/test_auxiliary_client.py
      @@ -27,6 +27,9 @@
           _refresh_nous_recommended_model,
           _normalize_aux_provider,
           _try_payment_fallback,
      +    _try_openrouter,
      +    _OPENROUTER_MODEL,
      +    OPENROUTER_BASE_URL,
           _resolve_auto,
           _resolve_xai_oauth_for_aux,
           _CodexCompletionsAdapter,
      @@ -919,6 +922,35 @@ def test_explicit_openrouter_missing_env_keeps_not_set_warning(self, monkeypatch
                   for record in caplog.records
               )
       
      +    def test_try_openrouter_pool_exhausted_falls_back_to_env(self, monkeypatch):
      +        """Pool present but exhausted → fall through to OPENROUTER_API_KEY env var."""
      +        monkeypatch.setenv("OPENROUTER_API_KEY", "sk-or-env-fallback")
      +        with patch("agent.auxiliary_client._select_pool_entry", return_value=(True, None)), \
      +             patch("agent.auxiliary_client.OpenAI") as mock_openai:
      +            mock_client = MagicMock(name="openrouter_client")
      +            mock_openai.return_value = mock_client
      +
      +            client, model = _try_openrouter()
      +
      +        assert client is mock_client
      +        assert model == _OPENROUTER_MODEL
      +        mock_openai.assert_called_once()
      +        assert mock_openai.call_args.kwargs["api_key"] == "sk-or-env-fallback"
      +        assert mock_openai.call_args.kwargs["base_url"] == OPENROUTER_BASE_URL
      +
      +    def test_try_openrouter_pool_exhausted_no_env_marks_unhealthy(self, monkeypatch):
      +        """Pool exhausted AND no env var → final failure marks provider unhealthy."""
      +        monkeypatch.delenv("OPENROUTER_API_KEY", raising=False)
      +        with patch("agent.auxiliary_client._select_pool_entry", return_value=(True, None)), \
      +             patch("agent.auxiliary_client._mark_provider_unhealthy") as mock_mark, \
      +             patch("agent.auxiliary_client.OpenAI") as mock_openai:
      +            client, model = _try_openrouter()
      +
      +        assert client is None
      +        assert model is None
      +        mock_openai.assert_not_called()
      +        mock_mark.assert_called_once_with("openrouter", ttl=60)
      +
       class TestGetTextAuxiliaryClient:
           """Test the full resolution chain for get_text_auxiliary_client."""
       

2 PRs closed without merging

From the close comments: closed without comment 1 · done elsewhere 1

  • #10655 fix(auxiliary): fall back to OPENROUTER_API_KEY when pool entry is missing · done elsewhere → c56b39c, #53906, #23495
  • #36940 fix(auxiliary): improve "no auxiliary LLM provider" warning messages (#10149) · closed without comment
Closed issues · 1
  • Closed#10149[Bug]: No auxiliary LLM provider configured
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.50: the share of item 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.

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 Lab

At a glance

Subsystem
agent
Merged PRs
#53906
Closed issues
1
Attempts
2 PRs closed without merging
Fix link checked
28 Jun 2026

For your agent

The same facts, typed.