{"repo":"NousResearch/hermes-agent","public_id":"58515","display_label":"Fix auxiliary task base_url/api_key ignored with explicit provider","summary":"These issues and PRs address a bug where auxiliary task configuration (base_url and api_key) is not honored when a provider is passed explicitly. The fix ensures those settings are respected in that code path.","subsystem":null,"counts":{"members":3,"open_issues":0,"open_issues_distinct":0,"open_prs":0,"closed_issues":1,"merged_prs":1,"attempt_prs":1},"landed_fix":{"status":"merged_to_main","basis":"structural","pr":59140,"merged_at":"2026-07-05T21:41:44+00:00"},"resolution":{"state":"resolved","by":"pr-59140"},"freshness":{"state":"verified","last_verified_at":"2026-07-05T21:41:44+00:00","is_stale":false},"grouping":{"backbone":"STRUCTURAL_SPANNING","link_density":0.6666666666666666},"fix_edges":[{"issue_number":58515,"pr_number":59140,"tier":"verified","basis":"closing_ref","confidence":0.95,"recoverable_from_timeline":true,"pr_merged_at":"2026-07-05T21:41:44+00:00"}],"members":[{"kind":"issue","number":58515,"title":"_resolve_task_provider_model ignores auxiliary.<task>.base_url when provider passed explicitly","url":null,"state":"closed"},{"kind":"pr","number":58520,"title":"fix(agent): honor auxiliary.<task>.base_url/api_key when provider is passed explicitly","url":null,"state":"closed","close_reason":{"refs":[{"kind":"commit","value":"9ad912a79","number":0},{"kind":"pr","value":"#59140","number":59140}],"category":"merged_via","implication":"superseded"},"merged":false},{"kind":"pr","number":59140,"title":"fix(agent): honor auxiliary.<task>.base_url/api_key when provider is passed explicitly","url":null,"state":"merged","close_reason":{"category":"merged"},"merged":true,"is_fix_pr":true,"fix_tier":"verified","files_changed":["agent/auxiliary_client.py","tests/agent/test_auxiliary_client.py"],"fix_hunks":[{"file":"agent/auxiliary_client.py","hunks":["@@ -5532,6 +5532,18 @@ def _preserve_provider_with_base_url(prov: Optional[str]) -> bool:\n     if cfg_provider:\n         cfg_provider, cfg_base_url = _expand_direct_api_alias(cfg_provider, cfg_base_url)\n \n+    # An explicit provider arg without an explicit base_url must not bypass\n+    # the task's configured endpoint: adopt auxiliary.<task>.base_url/api_key\n+    # when the config targets the same provider (or names none), so the\n+    # early `if provider:` return below carries the configured endpoint\n+    # instead of falling through to main-runtime resolution (#58515).\n+    # An explicit \"auto\" is excluded — it means \"inherit / auto-detect\" and\n+    # must keep flowing through the existing auto-resolution chain.\n+    if provider and provider != \"auto\" and not base_url and cfg_base_url and cfg_provider in (None, provider):\n+        base_url = cfg_base_url\n+        if not api_key:\n+            api_key = [redacted:secret-assignment]\n+\n     if base_url and _preserve_provider_with_base_url(provider):\n         return provider, resolved_model, base_url, api_key, resolved_api_mode\n     if base_url:"]},{"file":"tests/agent/test_auxiliary_client.py","hunks":["@@ -168,6 +168,112 @@ def test_direct_openai_alias_with_base_url_still_routes_as_custom(self):\n         assert api_key == \"sk-test\"\n         assert api_mode is None\n \n+    def test_explicit_provider_adopts_configured_task_endpoint(self):\n+        \"\"\"Explicit provider matching the configured one must not bypass\n+        auxiliary.<task>.base_url/api_key (#58515).\"\"\"\n+        task_config = {\n+            \"provider\": \"custom\",\n+            \"model\": \"meta/llama-3.2-11b-vision-instruct\",\n+            \"base_url\": \"https://integrate.api.nvidia.com/v1\",\n+            \"api_key\": \"[redacted:secret-assignment]\",\n+        }\n+        with patch(\"agent.auxiliary_client._get_auxiliary_task_config\", return_value=task_config):\n+            resolved_provider, model, base_url, api_key, api_mode = _resolve_task_provider_model(\n+                task=\"vision\",\n+                provider=\"custom\",\n+                model=\"meta/llama-3.2-11b-vision-instruct\",\n+            )\n+\n+        assert resolved_provider == \"custom\"\n+        assert base_url == \"https://integrate.api.nvidia.com/v1\"\n+        assert api_key == \"nvapi-secret\"\n+        assert model == \"meta/llama-3.2-11b-vision-instruct\"\n+        assert api_mode is None\n+\n+    def test_explicit_provider_adopts_endpoint_when_config_names_no_provider(self):\n+        task_config = {\n+            \"base_url\": \"https://nim.example/v1\",\n+            \"api_key\": \"[redacted:secret-assignment]\",\n+        }\n+        with patch(\"agent.auxiliary_client._get_auxiliary_task_config\", return_value=task_config):\n+            resolved_provider, model, base_url, api_key, api_mode = _resolve_task_provider_model(\n+                task=\"vision\",\n+                provider=\"custom\",\n+            )\n+\n+        assert resolved_provider == \"custom\"\n+        assert base_url == \"https://nim.example/v1\"\n+        assert api_key == \"cfg-key\"\n+\n+    def test_explicit_first_class_provider_with_matching_config_keeps_identity(self):\n+        task_config = {\n+            \"provider\": \"anthropic\",\n+            \"base_url\": \"https://anthropic-proxy.example/v1\",\n+            \"api_key\": \"[redacted:secret-assignment]\",\n+        }\n+        with patch(\"agent.auxiliary_client._get_auxiliary_task_config\", return_value=task_config):\n+            resolved_provider, model, base_url, api_key, api_mode = _resolve_task_provider_model(\n+                task=\"compression\",\n+                provider=\"anthropic\",\n+            )\n+\n+        assert resolved_provider == \"anthropic\"\n+        assert base_url == \"https://anthropic-proxy.example/v1\"\n+        assert api_key == \"cfg-key\"\n+\n+    def test_explicit_auto_provider_keeps_auto_resolution(self):\n+        \"\"\"provider=\"auto\" is a sentinel for \"inherit / auto-detect\" and must\n+        not adopt the configured endpoint — the auto chain owns resolution.\"\"\"\n+        task_config = {\n+            \"base_url\": \"https://nim.example/v1\",\n+            \"api_key\": \"[redacted:secret-assignment]\",\n+        }\n+        with patch(\"agent.auxiliary_client._get_auxiliary_task_config\", return_value=task_config):\n+            resolved_provider, model, base_url, api_key, api_mode = _resolve_task_provider_model(\n+                task=\"vision\",\n+                provider=\"auto\",\n+            )\n+\n+        assert resolved_provider == \"auto\"\n+        assert base_url is None\n+        assert api_key is None\n+\n+    def test_explicit_provider_differing_from_config_ignores_config_endpoint(self):\n+        \"\"\"A caller forcing a different provider keeps full explicit-arg\n+        priority — the configured endpoint belongs to cfg_provider only.\"\"\"\n+        task_config = {\n+            \"provider\": \"custom\",\n+            \"base_url\": \"https://nim.example/v1\",\n+            \"api_key\": \"[redacted:secret-assignment]\",\n+        }\n+        with patch(\"agent.auxiliary_client._get_auxiliary_task_config\", return_value=task_config):\n+            resolved_provider, model, base_url, api_key, api_mode = _resolve_task_provider_model(\n+                task=\"vision\",\n+                provider=\"nous\",\n+            )\n+\n+        assert resolved_provider == \"nous\"\n+        assert base_url is None\n+        assert api_key is None\n+\n+    def test_explicit_provider_and_base_url_still_win_over_config(self):\n+        task_config = {\n+            \"provider\": \"custom\",\n+            \"base_url\": \"https://configured.example/v1\",\n+            \"api_key\": \"[redacted:secret-assignment]\",\n+        }\n+        with patch(\"agent.auxiliary_client._get_auxiliary_task_config\", return_value=task_config):\n+            resolved_provider, model, base_url, api_key, api_mode = _resolve_task_provider_model(\n+                task=\"vision\",\n+                provider=\"custom\",\n+                base_url=\"https://explicit.example/v1\",\n+                api_key=\"[redacted:secret-assignment]\",\n+            )\n+\n+        assert resolved_provider == \"custom\"\n+        assert base_url == \"https://explicit.example/v1\"\n+        assert api_key == \"explicit-key\"\n+\n \n class TestBuildCallKwargsMaxTokens:\n     \"\"\"_build_call_kwargs should not cap output by default (#34530).\n"]}]}],"trust":{"default_tier":"verified","includes_suggested":false}}