Skip to content

Allow custom Anthropic-compatible providers to opt into adaptive thinking #4790

@mbazso

Description

@mbazso

What do you want to change?

Add an opt-in flag on Anthropic Messages model configs so custom Anthropic-compatible providers can declare that a model requires the adaptive thinking payload (thinking.type: "adaptive" plus output_config.effort) regardless of the model id.

In a code: an optional compat.forceAdaptiveThinking?: boolean on AnthropicMessagesCompat. When set, supportsAdaptiveThinking() returns the override, otherwise the existing id substring detection is used. Built-in Anthropic models are unchanged.

Why?

I use the pi agent with a corporate proxy that exposes a custom Anthropic-compatible provider, and I ran into an error after a new Anthropic model was released:

400 "thinking.type.enabled" is not supported for this model. Use "thinking.type.adaptive" and "output_config.effort" to control thinking behavior.

When I drilled into it, I found that my config refers to the newest model through the alias anthropic--claude-opus-latest, which the proxy resolves to whatever the latest available model is in the company tenant. pi sends
the legacy thinking payload for that id, and the upstream rejects it.

packages/ai/src/providers/anthropic.ts:supportsAdaptiveThinking() decides whether to send thinking.type: "adaptive" + output_config.effort (new) or thinking.type: "enabled" + budget_tokens (legacy) by substring-matching the model id against opus-4-6, opus-4-7, sonnet-4-6. Custom proxies that expose those models under their own id schemes never match, and thinkingLevelMap does not help because that branch is decided before the map is consulted.

Repro: in ~/.pi/agent/models.json, add a custom anthropic-messages provider with a model id like anthropic--claude-opus-latest and reasoning: true, set defaultThinkingLevel: "medium", and send any prompt against a proxy that requires the adaptive payload. The 400 above is returned. Built-in Anthropic models are unaffected.

How? (optional)

I have a patch on a fork: https://github.com/mbazso/pi/tree/feat/anthropic-adaptive-thinking-override

  • Adds forceAdaptiveThinking?: boolean to AnthropicMessagesCompat in packages/ai/src/types.ts.
  • supportsAdaptiveThinking() in packages/ai/src/providers/anthropic.ts now takes the model and checks model.compat?.forceAdaptiveThinking first, if not set falls back to the existing id-based detection.
  • getAnthropicCompat() returns Required<Omit<AnthropicMessagesCompat, "forceAdaptiveThinking">> because undefined carries meaning here (= use id-based detection).
  • CHANGELOG entry under ### Added in packages/ai/CHANGELOG.md.

npm run check passes; existing anthropic-thinking-disable and anthropic-opus-4-7-smoke tests pass.

Happy to open a PR with a regression test under packages/ai/test/ if this looks reasonable.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions