-
-
Notifications
You must be signed in to change notification settings - Fork 69.3k
fix(agents): stripThoughtSignatures modifies Anthropic thinking blocks, causing API rejection #29618
Description
Bug
stripThoughtSignatures in src/agents/pi-embedded-helpers/bootstrap.ts removes thought_signature fields from content blocks for cross-provider compatibility. However, it also modifies type: "thinking" and type: "redacted_thinking" blocks by spreading them into new objects and deleting properties.
Anthropic's API requires thinking/redacted_thinking blocks in the latest assistant message to be identical to the original response. When these modified blocks are replayed in a multi-turn session, the API rejects with:
messages.N.content.M: `thinking` or `redacted_thinking` blocks in the latest assistant message cannot be modified. These blocks must remain as they were in the original response.
Reproduction
- Use Anthropic provider with extended thinking enabled (e.g.
claude-opus-4-5) - Have a multi-turn conversation where thinking blocks are stored in the session file
- On a subsequent turn,
sanitizeSessionHistory→sanitizeSessionMessagesImages→stripThoughtSignaturesmodifies the thinking blocks - API rejects the request
Root Cause
In stripThoughtSignatures (bootstrap.ts:64), the .map() callback processes ALL content blocks including thinking blocks. When a thinking block has a thought_signature starting with "msg_", it gets spread into a new object with the signature deleted:
const next = { ...rec };
if (stripSnake) {
delete next.thought_signature;
}
return next;This produces a structurally different object that Anthropic's API detects as modified.
Fix
Skip type: "thinking" and type: "redacted_thinking" blocks in stripThoughtSignatures:
const blockType = (block as { type?: unknown }).type;
if (blockType === "thinking" || blockType === "redacted_thinking") {
return block;
}These blocks should never have their signatures stripped since they must be preserved verbatim for Anthropic. The signature stripping is only needed for cross-provider compatibility with Google/Gemini, which doesn't use thinking/redacted_thinking block types.
Environment
- OpenClaw v2026.2.25+
- Anthropic provider with
claude-opus-4-5 - Discord channel sessions with extended thinking