Skip to content

fix(minimax): recognize Anthropic-compatible /anthropic endpoint in M3 reasoning controls - #74205

Closed
bbasketballer75 wants to merge 1 commit into
NousResearch:mainfrom
bbasketballer75:fix/minimax-anthropic-url-detection
Closed

fix(minimax): recognize Anthropic-compatible /anthropic endpoint in M3 reasoning controls#74205
bbasketballer75 wants to merge 1 commit into
NousResearch:mainfrom
bbasketballer75:fix/minimax-anthropic-url-detection

Conversation

@bbasketballer75

Copy link
Copy Markdown

Extends the MiniMaxProfile.build_api_kwargs_extras provider plugin to recognize MiniMax's Anthropic-compatible /anthropic endpoint at api.minimax.io/anthropic, in addition to the existing api.minimax.io/v1 OpenAI-compatible route.

Why this is separate from #66694

#66694 (fix(minimax): preserve M3 adaptive thinking on Anthropic routes) covers the Anthropic adapter layer — the request kwargs that go out as Anthropic thinking: {"type": "adaptive"} on the auxiliary_client adapter path. That's correct and stays open.

This PR covers the provider plugin layer — the extra_body that goes out on the OpenAI-compatible request shape that MiniMax's /anthropic endpoint also accepts. Different code path, different kwargs structure.

The bug

On the /anthropic endpoint, omitting thinking causes MiniMax-M3 to default to OFF (per MiniMax docs). Previously, the provider plugin only matched /v1, so requests to /anthropic got an empty extra_body and M3 returned thinking as disabled.

The fix

Add _is_minimax_global_anthropic_base_url() helper that matches api.minimax.io/anthropic. Update build_api_kwargs_extras to:

  • Accept both /v1 and /anthropic (the existing /v1 condition becomes an OR with the new /anthropic condition).
  • Send reasoning_split=True only on /v1 (the /anthropic endpoint already returns thinking as native content blocks, no split flag needed).
  • Send thinking: {type: adaptive} (or disabled if reasoning is explicitly disabled) on both routes.

Out of scope

The /anthropic route also requires stateful replay preservation across multi-turn tool calls, which is the focus of the Anthropic adapter work in #66694. The provider plugin here only handles the request-shape kwargs.

Copilot AI review requested due to automatic review settings July 29, 2026 16:27

Copilot AI 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.

Pull request overview

Extends the MiniMax provider plugin’s M3 reasoning controls to also recognize MiniMax’s Anthropic-compatible global /anthropic base URL, so the OpenAI-shaped extra_body can enable/disable M3 “thinking” correctly on both /v1 and /anthropic routes.

Changes:

  • Add _is_minimax_global_anthropic_base_url() to detect https://api.minimax.io/anthropic.
  • Update MiniMaxProfile.build_api_kwargs_extras() to apply thinking on /v1 and /anthropic, while only emitting reasoning_split=True for /v1.
  • Clarify provider-profile docstrings to reflect dual-route behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +58 to +62
is_m3 = _is_minimax_m3(model)
is_oai = _is_minimax_global_openai_base_url(base_url)
is_ant = _is_minimax_global_anthropic_base_url(base_url)

if not is_m3 or (not is_oai and not is_ant):
@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/plugins Plugin system and bundled plugins provider/minimax MiniMax (Anthropic transport) labels Jul 29, 2026
…3 reasoning controls

Extends the `MiniMaxProfile.build_api_kwargs_extras` provider plugin to
recognize MiniMax's Anthropic-compatible `/anthropic` endpoint at
`api.minimax.io/anthropic`, in addition to the existing
`api.minimax.io/v1` OpenAI-compatible route.

## Why this is separate from NousResearch#66694

NousResearch#66694 (`fix(minimax): preserve M3 adaptive thinking on Anthropic routes`)
covers the Anthropic adapter layer — the request kwargs that go out as
Anthropic `thinking: {"type": "adaptive"}` on the `auxiliary_client`
adapter path. That's correct and stays open.

This PR covers the provider plugin layer — the `extra_body` that goes out
on the OpenAI-compatible request shape that MiniMax's `/anthropic` endpoint
also accepts. Different code path, different kwargs structure.

## The bug

On the `/anthropic` endpoint, omitting `thinking` causes MiniMax-M3 to
default to OFF (per MiniMax docs). Previously, the provider plugin only
matched `/v1`, so requests to `/anthropic` got an empty extra_body and M3
returned thinking as disabled.

## The fix

Add `_is_minimax_global_anthropic_base_url()` helper that matches
`api.minimax.io/anthropic`. Update `build_api_kwargs_extras` to:
- Accept both `/v1` and `/anthropic` (the existing `/v1` condition becomes
  an OR with the new `/anthropic` condition).
- Send `reasoning_split=True` only on `/v1` (the `/anthropic` endpoint
  already returns thinking as native content blocks, no split flag
  needed).
- Send `thinking: {type: adaptive}` (or `disabled` if reasoning is
  explicitly disabled) on both routes.

