fix: tolerate thinking blocks without a signature#1073
Open
Magic-Man-us wants to merge 1 commit into
Open
Conversation
The message parser hard-indexed block["signature"] when building a ThinkingBlock, so an assistant message containing an unsigned thinking block (emitted by some Anthropic-compatible backends) raised MessageParseError and aborted the whole query (anthropics#949). The user-message branch also had no thinking case, silently dropping thinking blocks replayed on resume. - Parse signature with block.get("signature", "") in both the assistant and user content branches. - Add a thinking case to the user-message branch so replayed thinking blocks are preserved. - Default ThinkingBlock.signature to "" to reflect that it may be absent on the wire. - Add parser tests for the unsigned-assistant and user-branch cases. Fixes anthropics#949
There was a problem hiding this comment.
Pull request overview
Fixes parsing compatibility with Anthropic-compatible backends that emit thinking content blocks without a signature, and ensures thinking blocks are preserved when replayed inside user messages (e.g., resume/session replay).
Changes:
- Make
signatureoptional when parsing assistantthinkingblocks (defaults to""when absent). - Preserve
thinkingblocks in the user-message parsing branch. - Update
ThinkingBlockto defaultsignatureto""and add regression tests for both scenarios.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
src/claude_agent_sdk/_internal/message_parser.py |
Uses block.get("signature", "") for thinking blocks and adds a thinking case to user content parsing. |
src/claude_agent_sdk/types.py |
Defaults ThinkingBlock.signature to "" to reflect optional presence on the wire. |
tests/test_message_parser.py |
Adds tests covering unsigned assistant thinking blocks and thinking blocks within user messages. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
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.
Summary
Fixes #949. The message parser hard-indexed
block["signature"]when constructing aThinkingBlock, so an assistant message containing an unsigned thinking block (emitted by some Anthropic-compatible backends) raisedMessageParseError: Missing required field in assistant message: 'signature'and aborted the entire query.While fixing it I found a related gap: the user-message branch of the parser had no
thinkingcase at all, so thinking blocks replayed inside a user message (e.g. on session resume) were silently dropped.Changes
_internal/message_parser.py— parse the signature withblock.get("signature", "")in the assistant branch (no longer crashes on absence)._internal/message_parser.py— add athinkingcase to the user-message branch so replayed thinking blocks are preserved instead of dropped.types.py— defaultThinkingBlock.signatureto"", reflecting that the field may be absent on the wire.tests/test_message_parser.py— add tests for the unsigned-assistant-thinking case and the user-branch thinking case.Test plan
ruff check src/ tests/— cleanruff format --check src/ tests/— cleanmypy src/— cleanpytest tests/— 987 passed, 5 skipped