Skip to content

fix(bedrock): clamp top_p >= 0.95 for adaptive thinking, not just legacy budget#3472

Open
resrever wants to merge 1 commit into
tailcallhq:mainfrom
resrever:fix/bedrock-adaptive-top-p
Open

fix(bedrock): clamp top_p >= 0.95 for adaptive thinking, not just legacy budget#3472
resrever wants to merge 1 commit into
tailcallhq:mainfrom
resrever:fix/bedrock-adaptive-top-p

Conversation

@resrever

@resrever resrever commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

What

ModelSpecificReasoning normalizes reasoning per model family before the Bedrock conversion runs. Previously the top_p >= 0.95 clamp in ConverseStreamInput::from_domain fired only when the legacy thinking.enabled (budget) shape was being emitted. This change applies the clamp whenever any thinking shape is active (reasoning_on), covering thinking.adaptive (Opus 4.6 / Sonnet 4.6) as well.

The only broken combo was AdaptiveFriendly models (Opus 4.6, Sonnet 4.6) on Bedrock, where top_p was passed through untouched alongside thinking.adaptive. Opus 4.7 / 4.8 are unaffected (ModelSpecificReasoning strips top_p to None for them before conversion), and the direct Anthropic / Vertex paths were already correct.

Why

Anthropic-on-Bedrock rejects top_p < 0.95 for adaptive thinking, not just the legacy budget shape. Confirmed against the live endpoint — without this fix, an adaptive-thinking request with top_p < 0.95 returns:

ERROR: ValidationException: The model returned the following errors: `top_p` must be
greater than or equal to 0.95 or unset when thinking is enabled or in adaptive mode.
Please consult our documentation at
https://docs.claude.com/en/docs/build-with-claude/extended-thinking#important-considerations-when-using-extended-thinking

With the fix applied, the request succeeds (no error).

Test

  • Renamed test_from_domain_context_adaptive_thinking_does_not_clamp_top_p -> ..._clamps_top_p and inverted the assertion (top_p >= 0.95). This reverses the earlier assumption that adaptive thinking should leave top_p untouched.
  • cargo test -p forge_repo passes.
  • Verified end-to-end against the live Bedrock endpoint (error above no longer occurs).

…acy budget

Anthropic-on-Bedrock enforces the top_p >= 0.95-or-unset constraint for
both thinking.enabled (legacy budget) and thinking.adaptive modes.  The
previous code only applied the clamp for emits_legacy_thinking, leaving
top_p unconstrained for Opus 4.6 / Sonnet 4.6 in adaptive mode.

The direct Anthropic and Vertex AI paths were already correct (ReasoningTransform
strips top_p to None whenever is_reasoning_supported()).  Opus 4.7/4.8 on
Bedrock were also fine (ModelSpecificReasoning strips top_p before conversion).
The only broken combo was AdaptiveFriendly models (Opus 4.6, Sonnet 4.6) on
Bedrock where top_p was passed through untouched alongside thinking.adaptive.

Fix: change the adjusted_top_p guard from emits_legacy_thinking to reasoning_on.
Update the test that previously asserted adaptive thinking left top_p untouched.
@github-actions github-actions Bot added the type: fix Iterations on existing features or infrastructure. label Jun 8, 2026
@resrever resrever marked this pull request as ready for review June 8, 2026 22:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: fix Iterations on existing features or infrastructure.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant