Skip to content

fix: Dedupe duplicate signed thinking blocks to fix Anthropic 400 (#10080) - #10083

Merged
jbg merged 9 commits into
mainfrom
micn/duplicated-thinking
Jul 9, 2026
Merged

fix: Dedupe duplicate signed thinking blocks to fix Anthropic 400 (#10080)#10083
jbg merged 9 commits into
mainfrom
micn/duplicated-thinking

Conversation

@michaelneale

@michaelneale michaelneale commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

my take at fixing: #10080

hopefully will prevent but also deals with past sessions that have duplicates

Fixes #10080

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.
@michaelneale
michaelneale marked this pull request as ready for review June 29, 2026 05:41

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 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".

Comment thread crates/goose-providers/src/conversation.rs Outdated
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.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 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".

Comment thread crates/goose/src/agents/agent.rs Outdated
* origin/main:
  task(acp): upgrade SDK and use new HTTP/WS crate (#10082)
  fix(providers): reject non-object tool-call arguments instead of panicking (#9832)

# Conflicts:
#	crates/goose/src/agents/agent.rs
…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.
@michaelneale
michaelneale requested review from DOsinga and jh-block June 29, 2026 07:43

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 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".

Comment thread crates/goose-providers/src/conversation.rs Outdated
* origin/main:
  chore: Remove legacy MCP-UI proxy support (#10086)
  Remove session_id from provider streaming trait methods (#9984)
  fix(cli): update help text for --session-id (#10077)

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 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".

Comment on lines +551 to +555
if is_signed && seen.contains(content) {
continue;
}
if is_signed {
seen.push(content.clone());

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 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,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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 ianballou left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I am using Goose with Anthropic models via the vertex API. This PR unblocks my use of the Anthropic models, thanks!

@jbg
jbg added this pull request to the merge queue Jul 8, 2026
Merged via the queue into main with commit e09289c Jul 9, 2026
25 checks passed
@jbg
jbg deleted the micn/duplicated-thinking branch July 9, 2026 00:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Anthropic 400: persisted duplicate signed thinking blocks break Claude sessions on replay

6 participants