Skip to content

fix: convert adaptive thinking to enabled for Bedrock models that don't support it#220

Open
blinkagent[bot] wants to merge 3 commits intomainfrom
fix/bedrock-adaptive-thinking-fallback
Open

fix: convert adaptive thinking to enabled for Bedrock models that don't support it#220
blinkagent[bot] wants to merge 3 commits intomainfrom
fix/bedrock-adaptive-thinking-fallback

Conversation

@blinkagent
Copy link

@blinkagent blinkagent bot commented Mar 16, 2026

When Claude Code sends thinking.type: "adaptive" (the default for Opus 4.6 / Sonnet 4.6), Bedrock models that predate adaptive thinking support (e.g. Sonnet 4.5 in GovCloud us-gov-west-1) reject the request with a 400 error:

thinking: Input tag 'adaptive' found using 'type' does not match any of the expected tags: 'disabled', 'enabled' 

Changes

intercept/messages/base.go

  • Added bedrockModelSupportsAdaptiveThinking() to detect whether the target Bedrock model supports adaptive thinking (only Opus 4.6 and Sonnet 4.6 do)
  • Added convertAdaptiveThinkingForBedrock() which converts {"type": "adaptive"} to {"type": "enabled", "budget_tokens": 10000} when the target model doesn't support it
  • Extended augmentRequestForBedrock() to call the new conversion after the model name remap

intercept/messages/base_test.go

  • Added TestBedrockModelSupportsAdaptiveThinking — 11 cases covering all model name formats
  • Added TestConvertAdaptiveThinkingForBedrock — 6 cases: conversion for non-4.6 models, preservation for 4.6 models, no-op for enabled/disabled/absent thinking

Fixes #219

…'t support it When Claude Code sends thinking.type: "adaptive" (the default for Opus 4.6 / Sonnet 4.6), Bedrock models that predate adaptive thinking support (e.g. Sonnet 4.5 in GovCloud) reject the request with a 400 error. This adds thinking parameter transformation to augmentRequestForBedrock(): if the target model does not support adaptive thinking, it converts {"type": "adaptive"} to {"type": "enabled", "budget_tokens": 10000}. Models that support adaptive thinking (Opus 4.6, Sonnet 4.6) are detected by model name and left unchanged. Fixes #219
@uzair-coder07
Copy link

I have used blink to create this PR. I will take a look at the code and will test it out before I ask for a review.

@uzair-coder07
Copy link

I had a first pass through the code and I believe hardcoding the budget_tokens to 10000 can backfire since Anthropic API requires budget_tokens < max_tokens? Maybe we should be checking the request's max_tokens. If a client sends a request with max_tokens: 8000 (or less), Then we might run into another 400 error like "max_tokens must be greater than thinking.budget_tokens".

blink-so bot and others added 2 commits March 16, 2026 21:30
The Anthropic API requires budget_tokens < max_tokens, and Bedrock enforces a minimum of 1024 for budget_tokens. A hardcoded fallback of 10000 could violate the first constraint if max_tokens is small. Now adaptiveFallbackBudgetTokens() computes budget_tokens as 80% of max_tokens, clamped to the Bedrock minimum of 1024. When max_tokens is absent or zero, the default of 10000 is used. When max_tokens is too small to accommodate the minimum, half of max_tokens is used.
adaptiveFallbackBudgetTokens now returns (int64, bool). When max_tokens is present but too small to accommodate Bedrock's minimum budget_tokens of 1024, it returns (0, false) instead of halving the value below the minimum. convertAdaptiveThinkingForBedrock checks the ok return and skips the conversion on false, logging a warning and leaving the payload unchanged. This surfaces a clear upstream error rather than sending a known-bad budget_tokens that would cause a different 400. Fixes the edge case introduced in 252e414 where max_tokens <= 1280 produced a budget_tokens below minBedrockBudgetTokens. Updates TestConvertAdaptiveThinkingForBedrock to assert the conversion is skipped rather than asserting the previously broken half-value. Adds TestAdaptiveFallbackBudgetTokens to directly cover all input classes of the helper, including the two false cases.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant