Skip to content

fix(models): skip empty text parts in Anthropic message conversion - #6983

Open
MarcHuang168 wants to merge 1 commit into
google:mainfrom
MarcHuang168:fix-anthropic-empty-text-part
Open

fix(models): skip empty text parts in Anthropic message conversion#6983
MarcHuang168 wants to merge 1 commit into
google:mainfrom
MarcHuang168:fix-anthropic-empty-text-part

Conversation

@MarcHuang168

Copy link
Copy Markdown

Link to Issue or Description of Change

Link to an existing issue:

Closes: #6982

Problem:

AnthropicLlm converts each Part into an Anthropic content block in _part_to_message_block. A part carrying only an empty text string (Part(text='')) matches no branch — if part.text: is false for '' — and falls through to the final raise NotImplementedError("Not supported yet: ..."), failing the whole model call with a misleading error.

ADK emits such parts itself: code_executors/code_execution_utils.py writes Part(text='') into the content when a code execution produces no output. The LiteLLM path already tolerates empty text parts, so the same conversation works via LiteLlm but fails via the native AnthropicLlm adapter.

Solution:

Add _is_empty_text_part() (a part whose only payload is an empty text, optionally with thought) and skip such parts in _content_to_message_param, logging at debug level. This mirrors the adapter's existing warn-and-skip handling of unsupported media in assistant turns, and Anthropic rejects empty text blocks anyway. Parts that carry other payload alongside empty text (e.g. a function_call) are unaffected, and the NotImplementedError fallback for genuinely unsupported part types is kept.

Testing Plan

Unit Tests:

  • I have added or updated unit tests for my change.
  • All unit tests pass locally.

Added in tests/unittests/models/test_anthropic_llm.py:

  • test_content_to_message_param_skips_empty_text_part — an empty text part is dropped and the remaining text block is preserved.
  • test_content_to_message_param_keeps_non_text_payload_with_empty_text — a part with text='' plus a function_call still produces a tool_use block.

Verified the first test fails without the fix:

$ git stash push -- src/google/adk/models/anthropic_llm.py
$ pytest tests/unittests/models/test_anthropic_llm.py -q -k empty_text
1 failed, 1 passed, 151 deselected
$ git stash pop

With the fix:

$ pytest tests/unittests/models/test_anthropic_llm.py -q
153 passed
$ pytest tests/unittests -q -n auto
13749 passed, 81 skipped, 26 xfailed, 2 xpassed

pre-commit run --files <the two changed files>: all hooks pass.

Manual End-to-End (E2E) Tests:

Ran the reproduction from #6982 (content_to_message_param on a Content with Part(text="run it") and Part(text="")). Before: NotImplementedError: Not supported yet: ... text='' .... After: {'role': 'user', 'content': [{'text': 'run it', 'type': 'text'}]}.

Checklist

  • I have read the CONTRIBUTING.md document.
  • I have performed a self-review of my own code.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.
  • I have manually tested my changes end-to-end.
  • Any dependent changes have been merged and published in downstream modules.

Additional context

Prepared with Claude assistance; the bug was reproduced, and the change reviewed and tested, by me.

ADK can emit Part(text='') itself (e.g. code execution with no output),
and Anthropic rejects empty text blocks; the adapter fell through to
NotImplementedError and failed the whole request. Skip such parts,
matching the LiteLLM path.

Prepared with Claude assistance; reviewed and tested by author.
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.

AnthropicLlm raises NotImplementedError on empty text parts that ADK itself emits (e.g. code execution with no output)

2 participants