Skip to content

fix(amazon-bedrock): do not replay unsigned reasoning content in multi-turn messages#14724

Closed
KiraPC wants to merge 1 commit into
vercel:mainfrom
KiraPC:fix/14720
Closed

fix(amazon-bedrock): do not replay unsigned reasoning content in multi-turn messages#14724
KiraPC wants to merge 1 commit into
vercel:mainfrom
KiraPC:fix/14720

Conversation

@KiraPC
Copy link
Copy Markdown

@KiraPC KiraPC commented Apr 24, 2026

PR #13972 fixed a bug where trimIfLast() invalidated Anthropic reasoning signatures by trimming trailing whitespace. During that refactoring, the code structure in convert-to-bedrock-chat-messages.ts changed from:

if (reasoningMetadata != null) {
  if (reasoningMetadata.signature != null) { /* replay with trim */ }
  else if (reasoningMetadata.redactedData != null) { /* replay redacted */ }
}
// unsigned reasoning → silently dropped (no else branch)

to:

if (reasoningMetadata?.signature != null) { /* replay without trim  */ }
else if (reasoningMetadata?.redactedData != null) { /* replay redacted */ }
else { /* replay unsigned reasoning as reasoningContent ← NEW catch-all */ }

The outer if (reasoningMetadata != null) guard was removed and replaced with optional chaining. This inadvertently introduced an else catch-all that replays unsigned reasoning (reasoning parts with no providerMetadata) as reasoningContent blocks — a case that was previously silently dropped.

The PR #13972 commit message states: "reasoning blocks without a signature still get trimmed as before", but Anthropic models always include a signature. The only case reaching the else branch is unsigned reasoning from non-Anthropic models (e.g., OpenAI extended thinking on Bedrock), which should not be replayed.

Summary

  • Remove the else catch-all branch in the reasoning case of convertToBedrockChatMessages
  • Reasoning parts without signature or redactedData are now silently dropped (restoring pre-fix(amazon-bedrock): preserve reasoning text when signature is present #13972 behavior for this specific case)
  • Signed reasoning (Anthropic) and redacted reasoning remain completely unaffected
  • Add comment explaining why unsigned reasoning is intentionally not replayed
  • Update tests to verify unsigned reasoning is dropped rather than replayed

Why the else branch is unnecessary

  • Anthropic always includes a cryptographic signature → handled by the if branch
  • Anthropic redacted reasoning always has redactedData → handled by the else if branch
  • Non-Anthropic models (OpenAI) produce unsigned reasoning that should not be replayed — replaying it causes the model to leak raw <reasoning> tags into the visible text response

Manual Verification

Tested against real Bedrock models with a multi-turn agent + tool-use scenario (non-streaming generateText):

Model Without fix With fix
openai.gpt-oss-120b-1:0 Leaks <reasoning> tags (33-100% of runs) No leak
us.anthropic.claude-sonnet-4-20250514-v1:0 OK (reasoning with signature) OK
moonshotai.kimi-k2.5 OK (no reasoning blocks) OK
amazon.nova-pro-v1:0 OK (no reasoning blocks) OK

Checklist

  • Tests have been added / updated (for bug fixes / features)
  • Documentation has been added / updated (for bug fixes / features)
  • A patch changeset for relevant packages has been added (for bug fixes / features - run pnpm changeset in the project root)
  • I have reviewed this pull request (self-review)

Related Issues

…i-turn messages

Remove the else branch in convertToBedrockChatMessages that replayed
unsigned reasoning (no signature, no redactedData) as reasoningContent
blocks. This was inadvertently introduced in vercel#13972 when the outer
if (reasoningMetadata != null) guard was replaced with optional chaining.

The only case reaching this branch was OpenAI models with extended
thinking on Bedrock, which produce reasoningContent without a signature.
Replaying it caused the model to leak raw <reasoning> tags into the
visible text response.

Signed (Anthropic) and redacted reasoning are unaffected.
@aayush-kapoor
Copy link
Copy Markdown
Collaborator

signed github commits are needed for community PRs

@aayush-kapoor
Copy link
Copy Markdown
Collaborator

continued in #15181; will add you as a co-author

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.

bug(amazon-bedrock): <reasoning> tags leaked into text response for OpenAI models on Bedrock during multi-turn tool use

2 participants