Skip to content

fix(bedrock): send a placeholder for empty assistant turns on Converse - #429

Merged
cpsievert merged 2 commits into
posit-dev:mainfrom
ebarkhordar:fix/426-converse-empty-assistant-turn-placeholder
Sep 8, 2026
Merged

fix(bedrock): send a placeholder for empty assistant turns on Converse#429
cpsievert merged 2 commits into
posit-dev:mainfrom
ebarkhordar:fix/426-converse-empty-assistant-turn-placeholder

Conversation

@ebarkhordar

Copy link
Copy Markdown
Contributor

Fixes #426.

The audit turned up one gap, and it is on the Converse side. as_converse_messages() appends each turn's content array unconditionally, so an assistant turn with no content blocks goes on the wire as content: [], which Converse rejects. _as_turn() produces exactly that turn when a response carries no content blocks, including the case where message is absent because a guardrail intervened before the model produced any. This sends the same "[empty string]" placeholder as #421 rather than dropping the turn, so user/assistant alternation stays intact.

Empty thinking blocks are already handled here. content_from_converse_block() reads reasoningContent.get("reasoningText") or {} and then .get("text", ""), so a block carrying only a signature, one with no reasoningText at all, one where it is None, and a redactedContent block all return ContentThinking(thinking="") without raising. I checked those four shapes and changed nothing there.

The other two Bedrock providers need nothing either. BedrockMessagesProvider subclasses AnthropicProvider and does not override _as_message_params, so #421 covers it, and BedrockResponsesProvider goes through the OpenAI path.

Verified at c21e2451:

  • test_empty_assistant_turn_gets_a_placeholder fails without the change, with assert [] == [{'text': '[empty string]'}].
  • test_empty_user_turn_is_left_alone pins the scope rather than the bug, so I checked it can fail: dropping the role check from the guard turns it red.
  • Full suite on 3.10 and 3.14, ruff check chatlas clean, and pyright reports only the one pre-existing _content_image.py error that main reports too.

I could not check the rejection itself, since this machine has no AWS credentials, and botocore's service model puts no minimum on the content array, so nothing client-side complains about content: [] today. A caller who passes their own messages through kwargs still bypasses this path.

The entry landed under the 0.23.0 heading, which shipped on 2026-09-04.
Release commit c21e245 renames Unreleased to the version at release time,
so a new section is where a post-release fix belongs.
@ebarkhordar

Copy link
Copy Markdown
Contributor Author

The three red workflows are not from this branch.

test (3.12) runs the suite green (1265 passed, 46 skipped) and then dies in make check-types on chatlas/_content_image.py:159, where pyright rejects register_heif_opener as not exported from pillow_heif. test-live fails 362 tests on Missing credentials ... OPENAI_API_KEY, which a fork PR does not get. Check provider types and pricing asks for make update-types, make update-pricing and make update-bedrock-apis to be run and committed.

This branch sits on c21e245, 0 ahead and 0 behind main, and touches only the bedrock converse provider, its test and the changelog. Those three workflows last ran on main at that same commit on 2026-09-04 and were green then.

Separately, I moved the changelog entry into a new ## [Unreleased] section. It had gone under ## [0.23.0] - 2026-09-04, which had already shipped.

@cpsievert

Copy link
Copy Markdown
Collaborator

Thanks!

@cpsievert
cpsievert merged commit 2036eea into posit-dev:main Sep 8, 2026
0 of 7 checks passed
@ebarkhordar
ebarkhordar deleted the fix/426-converse-empty-assistant-turn-placeholder branch September 8, 2026 15:25
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.

Bedrock: handle empty thinking blocks and empty responses

2 participants