Repository navigation
Python: Fix Bedrock parallel tool-call results rejected by Converse - #14074
Lucas Kim (kimnamu) wants to merge 3 commits into
Conversation
When a model requests multiple tools in a single turn, the function-calling
loop appends one ChatMessageContent per tool call and one per tool result.
The Bedrock connector mapped each of these 1:1 to a Converse message, so N
parallel tool results became N separate user messages each with a single
toolResult block. Converse rejects this with:
Expected toolResult blocks at messages.X.content for the following
Ids: ... but found: ...
Merge consecutive messages that map to the same Bedrock role in
_prepare_chat_history_for_request, so all toolUse blocks for an assistant
turn land in one assistant message and all toolResult blocks land in one
user message. This mirrors the existing behavior of the sibling Anthropic
connector, which already groups parallel tool messages.
Python analogue of microsoft#13647 (reported for .NET).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds Bedrock Converse compatibility by coalescing consecutive same-role messages (notably parallel tool calls/results) into single messages to avoid Bedrock request validation errors.
Changes:
- Update Bedrock chat history preparation to merge consecutive messages that map to the same Bedrock role.
- Add a unit test verifying parallel tool call + tool result messages are merged into the required Bedrock structure.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| python/semantic_kernel/connectors/ai/bedrock/services/bedrock_chat_completion.py | Merge consecutive same-role Bedrock messages by concatenating content blocks. |
| python/tests/unit/connectors/ai/bedrock/services/test_bedrock_chat_completion.py | Add test coverage for merging parallel tool calls/results into single assistant/user messages. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Build a new combined content list instead of in-place += (clearer type intent, no mutation of the previous message), per review feedback. - Add a regression test for merging consecutive non-tool same-role messages.
|
Thanks for the review! Addressed both points in the latest commit:
Full bedrock connector suite passes (40 tests); |
|
@microsoft-github-policy-service agree |
|
Evan Mattson (@moonbox3) Thank you for keeping the Python Bedrock connector moving (I saw #14363 land earlier this month) and for the time you give to community PRs in this area. This PR is still applicable on current
When it fits your schedule, would you be willing to take a look (or approve the workflow run so CI can confirm the above)? If this isn't a priority right now, tell me and I'll close it to keep your queue clean. |
Thanks to the SK maintainers for the Bedrock connector and the consistent connector design — this change just fills a gap the sibling Anthropic connector already handles.
Motivation and Context
Fixes #14073. Python analogue of #13647 (.NET).
When a model calls multiple tools in one turn, SK emits one
ChatMessageContentper tool call/result._prepare_chat_history_for_requestmapped each 1:1 to a Converse message, so paralleltoolResults landed in separate user messages → Converse rejects:Expected toolResult blocks at messages.X.content ....Description
Merge consecutive messages that map to the same Bedrock role, so all
toolUseblocks land in one assistant message and alltoolResultblocks in one user message. Mirrors the existing Anthropic connector (formatted_messages[-1][content_key] += ...).toolUsemessagestoolUseblockstoolResultmessages (Converse rejects)toolResultblocks_format_*converters, public API/argsContribution Checklist
test_prepare_chat_history_for_request_merges_parallel_tool_results. Reverting only the source makes it fail withassert 5 == 3(proving it catches the bug); with the fix the full bedrock unit suite passes (114 passed).ruff format/ruff check/mypyclean.This contribution was prepared with the help of an AI agent (Claude Code); a human reviewed the change, reasoning, and test results before submission.