{{ message }}
Repository navigation
fix(anthropic): store redacted thinking as bytes and re-encode on send - #4593
Merged
pgrayy merged 1 commit intoOct 1, 2026
Conversation
The Messages API delivers redacted thinking data as a base64 string
(RedactedThinkingBlock.data). AnthropicModel passed that string straight
into ReasoningBlock.redactedContent, whose contract is Uint8Array with a
base64 toJSON/fromJSON round-trip, via a compile-time-only cast. Every
Message.clone() or session save/restore therefore re-encoded the value,
and the redacted_thinking block sent back to Anthropic serialized the
bytes as {"0":69,"1":109,...} instead of the verbatim base64 string,
which the Messages API rejects for multi-turn tool use.
Decode the data to bytes on the way in and encode it back to base64 on
the way out, matching the Bedrock path and the ReasoningBlock contract.
pgrayy
approved these changes
Oct 1, 2026
Contributor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Description
The Messages API delivers redacted thinking as a base64 string (
RedactedThinkingBlock.data), butAnthropicModel.streamstored that string straight intoReasoningBlock.redactedContent— declaredUint8Array, with a base64toJSON()/fromJSON()contract — through a compile-time-only cast (strands-ts/src/models/anthropic.ts:307).The first turn works by luck: the string passes through untouched. But the first
Message.clone()or session save/restore round-trips the block throughtoJSON()/fromJSON(), which re-encodes the value into the ASCII bytes of the base64 string. The next request'sredacted_thinkingblock then serialized as an indexed object ({"0":69,"1":109,...}) instead of the verbatim base64 string (anthropic.ts:836-839), which the Messages API rejects — breaking multi-turn tool use for conversations whose reasoning comes back encrypted.This decodes the data to bytes on ingestion and encodes it back to base64 when formatting the request, matching the Bedrock path (which already stores the AWS SDK's
Uint8Arraydirectly) and the documentedReasoningBlockJSON contract.Related Issues
Fixes #4587
Documentation PR
Not needed — the stored representation now matches the already-documented
ReasoningBlockcontract (strands-ts/src/types/messages.ts:534,548); no public API surface changes.Type of Change
Bug fix
Testing
From
strands-ts/on this branch:npx vitest run --project unit-node src/models/__tests__/anthropic.test.ts— 137 passed, including the new regression test (fails onmainat the first assertion: the streamedredactedContentis the raw string, not the bytes its type declares)npx vitest run --project unit-node src/models/— 941 passed (15 files)npm test— 4762 passed (169 files)npx vitest run --project unit-browser src/models/__tests__/anthropic.test.ts— 135 passednpm run lint,npm run format:check,npm run type-check— all cleanI ran
hatch run prepare— TS-only change; the npm gates above cover itChecklist
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.