fix: Dedupe duplicate signed thinking blocks to fix Anthropic 400 (#10080) - #10083
Conversation
Add a dedupe_signed_thinking pass to the conversation fixer that removes duplicate signed thinking/redacted_thinking blocks within an assistant message. This repairs both new and existing sessions where a standalone thinking message and a tool-call message that re-embeds the same signed thinking get merged into a single turn with adjacent duplicate thinking blocks, which Anthropic rejects with a 400.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d065bb2378
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Implements the source-side fix: when persisting an assistant turn that emitted thinking + tool calls, only unsigned thinking (Kimi/DeepSeek/ Gemini) is echoed onto each split tool-call message. Signed thinking (Anthropic) already lives on the standalone thinking message, so echoing it again produced duplicate signed blocks that merge_consecutive_messages collapsed into one assistant turn, which Anthropic rejects with a 400. Adds is_signed_thinking helper and a unit test. The dedupe pass from the prior commit remains as a guardrail and to repair existing sessions.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4091fe68c9
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
…s change P2 #1: dedupe_signed_thinking now only collapses signed thinking blocks (non-empty signature) and redacted thinking, leaving duplicate unsigned reasoning summaries (from non-Anthropic providers) untouched. P2 #2: reverted the agent.rs change that stripped signed thinking from all split tool-call messages, which would have left later split messages in a multi-tool turn without their thinking. The dedupe pass alone now handles the fix at a single layer: each split assistant message keeps its own single signed thinking block, and within-message duplicates are collapsed. Adds a test that duplicate unsigned thinking is preserved.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4a1567c939
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: af8df7c727
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if is_signed && seen.contains(content) { | ||
| continue; | ||
| } | ||
| if is_signed { | ||
| seen.push(content.clone()); |
There was a problem hiding this comment.
Keep thinking on split Anthropic tool calls
Fresh evidence versus the earlier agent.rs thread: agent.rs now copies the signed block onto every split request, but the conversation-wide seen check here strips it from the second and later assistant tool-use messages during fix_conversation. For an Anthropic/Bedrock response with one signed thinking block and multiple tool calls persisted as assistant(thinking, tool1), tool_result, assistant(thinking, tool2), the second assistant serializes as a bare tool_use; Anthropic's extended-thinking tool-use docs show that omitting the thinking block before a tool_use is rejected, so these multi-tool thinking turns can still 400: https://platform.claude.com/cookbook/extended-thinking-extended-thinking-with-tool-use
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7c18031e91
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| fix_empty_tool_results, | ||
| fix_tool_calling, | ||
| merge_consecutive_messages, | ||
| dedupe_signed_thinking, |
There was a problem hiding this comment.
Run dedupe after dropping leading assistant messages
When a repaired history starts with an assistant signed-thinking block, this pass records that block in seen even though fix_lead_trail immediately discards the leading assistant afterward. If the first kept assistant tool-use message repeats the same signed block (the legacy duplicate shape this fixer is meant to repair), the dedupe pass strips the later copy and then the original copy is removed, leaving the replayed tool-use without its signed thinking. Move this pass after lead/trail cleanup, or avoid seeding seen from messages that will be dropped.
Useful? React with 👍 / 👎.
ianballou
left a comment
There was a problem hiding this comment.
I am using Goose with Anthropic models via the vertex API. This PR unblocks my use of the Anthropic models, thanks!
my take at fixing: #10080
hopefully will prevent but also deals with past sessions that have duplicates
Fixes #10080