Skip to content

Bedrock: add adaptive thinking support for Claude Sonnet 4.6 / Opus 4.6 #5304

Description

@iddoaviram-rs

Initial Checks

  • I'm using the latest version of Pydantic AI
  • I've searched for my issue in the issue tracker before opening this issue

Description

The Bedrock provider does not support thinking.type: "adaptive", which AWS requires for Claude Sonnet 4.6 and Opus 4.6. The provider always sends {"type": "enabled", "budget_tokens": N}, which is deprecated for these models.

This has a concrete impact: we tested directly against the Bedrock Converse API and confirmed that with thinking.type: "enabled", thinking is silently disabled after the first generation in multi-turn agent runs. The model thinks on the first call but produces zero reasoningContent blocks on all subsequent calls (after tool use), regardless of whether thinking blocks are properly round-tripped in the message history.

Switching to thinking.type: "adaptive" restores thinking on subsequent generations:

Call Thinking config Thinking blocks round-tripped Produces thinking
1st enabled + budget_tokens N/A Yes
2nd enabled + budget_tokens Yes No
2nd enabled + budget_tokens No No
2nd adaptive Yes Yes
2nd adaptive No No

This means any pydantic-ai user running a multi-turn agent on Bedrock with Sonnet 4.6 / Opus 4.6 silently gets no reasoning after the first LLM call — where tool results are interpreted and decisions are made.

The Anthropic direct API provider already supports adaptive thinking (#4216, #3894). The Bedrock provider does not — the unified thinking docs note "No adaptive support" for Bedrock.

Note: the effort sub-parameter inside adaptive (e.g. {"type": "adaptive", "effort": "high"}) is not yet accepted by the Bedrock Converse API — it returns ValidationException: thinking.adaptive.effort: Extra inputs are not permitted. Plain {"type": "adaptive"} works and defaults to high.

Workaround

Pass the config manually via bedrock_additional_model_requests_fields:

BedrockModelSettings(
    bedrock_additional_model_requests_fields={
        "thinking": {"type": "adaptive"}
    }
)

This works because _translate_thinking skips the thinking key when it's already present in the additional fields.

Python, Pydantic AI & LLM client version

  • Python: 3.12
  • Pydantic AI: 1.85.1
  • boto3 / botocore (Bedrock)

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions