Skip to content

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

Closed
toilmonkey0-cyber wants to merge 2 commits into
NousResearch:mainfrom
toilmonkey0-cyber:fix/minimax-oauth-auxiliary-vision

Conversation

@toilmonkey0-cyber

@toilmonkey0-cyber toilmonkey0-cyber commented Jul 9, 2026

Copy link
Copy Markdown

Bug

minimax-oauth has auth_type="oauth_minimax" in PROVIDER_REGISTRY, but resolve_provider_client() has no branch that handles this auth type. It falls through every if pconfig.auth_type == ... check and returns (None, None).

This silently breaks all 12 default auxiliary tasks when auxiliary.<task>.provider resolves to minimax-oauth (either explicitly or via auto fallback when it is the main provider):

Task Failure mode
vision browser_vision / vision_analyze fail with code: 1211, "Unknown Model"
compression Context compression silently no-ops — long sessions hit overflow and die
title_generation Title generation failed: Provider 'minimax-oauth' is set in config.yaml but no API key was found
web_extract Silent no-op
skills_hub Silent no-op
approval Silent no-op
mcp Silent no-op
memory_query_rewrite Silent no-op
tts_audio_tags Silent no-op
triage_specifier Silent no-op
kanban_decomposer Silent no-op
profile_describer Silent no-op

The 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") returns None, 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:

WARNING: Vision provider minimax-oauth unavailable, falling back to auto vision backends
WARNING: browser_vision failed: Error code: 400 - {'error': {'code': '1211', 'message': 'Unknown Model, please check the model code.'}}

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/messages with 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 in resolve_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 at api.minimax.io/anthropic, and wraps it in AnthropicAuxiliaryClient with is_oauth=False.

is_oauth=False (corrected per @teknium1's review): the is_oauth flag 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.py already keeps third-party Anthropic-compatible providers out of the is_oauth path.

2. minimax-oauth branch in resolve_provider_client()

Placed right after the existing xai-oauth branch, before the custom endpoint 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_client against the /anthropic endpoint, which speaks Anthropic Messages — not OpenAI chat.completions.

Verification

Before patch: browser_vision on any page → code: 1211, "Unknown Model"

After patch: browser_vision on localhost landing page → MiniMax-M3 successfully reads and describes the page:

Here's a detailed breakdown of what I can see: The page uses a dark theme... LETHAL BRIDGE in a monospace, retro/terminal-style font... A dark red/maroon colored US map sits behind the central card... THREAT LEVEL / MODERATE... scrolling marquee with text reading "43% OF US BRIDGES ARE >50 YEARS OLD"

Client build verified:

>>> _build_minimax_oauth_aux_client('MiniMax-M3')
AnthropicAuxiliaryClient, model=MiniMax-M3
  base_url: https://api.minimax.io/anthropic

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: returns AnthropicAuxiliaryClient with is_oauth=False
  • test_auxiliary_client_minimax_oauth_async_routes_through_anthropic — async: returns AsyncAnthropicAuxiliaryClient with is_oauth=False
  • test_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 fallback
4 passed in 2.04s

Test environment

  • Hermes v0.18.2 on Windows
  • MiniMax OAuth (Coding Plan, global region)
  • auxiliary.vision: { provider: minimax-oauth, model: MiniMax-M3 }
  • 3 profiles affected by this bug — all fixed by this single patch

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 UnboundLocalError on OpenAI(...)).

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.
@alt-glitch alt-glitch added type/bug Something isn't working comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint provider/minimax MiniMax (Anthropic transport) P3 Low — cosmetic, nice to have duplicate This issue or pull request already exists labels Jul 9, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Duplicate of #22213 (earliest open PR for this fix, same code site agent/auxiliary_client.py, same mechanism: add the oauth_minimax branch + _build_minimax_oauth_aux_client()). Saturated cluster of open competing fixes: #36779, #42128, #49232. Maintainer to pick the canonical one.

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:2499 sets is_oauth=True. That flag is native-Anthropic/Claude-Code-specific: agent/agent_init.py:790-798 explicitly keeps third-party Anthropic-compatible providers such as MiniMax out of it, and agent/anthropic_adapter.py:2493-2581 shows it injects Claude Code identity and tool-name transforms.
  • agent/auxiliary_client.py:2495 returns an OpenAI client against the /anthropic endpoint after construction failure. Current agent/auxiliary_client.py:714-721 documents 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-1908 provides 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.

