You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is the symmetric counterpart to #219 (fixed by #225).
#225 added adaptive → enabled conversion in augmentRequestForBedrock() for older Bedrock models that don't support adaptive thinking. The reverse conversion is missing: when Claude Code sends thinking.type: "enabled" (its fallback default when it cannot introspect the target model's capabilities) and the resolved Bedrock model is adaptive-only (Opus 4.7+), the body is forwarded unchanged and Bedrock 400s.
With AI Bridge in the path, Claude Code cannot read the application inference profile metadata (the request goes to Coder, not directly to Bedrock), so it falls back to the deprecated enabled shape — which Opus 4.7 rejects per the model card:
Claude Opus 4.7 only supports thinking.type: "adaptive" for extended thinking. Unlike Claude Opus 4.6, thinking.type: "enabled" with budget_tokens is not supported and will return a 400 error.
Error
API Error: 400 {"error":{"message":"POST \"https://bedrock-runtime.us-east-1.amazonaws.com/v1/messages\": 400 Bad Request {\"message\":\"\\\"thinking.type.enabled\\\" is not supported for this model. Use \\\"thinking.type.adaptive\\\" and \\\"output_config.effort\\\" to control thinking behavior.\"}", "type":"api_error"}, ...}
Direct AI Bridge probe with the legacy shape reproduces the 400:
curl -H "x-api-key: $CODER_TOKEN" \
-H 'Content-Type: application/json' \
-H 'anthropic-version: 2023-06-01' \
-X POST https://<coder>/api/v2/aibridge/anthropic/v1/messages \
-d '{"model":"us.anthropic.claude-opus-4-7","max_tokens":2048, "thinking":{"type":"enabled","budget_tokens":1024}, "messages":[{"role":"user","content":"hi"}]}'# -> HTTP 400 "thinking.type.enabled" is not supported for this model
The same call against us.anthropic.claude-opus-4-6-v1 succeeds (4.6 still accepts both shapes).
Root cause
In intercept/messages/base.go, augmentRequestForBedrock() already gates on bedrockModelSupportsAdaptiveThinking(model) and calls convertAdaptiveThinkingForBedrock() when the target doesn't support adaptive. There is no symmetric helper for the case where the target only supports adaptive and the incoming request uses enabled.
Proposed fix
In augmentRequestForBedrock(), add the symmetric transformation:
Introduce an "adaptive-only" capability set (Opus 4.7+, presumably future Opus 4.x and Sonnet 4.x as they ship in adaptive-only mode).
If thinking.type == "enabled" and the resolved Bedrock model is in that set, rewrite the body to:
thinking: { type: "adaptive" }
output_config.effort derived from the original budget_tokens / max_tokens ratio (mirror of the OpenRouter-style mapping used in fix: remove unsupported fields from requests to Bedrock #225, but in reverse: budget < ~25% of max → low, < ~50% → medium, otherwise → high).
Drop budget_tokens and any related legacy fields the new shape doesn't accept.
The capability set can be hard-coded for now (mirroring the existing string-contains style of bedrockModelSupportsAdaptiveThinking) or driven from the same Bedrock model metadata Claude Code uses when it has direct access.
Workaround
Pin CODER_AIBRIDGE_BEDROCK_MODEL to us.anthropic.claude-opus-4-6-v1. Operationally works but loses 4.7 quality and requires every operator to know to avoid 4.7+ until the underlying fix lands.
Why this matters
Without the fix, every customer using AI Bridge → Bedrock with the (commonly recommended) Opus 4.7 model has Claude Code completely broken — every request 400s, in both thinking and non-thinking flows.
The error surface is misleading: the 400 looks like a config problem; you have to dig two layers down to realize it's a body-shape mismatch between Claude Code and the Bedrock model.
Summary
This is the symmetric counterpart to #219 (fixed by #225).
#225 added
adaptive → enabledconversion inaugmentRequestForBedrock()for older Bedrock models that don't support adaptive thinking. The reverse conversion is missing: when Claude Code sendsthinking.type: "enabled"(its fallback default when it cannot introspect the target model's capabilities) and the resolved Bedrock model is adaptive-only (Opus 4.7+), the body is forwarded unchanged and Bedrock 400s.With AI Bridge in the path, Claude Code cannot read the application inference profile metadata (the request goes to Coder, not directly to Bedrock), so it falls back to the deprecated
enabledshape — which Opus 4.7 rejects per the model card:Error
Reproduction
Coder server with:
CODER_AIBRIDGE_ENABLED=trueCODER_AIBRIDGE_BEDROCK_REGION=us-east-1CODER_AIBRIDGE_BEDROCK_MODEL=us.anthropic.claude-opus-4-7Direct AI Bridge probe with the legacy shape reproduces the 400:
The same call against
us.anthropic.claude-opus-4-6-v1succeeds (4.6 still accepts both shapes).Root cause
In
intercept/messages/base.go,augmentRequestForBedrock()already gates onbedrockModelSupportsAdaptiveThinking(model)and callsconvertAdaptiveThinkingForBedrock()when the target doesn't support adaptive. There is no symmetric helper for the case where the target only supports adaptive and the incoming request usesenabled.Proposed fix
In
augmentRequestForBedrock(), add the symmetric transformation:thinking.type == "enabled"and the resolved Bedrock model is in that set, rewrite the body to:thinking: { type: "adaptive" }output_config.effortderived from the originalbudget_tokens/max_tokensratio (mirror of the OpenRouter-style mapping used in fix: remove unsupported fields from requests to Bedrock #225, but in reverse:budget < ~25%of max →low,< ~50%→medium, otherwise →high).budget_tokensand any related legacy fields the new shape doesn't accept.Anthropic-Beta: interleaved-thinking-2025-05-14(and friends) header handling for adaptive-only models, similar to the GovCloud header strip in bug:Anthropic-Betaheader forwarded to Bedrock causesinvalid beta flagerrors #221 / fix: filter unsupported Anthropic-Beta headers from Bedrock #226. Best evidence is that Opus 4.7 still accepts those beta flags, so this may be a no-op — but worth verifying alongside the body rewrite.The capability set can be hard-coded for now (mirroring the existing string-contains style of
bedrockModelSupportsAdaptiveThinking) or driven from the same Bedrock model metadata Claude Code uses when it has direct access.Workaround
Pin
CODER_AIBRIDGE_BEDROCK_MODELtous.anthropic.claude-opus-4-6-v1. Operationally works but loses 4.7 quality and requires every operator to know to avoid 4.7+ until the underlying fix lands.Why this matters
The reporter has offered to test a candidate fix on a staging cluster running v2.32.1.
References
thinking.type: "adaptive"requests #219 — Bedrock models that don't support adaptive thinking rejectthinking.type: "adaptive"Anthropic-Betaheader forwarded to Bedrock causesinvalid beta flagerrors #221 / fix: filter unsupported Anthropic-Beta headers from Bedrock #226 — Anthropic-Beta header forwarding to Bedrockthinking.type.enablednot supported still happens in 2.1.113Created on behalf of @stirby