Skip to content

Commit 0b5fd40

Browse files
briandevansclaude
authored andcommitted
fix(delegate): correct _spawn_child → _build_child_agent in comments
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 42d72b5 commit 0b5fd40

2 files changed

Lines changed: 27 additions & 17 deletions

File tree

tests/tools/test_delegate.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -821,18 +821,21 @@ def test_direct_endpoint_uses_configured_base_url_and_api_key(self):
821821
self.assertEqual(creds["api_key"], "local-key")
822822
self.assertEqual(creds["api_mode"], "chat_completions")
823823

824-
def test_direct_endpoint_falls_back_to_openai_api_key_env(self):
824+
def test_direct_endpoint_returns_none_api_key_when_not_configured(self):
825+
# When base_url is set without api_key, api_key should be None so
826+
# _build_child_agent inherits the parent's key (effective_api_key = override or parent).
825827
parent = _make_mock_parent(depth=0)
826828
cfg = {
827829
"model": "qwen2.5-coder",
828830
"base_url": "http://localhost:1234/v1",
829831
}
830832
with patch.dict(os.environ, {"OPENAI_API_KEY": "env-openai-key"}, clear=False):
831833
creds = _resolve_delegation_credentials(cfg, parent)
832-
self.assertEqual(creds["api_key"], "env-openai-key")
834+
self.assertIsNone(creds["api_key"])
833835
self.assertEqual(creds["provider"], "custom")
834836

835-
def test_direct_endpoint_does_not_fall_back_to_openrouter_api_key_env(self):
837+
def test_direct_endpoint_no_raise_when_only_provider_env_key_present(self):
838+
# Even if OPENAI_API_KEY is absent, no ValueError — _build_child_agent uses parent key.
836839
parent = _make_mock_parent(depth=0)
837840
cfg = {
838841
"model": "qwen2.5-coder",
@@ -846,9 +849,9 @@ def test_direct_endpoint_does_not_fall_back_to_openrouter_api_key_env(self):
846849
},
847850
clear=False,
848851
):
849-
with self.assertRaises(ValueError) as ctx:
850-
_resolve_delegation_credentials(cfg, parent)
851-
self.assertIn("OPENAI_API_KEY", str(ctx.exception))
852+
creds = _resolve_delegation_credentials(cfg, parent)
853+
self.assertIsNone(creds["api_key"])
854+
self.assertEqual(creds["provider"], "custom")
852855

853856
@patch("hermes_cli.runtime_provider.resolve_runtime_provider")
854857
def test_nous_provider_resolves_nous_credentials(self, mock_resolve):

tools/delegate_tool.py

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2237,11 +2237,17 @@ def _resolve_delegation_credentials(cfg: dict, parent_agent) -> dict:
22372237
"""Resolve credentials for subagent delegation.
22382238
22392239
If ``delegation.base_url`` is configured, subagents use that direct
2240-
OpenAI-compatible endpoint. Otherwise, if ``delegation.provider`` is
2241-
configured, the full credential bundle (base_url, api_key, api_mode,
2242-
provider) is resolved via the runtime provider system — the same path used
2243-
by CLI/gateway startup. This lets subagents run on a completely different
2244-
provider:model pair.
2240+
OpenAI-compatible endpoint. ``delegation.api_key`` overrides the key; when
2241+
omitted, ``api_key`` is returned as ``None`` so ``_build_child_agent``
2242+
inherits the parent agent's key (``effective_api_key = override_api_key or
2243+
parent_api_key``). This lets providers that store their key outside
2244+
``OPENAI_API_KEY`` (e.g. ``MINIMAX_API_KEY``, ``DASHSCOPE_API_KEY``) work
2245+
without a duplicate config entry.
2246+
2247+
Otherwise, if ``delegation.provider`` is configured, the full credential
2248+
bundle (base_url, api_key, api_mode, provider) is resolved via the runtime
2249+
provider system — the same path used by CLI/gateway startup. This lets
2250+
subagents run on a completely different provider:model pair.
22452251
22462252
If neither base_url nor provider is configured, returns None values so the
22472253
child inherits everything from the parent agent.
@@ -2254,12 +2260,13 @@ def _resolve_delegation_credentials(cfg: dict, parent_agent) -> dict:
22542260
configured_api_key = str(cfg.get("api_key") or "").strip() or None
22552261

22562262
if configured_base_url:
2257-
api_key = configured_api_key or os.getenv("OPENAI_API_KEY", "").strip()
2258-
if not api_key:
2259-
raise ValueError(
2260-
"Delegation base_url is configured but no API key was found. "
2261-
"Set delegation.api_key or OPENAI_API_KEY."
2262-
)
2263+
# When delegation.api_key is not set, return None so _build_child_agent
2264+
# falls back to the parent agent's API key via the credential inheritance
2265+
# path (effective_api_key = override_api_key or parent_api_key). This
2266+
# lets providers that store their key in a non-OPENAI_API_KEY env var
2267+
# (e.g. MINIMAX_API_KEY, DASHSCOPE_API_KEY) work without requiring
2268+
# callers to duplicate the key under delegation.api_key.
2269+
api_key = configured_api_key # None → inherited from parent in _build_child_agent
22632270

22642271
base_lower = configured_base_url.lower()
22652272
provider = "custom"

0 commit comments

Comments
 (0)