Comment thread agent/auxiliary_client.py Outdated
return real_client, model
return (
AnthropicAuxiliaryClient(
real_client, model, token_provider, base_url, is_oauth=True

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread agent/auxiliary_client.py Outdated
)
# 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)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-contained Sweeper blast radius: contained — one narrow path / opt-in / few users labels Jul 11, 2026
@fueg0

fueg0 commented Jul 15, 2026

Copy link
Copy Markdown

idk if I'm allowed but:
+1 from me.

This issue has been blocking something I'm developing, so I brought this PR into a local branch and successfully tested with a /moa of 3 hermes profiles all using minimax oauth and was able to verify that my own thing works with this change included.

@alt-glitch alt-glitch removed the sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades label Jul 15, 2026
@teknium1 teknium1 added the area/compression Context compression and continuation sessions label Jul 19, 2026
… 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
@toilmonkey0-cyber

Copy link
Copy Markdown
Author

Thanks for the detailed review @teknium1 — all three blockers addressed in 7669959:

1. is_oauth=Trueis_oauth=False
Fixed. MiniMax OAuth is a third-party Anthropic-compatible endpoint, not Claude Code OAuth. The is_oauth flag injects Claude Code system-prompt identity + tool-name transforms that must not apply here. Added a comment pointing to agent_init.py which already keeps third-party Anthropic-compatible providers out of the is_oauth path.

2. Removed OpenAI-wire fallback
Fixed. The /anthropic endpoint speaks Anthropic Messages, not OpenAI chat.completions. On construction failure the builder now returns (None, None) so the caller's auto-fallback chain picks the next configured provider cleanly, rather than emitting misformatted requests.

3. Added routing-contract tests
New file: tests/agent/test_auxiliary_client_minimax_oauth.py (4 tests, all passing). Mirrors the xAI OAuth pattern (test_auth_xai_oauth_provider.py):

  • test_auxiliary_client_routes_minimax_oauth_through_anthropic — sync: returns AnthropicAuxiliaryClient with is_oauth=False
  • test_auxiliary_client_minimax_oauth_async_routes_through_anthropic — async: returns AsyncAnthropicAuxiliaryClient with is_oauth=False
  • test_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 fallback
4 passed in 2.04s

Also re-ran the existing minimax + xai-oauth auxiliary suites (70 passed, 0 failed).

@alt-glitch alt-glitch added tool/vision Vision analysis and image generation P2 Medium — degraded but workaround exists needs-decision Awaiting maintainer decision before any implementation area/auth Authentication, OAuth, credential pools and removed duplicate This issue or pull request already exists P3 Low — cosmetic, nice to have labels Jul 21, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

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 shawnhansen left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+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 docs
  • vision — same as OP
  • web_extract — same
  • compression — 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 loop
  • skills_hub — silent no-op, worst failure mode
  • approval, 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.

@toilmonkey0-cyber toilmonkey0-cyber changed the title fix: minimax-oauth auxiliary tasks fail silently (vision, compression, title gen) 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) Jul 25, 2026
@andrexibiza

Copy link
Copy Markdown
Contributor

Consolidation note (dup-campaign, 2026-08-03): for the #21521 oauth_minimax complex, the fresh current-head fix is PR #77419 (#77419) — cherry-picked from #47703 (authorship preserved, check-attribution green), same refreshable-credential contract as this PR (resolve_minimax_oauth_runtime_credentials(as_token_provider=True) + persisted runtime base_url), plus 5 regression tests, docs, and all CI green on current main (8 test slices, ruff, Windows footguns, docs-site).

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.

@alt-glitch alt-glitch added P3 Low — cosmetic, nice to have and removed P2 Medium — degraded but workaround exists needs-decision Awaiting maintainer decision before any implementation labels Aug 3, 2026
@alt-glitch alt-glitch added the duplicate This issue or pull request already exists label Aug 3, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Duplicate of #77419: both route MiniMax OAuth auxiliary tasks through AnthropicAuxiliaryClient. #77419 is the earlier, broader current implementation.

@alt-glitch alt-glitch added needs-decision Awaiting maintainer decision before any implementation and removed duplicate This issue or pull request already exists labels Aug 3, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Related: #22213 uses the older OpenAI-wire approach. The current head instead uses the Anthropic Messages route; #77419 is the broader current competing repair with additional dispatch coverage. Maintainer choice is needed.

@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Correction: related to #22213, not a duplicate. The current #61585 head uses the Anthropic-compatible MiniMax OAuth wire path and explicitly avoids the OpenAI-wire fallback, which requires a maintainer mechanism choice.

@alt-glitch alt-glitch added duplicate This issue or pull request already exists and removed needs-decision Awaiting maintainer decision before any implementation tool/vision Vision analysis and image generation area/auth Authentication, OAuth, credential pools area/compression Context compression and continuation sessions labels Aug 3, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

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).

@alt-glitch alt-glitch added area/auth Authentication, OAuth, credential pools sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data and removed duplicate This issue or pull request already exists labels Aug 3, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Current live diffs show #61585, #68620, and #22213 pursue the same MiniMax OAuth auxiliary goal through distinct mechanisms. They are recorded as related competing fixes pending maintainer selection, not duplicates.

@alt-glitch alt-glitch removed the sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data label Aug 3, 2026
@toilmonkey0-cyber

Copy link
Copy Markdown
Author

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:

  • is_oauth=False with the same agent_init.py guard rationale
  • ✅ No OpenAI-wire fallback to /anthropic — returns (None, None) on failure
  • ✅ 5 routing-contract tests (I pulled the branch and ran them: 5/5 pass, 417 existing aux/oauth tests pass, 0 regressions)

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 /moa test, shawnhansen's independent root-cause confirmation) carried over to the consolidation decision.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/auth Authentication, OAuth, credential pools comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint P3 Low — cosmetic, nice to have provider/minimax MiniMax (Anthropic transport) sweeper:blast-contained Sweeper blast radius: contained — one narrow path / opt-in / few users type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants