Skip to content

Python: Fix Claude Opus 5.5 on Bedrock by skipping reasoningContent blocks - #14469

Open
Lucas Kim (kimnamu) wants to merge 1 commit into
microsoft:mainfrom
kimnamu:fix/bedrock-opus-5-5
Open

Lucas Kim (kimnamu) wants to merge 1 commit into
microsoft:mainfrom
kimnamu:fix/bedrock-opus-5-5

Conversation

@kimnamu

Copy link
Copy Markdown

Motivation and Context

Thanks to the Python team for the Bedrock connector (#9100) and #12395, which let the Claude Opus 5.5 profile IDs load unchanged.

Fixes #14468

With no thinking settings, Claude Opus 5.5 (and Opus 5) on Bedrock send a reasoningContent block first whenever the model decides to think. How often depends on the prompt (Opus 5.5, raw converse: "Weather in Paris? brief" 5/5, "Hello" 0/5). BedrockChatCompletion then raises (non-streaming) or reads the reasoning delta as toolUse (streaming).

case (live, us-east-1) Before (main) After
us.anthropic.claude-opus-5-5, "Weather in Paris? brief", non-streaming ❌ 0/5 ServiceInvalidResponseError: Unsupported content type ... reasoningContent ✅ 5/5
same, streaming ❌ 0/5 KeyError: 'toolUse' ✅ 5/5
global.anthropic.claude-opus-5-5, both modes ❌ 0/3 each ✅ 3/3 each
us.anthropic.claude-opus-5, both modes ❌ 0/3 each ✅ 3/3 each
Opus 5.5, Auto(auto_invoke=False), model thinks before the tool calls ❌ 2/2 ServiceInvalidResponseError ✅ 2/2 TOOL_CALLS
Opus 5.5, Auto() auto-invoke, model thinks after the tool result ❌ 3/3 ServiceInvalidResponseError ✅ 3/3 STOP
Opus 5.5, "Hello" (no reasoning block) ✅ 3/3 ✅ unchanged
Claude Haiku 4.5, Nova Lite, both modes ✅ ✅ unchanged
Existing Bedrock unit tests (text/image/toolUse, unknown stream event raises) ✅ 113 passed ✅ unchanged
Public API ✅ ✅ unchanged

Parallel tool calls with auto-invoke still fail with Expected toolResult blocks at messages.2.content. That is #14073 (fix in #14074); it also fails on main with Opus 5 and no reasoning block.

Description

  • _create_chat_message_content: skip reasoningContent next to the text/image/toolUse branches (the else at L257 raised). Other unknown blocks still raise.
  • _parse_content_block_delta_event: build items with if/elif like _parse_content_block_start_event. Deltas that are neither text nor toolUse (reasoningContent, citation) now give an empty chunk instead of an accidental KeyError on ["toolUse"] (L346-348).

The Anthropic connector also reads only TextBlock and tool-use blocks (anthropic_chat_completion.py L267-269). Surfacing ReasoningContent would need _format_assistant_message to send it back with its signature; left for a follow-up.

References: https://www.anthropic.com/news/claude-opus-5-5 · https://platform.claude.com/docs/en/models/opus-5-5/migration-guide · https://platform.claude.com/docs/en/about-claude/models/overview

Tests (red/green, lint, live)

New tests kept, source reverted to main:

E   semantic_kernel.exceptions.service_exceptions.ServiceInvalidResponseError: Unsupported content type in the response: {'reasoningContent': {'reasoningText': {'text': '', 'signature': 'sig'}}}
E   KeyError: 'toolUse'
FAILED tests/unit/connectors/ai/bedrock/services/test_bedrock_chat_completion.py::test_bedrock_chat_completion_skips_reasoning_content
FAILED tests/unit/connectors/ai/bedrock/services/test_bedrock_chat_completion.py::test_bedrock_streaming_chat_completion_skips_reasoning_delta
2 failed, 113 passed in 0.14s

With the fix:

$ uv run pytest tests/unit/connectors/ai/bedrock
115 passed in 0.09s
$ uv run ruff check <changed files>          -> All checks passed!
$ uv run ruff format --check <changed files> -> 2 files already formatted
$ uv run mypy --config-file mypy.ini bedrock_chat_completion.py -> Success: no issues found in 1 source file

How often the block appears (raw boto3 converse, no thinking settings):

us.anthropic.claude-opus-5-5 'Hello': reasoningContent in 0/5  ['text']
us.anthropic.claude-opus-5-5 'Say hi in 3 words.': reasoningContent in 3/5  ['reasoningContent,text', 'text']
us.anthropic.claude-opus-5-5 'Weather in Paris? brief': reasoningContent in 5/5  ['reasoningContent,text']
us.anthropic.claude-opus-5 'Hello': reasoningContent in 3/3  ['reasoningContent,text']
us.anthropic.claude-opus-5 'Say hi in 3 words.': reasoningContent in 0/3  ['text']
us.anthropic.claude-opus-5 'Weather in Paris? brief': reasoningContent in 2/3  ['reasoningContent,text', 'text']

Live through BedrockChatCompletion, same scripts, only the source file differs:

before us.anthropic.claude-opus-5-5 non-streaming OK 0/5  ServiceInvalidResponseError: Unsupported content type in the response: {'reasoningContent': ...
before us.anthropic.claude-opus-5-5 streaming OK 0/5  KeyError: 'toolUse'
before global.anthropic.claude-opus-5-5 non-streaming OK 0/3
before global.anthropic.claude-opus-5-5 streaming OK 0/3
before us.anthropic.claude-opus-5 non-streaming OK 0/3
before us.anthropic.claude-opus-5 streaming OK 0/3
after  us.anthropic.claude-opus-5-5 non-streaming OK 5/5
after  us.anthropic.claude-opus-5-5 streaming OK 5/5
after  global.anthropic.claude-opus-5-5 non-streaming OK 3/3
after  global.anthropic.claude-opus-5-5 streaming OK 3/3
after  us.anthropic.claude-opus-5 non-streaming OK 3/3
after  us.anthropic.claude-opus-5 streaming OK 3/3

Tool calls on us.anthropic.claude-opus-5-5 (one get_weather(city) function):

prompt A: "I am deciding between Paris, Lyon and Nice for a picnic tomorrow; think about which cities matter, check the weather where needed, and recommend one."
prompt B: "Think about whether tomorrow suits a picnic in Paris: check the weather with the tool, then recommend yes or no."

before A Auto(auto_invoke=False) run1: ServiceInvalidResponseError: Unsupported content type in the response: {'reasoningContent': ...
before A Auto(auto_invoke=False) run2: ServiceInvalidResponseError: Unsupported content type in the response: {'reasoningContent': ...
after  A Auto(auto_invoke=False) run1: FinishReason.TOOL_CALLS raw=['reasoningContent', 'text', 'toolUse', 'toolUse', 'toolUse']
after  A Auto(auto_invoke=False) run2: FinishReason.TOOL_CALLS raw=['reasoningContent', 'text', 'toolUse', 'toolUse', 'toolUse']
before B Auto() runs 1-3: ServiceInvalidResponseError: Unsupported content type in the response: {'reasoningContent': ...
after  B Auto() runs 1-3: FinishReason.STOP first-turn raw=['toolUse'] final-turn raw=['reasoningContent', 'text'] roles=['user', 'assistant', 'tool']
before A Auto(auto_invoke=True) runs 1-2: ServiceInvalidResponseError: Unsupported content type in the response: {'reasoningContent': ...
after  A Auto(auto_invoke=True) runs 1-2: ValidationException: ... Expected toolResult blocks at messages.2.content ...   (#14073)
before A Auto(auto_invoke=True) on us.anthropic.claude-opus-5, first turn without reasoning, runs 1-2: ValidationException: ... Expected toolResult blocks at messages.2.content ...

Contribution Checklist

…locks

With no thinking settings, Claude Opus 5.5 (and Opus 5) on Bedrock send a
reasoningContent block ahead of the text or toolUse blocks whenever the model
decides to think; how often depends on the prompt. The Converse response
parser raised ServiceInvalidResponseError on that block, and the streaming
delta parser read the reasoning delta as toolUse (KeyError).

Skip reasoningContent blocks in responses; other unknown blocks still raise.
Stream deltas that are neither text nor toolUse now give an empty chunk, like
_parse_content_block_start_event. Nothing is surfaced or sent back.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟢 Approval recommended

No unresolved review issues were identified, and the regression tests pass.

Review effort: Lite
Findings: None

What changed in this PR

Fixes Bedrock Claude responses by safely ignoring reasoningContent blocks while preserving text and tool-call handling.

Changes:

  • Skips reasoning blocks in non-streaming responses.
  • Ignores unsupported reasoning deltas during streaming.
  • Adds regression tests for both paths.
File Description
python/​tests/​unit/​connectors/​ai/​bedrock/​services/​test_bedrock_chat_completion.py Adds reasoning-content regression tests.
python/​semantic_kernel/​connectors/​ai/​bedrock/​services/​bedrock_chat_completion.py Updates Bedrock response and stream parsing.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@kimnamu

Copy link
Copy Markdown
Author

Eduard van Valkenburg (@eavanvalkenburg) Thank you for re-running Merge Gatekeeper on this PR on Sept 28, and for working through the Python PRs while SK isn't taking new features.

This one fixes an error that is still on main@11f0723: the connector raises on a reasoningContent block, which Claude Opus 5.5 sends whenever it decides to think (live repro in #14468 on ca40aa7; the connector code is unchanged since). The change is a skip branch in the non-streaming and streaming parsers, 2 files, +79/-11 including two unit tests.

Status OPEN, mergeable. Behind main by 19 commits, none touching the Bedrock connector or its tests; merges cleanly
CI All 15 Python Unit Tests jobs (3.10–3.13, ubuntu/windows/macos), pre-commit, typos and coverage pass. review and add_label are rejected by the github-app-auth environment rule for fork PRs (#14438), which also fails Merge Gatekeeper
Base main@11f0723 source + this PR's tests: 2 failed, 113 passed. This PR merged with main@11f0723: 115 passed
$ uv run pytest tests/unit/connectors/ai/bedrock    # main@11f0723 source + this PR's tests
E   ServiceInvalidResponseError: Unsupported content type in the response: {'reasoningContent': {'reasoningText': {'text': '', 'signature': 'sig'}}}
E   KeyError: 'toolUse'    (bedrock_chat_completion.py:348)
FAILED .../test_bedrock_chat_completion.py::test_bedrock_chat_completion_skips_reasoning_content
FAILED .../test_bedrock_chat_completion.py::test_bedrock_streaming_chat_completion_skips_reasoning_delta
2 failed, 113 passed in 0.38s

$ uv run pytest tests/unit/connectors/ai/bedrock    # this PR merged with main@11f0723
115 passed in 0.18s

When you have a moment, could you review it?

If this isn't a priority right now, tell me and I'll close it to keep your queue clean.

This branch had an error being deployed

1 failed deployment
github-app-auth — 33f6ee9b Deployed Sep 23, 2026 by kimnamu via review #530
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: Bug: Claude Opus 5.5 on Bedrock fails with "Unsupported content type" on reasoningContent blocks

2 participants