Skip to content

fix(providers/anthropic): convert reasoning effort to budget thinking on pre-4.6 models#47

Merged
ibetitsmike merged 2 commits into
coder_2_33from
mike/anthropic-legacy-effort
Jul 18, 2026
Merged

fix(providers/anthropic): convert reasoning effort to budget thinking on pre-4.6 models#47
ibetitsmike merged 2 commits into
coder_2_33from
mike/anthropic-legacy-effort

Conversation

@ibetitsmike

Copy link
Copy Markdown

Problem

Setting ProviderOptions.Effort always sends thinking: {type: "adaptive"} plus output_config.effort. Models older than Claude 4.6 (Haiku 4.5, Sonnet 4.5, all 3.x) reject that shape with HTTP 400 adaptive thinking is not supported on this model, so any caller that applies an effort dial to a legacy Anthropic model gets a hard failure on every request.

Related latent bug: the API's output_config.effort enum is low|medium|high|max, but callers can pass wider scales (none, minimal, xhigh), which were forwarded raw.

Changes

  • Gate the adaptive path on new supportsAdaptiveThinking: Claude >= 4.6 parsed from the model ID, tolerant of Bedrock prefixes/suffixes (us.anthropic.claude-haiku-4-5-20251001-v1:0) and both name orders (claude-sonnet-4-6, claude-3-5-haiku). Unparseable names fail closed to legacy, so a bad parse degrades to the safe enabled shape, never a 400. The claude-mythos-preview allowlist is kept.
  • On legacy models, convert effort into {type: "enabled", budget_tokens} derived from the per-call max_tokens (ratios mirror the coder/aibridge Anthropic shim: low .2, medium .5, high .8, xhigh .9, max .95, minimal = 1024 floor). If the derived budget would fall below the API's 1024-token minimum, thinking is omitted entirely (keeps small-max_tokens calls like title generation working). The derived budget wins over a configured Thinking.BudgetTokens so the effort dial stays live; Effort == nil behavior is unchanged.
  • The legacy path mirrors the existing enabled-thinking side effects: thinking_display and stripping temperature/top_p/top_k with warnings (extracted into a shared helper).
  • Normalize effort before sending on adaptive models: minimal -> low, xhigh -> max. New EffortNone (none) disables thinking entirely on any model.

The Bedrock provider wraps this one, so the fix covers Bedrock model IDs too.

Validation

  • go test ./... passes.
  • New unit tests: version gating table, legacy budget derivation (incl. Bedrock-prefixed IDs, budget floor, small max_tokens, effort-vs-budget precedence), effort none, normalization on adaptive models, and sampling-param stripping with warnings.

This PR was authored by Mux, an AI coding agent, acting on Mike's behalf.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7b40c065b0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread providers/anthropic/anthropic.go
@ibetitsmike

Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 97d27c873f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread providers/anthropic/anthropic.go Outdated
Comment thread providers/anthropic/anthropic.go Outdated
ibetitsmike added a commit to coder/coder that referenced this pull request Jul 18, 2026
…pic models

A model config with reasoning_effort on a legacy Anthropic model such
as claude-haiku-4-5 failed every generation with HTTP 400 "adaptive
thinking is not supported on this model", because the fantasy
Anthropic provider always serialized effort as adaptive thinking plus
output_config.effort.

Bump the coder/fantasy pin to coder/fantasy#47, which converts effort
into enabled budget thinking (budget derived from max_tokens) on
models older than Claude 4.6 and keeps the adaptive shape for newer
ones. Effort values outside the API enum are normalized, and none now
disables thinking entirely.

Update the compaction override test to cover both the legacy and the
adaptive-capable request shapes, and add a regression test asserting
a claude-haiku-4-5 config with reasoning_effort produces enabled
thinking with the derived budget and no output_config.
@ibetitsmike
ibetitsmike force-pushed the mike/anthropic-legacy-effort branch from 97d27c8 to be69f8e Compare July 18, 2026 17:06
@ibetitsmike

Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: be69f8e870

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread providers/anthropic/anthropic.go
@ibetitsmike
ibetitsmike force-pushed the mike/anthropic-legacy-effort branch from be69f8e to 81ae747 Compare July 18, 2026 17:15
@ibetitsmike

Copy link
Copy Markdown
Author

@codex review

ibetitsmike added a commit to coder/coder that referenced this pull request Jul 18, 2026
…pic models

A model config with reasoning_effort on a legacy Anthropic model such
as claude-haiku-4-5 failed every generation with HTTP 400 "adaptive
thinking is not supported on this model", because the fantasy
Anthropic provider always serialized effort as adaptive thinking plus
output_config.effort.

Bump the coder/fantasy pin to coder/fantasy#47, which converts effort
into enabled budget thinking (budget derived from max_tokens) on
models older than Claude 4.6 and keeps the adaptive shape for newer
ones. Effort values outside the API enum are normalized, and none now
disables thinking entirely.

Update the compaction override test to cover both the legacy and the
adaptive-capable request shapes, and add a regression test asserting
a claude-haiku-4-5 config with reasoning_effort produces enabled
thinking with the derived budget and no output_config.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 81ae747916

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread providers/anthropic/anthropic.go
Comment thread providers/anthropic/anthropic.go Outdated
@ibetitsmike
ibetitsmike force-pushed the mike/anthropic-legacy-effort branch from 81ae747 to 1118bd7 Compare July 18, 2026 17:25
@ibetitsmike

Copy link
Copy Markdown
Author

@codex review

ibetitsmike added a commit to coder/coder that referenced this pull request Jul 18, 2026
…pic models

A model config with reasoning_effort on a legacy Anthropic model such
as claude-haiku-4-5 failed every generation with HTTP 400 "adaptive
thinking is not supported on this model", because the fantasy
Anthropic provider always serialized effort as adaptive thinking plus
output_config.effort.

Bump the coder/fantasy pin to coder/fantasy#47, which converts effort
into enabled budget thinking (budget derived from max_tokens) on
models older than Claude 4.6 and keeps the adaptive shape for newer
ones. Effort values outside the API enum are normalized, and none now
disables thinking entirely.

Update the compaction override test to cover both the legacy and the
adaptive-capable request shapes, and add a regression test asserting
a claude-haiku-4-5 config with reasoning_effort produces enabled
thinking with the derived budget and no output_config.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1118bd7aef

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread providers/anthropic/anthropic_test.go Outdated
Comment thread providers/anthropic/anthropic.go
@ibetitsmike
ibetitsmike force-pushed the mike/anthropic-legacy-effort branch from 1118bd7 to 01904cc Compare July 18, 2026 17:36
@ibetitsmike

Copy link
Copy Markdown
Author

@codex review

ibetitsmike added a commit to coder/coder that referenced this pull request Jul 18, 2026
…pic models

A model config with reasoning_effort on a legacy Anthropic model such
as claude-haiku-4-5 failed every generation with HTTP 400 "adaptive
thinking is not supported on this model", because the fantasy
Anthropic provider always serialized effort as adaptive thinking plus
output_config.effort.

Bump the coder/fantasy pin to coder/fantasy#47, which converts effort
into enabled budget thinking (budget derived from max_tokens) on
models older than Claude 4.6 and keeps the adaptive shape for newer
ones. Effort values outside the API enum are normalized, and none now
disables thinking entirely.

Update the compaction override test to cover both the legacy and the
adaptive-capable request shapes, and add a regression test asserting
a claude-haiku-4-5 config with reasoning_effort produces enabled
thinking with the derived budget and no output_config.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 01904cc959

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread providers/anthropic/anthropic_test.go Outdated
… on pre-4.6 models

Effort previously always sent thinking type "adaptive" plus
output_config.effort, which models older than Claude 4.6 reject with
an HTTP 400 ("adaptive thinking is not supported on this model").

- Gate the adaptive path on supportsAdaptiveThinking (Claude >= 4.6,
  parsed from the model ID, tolerant of Bedrock prefixes and both
  name orders; unparseable names are treated as legacy).
- On legacy models, convert effort into enabled thinking with a
  budget derived from max_tokens (ratios mirror the coder/aibridge
  shim), omitting thinking when the budget would fall below the
  API's 1024-token minimum.
- Normalize effort values outside the output_config.effort enum:
  minimal maps to low, xhigh maps to max, and none disables thinking
  entirely.
@ibetitsmike
ibetitsmike force-pushed the mike/anthropic-legacy-effort branch from 01904cc to fdf4de1 Compare July 18, 2026 17:45
@ibetitsmike

Copy link
Copy Markdown
Author

@codex review

ibetitsmike added a commit to coder/coder that referenced this pull request Jul 18, 2026
…pic models

