From 88720c6928cd49dc040e1f06cc2511e2d527045b Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Mon, 5 Oct 2026 09:19:45 +0200 Subject: [PATCH] fix: tool calls get mixed up between rounds when the model reuses tool call ids (#31887) Some providers, like Kimi K3 on OpenRouter, number their tool calls from zero again each time the model calls tools within the same reply. A later batch of calls then overwrote the earlier calls with the same id, so the saved chat showed the earlier calls with the later arguments, and the model was sent its earlier results next to the wrong arguments. A new tool call whose id is already used in the same reply now gets a fresh id, so every call keeps its own arguments and result, and providers that send unique ids are untouched. Tested before and after against a mock provider that reuses ids on every round. Fixes #28305 --- backend/open_webui/utils/middleware.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py index a48f42d960..27d4b8b559 100644 --- a/backend/open_webui/utils/middleware.py +++ b/backend/open_webui/utils/middleware.py @@ -5202,6 +5202,13 @@ async def streaming_chat_response_handler(response, ctx): if delta_tool_call['function'].get('name') is None: delta_tool_call['function']['name'] = '' delta_tool_call['id'] = delta_tool_call.get('id') or output_id('fc') + # Some providers restart tool call ids on every round + if any( + item.get('type') == 'function_call' + and item.get('call_id') == delta_tool_call['id'] + for item in full_output() + ): + delta_tool_call['id'] = output_id('fc') delta_arguments = delta_tool_call['function'].get('arguments') if not isinstance(delta_arguments, str): delta_tool_call['function']['arguments'] = (