From 24eae1fa153252530bfb259b4ac03b4e94950258 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=A7=E6=BF=91=E7=BA=A2=E8=8E=89=E6=A0=96=EF=BC=88BOT?= =?UTF-8?q?=EF=BC=89?= <1051445024@qq.com> Date: Mon, 10 Aug 2026 17:24:01 +0800 Subject: [PATCH] fix(agent): preserve MoA facade when rebuilding primary client (stream retry, rotation, fallback+restore) When agent.provider == "moa", the MoAClient facade *is* the client - there is no real OpenAI wire endpoint behind the moa://local placeholder. Client rebuilds (_replace_primary_openai_client: stream-retry pool cleanup, credential rotation, dead-connection cleanup, fallback+restore) go through create_openai_client and produce a native OpenAI client while provider stays "moa". The next primary call then either raises a `_moa_prepared_request` TypeError (#78382) or, when _client_kwargs carry an unrelated relay base_url, leaks the request to a foreign gateway (observed as HTTP 503 "group ... no available channel" from an unrelated new-api relay right after an aggregator empty-stream retry). Fix: in create_openai_client, when provider is "moa", return build_moa_facade(agent, model) instead of a native client. This covers every rebuild entry point. The three already-fixed call sites (restore_primary_runtime, try_recover_primary_transport, switch_model) assign the facade directly and do not go through create_openai_client, so they are unaffected. Closes #78382 --- agent/agent_runtime_helpers.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/agent/agent_runtime_helpers.py b/agent/agent_runtime_helpers.py index 6d9db26f71..ded31d0d8f 100644 --- a/agent/agent_runtime_helpers.py +++ b/agent/agent_runtime_helpers.py @@ -2370,6 +2370,17 @@ def create_openai_client(agent, client_kwargs: dict, *, reason: str, shared: boo # copy locks the contract so future transport/keepalive work can't reintroduce # the same class of bug. client_kwargs = dict(client_kwargs) + # The MoA virtual provider has no real OpenAI wire endpoint - the facade + # *is* the client. Rebuilding a native OpenAI client while + # agent.provider == "moa" (client replacement, stream-retry pool cleanup, + # credential rotation, fallback+restore) drops the facade: the next primary + # call either raises a `_moa_prepared_request` TypeError (#78382) or, when + # _client_kwargs carry an unrelated relay base_url, leaks the request to a + # foreign gateway. Rebuild the facade instead (build_moa_facade also + # re-wires the reference relay, see #53802). + if (getattr(agent, "provider", "") or "").strip().lower() == "moa": + from agent.moa_loop import build_moa_facade + return build_moa_facade(agent, getattr(agent, "model", None) or "default") ssl_ca_cert = client_kwargs.pop("ssl_ca_cert", None) ssl_verify_cfg = client_kwargs.pop("ssl_verify", None) httpx_verify = resolve_httpx_verify(ca_bundle=ssl_ca_cert, ssl_verify=ssl_verify_cfg)