A model config with reasoning_effort on a legacy Anthropic model such
as claude-haiku-4-5 failed every generation with HTTP 400 "adaptive
thinking is not supported on this model", because the fantasy
Anthropic provider always serialized effort as adaptive thinking plus
output_config.effort.

Bump the coder/fantasy pin to coder/fantasy#47, which converts effort
into enabled budget thinking (budget derived from max_tokens) on
models older than Claude 4.6 and keeps the adaptive shape for newer
ones. Effort values outside the API enum are normalized, and none now
disables thinking entirely.

Update the compaction override test to cover both the legacy and the
adaptive-capable request shapes, and add a regression test asserting
a claude-haiku-4-5 config with reasoning_effort produces enabled
thinking with the derived budget and no output_config.
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Hooray!

Reviewed commit: fdf4de16c5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Run the scanner with Go 1.26.5 so the stdlib crypto/tls finding
(GO-2026-5856) is fixed, and bump golang.org/x/image to v0.43.0
for GO-2026-5061.
@ibetitsmike
ibetitsmike merged commit a63de4b into coder_2_33 Jul 18, 2026
11 checks passed
ibetitsmike added a commit to coder/coder that referenced this pull request Jul 18, 2026
coder/fantasy#47 merged; replace the PR-head pseudo-version with the
squash commit a63de4b40315 on coder_2_33 (identical tree).
ibetitsmike added a commit to coder/coder that referenced this pull request Jul 18, 2026
## Problem

A chat model config with `reasoning_effort` set on a pre-4.6 Anthropic
model (for example `claude-haiku-4-5`) fails every generation with HTTP
400 `adaptive thinking is not supported on this model`, surfaced in chat
as "Anthropic returned an unexpected error." The fantasy Anthropic
provider always serialized effort as `thinking: {type: "adaptive"}` plus
`output_config.effort`, a shape only Claude 4.6+ accepts.

## Changes

- Bump the coder/fantasy pin to include coder/fantasy#47: the provider
now converts effort into `{type: "enabled", budget_tokens}` on models
older than Claude 4.6, with the budget derived from the call's
`max_tokens` (aibridge-mirroring ratios, 1024-token API floor; below the
floor thinking is omitted, which keeps small-budget calls like title
generation working). Adaptive-capable models keep the current shape, and
Opus 4.5 keeps `output_config.effort` alongside the derived budget since
it supports effort without adaptive thinking. Models older than Claude
3.7 predate extended thinking, so effort sends no thinking at all there.
`minimal` is normalized to `low`, `xhigh` falls back to `max` on
adaptive models that predate the xhigh tier (Claude 4.7+); effort `none`
disables thinking, including an explicit `thinking: {type: "disabled"}`
on Claude 5+ models that otherwise run adaptive thinking by default. The
Bedrock provider wraps the Anthropic one, so both are covered, and
Vertex-style `@date` model IDs parse correctly.
- `TestActiveServer_CompactionModelOverride` previously codified the
buggy shape (asserting `output_config.effort` sent to
`claude-3-5-haiku-latest`). The summary-routing subtest is now a
three-case table: pre-thinking override models (Claude 3.5) expect no
thinking, legacy budget-thinking ones (Haiku 4.5) expect enabled
thinking with the derived budget, adaptive-capable ones still expect
`output_config.effort`.
- New regression test `TestActiveServer_AnthropicModelReasoningEffort`:
a `claude-haiku-4-5` config with `reasoning_effort` produces enabled
thinking with the derived budget and no `output_config` on the wire, and
a `claude-sonnet-5` config with effort `none` sends an explicit thinking
disable.
- `chattest.AnthropicRequest` gains a `Thinking` field so tests can
assert the thinking config.
- One-sentence note in the chatd ARCHITECTURE reasoning-effort section.

No chatd production code changes: `ApplyReasoningEffort` keeps setting
`Effort`, which is now valid for every Anthropic model.

## Validation

- `go test ./coderd/x/chatd/...` passes (19 packages).
- Fork PR validated separately: full fantasy test suite plus new
provider unit tests (version gating incl. Vertex/Bedrock IDs, budget
derivation, floor behavior, normalization, effort `none` incl. Claude 5+
disable, Opus 4.5 effort preservation, sampling-param stripping),
golangci-lint clean.

Closes
[CODAGT-812](https://linear.app/codercom/issue/CODAGT-812/reasoning-effort-on-pre-46-anthropic-models-fails-generations-with).

> This PR was authored by Mux, an AI coding agent, acting on Mike's
behalf.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant