Repository navigation
Python: preserve empty signed Anthropic thinking blocks on streaming replay - #8171
Conversation
Empty thinking="" plus a signature_delta was coalesced to text=None, so the Anthropic serializer treated it as an orphan signature and dropped it before tool_use replay. Keep "" distinct from None through merge. Fixes microsoft#8168
There was a problem hiding this comment.
🔵 Needs a closer look
It changes shared reasoning aggregation in a high-risk provider replay path requiring broader validation.
Pull request overview
Preserves empty signed Anthropic thinking blocks during streaming aggregation and replay.
Changes:
- Distinguishes empty reasoning text from absent text during merging.
- Adds core and Anthropic replay regression coverage.
File summaries
| File | Description |
|---|---|
python/packages/core/agent_framework/_types.py |
Preserves empty reasoning text during aggregation. |
python/packages/core/tests/core/test_types.py |
Tests empty and absent reasoning-text merges. |
python/packages/anthropic/tests/test_anthropic_client.py |
Tests serialization and end-to-end streaming replay. |
Review details
- Files reviewed: 3/3 changed files
- Comments generated: 0
- Review effort level: Balanced
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
|
@microsoft-github-policy-service agree |
|
CLA signed — license/cla is green now. Thanks for reviewing when you have a chance. |
|
Use a ternary for combined_text so Package Checks lint passes.
|
Updated the PR body to the approved template, and fixed the Package Checks lint ( |
|
please fix the failing CI/CD checks thanks |
|
CI is green on the latest tip now — Package Checks, Typing (zuban), Pre-commit, Samples, and the Python matrix all pass. Ready for another look when you have a chance. |
Motivation & Context
Anthropic can emit a thinking block with
thinking=""followed by asignature_delta. Stream aggregation was collapsing empty string toNone, so the Anthropic serializer treated a real empty signed thinking block as an orphan signature and dropped it before tool-result replay. Nonempty thinking text was already preserved.Fixes #8168
Description & Review Guide
""distinct fromNoneinContent._add_text_reasoning_contentwhen merging reasoning text, so empty signed Anthropic thinking survives aggregation and replay.{"type": "thinking", "thinking": "", "signature": ...}before the tool call when that is what the stream produced. Both-Nonestill staysNone._types.py(""vsNone) and the Anthropic streaming replay regression.Related Issue
Fixes #8168
Contribution Checklist
breaking changelabel (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.