Skip to content

fix(bedrock): keep mid-conversation system messages in place on converse path - #41057

Closed
ege-arhan wants to merge 7 commits into
BerriAI:mainfrom
ege-arhan:fix/issue-41043
Closed

ege-arhan wants to merge 7 commits into
BerriAI:mainfrom
ege-arhan:fix/issue-41043

Conversation

@ege-arhan

Copy link
Copy Markdown
Contributor

Problem

AmazonConverseConfig._transform_system_message hoists EVERY role:system message to the top-level Bedrock system block, regardless of position. A mid-conversation system reminder appended each turn mutates the system prefix every turn, so Bedrock implicit prompt caching (keyed on exact prompt prefix) never matches — full prefix re-written each request (Fixes #41043).

The Invoke path fixed the same bug class via #32578/#32831 (supports_mid_conversation_system flag, keep in place). The Converse path never got the same treatment.

Solution

Only the leading run of system entries is hoisted to the top-level system block. Mid-conversation system entries are converted to user turns in place (with an operator-note prefix, mirroring AnthropicMessagesTransformation._system_role_message_as_user), because Converse only accepts user/assistant roles in messages[]. This keeps the system prefix and everything before the entry byte-identical, preserving the implicit cache.

Details:

  • Leading system run behavior unchanged (hoist + cachePoint handling preserved).
  • Converted entries carry text + per-block cache_control over to the user turn.
  • Empty system entries (no text) are dropped, matching old extract-nothing behavior.
  • A system run wedged between an assistant tool-call turn and its tool-result turn is placed after the tool result (same ordering rule as the Invoke fix), so the tool call/result pair is never split.

Impact

  • bedrock/converse/* requests with per-turn system reminders now reuse the cached prefix instead of re-writing it.
  • Requests without mid-conversation system messages are unaffected (identical output).

Evidence

  • tests/test_litellm/llms/bedrock/chat/test_converse_transformation.py: 261 passed.
  • Behavior checks: leading hoist preserved; mid-conversation entry becomes in-place user turn; system blocks byte-identical across turns T1->T2; downstream _bedrock_converse_messages_pt emits only user/assistant roles; tool-call/result ordering preserved; cache_control carried over.

Fixes #41043.

@ege-arhan
ege-arhan requested a review from a team September 14, 2026 09:18
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@CLAassistant

CLAassistant commented Sep 14, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@codspeed

codspeed Bot commented Sep 14, 2026 •

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 31 untouched benchmarks


Comparing ege-arhan:fix/issue-41043 (3dd2141) with main (071cb49)

Open in CodSpeed

@greptile-apps

greptile-apps Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR keeps mid-conversation Bedrock Converse system reminders in the message sequence instead of hoisting them into the cache-sensitive system prefix

  • Converts later system entries into operator-noted user turns while preserving text-block cache controls
  • Reorders reminders around assistant tool calls and tool results
  • Mishandles multiple consecutive tool results by moving the reminder after only the first result
  • Adds no regression coverage for the changed transformation

Confidence Score: 4/5

This PR is not safe to merge until multi-result tool ordering and the explicit regression-test and source-comment requirements are addressed

The reordering emits a postponed system reminder after the first of several tool results, so downstream conversion combines ordinary text with tool-result content in a Bedrock turn

Files Needing Attention: litellm/llms/bedrock/chat/converse_transformation.py

Important Files Changed

Filename Overview
litellm/llms/bedrock/chat/converse_transformation.py Changes system-message placement and cache handling, but breaks ordering when an assistant call has multiple consecutive tool results

Reviews (1): Last reviewed commit: "fix(bedrock): keep mid-conversation syst..." | Re-trigger Greptile

Comment on lines +1283 to +1287
if self._opens_with_tool_result(message):
run: Final = self._system_run_before(messages, index)
prev_idx: Final = index - len(run) - 1
if run and prev_idx >= 0 and self._assistant_has_tool_calls(messages[prev_idx]):
return (message, *run)

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.

P1 Tool Results Are Split With consecutive results, this moves the note after the first, mixing text into Bedrock’s tool-result turn and causing rejection

}
return cast(AllMessageValues, converted)

def _transform_system_message(

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.

P2 Regression Test Is Missing This bug fix adds no regression test, violating the repository requirement to prevent this behavior from recurring unnoticed before merging

Context Used: CLAUDE.md (source)

Comment on lines 1225 to 1227
cache_point["ttl"] = ttl
return cache_point

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.

P2 Comments Violate Repository Policy This straightforward comment, plus similar comments at lines 1333 and 1366, violates the source-comment requirement and must be removed before merging

Context Used: CLAUDE.md (source)

text_block["cache_control"] = m["cache_control"]
text_blocks.append(text_block)
converted: dict = {
"role": "user",

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.

Medium: Mid-conversation system instructions lose authority

Bedrock receives this content with the user role, and the downstream message processor merges it with adjacent user turns. For applications that add authorization or safety policy reminders during a conversation, an end user can now supply conflicting instructions at the same priority; the explanatory text does not restore system-role precedence. Preserve these entries in the top-level system field, reject unsupported mid-conversation system messages, or make this lossy conversion an explicit opt-in rather than changing their trust level by default.

@veria-ai

veria-ai Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

PR overview

This pull request changes the Bedrock Converse transformation to retain mid-conversation system messages at their original position in the message sequence. It adjusts how these messages are represented when preparing requests for Bedrock.

One security concern remains open: these system instructions are sent with user-level authority and may be merged with nearby user turns. In applications that rely on mid-conversation messages for authorization or safety policy reminders, a user could provide conflicting instructions at the same priority, weakening policy enforcement; no issues have yet been addressed.

Open issues (1)

Fixed/addressed: 0 · PR risk: 4/10

@codecov

codecov Bot commented Sep 14, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.82353% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...tellm/llms/bedrock/chat/converse_transformation.py 98.82% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

- non-dict guard in _opens_with_tool_result
- in-place conversion without tool context
- str/list cache_control preservation in mid-conversation path
- drop unreachable non-system guard in hoisted loop
@mateo-berri

Copy link
Copy Markdown
Contributor

#42630 is merged and keeps mid-conversation system messages in place on the Converse path too, so closing this as agreed. Thanks for the fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants