{"repo":"NousResearch/hermes-agent","public_id":"10300","display_label":"Model routing prefers OpenRouter over direct providers","summary":"These issues and PRs concern a bug where the /model command silently routes requests through OpenRouter instead of using configured direct providers. Fixes and feature work address provider detection and profile provider usage during model switching.","subsystem":null,"counts":{"members":5,"open_issues":0,"open_issues_distinct":0,"open_prs":0,"closed_issues":2,"merged_prs":1,"attempt_prs":2},"landed_fix":{"status":"merged_to_main","basis":"structural","pr":10780},"resolution":{"state":"partially_resolved","by":"pr-10780"},"freshness":{"state":"stale","last_verified_at":"2026-04-16T09:27:21+00:00","is_stale":true},"grouping":{"backbone":"STRUCTURAL_PARTIAL","link_density":0.33599999999999997},"fix_edges":[{"issue_number":10300,"pr_number":10780,"tier":"verified","basis":"closing_ref","confidence":0.95,"recoverable_from_timeline":true}],"members":[{"kind":"issue","number":10300,"title":"/model silently routes to OpenRouter for direct providers (minimax-cn, zai, etc.)","url":null,"state":"closed"},{"kind":"issue","number":14554,"title":"[Bug]: Multi Model for Profile don't work","url":null,"state":"closed"},{"kind":"pr","number":10466,"title":"fix(model): prefer direct providers over OpenRouter fallback","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#10780","number":10780}],"category":"uncategorized","implication":"needs_llm"},"merged":false},{"kind":"pr","number":10780,"title":"fix: stop /model from silently rerouting direct providers to OpenRouter","url":null,"state":"merged","close_reason":{"category":"merged","implication":"superseded"},"merged":true,"is_fix_pr":true,"fix_tier":"verified","files_changed":["hermes_cli/models.py"],"fix_hunks":[{"file":"hermes_cli/models.py","hunks":["@@ -1064,7 +1064,8 @@ def detect_provider_for_model(\n             break\n \n     if direct_match:\n-        # Check if we have credentials for this provider\n+        # Check if we have credentials for this provider — env vars,\n+        # credential pool, or auth store entries.\n         has_creds = False\n         try:\n             from hermes_cli.auth import PROVIDER_REGISTRY","@@ -1077,16 +1078,28 @@ def detect_provider_for_model(\n                         break\n         except Exception:\n             pass\n-\n-        if has_creds:\n-            return (direct_match, name)\n-\n-        # No direct creds — try to find this model on OpenRouter instead\n-        or_slug = _find_openrouter_slug(name)\n-        if or_slug:\n-            return (\"openrouter\", or_slug)\n-        # Still return the direct provider — credential resolution will\n-        # give a clear error rather than silently using the wrong provider\n+        # Also check credential pool and auth store — covers OAuth,\n+        # Claude Code tokens, and other non-env-var credentials (#10300).\n+        if not has_creds:\n+            try:\n+                from agent.credential_pool import load_pool\n+                pool = load_pool(direct_match)\n+                if pool.has_credentials():\n+                    has_creds = True\n+            except Exception:\n+                pass\n+        if not has_creds:\n+            try:\n+                from hermes_cli.auth import _load_auth_store\n+                store = _load_auth_store()\n+                if direct_match in store.get(\"providers\", {}) or direct_match in store.get(\"credential_pool\", {}):\n+                    has_creds = True\n+            except Exception:\n+                pass\n+\n+        # Always return the direct provider match.  If credentials are\n+        # missing, the client init will give a clear error rather than\n+        # silently routing through the wrong provider (#10300).\n         return (direct_match, name)\n \n     # --- Step 2: check OpenRouter catalog ---\n"]}]},{"kind":"pr","number":14584,"title":"fix(cli): use profile providers during model switch","url":null,"state":"closed","close_reason":{"category":"implemented_elsewhere","implication":"superseded"},"merged":false}],"trust":{"default_tier":"verified","includes_suggested":false}}