Skip to content

fix(aux): prefer _resolve_auto's model over pre-filled MoA preset name in auto branch - #58638

Closed
a844810597 wants to merge 1 commit into
NousResearch:mainfrom
a844810597:fix/moa-aux-auto-model-override
Closed

fix(aux): prefer _resolve_auto's model over pre-filled MoA preset name in auto branch#58638
a844810597 wants to merge 1 commit into
NousResearch:mainfrom
a844810597:fix/moa-aux-auto-model-override

Conversation

@a844810597

Copy link
Copy Markdown

Bug

When MoA (Mixture-of-Agents) is the active main provider, auxiliary tasks (title generation, compression, vision, session search, etc.) configured with provider: auto fail with HTTP 400 — the MoA preset name is sent as the model ID instead of the real aggregator model.

Visible symptom (from agent.log):

Auxiliary title_generation: using auto (default) at http://172.24.48.1:18089/v1/
Title generation failed: Error code: 400 - {"error":"...用户对该模型无权限...TM.00001005..."}

Note using auto (default)"default" is the MoA preset name, not a valid model ID.

All auxiliary tasks using provider: auto (the default for title_generation, compression, vision, web_extract, session_search, curator, mcp, skills_hub, monitor, profile_describer, triage_specifier, kanban_decomposer, approval, tts_audio_tags) are affected when MoA is the main provider.

Root Cause

In agent/auxiliary_client.py, resolve_provider_client() has a model pre-fill step before the auto branch:

# Line ~4005
if not model:
    model = _get_aux_model_for_provider(provider) or _read_main_model() or model

When MoA is active, set_runtime_main(provider="moa", model="default", ...) sets the process-global _RUNTIME_MAIN_MODEL = "default" (the preset name — MoA has no real HTTP endpoint). So _read_main_model() returns "default" and model gets pre-filled with it.

Then in the auto branch:

# Line ~4150
if provider == "auto":
    client, resolved = _resolve_auto(main_runtime=main_runtime, task=task)
    ...
    final_model = model or resolved   # ← model="default" is truthy → final_model="default"

_resolve_auto() correctly resolves MoA → aggregator and returns the real model ID (e.g. "maas-glm-5.2-aliyun"). This resolution was added by #53827 (merged 2026-06-27) via the if main_provider == "moa": block inside _resolve_auto(). But final_model = model or resolved picks the pre-filled model="default" (truthy) over the correct resolved value, overriding #53827's fix.

The request goes out with model="default" → the backend rejects it (400 / TM.00001005 / "not a valid model ID").

Why PR #53827 Didn't Fully Fix This

#53827 fixed _resolve_auto() to return the correct aggregator model. But the bug is one level up: resolve_provider_client()'s auto branch overrides _resolve_auto()'s return value with the pre-filled model. The pre-fill comes from _read_main_model(), which returns the MoA preset name — a value that is truthy but not a valid model ID for any real endpoint.

Layer Fixed by Status
_resolve_auto() MoA→aggregator resolution #53827 ✅ Merged
resolve_provider_client() auto branch model override This PR ❌ Not fixed on main

Fix

One-line change in resolve_provider_client()'s auto branch:

-        final_model = model or resolved
+        # _resolve_auto() already handles MoA preset → aggregator resolution
+        # (PR #53827). Its returned ``resolved`` model is the real model ID
+        # the endpoint accepts. The pre-filled ``model`` from
+        # _read_main_model() may be a MoA preset name (e.g. "default") that
+        # is NOT a valid model ID — using it overrides _resolve_auto's
+        # correct resolution and causes HTTP 400. Prefer ``resolved`` so
+        # the auto-detect chain's answer wins; ``model`` remains as
+        # fallback when _resolve_auto returns None (non-MoA fallthrough).
+        final_model = resolved or model

resolved (from _resolve_auto(), which handles MoA→aggregator) takes precedence. model remains as fallback for the non-MoA fallthrough case where _resolve_auto returns None.

Verification

Before fix (live hermes chat --provider moa -m default)

agent.log:

Auxiliary title_generation: using auto (default) at http://172.24.48.1:18089/v1/
WARNING agent.title_generator: Title generation failed: Error code: 400 - TM.00001005 用户对该模型无权限

After fix (same command)

agent.log:

Auxiliary auto-detect: using main provider custom:codeagent (maas-glm-5.2-aliyun)
Auxiliary title_generation: using auto (maas-glm-5.2-aliyun) at http://172.24.48.1:18089/v1/

No error follows. Model correctly resolved to aggregator's maas-glm-5.2-aliyun instead of preset name "default".

Direct resolution test

from agent.auxiliary_client import set_runtime_main, resolve_provider_client
set_runtime_main(provider="moa", model="default", base_url="moa://local",
                 api_key="moa-virtual-provider", api_mode="chat_completions")
client, model = resolve_provider_client("auto", None, task="title_generation")
# Before:  model = "default" (preset name → 400)
# After:   model = "maas-glm-5.2-aliyun" (aggregator model → works)

Test Plan

Risk Assessment

Low — The change only affects the provider == "auto" branch of resolve_provider_client(), and only changes behavior when _resolve_auto() returns a non-None resolved value. For non-MoA providers, _resolve_auto() returns the same model that _read_main_model() would have pre-filled (they read the same source), so resolved or model produces the same result as model or resolved. For MoA providers, resolved is the correct aggregator model and model is the invalid preset name — so the new order is strictly better. The model fallback is preserved for the case where _resolve_auto() returns None (fallthrough to Step 2/3).

… auto branch

When MoA is the main provider, _read_main_model() returns the preset name
(e.g. "default"), which pre-fills the ``model`` arg in
resolve_provider_client(). The auto branch then does
``final_model = model or resolved``, which picks the preset name over
_resolve_auto()'s correctly-resolved aggregator model — sending an invalid
model ID to the endpoint and causing HTTP 400.

PR NousResearch#53827 fixed _resolve_auto() to resolve MoA→aggregator, but the
pre-filled model override one level up in resolve_provider_client() still
clobbers its return value. Swap the precedence so ``resolved`` wins.

Verified live: title_generation on a MoA session now resolves to
maas-glm-5.2-aliyun (the aggregator) instead of "default" (the preset
name), and the 400 error is gone.
@a844810597 a844810597 closed this Jul 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant