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
@github-actions

Copy link
Copy Markdown

Action required: PR inactive for 5 days.
Status update or closure in 10 days.

@github-actions github-actions Bot added the state: inactive No current action needed/possible; issue fixed, out of scope, or superseded. label Jun 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

state: inactive No current action needed/possible; issue fixed, out of scope, or superseded. type: fix Iterations on existing features or infrastructure.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant