diff --git a/tools/delegate_tool.py b/tools/delegate_tool.py index bbe79bc8512..2e25016a4f0 100644 --- a/tools/delegate_tool.py +++ b/tools/delegate_tool.py @@ -988,6 +988,44 @@ def _build_child_progress_callback( return _callback +def _normalized_runtime_url(value: Any) -> str: + return str(value or "").strip().rstrip("/") + + +def _inherit_parent_base_url(parent_agent, fallback_base_url: Optional[str]) -> Optional[str]: + """Return the base URL the parent is actually calling, not a stale attribute. + + ``parent_agent.base_url`` can still carry a leftover OpenRouter URL from an + old config while the live OpenAI client in ``_client_kwargs`` already points + at local Ollama. Subagents must inherit the active endpoint or they 401 + against OpenRouter with a dummy/local key. + """ + surface_url = _normalized_runtime_url(fallback_base_url) + client_kwargs = getattr(parent_agent, "_client_kwargs", None) + if isinstance(client_kwargs, dict): + kwargs_url = _normalized_runtime_url(client_kwargs.get("base_url")) + if ( + kwargs_url + and kwargs_url != surface_url + and kwargs_url.startswith(("http://", "https://")) + ): + return kwargs_url + + client = getattr(parent_agent, "client", None) + if client is not None: + live_raw = getattr(client, "base_url", "") + if isinstance(live_raw, str): + live_url = _normalized_runtime_url(live_raw) + if ( + live_url + and live_url != surface_url + and live_url.startswith(("http://", "https://")) + ): + return live_url + + return fallback_base_url or None + + def _build_child_agent( task_index: int, goal: str, @@ -1144,6 +1182,8 @@ def _build_child_agent( effective_model = model or parent_agent.model effective_provider = override_provider or getattr(parent_agent, "provider", None) effective_base_url = override_base_url or parent_agent.base_url + if not override_base_url: + effective_base_url = _inherit_parent_base_url(parent_agent, effective_base_url) effective_api_key = override_api_key or parent_api_key # Bug #20558 / PR #20563: api_mode must NOT be inherited when the child uses a # different provider than the parent — each provider has its own API surface