Bug: _resolve_delegation_credentials() resolves api_key from OPENAI_API_KEY instead of the provider credential chain when delegation.base_url is set
Version: v0.11.0 (2026.4.23)
Affected file: tools/delegate_tool.py — _resolve_delegation_credentials()
Severity: P2 — degraded but workaround exists
Root Cause
When delegation.base_url is configured, the base_url branch resolves api_key as:
api_key = configured_api_key or os.getenv("OPENAI_API_KEY", "").strip()
This bypasses the provider credential pool entirely. If OPENAI_API_KEY is unset and the provider key lives in its own env var (e.g. MINIMAX_API_KEY, DASHSCOPE_API_KEY), the child agent receives an empty API key → 401 Unauthorized.
By contrast, the provider-only path (lines 2240+) correctly calls resolve_runtime_provider() which consults the credential pool — so users who omit base_url get correct key resolution. The inconsistency only affects users who set delegation.base_url.
Steps to Reproduce
- Configure MiniMax as provider with
MINIMAX_API_KEY set in environment
- Set in
config.yaml:
delegation:
provider: minimax
base_url: https://api.minimax.io/anthropic
api_key: ''
- Call
delegate_task(goal="test", context="test", toolsets=['terminal'], role='leaf')
- Child agent receives 401 — api_key resolved as empty string from
OPENAI_API_KEY
Proposed Fix
In the base_url branch of _resolve_delegation_credentials(), resolve api_key from the provider credential chain when configured_provider is set:
if configured_api_key:
api_key = configured_api_key
elif configured_provider:
try:
from hermes_cli.runtime_provider import resolve_runtime_provider
runtime = resolve_runtime_provider(requested=configured_provider)
api_key = runtime.get("api_key", "") or os.getenv("OPENAI_API_KEY", "").strip()
except Exception:
api_key = os.getenv("OPENAI_API_KEY", "").strip()
else:
api_key = os.getenv("OPENAI_API_KEY", "").strip()
This matches the credential resolution behaviour of the provider-only path.
Workaround
Explicitly set delegation.api_key in config.yaml to the provider's API key value. This is not ideal as it duplicates credentials.
Context
Discovered while setting up MiniMax M2.7 as the delegation model on v0.10.0. Three compounding bugs were found and patched locally. Two have since been resolved in v0.11.0 (auth header conflict in anthropic_adapter.py, and api_mode detection for MiniMax URLs). This remaining issue persists in v0.11.0.
Happy to open a PR with the fix if useful.
Bug:
_resolve_delegation_credentials()resolvesapi_keyfromOPENAI_API_KEYinstead of the provider credential chain whendelegation.base_urlis setVersion: v0.11.0 (2026.4.23)
Affected file:
tools/delegate_tool.py—_resolve_delegation_credentials()Severity: P2 — degraded but workaround exists
Root Cause
When
delegation.base_urlis configured, thebase_urlbranch resolvesapi_keyas:This bypasses the provider credential pool entirely. If
OPENAI_API_KEYis unset and the provider key lives in its own env var (e.g.MINIMAX_API_KEY,DASHSCOPE_API_KEY), the child agent receives an empty API key → 401 Unauthorized.By contrast, the
provider-only path (lines 2240+) correctly callsresolve_runtime_provider()which consults the credential pool — so users who omitbase_urlget correct key resolution. The inconsistency only affects users who setdelegation.base_url.Steps to Reproduce
MINIMAX_API_KEYset in environmentconfig.yaml:delegate_task(goal="test", context="test", toolsets=['terminal'], role='leaf')OPENAI_API_KEYProposed Fix
In the
base_urlbranch of_resolve_delegation_credentials(), resolveapi_keyfrom the provider credential chain whenconfigured_provideris set:This matches the credential resolution behaviour of the
provider-only path.Workaround
Explicitly set
delegation.api_keyinconfig.yamlto the provider's API key value. This is not ideal as it duplicates credentials.Context
Discovered while setting up MiniMax M2.7 as the delegation model on v0.10.0. Three compounding bugs were found and patched locally. Two have since been resolved in v0.11.0 (auth header conflict in
anthropic_adapter.py, andapi_modedetection for MiniMax URLs). This remaining issue persists in v0.11.0.Happy to open a PR with the fix if useful.