Summary
The Python Anthropic provider can serialize a signature-only reasoning content item as an invalid Anthropic thinking block during post-tool replay.
When a Content.from_text_reasoning(text=None, protected_data=...) item is included in an assistant message, _prepare_message_for_anthropic() currently emits:
{ "type": "thinking", "thinking": null, "signature": "..." }
Anthropic rejects a follow-up request with:
messages.1.content.0.thinking.thinking: Input should be a valid string
This can occur after tool use when adaptive thinking is enabled and prior assistant/tool messages are replayed into a follow-up model request.
No-network repro shape
This reproduces in provider serialization without calling Anthropic:
from agent_framework import Content, Message
from agent_framework.anthropic import AnthropicClient
client = AnthropicClient(api_key="dummy", model="claude-opus-4-7")
call_id = "toolu_probe"
messages = [
Message(role="user", contents=["Use the lookup tool."]),
Message(
role="assistant",
contents=[
Content.from_text_reasoning(text=None, protected_data="sig_probe"),
Content.from_function_call(call_id=call_id, name="lookup", arguments={"id": "1"}),
],
),
Message(role="tool", contents=[Content.from_function_result(call_id=call_id, result="ok")]),
]
prepared = client._prepare_messages_for_anthropic(messages)
assert prepared[1]["content"][0]["type"] == "thinking"
assert prepared[1]["content"][0]["thinking"] is None
Expected behavior
The provider should not emit Anthropic thinking blocks where thinking is not a string.
For a signature-only reasoning item, likely behavior is either:
- attach the signature to the preceding
thinking block when one exists and does not already have a signature, or
- skip the orphan signature-only reasoning item rather than serializing
thinking: null.
Local validation
A local patch that skips text_reasoning items with text is None, attaching protected_data to the previous thinking block when possible, makes the no-network serialization repro stop emitting null thinking.
Focused test result:
python/packages/anthropic/tests/test_anthropic_client.py -k "text_reasoning or signature_delta"
5 passed
Related issues
This is separate from:
Summary
The Python Anthropic provider can serialize a signature-only reasoning content item as an invalid Anthropic thinking block during post-tool replay.
When a
Content.from_text_reasoning(text=None, protected_data=...)item is included in an assistant message,_prepare_message_for_anthropic()currently emits:{ "type": "thinking", "thinking": null, "signature": "..." }Anthropic rejects a follow-up request with:
This can occur after tool use when adaptive thinking is enabled and prior assistant/tool messages are replayed into a follow-up model request.
No-network repro shape
This reproduces in provider serialization without calling Anthropic:
Expected behavior
The provider should not emit Anthropic
thinkingblocks wherethinkingis not a string.For a signature-only reasoning item, likely behavior is either:
thinkingblock when one exists and does not already have a signature, orthinking: null.Local validation
A local patch that skips
text_reasoningitems withtext is None, attachingprotected_datato the previous thinking block when possible, makes the no-network serialization repro stop emitting null thinking.Focused test result:
Related issues
This is separate from:
additional_beta_flagsleak