From 05ebb966cf7555aa3690a9fae11188b83f68daf1 Mon Sep 17 00:00:00 2001 From: Yufeng He <40085740+he-yufeng@users.noreply.github.com> Date: Tue, 2 Jun 2026 08:48:42 +0800 Subject: [PATCH] fix: skip orphan anthropic thinking signatures (#5784) --- .../agent_framework_anthropic/_chat_client.py | 9 ++++ .../anthropic/tests/test_anthropic_client.py | 42 +++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/python/packages/anthropic/agent_framework_anthropic/_chat_client.py b/python/packages/anthropic/agent_framework_anthropic/_chat_client.py index 98c181f152..c90b061b4f 100644 --- a/python/packages/anthropic/agent_framework_anthropic/_chat_client.py +++ b/python/packages/anthropic/agent_framework_anthropic/_chat_client.py @@ -803,6 +803,15 @@ class RawAnthropicClient( } a_content.append(mcp_result) case "text_reasoning": + if content.text is None: + if ( + content.protected_data + and a_content + and a_content[-1].get("type") == "thinking" + and "signature" not in a_content[-1] + ): + a_content[-1]["signature"] = content.protected_data + continue thinking_block: dict[str, Any] = {"type": "thinking", "thinking": content.text} if content.protected_data: thinking_block["signature"] = content.protected_data diff --git a/python/packages/anthropic/tests/test_anthropic_client.py b/python/packages/anthropic/tests/test_anthropic_client.py index 0cfec3423c..abad158b8c 100644 --- a/python/packages/anthropic/tests/test_anthropic_client.py +++ b/python/packages/anthropic/tests/test_anthropic_client.py @@ -485,6 +485,48 @@ def test_prepare_message_for_anthropic_text_reasoning_with_signature( assert result["content"][0]["signature"] == "sig_abc123" +def test_prepare_message_for_anthropic_attaches_signature_only_reasoning( + mock_anthropic_client: MagicMock, +) -> None: + client = create_test_anthropic_client(mock_anthropic_client) + message = Message( + role="assistant", + contents=[ + Content.from_text_reasoning(text="Let me think about this..."), + Content.from_text_reasoning(text=None, protected_data="sig_abc123"), + ], + ) + + result = client._prepare_message_for_anthropic(message) + + assert result["content"] == [ + {"type": "thinking", "thinking": "Let me think about this...", "signature": "sig_abc123"} + ] + + +def test_prepare_message_for_anthropic_skips_orphan_signature_only_reasoning( + mock_anthropic_client: MagicMock, +) -> None: + client = create_test_anthropic_client(mock_anthropic_client) + message = Message( + role="assistant", + contents=[ + Content.from_text_reasoning(text=None, protected_data="sig_abc123"), + Content.from_function_call( + call_id="call_123", + name="get_weather", + arguments={"location": "San Francisco"}, + ), + ], + ) + + result = client._prepare_message_for_anthropic(message) + + assert len(result["content"]) == 1 + assert result["content"][0]["type"] == "tool_use" + assert result["content"][0]["id"] == "call_123" + + def test_prepare_message_for_anthropic_mcp_server_tool_call( mock_anthropic_client: MagicMock, ) -> None: