Skip to content

fix(aws): accept tool_call content blocks in convertAIMessageToConverseMessage - #11633

Open
Lukas Buck (L4XB) wants to merge 1 commit into
langchain-ai:mainfrom
L4XB:fix/11476-aws-tool-call-content-block
Open

Lukas Buck (L4XB) wants to merge 1 commit into
langchain-ai:mainfrom
L4XB:fix/11476-aws-tool-call-content-block

Conversation

@L4XB

Copy link
Copy Markdown

Fixes #11476.

The bug

convertAIMessageToConverseMessage walks an assistant message's content array and throws on any block type it does not recognise:

Unsupported content block type: tool_call with content of { ... }

A tool_call block is one of those, even though the same call is serialized a few lines below from msg.tool_calls. An AIMessage carries both views — content blocks and tool_calls — so the converter rejected a message shape this class produces itself. Any agent loop that replays assistant turns as standard content blocks hits it.

The fix

Handle tool_call before the throw. When msg.tool_calls already carries the same id and name, the block is the duplicate and is skipped, so the toolUse is emitted exactly once, from the existing tool_calls pass.

When it does not, the block is converted to a toolUse here instead of being skipped. That branch matters: core only syncs content and tool_calls when an AIMessage is constructed with contentBlocks (libs/langchain-core/src/messages/ai.ts), so a message assembled through content can carry the block with tool_calls empty. A blanket skip would drop that call silently — which is the failure the throw was there to prevent in the first place.

Scope is the standard tool_call block. Anthropic's provider-shaped tool_use is not produced by this class, so it stays with the existing throw rather than being mapped on a guess about which of args/input it carries.

Tests

Three cases in libs/providers/langchain-aws/src/tests/chat_models.test.ts:

  • a message holding the call both as a tool_call block and in tool_calls converts without throwing, and yields one toolUse, in the block's position relative to the text;
  • a message holding only the block converts it, so nothing is dropped;
  • an actually unknown block type still throws, unchanged.
npx vitest run src/tests/chat_models.test.ts    # 70 passed, no type errors

Checked against mutants rather than only against the fix: on main the first two fail and the third passes; skipping the block unconditionally (the shape the issue suggests) fails the second; emitting it without the duplicate check fails the first, with two toolUse blocks for one call.

oxlint and oxfmt --check are clean, and a changeset is included.

…seMessage

`convertAIMessageToConverseMessage` threw `Unsupported content block type:
tool_call` on any assistant message whose `content` array carried a standard
`tool_call` block, while serializing the same call from `msg.tool_calls` a few
lines below. An AIMessage holds both views, so the converter rejected a shape
this class produces itself.

Skip the block when `msg.tool_calls` already carries the same id and name.
When it does not, convert the block to a `toolUse` rather than skipping it:
core only keeps `content` and `tool_calls` in sync for a message built with
`contentBlocks`, so one assembled through `content` can hold the block alone,
and a blanket skip would drop that call silently — the failure the throw was
there to prevent.

Scope is the standard `tool_call` block. Anthropic's provider-shaped
`tool_use` is not produced by this class and is left to the existing throw.

Fixes langchain-ai#11476
@changeset-bot

changeset-bot Bot commented Sep 13, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 8c1ff18

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@langchain/aws Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ChatBedrockConverse throws 'Unsupported content block type: tool_call' on tool_call content blocks it should skip

1 participant