Repository navigation
Description
Description
AWS Bedrock with the new Kimi K2 Thinking model (https://aws.amazon.com/blogs/aws/amazon-bedrock-adds-fully-managed-open-weight-models/) seems to end the conversation abruptly. It looks like it sometimes parses tool calls as "text-delta" instead of an actual tool call, which shows up as text in my chat app.
Here is a sample log:
{"type":"start","messageId":"yhfl7aguy69p78kdaupavgr0"}{"type":"start","messageId":"zdeo0nspwe3nd4cv0n9pl4q9"}{"type":"start-step"}{"type":"reasoning-start","id":"1"}{"type":"reasoning-delta","id":"1","delta":" The user is asking if they have"}{"type":"reasoning-delta","id":"1","delta":" any \"cursor files\" in their repository. This likely refers to Cursor editor configuration files (like .cursorrules) or possibly files related to cursor/cursor-based operations in the code.\n\nLet me"}{"type":"reasoning-delta","id":"1","delta":" search for files with \""}{"type":"reasoning-delta","id":"1","delta":"cursor\" in the name or path."}{"type":"reasoning-end","id":"1"}{"type":"tool-input-start","toolCallId":"tooluse_OEppyvDpRkWByqqI-Ixz0A","toolName":"glob_search"}{"type":"tool-input-delta","toolCallId":"tooluse_OEppyvDpRkWByqqI-Ixz0A","inputTextDelta":"{\"pattern\": \"**/*cursor*\"}"}{"type":"tool-input-available","toolCallId":"tooluse_OEppyvDpRkWByqqI-Ixz0A","toolName":"glob_search","input":{"pattern":"**/*cursor*"}}{"type":"text-start","id":"4"}{"type":"text-delta","id":"4","delta":"{\"pattern\": "}{"type":"text-delta","id":"4","delta":"\"**/*cursor*\"}"}{"type":"text-end","id":"4"}{"type":"tool-output-available","toolCallId":"tooluse_OEppyvDpRkWByqqI-Ixz0A","output":{"files":["FILE1","FILE2"]}}{"type":"finish-step"}{"type":"start-step"}{"type":"reasoning-start","id":"1"}{"type":"reasoning-delta","id":"1","delta":" Yes, you have cursor files in your repo:\n1. FILE1\n2. FILE2\n\nLet me read the"}{"type":"reasoning-delta","id":"1","delta":" TypeScript file to see what it contains."}{"type":"reasoning-end","id":"1"}{"type":"text-start","id":"2"}{"type":"text-delta","id":"2","delta":"{\"target_file\": "}{"type":"text-delta","id":"2","delta":"\"FILE1\"} "}{"type":"text-delta","id":"2","delta":"<|tool_calls_section_end|>"}{"type":"text-end","id":"2"}{"type":"finish-step"}{"type":"finish","finishReason":"stop"}
I also had to add a custom transform because every time it made a tool call, it would add the tool markers in the "text" field as well. Here's a sample:
() =>
new TransformStream({
transform(chunk, controller) {
if (chunk.type === "text-delta") {
// Remove Kimi K2 tool call markers
const cleanedText = chunk.text
.replace(/<\|tool_call_begin\|>/g, "")
.replace(/<\|tool_call_argument_begin\|>/g, "")
.replace(/<\|tool_call_end\|>/g, "")
.replace(/functions\.\w+:\d+/g, "")
.trim()
// Only enqueue if there's actual text left after cleaning
if (cleanedText) {
controller.enqueue({
...chunk,
text: cleanedText,
})
}
} else {
// Pass through all other chunk types unchanged
controller.enqueue(chunk)
}
},
}),
Note: this only happens for some calls, sometimes it works correctly, and sometimes it doesn't.
I realize this model just came out, so if there's a temporary workaround to parse the tool calls correctly, that would be much appreciated!
AI SDK Version
Packages: "@ai-sdk/amazon-bedrock": "4.0.2", "ai": "6.0.2",
Code of Conduct
- I agree to follow this project's Code of Conduct
Activity
aayush-kapoor commentedon Dec 24, 2025
hi! can you provide a small reproduction code for this issue?
fix(bedrock): route Kimi/Moonshot models via bedrock-mantle OpenAI-co…
fix(ai): route Kimi/Moonshot models via bedrock-mantle instead of Con…
fix(ai): route Kimi/Moonshot models via bedrock-mantle instead of Con…
fix(ai): route Kimi/Moonshot models via bedrock-mantle instead of Con…
fix(ai): route Kimi/Moonshot models via bedrock-mantle instead of Con…
fix(ai): route Kimi/Moonshot models via bedrock-mantle instead of Con…
fix: mitigate Kimi K2.5 premature end_turn on Bedrock Converse API
fix(ai): route Kimi/Moonshot models via bedrock-mantle instead of Con…
fix(ai): route Kimi/Moonshot models via bedrock-mantle instead of Con…
fix(ai): route Kimi/Moonshot models via bedrock-mantle instead of Con…
fix(ai): route Kimi/Moonshot models via bedrock-mantle instead of Con…
12 remaining items
lgrammel commentedon Jul 22, 2026
Bug Reproduction
Bug was reproduced.
Branch:
release-v5.0PR: successful reproduction pull request
Details
read_fileas a structured tool call and returnFOUND ISSUE_11409_CONTENT; the final live run instead emitted the intended call as visible text, skipped execution, and stopped early in 1 of 10 attempts.examples/ai-functions/src/reproduction/amazon-bedrock-kimi-k2-thinking-tool-call.tsreproduces the intermittent user-visible failure against live Amazon Bedrock.packages/amazon-bedrock/src/__fixtures__/issue-11409-kimi-k2-thinking-glob-search.chunks.txtrecords the preceding successful structuredglob_searchcall.packages/amazon-bedrock/src/__fixtures__/issue-11409-kimi-k2-thinking-read-file.chunks.txtrecords Bedrock returning<function=read_file>as text followed bystopReason: "end_turn"instead of a structured tool-use event.packages/amazon-bedrock/src/issue-11409.test.tsreplays the live fixtures and fails becauseread_fileis absent, tool syntax is visible, and the final answer is missing.examples/ai-functions/package.jsonandpnpm-lock.yamlprovide the runnable reproduction workspace.[email protected]and@ai-sdk/[email protected]; the reporter's exact[email protected]and@ai-sdk/[email protected]versions were not executed.Relevant Documentation
lgrammel commentedon Jul 22, 2026
Bugfix
Created bugfix and opened PR: #17732
Root Cause
The Bedrock stream adapter treated every Converse text delta as user-visible content and trusted
end_turn, with no recovery when Kimi serialized a known tool call into text. Recorded chunks confirmed the missingtoolUseevent and text-encodedread_filerequest.Summary
Added Kimi-specific parsing for serialized tool calls, converted leaked thinking and tool syntax into structured stream events, suppressed duplicate serialized arguments, returned a tool-call finish reason, removed reproduction artifacts, and added a patch changeset.
Testing
Added streaming regression coverage for recovering a split text-encoded tool call and suppressing text duplicated after a structured tool call.
lgrammel commentedon Jul 22, 2026
Bugfix updated
Updated PR: #17732
Root Cause
The adapter trusted Kimi text and reasoning deltas as displayable content and accepted
end_turneven when they contained serialized tool calls. Issue samples, parser probes, and a live Bedrock response confirmed XML, native-marker, bare-JSON, and reasoning-content variants.Update
Added bare-JSON inference for uniquely matching tool schemas, reasoning-content recovery, selective candidate buffering, incremental ordinary streaming, and key-order-independent duplicate detection.
ai-sdk-factory commentedon Jul 30, 2026
Bug Reproduction
Bug was reproduced.
Branch:
release-v5.0PR: successful reproduction pull request
Details
read_fileas a structured tool call and returnFOUND ISSUE_11409_CONTENT; the recorded Bedrock response instead emits<function=read_file>as visible text, returnsend_turn, skips the tool, and omits the final answer.packages/amazon-bedrock/src/__fixtures__/issue-11409-kimi-k2-thinking-glob-search.chunks.txtandpackages/amazon-bedrock/src/__fixtures__/issue-11409-kimi-k2-thinking-read-file.chunks.txt.packages/amazon-bedrock/src/issue-11409.test.tsreplays those responses and asserts the final user-visible behavior, including structured tool execution, hidden tool syntax, and the required final answer.packages/amazon-bedrock/src/bedrock-chat-language-model.tsforwards Converse text deltas as visible text and acceptsend_turnwithout recovering Kimi's serialized tool call, placing a meaningful fix in the AI SDK Bedrock adapter.examples/ai-functions/src/reproduction/amazon-bedrock-kimi-k2-thinking-tool-call.ts,examples/ai-functions/package.json, andpnpm-lock.yamlprovide the live reproduction workspace; 20 completed current live attempts executedread_filestructurally, but further intermittent testing was blocked by HTTP 429Provider request budget exhausted.[email protected]and@ai-sdk/[email protected]; the reporter's[email protected]and@ai-sdk/[email protected]versions are not part ofrelease-v5.0and were not installed.Relevant Documentation
ai-sdk-factory commentedon Jul 30, 2026
Bugfix
Created bugfix and opened PR: #18205
Root Cause
The Bedrock stream adapter forwarded every text and reasoning delta directly and trusted end_turn even when recorded responses contained serialized known-tool syntax instead of toolUse events.
Summary
Added Kimi-specific recovery for XML, native-marker, bare-JSON, and reasoning-encoded tool calls, suppressed duplicate serialized arguments, emitted structured tool events and tool-call finish reasons, and added a patch changeset.
Testing
Added five streaming regressions covering split XML calls, bare JSON, reasoning content, duplicate suppression, and incremental ordinary text.
gr2m commentedon Aug 31, 2026
Closing this as upstream/not currently reproducible.
The captured Bedrock response emitted the intended tool call as text with
stopReason: "end_turn". AI SDK handled that response as received.I also tried the second turn directly against Bedrock, without AI SDK:
curl reproduction
Bedrock now returns a structured
toolUseblock withstopReason: "tool_use". I could not reproduce the failure.It may have been fixed upstream. It may also be intermittent or specific to
ConverseStream. Adding model-specific parsing for malformed tool-call text would be brittle, so we do not plan to handle it in AI SDK. We can revisit if there is a current direct Bedrock reproduction.