fix: minimax-oauth auth_type unhandled — all 12 auxiliary tasks silently no-op (vision, compression, title gen, web_extract, skills_hub, approval, mcp, memory_query_rewrite, tts_audio_tags, triage_specifier, kanban_decomposer, profile_describer) - #61585
Conversation
minimax-oauth has auth_type='oauth_minimax' which was not handled by any branch in resolve_provider_client(). Every auxiliary task configured with auxiliary.<task>.provider: minimax-oauth (vision, title_generation, compression, web_extract, etc.) silently failed — the resolver returned (None, None), the vision auto-fallback picked the main provider (e.g. zai) but carried the MiniMax model name to the wrong endpoint, producing 'Unknown Model' (code 1211) errors. Fix follows the exact pattern already used for xai-oauth: a dedicated _build_minimax_oauth_aux_client() resolves OAuth credentials via resolve_minimax_oauth_runtime_credentials(as_token_provider=True), builds a native Anthropic client pointed at api.minimax.io/anthropic, and wraps it in AnthropicAuxiliaryClient with is_oauth=True. Verified: MiniMax-M3 (natively multimodal) now successfully processes screenshot analysis via browser_vision through the minimax-oauth provider.
Duplicate of #22213 (earliest open PR for this fix, same code site |
teknium1
left a comment
There was a problem hiding this comment.
Thanks for isolating the missing oauth_minimax auxiliary route. The premise is verified on current main: hermes_cli/auth.py:301-310 registers MiniMax OAuth as oauth_minimax, while agent/auxiliary_client.py:5094-5117 has no handler for it.
Problems
agent/auxiliary_client.py:2499setsis_oauth=True. That flag is native-Anthropic/Claude-Code-specific:agent/agent_init.py:790-798explicitly keeps third-party Anthropic-compatible providers such as MiniMax out of it, andagent/anthropic_adapter.py:2493-2581shows it injects Claude Code identity and tool-name transforms.agent/auxiliary_client.py:2495returns an OpenAI client against the/anthropicendpoint after construction failure. Currentagent/auxiliary_client.py:714-721documents that OpenAI wire requires/v1; this fallback is not a safe recovery path.- No test file is included.
tests/hermes_cli/test_auth_xai_oauth_provider.py:1840-1908provides the equivalent routing-contract coverage pattern.
Suggested changes
- Keep MiniMax’s callable refresh token, but pass
is_oauth=False. - Return
(None, None)on Anthropic-client construction failure rather than emitting OpenAI wire to/anthropic. - Add sync, async, and unauthenticated MiniMax OAuth resolver tests.
Automated hermes-sweeper review.
| return real_client, model | ||
| return ( | ||
| AnthropicAuxiliaryClient( | ||
| real_client, model, token_provider, base_url, is_oauth=True |
There was a problem hiding this comment.
is_oauth=True is reserved for native Anthropic/Claude Code compatibility transforms. Current main explicitly prevents third-party Anthropic-compatible providers such as MiniMax from taking that path (agent/agent_init.py:790-798), because it injects Claude Code identity and rewrites tool names. Keep the refresh-token callable, but pass is_oauth=False here.
| ) | ||
| # Last-resort: plain OpenAI client (the /anthropic endpoint may | ||
| # also accept OpenAI wire on some configurations). | ||
| real_client = _create_openai_client(api_key=token_provider, base_url=base_url) |
There was a problem hiding this comment.
This is not a safe fallback: the current auxiliary router documents that MiniMax /anthropic is Anthropic Messages wire and that OpenAI wire must use /v1 (agent/auxiliary_client.py:714-721). Return (None, None) after logging this construction failure unless a separately validated /v1 client path is supplied.
|
idk if I'm allowed but: This issue has been blocking something I'm developing, so I brought this PR into a local branch and successfully tested with a |
… fallback, add tests Three blockers from teknium1's review: 1. is_oauth=True → is_oauth=False The is_oauth flag is Claude-Code-OAuth-specific: it injects Claude Code system-prompt identity and tool-name transforms (_AnthropicCompletionsAdapter). MiniMax OAuth is a third-party Anthropic-compatible endpoint, not Claude Code, so those transforms must not apply. agent_init.py already keeps third-party Anthropic-compatible providers out of the is_oauth path. 2. Remove unsafe OpenAI-wire fallback on construction failure The /anthropic endpoint speaks Anthropic Messages, not OpenAI chat.completions. Returning (None, None) lets the caller's auto-fallback chain pick the next configured provider cleanly, rather than emitting misformatted requests to the wrong wire format. 3. Add routing contract tests (sync, async, unauthenticated, construction failure) Mirrors the xAI OAuth auxiliary test pattern. Pins: - Authenticated → AnthropicAuxiliaryClient with is_oauth=False - Async → AsyncAnthropicAuxiliaryClient with is_oauth=False - Unauthenticated → (None, None) - Construction failure → (None, None), no OpenAI fallback
|
Thanks for the detailed review @teknium1 — all three blockers addressed in 7669959: 1. 2. Removed OpenAI-wire fallback 3. Added routing-contract tests
Also re-ran the existing minimax + xai-oauth auxiliary suites (70 passed, 0 failed). |
Related: #61585 now differs materially from #22213 and the other oauth_minimax fixes: its current head uses the Anthropic-compatible client, avoids the failing OpenAI lazy-import path, and includes routing-contract tests. This is a competing implementation requiring maintainer selection, not a duplicate closure. |
shawnhansen
left a comment
There was a problem hiding this comment.
+1 from a downstream user who hit this today.
Workaround applied locally because I couldn't wait for the merge:
for task in title_generation vision web_extract compression skills_hub approval mcp memory_query_rewrite tts_audio_tags triage_specifier kanban_decomposer profile_describer; do
hermes config set "auxiliary.${task}.provider" xai-oauth
done
Scope check on my install (Linux, Hermes checkout from NousResearch/hermes-agent @ main, main provider minimax-oauth):
All 12 default-config aux tasks fail with No LLM provider configured for task=<name> provider=auto when auto falls back to resolve_provider_client("minimax-oauth"). Specifically:
title_generation— fire-and-forget; manifests as the warning in the docsvision— same as OPweb_extract— samecompression— same. This is the one I'm most worried about: long sessions hit the compression trigger routinely, so context summaries no-op silently until context overflow kills the loopskills_hub— silent no-op, worst failure modeapproval,mcp,memory_query_rewrite,tts_audio_tags,triage_specifier,kanban_decomposer,profile_describer— all silent no-op
The PR's fix matches what I'd drafted independently (_build_minimax_oauth_aux_client + branch in resolve_provider_client, reusing AnthropicAuxiliaryClient). Good.
I'm leaving this as a comment rather than APPROVE because I haven't actually tested the PR diff myself — just verified the same root cause from the downstream side and confirmed the proposed shape is correct. @knoal's prior +1 review with the A/B test on base SHA + yours after the patch landed is the load-bearing approval here.
One suggestion for the maintainer selection decision: scope this PR's commit message / description to mention all twelve aux tasks, not just the three named (vision, compression, title gen). Right now a triage agent reading vision, compression, title gen in the title might underweight the broad silent-no-op surface and route the issue through sweeper:blast-contained. The actual blast radius is broader than the title suggests.
Re: duplicate cluster (#22213, #36779, #42128, #49232, #23639) — concur with @alt-glitch's triage, this is the canonical one. Test base is cleanest (4 routing tests with mocked creds vs. #22213's single test that exposed the UnboundLocalError on OpenAI(...)).
Free-tier workaround for users blocked on the merge: set auxiliary.<task>.provider: xai-oauth (which already has a working resolver branch) for each aux task you actually use. No new auth needed if you already have xAI OAuth wired.
|
Consolidation note (dup-campaign, 2026-08-03): for the #21521 This PR predates the current named-OAuth router layout and carries a keep_open review on file; recommend close-as-superseded by #77419 (or rebase on top if you prefer your variant — the cluster only needs one merge). #77419's body carries Fixes/Closes for all 7 cluster issues. |
Correction: the current head is a duplicate of #68620, which already implements the same refreshable MiniMax OAuth runtime-credential and Anthropic Messages client path (including is_oauth=False). |
|
Consolidating toward #77419 to unblock the merge. Closing this one. Rationale — #77419 meets the same bar teknium1 set here (and that we addressed in 7669959), plus carries docs + a broader dispatch catch:
The cluster (#61585, #68620, #22213, #77419) only needs one merge. #77419 is the freshest against current main and has the broadest coverage. Picking it lets everyone move on. Thanks to the reviewers and +1-ers here — the validation from this thread (knoal's A/B test, fueg0's |
Bug
minimax-oauthhasauth_type="oauth_minimax"inPROVIDER_REGISTRY, butresolve_provider_client()has no branch that handles this auth type. It falls through everyif pconfig.auth_type == ...check and returns(None, None).This silently breaks all 12 default auxiliary tasks when
auxiliary.<task>.providerresolves tominimax-oauth(either explicitly or viaautofallback when it is the main provider):visionbrowser_vision/vision_analyzefail withcode: 1211, "Unknown Model"compressiontitle_generationTitle generation failed: Provider 'minimax-oauth' is set in config.yaml but no API key was foundweb_extractskills_hubapprovalmcpmemory_query_rewritetts_audio_tagstriage_specifierkanban_decomposerprofile_describerThe blast radius is broader than vision/compression/title-gen — triage should not route this through
sweeper:blast-contained.The misleading error chain
The vision auto-fallback masks the real problem. When
resolve_provider_client("minimax-oauth")returnsNone, the fallback picks the user's main provider (e.g.zai) but carries the MiniMax model name (e.g.MiniMax-M3) from the config. The main provider's API receives a model it doesn't recognize:MiniMax M3 is natively multimodal
MiniMax-M3 was trained with multimodality from day one (image, video, text). The model and endpoint handle vision perfectly — confirmed by direct API calls to
api.minimax.io/anthropic/v1/messageswith Anthropic-format image blocks. The bug is purely in Hermes's client resolution, not the model.Fix
Follows the exact pattern already used for
xai-oauth(which was fixed for the same class of bug — OAuth auth type with no handler inresolve_provider_client).1.
_build_minimax_oauth_aux_client(model)Resolves OAuth credentials via
resolve_minimax_oauth_runtime_credentials(as_token_provider=True)(the same function the main agent runtime uses), builds a native Anthropic client pointed atapi.minimax.io/anthropic, and wraps it inAnthropicAuxiliaryClientwithis_oauth=False.is_oauth=False(corrected per @teknium1's review): theis_oauthflag is Claude-Code-OAuth-specific — it injects Claude Code system-prompt identity and tool-name transforms. MiniMax OAuth is a third-party Anthropic-compatible endpoint, not Claude Code, so those transforms must not apply.agent_init.pyalready keeps third-party Anthropic-compatible providers out of theis_oauthpath.2.
minimax-oauthbranch inresolve_provider_client()Placed right after the existing
xai-oauthbranch, before thecustomendpoint branch. Same shape as xai-oauth: build client → null check → normalize model → return (with async + vision support).3. No OpenAI-wire fallback (per @teknium1's review)
On Anthropic client construction failure, the builder returns
(None, None)so the caller's auto-fallback chain picks the next configured provider cleanly. The previous version fell back to_create_openai_clientagainst the/anthropicendpoint, which speaks Anthropic Messages — not OpenAIchat.completions.Verification
Before patch:
browser_visionon any page →code: 1211, "Unknown Model"After patch:
browser_visionon localhost landing page → MiniMax-M3 successfully reads and describes the page:Client build verified:
Tests
New file:
tests/agent/test_auxiliary_client_minimax_oauth.py(4 tests, all passing). Mirrors the xAI OAuth auxiliary test pattern (test_auth_xai_oauth_provider.py):test_auxiliary_client_routes_minimax_oauth_through_anthropic— sync: returnsAnthropicAuxiliaryClientwithis_oauth=Falsetest_auxiliary_client_minimax_oauth_async_routes_through_anthropic— async: returnsAsyncAnthropicAuxiliaryClientwithis_oauth=Falsetest_auxiliary_client_minimax_oauth_returns_none_when_unauthenticated— no tokens →(None, None)test_auxiliary_client_minimax_oauth_no_openai_fallback_on_failure— construction failure →(None, None), no OpenAI fallbackTest environment
auxiliary.vision: { provider: minimax-oauth, model: MiniMax-M3 }Duplicate cluster
This is the canonical PR among the duplicates: #22213, #36779, #42128, #49232, #23639. Per @alt-glitch's triage, this PR has the cleanest test base (4 routing tests with mocked creds vs. #22213's single test that exposed an
UnboundLocalErroronOpenAI(...)).