## Out of scope

The `/anthropic` route also requires stateful replay preservation across
multi-turn tool calls, which is the focus of the Anthropic adapter work in
NousResearch#66694. The provider plugin here only handles the request-shape kwargs.
@bbasketballer75
bbasketballer75 force-pushed the fix/minimax-anthropic-url-detection branch from cb3375f to 913217a Compare July 29, 2026 18:43
@bbasketballer75

bbasketballer75 commented Jul 29, 2026

Copy link
Copy Markdown
Author

Rebased onto current origin/main (c3ffe27). Clean rebase.

As noted in the PR description, this PR complements #66694 (Anthropic adapter layer) — together they cover both sides of the M3 Anthropic-route contract: #66694 keeps thinking mode propagation alive in the adapter, this PR ensures the MiniMaxProfile.build_api_kwargs_extras only emits the right reasoning_split / native-thinking decision for the matched endpoint. Test coverage is in plugins/model-providers/minimax/tests/ (alongside this branch's +28 / -12 LOC).

@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 /v1 versus /anthropic distinction.

Problems

  • The added profile branch cannot alter the normal /anthropic request path. Current URL routing selects anthropic_messages for that suffix (hermes_cli/runtime_provider.py:135), and that transport calls build_anthropic_kwargs() directly (agent/transports/anthropic.py:63-78) rather than MiniMaxProfile.build_api_kwargs_extras(). The current M3 behavior to change is the manual-thinking branch at agent/anthropic_adapter.py:2866-2887.
  • This diff contains no tests: the PR file API lists only plugins/model-providers/minimax/__init__.py. Current profile tests instead assert /anthropic emits no OpenAI-route controls (tests/plugins/model_providers/test_minimax_profile.py:141-163).

Suggested changes

  • Consolidate this with the Anthropic adapter-layer work in #66694, where the endpoint/model gate can affect the actual Messages request.
  • Add enabled, disabled, unset, and endpoint/model-negative regression coverage through build_anthropic_kwargs() or AnthropicTransport.

Automated hermes-sweeper review.

if not _is_minimax_global_openai_base_url(base_url) or not _is_minimax_m3(model):
is_m3 = _is_minimax_m3(model)
is_oai = _is_minimax_global_openai_base_url(base_url)
is_ant = _is_minimax_global_anthropic_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.

/anthropic resolves to the anthropic_messages transport (hermes_cli/runtime_provider.py:135), which calls build_anthropic_kwargs() directly (agent/transports/anthropic.py:63-78) and does not consume this profile hook. Please place this endpoint/model-specific behavior in the Anthropic adapter (or consolidate it with #66694), where it changes the actual wire request.

@bbasketballer75

Copy link
Copy Markdown
Author

@teknium1 is right, and I verified it independently rather than taking the review at face value. Three findings, the first two decisive:

1. This is a no-op on the route it targets. A /anthropic base URL routes to the anthropic_messages transport (hermes_cli/runtime_provider.py:136-137), whose build_kwargs calls build_anthropic_kwargs() directly and takes no provider-profile argument (agent/transports/anthropic.py). build_api_kwargs_extras — the hook this PR changes — is reachable only from agent/auxiliary_client.py:7374 and agent/transports/chat_completions.py:583. All three MiniMax profiles declare api_mode="anthropic_messages", so the main conversation path never reaches this hook.

2. It breaks an existing test. Ran it on this branch:

FAILED tests/plugins/model_providers/test_minimax_profile.py::
  TestMinimaxM3OpenAIReasoningWireShape::
  test_non_m3_or_non_global_openai_routes_emit_no_openai_reasoning_knobs[MiniMax-M3-https://api.minimax.io/anthropic]
AssertionError: assert {'thinking': {'type': 'adaptive'}} == {}

1 failed, 16 passed. The PR ships no test changes, so this would land red.

3. The matcher misses the CN endpoint. _is_minimax_global_anthropic_base_url requires hostname api.minimax.io, but the minimax_cn profile eleven lines below declares base_url="https://api.minimaxi.com/anthropic". So even on the aux path where the hook does run, one of the two MiniMax Anthropic endpoints isn't covered.

#66694 already does this correctly. Its _is_minimax_anthropic_endpoint matches both api.minimax.io/anthropic and api.minimaxi.com/anthropic, and it's applied inside build_anthropic_kwargs (agent/anthropic_adapter.py:2913) — the layer that actually executes for these routes — with test coverage.

There's also a real hazard in landing both: _AnthropicCompletionsAdapter passes caller extra_body straight through, so on aux/MoA calls this PR would emit a body-level thinking alongside the top-level thinking #66694 sets — a double-specify.

Closing in favor of #66694. Correcting the record on my own earlier comment too: it claimed test coverage lives in plugins/model-providers/minimax/tests/; that directory doesn't exist — the tree has only __init__.py and plugin.yaml.

🤖 Verified and closed by Claude Code

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

Labels

comp/plugins Plugin system and bundled plugins 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 sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants