Skip to content

Replay assistant reasoning as Anthropic thinking blocks in buildMessageParam - #600

Open
PratikDhanave (PratikDhanave) wants to merge 4 commits into
microsoft:mainfrom
PratikDhanaveFork:replay-assistant-reasoning-thinking-blocks
Open

Replay assistant reasoning as Anthropic thinking blocks in buildMessageParam#600
PratikDhanave (PratikDhanave) wants to merge 4 commits into
microsoft:mainfrom
PratikDhanaveFork:replay-assistant-reasoning-thinking-blocks

Conversation

@PratikDhanave

Copy link
Copy Markdown
Contributor

What

buildMessageParam in provider/anthropicprovider/agent.go switches over the outbound msg.Contents but had no case for *message.TextReasoningContent. It handled TextContent, FunctionCallContent, FunctionResultContent and DataContent only.

The inbound path buildBlock produces exactly that type from Anthropic responses:

  • anthropic.ThinkingBlock -> TextReasoningContent{ProtectedData: Signature, Text: Thinking}
  • anthropic.RedactedThinkingBlock -> TextReasoningContent{ProtectedData: Data}

So when a prior assistant turn's history was sent back (e.g. multi-turn tool loops with extended thinking), the reasoning block and its cryptographic signature were silently dropped.

Fix

Add a *message.TextReasoningContent case that replays the block, appended in iteration order (Anthropic emits reasoning before the rest of the turn):

  • signature + text present -> anthropic.NewThinkingBlock(ProtectedData, Text)
  • data only (text empty) -> anthropic.NewRedactedThinkingBlock(ProtectedData)
  • both empty -> skipped, so streamed partials that never received a signature don't produce an invalid unsigned thinking block the API would reject.

Why

Preserving thinking-block signatures across turns is required for Anthropic extended-thinking with tool use; the signature must round-trip or the API rejects the replayed assistant turn. This matches the .NET/Python SDKs, which reserialize reasoning content back into thinking / redacted_thinking blocks rather than dropping them, keeping cross-SDK conversation replay behavior aligned.

Tests

Added black-box tests in the canonical agent_test.go, driven through the exported Run().Collect() path with the existing request-capturing httptest harness:

  • TestAssistantReasoningReplayedAsThinkingBlock — asserts a thinking block carrying signature sig123 is emitted first, ahead of the tool_use block.
  • TestAssistantRedactedReasoningReplayedAsRedactedThinkingBlock — asserts a redacted_thinking block with its data is emitted.
  • TestAssistantUnsignedReasoningIsSkipped — asserts an unsigned partial is dropped.

All three fail before the fix and pass after. go build ./..., go vet and go test on the package are green.

Copilot AI review requested due to automatic review settings July 23, 2026 05:33
@PratikDhanave
PratikDhanave (PratikDhanave) requested a review from a team as a code owner July 23, 2026 05:33

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes Anthropic conversation replay for extended-thinking/tool-use by ensuring prior assistant reasoning (TextReasoningContent) is serialized back into Anthropic thinking / redacted_thinking content blocks (including the required signature), instead of being silently dropped.

Changes:

  • Add *message.TextReasoningContent handling in buildMessageParam to emit thinking / redacted_thinking blocks and skip unsigned partial reasoning.
  • Add black-box request-capture tests validating correct replay behavior, ordering, and skipping of unsigned partials.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
provider/anthropicprovider/agent.go Re-serializes TextReasoningContent into Anthropic thinking blocks so signatures round-trip across turns.
provider/anthropicprovider/agent_test.go Adds request-body assertions to verify thinking/redacted_thinking replay and skipping unsigned partial reasoning.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@PratikDhanave
PratikDhanave (PratikDhanave) force-pushed the replay-assistant-reasoning-thinking-blocks branch 2 times, most recently from fdb090f to 5a91f90 Compare July 23, 2026 15:43
@github-actions

This comment has been minimized.

@github-actions github-actions Bot added the parity-approved Go API consistency review found no parity issues label Jul 23, 2026
@PratikDhanave
PratikDhanave (PratikDhanave) force-pushed the replay-assistant-reasoning-thinking-blocks branch from 5a91f90 to 9649fd1 Compare July 24, 2026 01:42
@github-actions

This comment has been minimized.

…geParam

buildMessageParam had no case for *message.TextReasoningContent, so a prior
assistant thinking block (and its signature) produced on the inbound path was
silently dropped when the message history was sent back to Anthropic. Add a
case that replays it as a thinking block (signature + text) or a
redacted_thinking block (data only), skipping unsigned streamed partials that
would be rejected as invalid unsigned thinking blocks.
@PratikDhanave
PratikDhanave (PratikDhanave) force-pushed the replay-assistant-reasoning-thinking-blocks branch from 9649fd1 to 99ee6b6 Compare July 24, 2026 09:37
@github-actions

This comment has been minimized.

# Conflicts:
#	provider/anthropicprovider/agent_test.go
@github-actions

This comment has been minimized.

# Conflicts:
#	provider/anthropicprovider/agent_test.go
@github-actions github-actions Bot added area:provider Changes files in the provider area area:provider/anthropic Changes files in the provider / anthropic area size:large At most 300 changed lines across at most 10 files pending-auto-risk Automatic risk classification is in progress labels Aug 20, 2026
@github-actions

This comment has been minimized.

@github-actions github-actions Bot added failed-auto-risk Automatic risk classification was inconclusive or failed and removed pending-auto-risk Automatic risk classification is in progress labels Aug 20, 2026
@qmuntal

Copy link
Copy Markdown
Member

Needs rebase.

# Conflicts:
#	provider/anthropicprovider/agent_test.go
@github-actions github-actions Bot added pending-auto-risk Automatic risk classification is in progress risk:medium Contained production impact requiring normal review depth and removed failed-auto-risk Automatic risk classification was inconclusive or failed pending-auto-risk Automatic risk classification is in progress labels Aug 22, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Parity Review: ✅ No issues found

This PR fixes a bug in the unexported buildMessageParam function in provider/anthropicprovider/agent.go where *message.TextReasoningContent was silently dropped when replaying prior assistant turns with extended thinking.

No exported Go APIs changed. The public-api-change label is not warranted.

Cross-SDK parity check: The upstream Python implementation (python/packages/anthropic/agent_framework_anthropic/_chat_client.py) applies the same round-trip logic — text_reasoning content with protected_data + text{type: "thinking", thinking: ..., signature: ...}; with only protected_data{type: "redacted_thinking", ...}; unsigned partials dropped. The Go fix matches this behavior exactly.

The parity-approved label already present on this PR remains correct.

Generated by Go API Consistency Review Agent · sonnet46 · 26.4 AIC · ⌖ 5.67 AIC · ⊞ 6K ·

@qmuntal
Quim Muntal (qmuntal) added this pull request to the merge queue Aug 24, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Aug 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:provider/anthropic Changes files in the provider / anthropic area area:provider Changes files in the provider area parity-approved Go API consistency review found no parity issues risk:medium Contained production impact requiring normal review depth size:large At most 300 changed lines across at most 10 files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants