You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Claude model throws UnsupportedOperationException("Not supported yet.") on thinking blocks from Claude 5 models #1630
So any Messages API response that contains a thinking or redacted_thinking block makes Claude.generateContent throw, and the agent run ends with that exception. ADK Java never sets thinking on the request (Claude.java:142-147). According to Anthropic's thinking docs (checked 2026-10-08), the Claude 5 models (Opus 5 and 5.5, Sonnet 5 and 5.5, Haiku 5.5, Fable 5 and 5.1, and the Mythos models) use adaptive thinking when that field is absent, and their display default is "omitted". Whenever the model decides to think, the response therefore contains a thinking block with empty text and a signature, at the start of the response or right before a tool_use block. Opus 4.8 and earlier, Sonnet 4.6 and earlier, and Haiku 4.5 do not think unless asked, which is probably why this has not come up before.
Skipping these blocks would stop the exception, and the API accepts a history without them, but the same docs mark passing them back, complete and unmodified, as required within a tool-use turn; without them the model loses its earlier reasoning. The request side has the matching gap: partToAnthropicMessageBlock (Claude.java:176-209) sends a thought Part that has text as an ordinary text block, dropping the signature, and throws the same exception for a thought Part that has only a signature.
Steps to Reproduce:
Use com.google.adk:google-adk 1.11.0 (or main at ce882374) with anthropic-java 2.15.0, the version ADK depends on.
Give a Claude model an AnthropicClient whose response has a thinking block followed by a text block (code below, with a mocked client).
Call generateContent, or run an LlmAgent that uses this model through InMemoryRunner.
Expected Behavior:
thinking and redacted_thinking blocks become thought Parts that keep the block's signature (or the redacted block's data) in thoughtSignature, and the next request sends them back as the same blocks. adk-python has used this mapping since google/adk-python@16952bd39 (src/google/adk/models/anthropic_llm.py), with one difference noted under Additional Context.
Observed Behavior:
java.lang.UnsupportedOperationException: Not supported yet.
at com.google.adk.models.Claude.anthropicContentBlockToPart(Claude.java:391)
at com.google.adk.models.Claude.convertAnthropicResponseToLlmResponse(Claude.java:354)
at com.google.adk.models.Claude.generateContent(Claude.java:158)
The same happens with a summarized thinking block (non-empty text) and with a redacted_thinking block. In an agent run, the Flowable returned by InMemoryRunner.runAsync terminates with this exception on the first model response that contains a thinking block. On the request side, which I tested by putting thought Parts in the history by hand (Claude cannot produce one today), a thought Part with text goes out as a text block (an omitted thought as an empty text block, a summarized one as visible text), and one with only a signature throws the same exception at Claude.java:209.
Environment Details:
ADK Library Version (see maven dependency): 1.11.0 and main at ce882374, with anthropic-java 2.15.0
OS: Windows 11 (not OS-specific)
TS Version (tsc --version): N/A (Java: Microsoft OpenJDK 17.0.19)
Model Information:
Which model is being used: claude-opus-5-5 as the model name in a mocked reproduction. The mocked AnthropicClient returns the documented block shape; I did not run it against the live API. Whether a response contains a thinking block is up to the model; per the docs, the models above can return one without being asked.
🟡 Optional Information
Regression:
No. Both conversion methods have thrown for these blocks since Claude was added in 0.1.0; it shows up now because the Claude 5 models think when thinking is not set.
Additional Context:
I have a draft fix in Claude.java (+23 lines) that uses the same mapping as google/adk-python@16952bd39: a thinking block becomes Part(text, thought=true, thoughtSignature=signature), a redacted_thinking block becomes Part(thought=true, thoughtSignature=data), and requests convert them back. With the draft, the code below returns a thought Part and a text Part, and in a tool-use turn the second request sends [thinking (same signature), tool_use]. I'll link the PR here.
One difference from adk-python: its request side sends a thought with empty text (what display: "omitted" returns) back as redacted_thinking with the signature as data, not as the thinking block the API returned. The draft checks whether the text is present rather than non-empty.
One question before the PR: if the history also holds thought Parts produced by another model (for example when the same agent ran on Gemini earlier in the session; other agents' thoughts are already skipped in Contents), should Claude drop them, or keep sending the ones with text as plain text, as it does today? Sending them as thinking blocks would fail, because Anthropic rejects signatures it cannot decode.
// The mocked client returns what the Messages API returns when the model thinks with// display "omitted": an empty thinking block with a signature, then the answer.AnthropicClientclient = mock(AnthropicClient.class);
MessageServicemessages = mock(MessageService.class);
Messageresponse = mock(Message.class);
when(client.messages()).thenReturn(messages);
when(messages.create(any(MessageCreateParams.class))).thenReturn(response);
when(response.content())
.thenReturn(
List.of(
ContentBlock.ofThinking(
ThinkingBlock.builder().thinking("").signature("EqQBCkYIBxgC...").build()),
ContentBlock.ofText(TextBlock.builder().text("4").citations(List.of()).build())));
Claudeclaude = newClaude("claude-opus-5-5", client);
LlmRequestrequest =
LlmRequest.builder()
.contents(List.of(Content.builder().role("user").parts(Part.fromText("2+2?")).build()))
.build();
claude.generateContent(request, false);
// throws java.lang.UnsupportedOperationException: Not supported yet.
(AnthropicClient, MessageService (com.anthropic.services.blocking) and the com.anthropic.models.messages types are from anthropic-java 2.15.0; Content and Part are com.google.genai.types. mock, when and any are Mockito 5, whose default inline mock maker is needed because Message is final.)
How often has this issue occurred?:
Always (100%) for a response that contains a thinking or redacted_thinking block.
Hi @innoprej, we really appreciate you reporting this and putting together a PR to fix it. I have successfully reproduced the issue you described and through local testing that your fix addresses this issue. currently, both the issue and your PR are under review by the team. We will keep you updated and let you know if we need any additional information.
Thanks for reproducing this and testing the fix in #1634. Two notes since I filed the issue:
The PR differs from adk-python in one more place than I mentioned above. A thought without a signature that Claude issued (no signature at all, or a binary one another model such as Gemini left) is sent as text, as before, or dropped if its text is empty, and never as a thinking block. adk-python sends an unsigned thought that has text as a thinking block with an empty signature. For my question above, this means thoughts from another model keep going out as text, which matches the "Send the other model's output as text and tool_use content" advice in Anthropic's preserved thinking docs. If you would rather drop them, it is a small change.
A known limitation, shared with adk-python: on Claude Fable 5.1, Opus 5.5, Sonnet 5.5 and Haiku 5.5, accounts created on or after 2026-08-31 get a 400 when a thinking block is sent back after system, tools or the earlier messages have changed since it was produced, and ADK rebuilds the system instruction on every request. The PR describes it and two possible follow-ups.
🔴 Required Information
Describe the Bug:
Claude.anthropicContentBlockToPartconverts onlytextandtool_useresponse blocks and throws for every other block type (Claude.java:374-391):So any Messages API response that contains a
thinkingorredacted_thinkingblock makesClaude.generateContentthrow, and the agent run ends with that exception. ADK Java never setsthinkingon the request (Claude.java:142-147). According to Anthropic's thinking docs (checked 2026-10-08), the Claude 5 models (Opus 5 and 5.5, Sonnet 5 and 5.5, Haiku 5.5, Fable 5 and 5.1, and the Mythos models) use adaptive thinking when that field is absent, and theirdisplaydefault is"omitted". Whenever the model decides to think, the response therefore contains athinkingblock with empty text and asignature, at the start of the response or right before atool_useblock. Opus 4.8 and earlier, Sonnet 4.6 and earlier, and Haiku 4.5 do not think unless asked, which is probably why this has not come up before.Skipping these blocks would stop the exception, and the API accepts a history without them, but the same docs mark passing them back, complete and unmodified, as required within a tool-use turn; without them the model loses its earlier reasoning. The request side has the matching gap:
partToAnthropicMessageBlock(Claude.java:176-209) sends a thoughtPartthat has text as an ordinary text block, dropping the signature, and throws the same exception for a thoughtPartthat has only a signature.Steps to Reproduce:
com.google.adk:google-adk1.11.0 (ormainatce882374) withanthropic-java2.15.0, the version ADK depends on.Claudemodel anAnthropicClientwhose response has a thinking block followed by a text block (code below, with a mocked client).generateContent, or run anLlmAgentthat uses this model throughInMemoryRunner.Expected Behavior:
thinkingandredacted_thinkingblocks become thoughtParts that keep the block'ssignature(or the redacted block'sdata) inthoughtSignature, and the next request sends them back as the same blocks. adk-python has used this mapping since google/adk-python@16952bd39 (src/google/adk/models/anthropic_llm.py), with one difference noted under Additional Context.Observed Behavior:
The same happens with a summarized thinking block (non-empty text) and with a
redacted_thinkingblock. In an agent run, theFlowablereturned byInMemoryRunner.runAsyncterminates with this exception on the first model response that contains a thinking block. On the request side, which I tested by putting thoughtParts in the history by hand (Claudecannot produce one today), a thoughtPartwith text goes out as a text block (an omitted thought as an empty text block, a summarized one as visible text), and one with only a signature throws the same exception atClaude.java:209.Environment Details:
mainatce882374, withanthropic-java2.15.0Model Information:
claude-opus-5-5as the model name in a mocked reproduction. The mockedAnthropicClientreturns the documented block shape; I did not run it against the live API. Whether a response contains a thinking block is up to the model; per the docs, the models above can return one without being asked.🟡 Optional Information
Regression:
No. Both conversion methods have thrown for these blocks since
Claudewas added in 0.1.0; it shows up now because the Claude 5 models think whenthinkingis not set.Additional Context:
Claude.java(+23 lines) that uses the same mapping as google/adk-python@16952bd39: athinkingblock becomesPart(text, thought=true, thoughtSignature=signature), aredacted_thinkingblock becomesPart(thought=true, thoughtSignature=data), and requests convert them back. With the draft, the code below returns a thoughtPartand a textPart, and in a tool-use turn the second request sends[thinking (same signature), tool_use]. I'll link the PR here.display: "omitted"returns) back asredacted_thinkingwith the signature asdata, not as thethinkingblock the API returned. The draft checks whether the text is present rather than non-empty.Parts produced by another model (for example when the same agent ran on Gemini earlier in the session; other agents' thoughts are already skipped inContents), shouldClaudedrop them, or keep sending the ones with text as plain text, as it does today? Sending them as thinking blocks would fail, because Anthropic rejects signatures it cannot decode.Claude, open) changes the same file and drops thinking deltas in the streaming path; [spring-ai] Bridge drops reasoning_content (thinking) — surface it as partial events and/or persist it #1616 is about the Spring AI bridge dropping reasoning content.Minimal Reproduction Code:
(
AnthropicClient,MessageService(com.anthropic.services.blocking) and thecom.anthropic.models.messagestypes are fromanthropic-java2.15.0;ContentandPartarecom.google.genai.types.mock,whenandanyare Mockito 5, whose default inline mock maker is needed becauseMessageis final.)How often has this issue occurred?:
thinkingorredacted_thinkingblock.