Skip to content

[integration][anthropic] Don't assume the first content block is text#916

Merged
wenjin272 merged 1 commit into
apache:mainfrom
Zhuoxi2000:fix-anthropic-tool-use-content
Jul 20, 2026
Merged

[integration][anthropic] Don't assume the first content block is text#916
wenjin272 merged 1 commit into
apache:mainfrom
Zhuoxi2000:fix-anthropic-tool-use-content

Conversation

@Zhuoxi2000

Copy link
Copy Markdown
Contributor

Linked issue: #914

Purpose of change

AnthropicChatModelConnection.chat read the response text via
message.content[0].text. When the model calls a tool, the response commonly
contains only a tool_use block, so content[0] is a ToolUseBlock and
.text raised AttributeError: 'ToolUseBlock' object has no attribute 'text'.
Both the tool_use and the plain-text return paths used this unsafe access,
even though the code just above already iterates message.content filtering by
type == "tool_use" — so the blocks are known to be mixed-type there.

Pick the first text block instead (falling back to "" when there is none) and
reuse it in both return paths.

Closes #914

Tests

Added test_anthropic_response_parsing.py with unit tests that mock the client,
so they need no API key and run in the regular unit test job: a tool_use
response with no leading text, one with a leading text block, and a plain text
response.

test_tool_use_response_without_leading_text fails on main with
AttributeError: 'ToolUseBlock' object has no attribute 'text' and passes with
this change.

  • pytest flink_agents/integrations/chat_models/anthropic/tests/: 5 passed,
    2 skipped (the existing API-key integration tests).
  • ruff check --no-fix / ruff format --check (pinned 0.11.13): clean.

API

No. chat() keeps its signature and still returns a ChatMessage. Text
responses are unaffected — the first text block is the same value content[0]
used to yield — it only stops crashing when the first block is not text.

Documentation

  • doc-needed
  • doc-not-needed
  • doc-included

When the Anthropic model calls a tool, the response commonly contains
only a tool_use block, so message.content[0] is a ToolUseBlock. Reading
message.content[0].text then raised
AttributeError: 'ToolUseBlock' object has no attribute 'text'. The same
block already iterates message.content filtering by type == "tool_use",
so the mixed block types are known here.

Pick the first text block instead (falling back to "" when there is
none), and reuse it in both the tool_use and plain-text return paths.

Add unit tests (mocked client, no API key) covering a tool_use response
with no leading text, one with a leading text block, and a plain text
response.

Closes apache#914
@github-actions github-actions Bot added doc-not-needed Your PR changes do not impact docs fixVersion/0.4.0 priority/major Default priority of the PR or issue. labels Jul 17, 2026
@wenjin272
wenjin272 marked this pull request as ready for review July 20, 2026 03:18

@wenjin272 wenjin272 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.

LGTM

@wenjin272 wenjin272 added the fixVersion/0.3.1 The feature or bug should be implemented/fixed in the 0.3.1 version. label Jul 20, 2026
@wenjin272
wenjin272 merged commit b5dd271 into apache:main Jul 20, 2026
54 of 55 checks passed
wenjin272 pushed a commit that referenced this pull request Jul 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

doc-not-needed Your PR changes do not impact docs fixVersion/0.3.1 The feature or bug should be implemented/fixed in the 0.3.1 version. fixVersion/0.4.0 priority/major Default priority of the PR or issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Anthropic chat model crashes on a tool_use response with no text block

2 participants