Bug: Credential pool key mix-up when multiple custom providers share the same base_url
Summary
When multiple custom_providers are configured with the same base_url but different api_key values, Hermes incorrectly resolves the credential pool, causing API requests to use the wrong API key.
Root Cause
File: agent/credential_pool.py
Function: get_custom_provider_pool_key(base_url: str)
def get_custom_provider_pool_key(base_url: str) -> str:
for provider in _iter_custom_providers():
if provider.get("base_url") == base_url:
return f"custom:{provider['name']}" # ← Always returns FIRST match
return ""
This function only matches by base_url, ignoring which provider name is actually being requested. When two providers share the same base_url, it always returns the pool key for the first one in iteration order.
Reproduction
Config
custom_providers:
- name: provider-a
base_url: http://<gateway-host>:<port>
api_key: sk-xxx...aaa
model: model-a
- name: provider-b
base_url: http://<gateway-host>:<port> # Same base_url
api_key: sk-xxx...bbb # Different key
model: model-b
hermes config set model.provider provider-b
hermes chat -q "Hello"
Result
- Expected: Uses
provider-b's key (sk-xxx...bbb)
- Actual: Uses
provider-a's key (sk-xxx...aaa) because get_custom_provider_pool_key() returns custom:provider-a
Evidence
agent.model_metadata - Failed to fetch model metadata: 401 Unauthorized
Direct API test with correct key:
requests.get("http://<gateway-host>:<port>/v1/models",
headers={"Authorization": "Bearer sk-xxx...bbb"})
# => 200 OK
Call Chain
resolve_runtime_provider()
└─ _try_resolve_from_custom_pool(base_url, ...)
└─ get_custom_provider_pool_key(base_url) # ← Bug here
└─ Returns "custom:provider-a" (first match)
└─ load_pool("custom:provider-a") # Wrong pool!
Environment
- Hermes v0.12.0 (upstream 5d3be89)
- Python 3.11, OpenAI SDK 2.32.0
Bug: Credential pool key mix-up when multiple custom providers share the same base_url
Summary
When multiple
custom_providersare configured with the samebase_urlbut differentapi_keyvalues, Hermes incorrectly resolves the credential pool, causing API requests to use the wrong API key.Root Cause
File:
agent/credential_pool.pyFunction:
get_custom_provider_pool_key(base_url: str)This function only matches by
base_url, ignoring which provider name is actually being requested. When two providers share the samebase_url, it always returns the pool key for the first one in iteration order.Reproduction
Config
Result
provider-b's key (sk-xxx...bbb)provider-a's key (sk-xxx...aaa) becauseget_custom_provider_pool_key()returnscustom:provider-aEvidence
Direct API test with correct key:
Call Chain
Environment