Repository navigation
fix(amazon-bedrock): support reasoningContent.redactedContent from the Converse API - #19058
Conversation
…nt` from the Converse API
`redactedContent` is the second member of the documented
ReasoningContentBlock union (and a member of ReasoningContentBlockDelta),
but neither the response schema nor the stream schema accepted it, so tool
calling with models that emit it (e.g. OpenAI models such as
`us.openai.gpt-5.6-luna`) failed validation: generateText threw
AI_APICallError on a successful response, and streamText emitted a spurious
error part.
The encrypted payload is now surfaced as a reasoning part carrying
`providerMetadata.{amazonBedrock,bedrock}.redactedContent` and replayed on
subsequent turns as `reasoningContent: { redactedContent }`, restoring the
model's reasoning state across tool calls. Streaming deltas are accumulated
and attached once via `reasoning-end`, because the merged provider metadata
of a reasoning part is last-write-wins.
c521b45 to
1531c67
Compare
Bugfix reviewOutcome: approved Fixes issueStatus: fully-addresses The response and streaming schemas now accept the documented redactedContent union member, surface it as provider metadata, accumulate split streaming payloads, and replay it unchanged on subsequent turns. Side effectsRisk: low Existing reasoningText and legacy redactedReasoning handling remain intact; the only observable addition is a reasoning part with redactedContent metadata for responses previously rejected or discarded. PerformanceRisk: low Streaming retains one encrypted payload per active reasoning block until block completion. This adds memory proportional to the payload size but no unbounded state beyond data required for replay. Backwards compatibilityRisk: low Existing stored messages and legacy redactedData metadata remain supported. Newly persisted response messages may contain the additive redactedContent metadata and will replay it without requiring migration. Breaking changesRisk: none No public exports, types, defaults, configurations, accepted inputs, or existing output shapes are removed or narrowed. Validation becomes more permissive, and the new provider metadata field is additive. ArchitectureRisk: none All changes remain inside the Amazon Bedrock provider and reuse its existing API types, reasoning metadata schema, response mapping, and message conversion boundaries; no cross-package source imports or dependency violations were introduced. Change scopeStatus: minimal The changed production files cover schema validation, provider metadata, streaming accumulation, request typing, and replay; the remaining changes are focused regression tests and the required patch changeset. SecurityRisk: low The change transports provider-encrypted data without decoding or executing it and introduces no credential, URL-handling, parsing, or authorization changes. TestingStatus: appropriate Tests cover non-streaming mapping, split streaming-delta accumulation, separation of multiple reasoning blocks, absence of stream errors, and outbound replay. The complete Amazon Bedrock Node and Edge suites each passed all 465 tests. VerificationInspected every diff hunk against origin/main and the surrounding provider/core metadata flow. The Amazon Bedrock Node and Edge suites passed, workspace type checking and formatting/lint checks passed, and git diff validation reported no whitespace errors. Relevant Documentation
|
gr2m
left a comment
There was a problem hiding this comment.
Looks good thank you Yuya!
|
🚀 Published in:
|
…` from the Converse API (#19139) ## Background `redactedContent` is the second member of the documented [`ReasoningContentBlock`](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ReasoningContentBlock.html) union (`reasoningText | redactedContent`) and a member of [`ReasoningContentBlockDelta`](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ReasoningContentBlockDelta.html), but neither the response schema nor the stream schema accepts it. Models that emit it — e.g. OpenAI models on Converse such as `us.openai.gpt-5.6-luna`, which return their encrypted reasoning in this shape alongside tool calls — currently fail validation: - `generateText` / `generateObject` with tools throw `AI_APICallError: Invalid JSON response` on an HTTP 200 response, making tool calling unusable - `streamText` with tools emits a spurious `AI_TypeValidationError` error part on every request and loses the reasoning block ## Summary - Both Zod schemas accept `redactedContent` (response `ReasoningContentBlock` and stream `contentBlockDelta.delta`). - The payload is surfaced as a `reasoning` part carrying `providerMetadata.{amazonBedrock,bedrock}.redactedContent`, mirroring how `redactedReasoning` is surfaced today. - `convert-to-amazon-bedrock-chat-messages` replays it as `reasoningContent: { redactedContent }` on subsequent turns. - Streaming deltas are accumulated in the content-block state and attached once via `reasoning-end`: a reasoning part's merged provider metadata is last-write-wins, so per-delta metadata would drop earlier chunks if the payload ever arrives split. - Existing `redactedReasoning` / `data` handling is left untouched. Surfacing + replay (rather than accept-and-drop) matters because the encrypted payload restores the model's reasoning state across tool-use turns. Verified against the raw Converse API with a two-turn tool conversation: replaying the block verbatim yields a correct answer from restored state (22 output tokens); stripping it forces the model to re-reason from scratch (509 output tokens) and it loses its earlier conclusion. Replaying via the legacy `redactedReasoning: { data }` shape is silently ignored by the current API, so a dedicated replay path for the documented shape is required. ## Verification - `pnpm test` in `packages/amazon-bedrock`: 465 tests pass. The new tests (response mapping, stream accumulation across split deltas, multi-block separation, replay conversion) fail without the fix. - End-to-end against real Bedrock (`us-east-1`, `us.openai.gpt-5.6-luna`), both `doGenerate` and `doStream`: turn 1 surfaces the reasoning part with `redactedContent` metadata, the turn-2 request contains the replayed `reasoningContent.redactedContent` block on the wire, no error parts, and the model answers from its restored reasoning state. ## Tasks - [x] Tests have been added / updated (for bug fixes / features) - [x] Documentation has been added / updated (for bug fixes / features) — provider docs describe reasoning provider metadata generically; no doc change needed - [x] A _patch changeset_ for relevant packages has been added (for bug fixes / features - run `pnpm changeset` in the project root) - [x] Formatting issues have been fixed (run `pnpm prettier-fix` in the project root) ## Future Work Anthropic models' redacted reasoning on the current Converse API is also documented as `redactedContent`; this change covers them as well, while keeping the legacy `redactedReasoning` / `data` paths for compatibility. ## Related Issues Closes #19062 (full reproduction and multi-turn replay measurements). Related: #19024 (closed; streaming variant of this validation error), #14720 (precedent for OpenAI-on-Converse reasoning handling). Closes #19115 Backport of #19058 --------- Co-authored-by: Yuya Matsumura <[email protected]> Co-authored-by: ai-sdk-factory <[email protected]> Co-authored-by: Gregor Martynus <[email protected]>
…` from the Converse API (#19142) ## Background `redactedContent` is the second member of the documented [`ReasoningContentBlock`](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ReasoningContentBlock.html) union (`reasoningText | redactedContent`) and a member of [`ReasoningContentBlockDelta`](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ReasoningContentBlockDelta.html), but neither the response schema nor the stream schema accepts it. Models that emit it — e.g. OpenAI models on Converse such as `us.openai.gpt-5.6-luna`, which return their encrypted reasoning in this shape alongside tool calls — currently fail validation: - `generateText` / `generateObject` with tools throw `AI_APICallError: Invalid JSON response` on an HTTP 200 response, making tool calling unusable - `streamText` with tools emits a spurious `AI_TypeValidationError` error part on every request and loses the reasoning block ## Summary - Both Zod schemas accept `redactedContent` (response `ReasoningContentBlock` and stream `contentBlockDelta.delta`). - The payload is surfaced as a `reasoning` part carrying `providerMetadata.{amazonBedrock,bedrock}.redactedContent`, mirroring how `redactedReasoning` is surfaced today. - `convert-to-amazon-bedrock-chat-messages` replays it as `reasoningContent: { redactedContent }` on subsequent turns. - Streaming deltas are accumulated in the content-block state and attached once via `reasoning-end`: a reasoning part's merged provider metadata is last-write-wins, so per-delta metadata would drop earlier chunks if the payload ever arrives split. - Existing `redactedReasoning` / `data` handling is left untouched. Surfacing + replay (rather than accept-and-drop) matters because the encrypted payload restores the model's reasoning state across tool-use turns. Verified against the raw Converse API with a two-turn tool conversation: replaying the block verbatim yields a correct answer from restored state (22 output tokens); stripping it forces the model to re-reason from scratch (509 output tokens) and it loses its earlier conclusion. Replaying via the legacy `redactedReasoning: { data }` shape is silently ignored by the current API, so a dedicated replay path for the documented shape is required. ## Verification - `pnpm test` in `packages/amazon-bedrock`: 465 tests pass. The new tests (response mapping, stream accumulation across split deltas, multi-block separation, replay conversion) fail without the fix. - End-to-end against real Bedrock (`us-east-1`, `us.openai.gpt-5.6-luna`), both `doGenerate` and `doStream`: turn 1 surfaces the reasoning part with `redactedContent` metadata, the turn-2 request contains the replayed `reasoningContent.redactedContent` block on the wire, no error parts, and the model answers from its restored reasoning state. ## Tasks - [x] Tests have been added / updated (for bug fixes / features) - [x] Documentation has been added / updated (for bug fixes / features) — provider docs describe reasoning provider metadata generically; no doc change needed - [x] A _patch changeset_ for relevant packages has been added (for bug fixes / features - run `pnpm changeset` in the project root) - [x] Formatting issues have been fixed (run `pnpm prettier-fix` in the project root) ## Future Work Anthropic models' redacted reasoning on the current Converse API is also documented as `redactedContent`; this change covers them as well, while keeping the legacy `redactedReasoning` / `data` paths for compatibility. ## Related Issues Closes #19062 (full reproduction and multi-turn replay measurements). Related: #19024 (closed; streaming variant of this validation error), #14720 (precedent for OpenAI-on-Converse reasoning handling). Closes #19111 Backport of #19058 --------- Co-authored-by: Yuya Matsumura <[email protected]> Co-authored-by: ai-sdk-factory <[email protected]> Co-authored-by: Gregor Martynus <[email protected]>
Background
redactedContentis the second member of the documentedReasoningContentBlockunion (reasoningText | redactedContent) and a member ofReasoningContentBlockDelta, but neither the response schema nor the stream schema accepts it. Models that emit it — e.g. OpenAI models on Converse such asus.openai.gpt-5.6-luna, which return their encrypted reasoning in this shape alongside tool calls — currently fail validation:generateText/generateObjectwith tools throwAI_APICallError: Invalid JSON responseon an HTTP 200 response, making tool calling unusablestreamTextwith tools emits a spuriousAI_TypeValidationErrorerror part on every request and loses the reasoning blockSummary
redactedContent(responseReasoningContentBlockand streamcontentBlockDelta.delta).reasoningpart carryingproviderMetadata.{amazonBedrock,bedrock}.redactedContent, mirroring howredactedReasoningis surfaced today.convert-to-amazon-bedrock-chat-messagesreplays it asreasoningContent: { redactedContent }on subsequent turns.reasoning-end: a reasoning part's merged provider metadata is last-write-wins, so per-delta metadata would drop earlier chunks if the payload ever arrives split.redactedReasoning/datahandling is left untouched.Surfacing + replay (rather than accept-and-drop) matters because the encrypted payload restores the model's reasoning state across tool-use turns. Verified against the raw Converse API with a two-turn tool conversation: replaying the block verbatim yields a correct answer from restored state (22 output tokens); stripping it forces the model to re-reason from scratch (509 output tokens) and it loses its earlier conclusion. Replaying via the legacy
redactedReasoning: { data }shape is silently ignored by the current API, so a dedicated replay path for the documented shape is required.Verification
pnpm testinpackages/amazon-bedrock: 465 tests pass. The new tests (response mapping, stream accumulation across split deltas, multi-block separation, replay conversion) fail without the fix.us-east-1,us.openai.gpt-5.6-luna), bothdoGenerateanddoStream: turn 1 surfaces the reasoning part withredactedContentmetadata, the turn-2 request contains the replayedreasoningContent.redactedContentblock on the wire, no error parts, and the model answers from its restored reasoning state.Tasks
pnpm changesetin the project root)pnpm prettier-fixin the project root)Future Work
Anthropic models' redacted reasoning on the current Converse API is also documented as
redactedContent; this change covers them as well, while keeping the legacyredactedReasoning/datapaths for compatibility.Related Issues
Closes #19062 (full reproduction and multi-turn replay measurements). Related: #19024 (closed; streaming variant of this validation error), #14720 (precedent for OpenAI-on-Converse reasoning handling).