2098 Commits

  • fix: assistant messages with only tool calls are sent with an empty string instead of null (#34265)
    When an assistant message has tool calls but no text, the OpenAI Chat Completions format uses `content: null`, since content is optional next to tool calls and OpenAI's own API returns null there. Open WebUI sent an empty string in two places: when replaying earlier tool calls from the chat history, and when converting requests from clients that use its Anthropic-compatible endpoint. For Claude models, LiteLLM 1.81.14 through 1.108.x replaces that empty string with "[System: Empty message content sanitised to satisfy protocol]", and the model then repeats that line in its replies (LiteLLM 1.109 and later leave the empty text out instead). These messages now go out with null content, which OpenAI and every provider tested on OpenRouter (Gemini, Claude, DeepSeek, Qwen, Mistral, Llama, Kimi and Grok) accept.
    
    Fixes #34264
  • fix: coding agent models get ids made only of letters, digits, dashes and underscores (#34171)
    Cursor and Pi model names carry brackets, equals signs, commas or slashes, and Open WebUI kept those in the ids of their agent models, so a pinned Cursor or Pi model opened a new chat on "Select a model". Agent models now get ids made only of letters, digits, dashes and underscores, with a few extra characters added when the name had to change, so two models never end up with the same id. The agent itself still runs on its own model name. Existing pins, default model choices and automations that point at an agent model whose name had other characters (dots included, as in most Codex models) stop matching and need the model picked again, and an existing chat with such an agent answers "Agent model is unavailable in the selected terminal" until the model is picked again.
    
    Fixes #34168
  • fix: a coding agent's error shows a technical dump with the whole system prompt (#34173)
    When the terminal refused to start a coding agent, for example because the system prompt was longer than Open Terminal accepts, the error under the reply was a technical dump of that refusal with the whole system prompt in it. Such a refusal now shows "Agent environment request failed". Refusals the terminal explains in plain words, such as another reply still running in the chat, keep showing that reason.
    
    Fixes #34172
  • fix: a compaction during a tool run drops the earlier conversation summary (#34151)
    When a turn started from an existing summary and its reply then compacted again between tool calls, the new summary was written without the earlier one whenever the plain summary prompt was used (a model with a filter, a separate Context Compaction Model, or a provider that refuses the cached replay). From the next turn on, everything the earlier summary held was gone. That compaction now gets the turn's summary as its previous summary, as a compaction at the start of a turn already does.
    
    Fixes #34141
  • fix: background memory review saves memories from temporary chats (#34263)
    With the background memory review on, Open WebUI looks back over the chat every few messages (10 by default) to save or update memories, and it did this in temporary chats too. Facts from a temporary chat could end up as memories that stayed after the chat was closed and showed up in later chats. The automatic review now skips temporary chats, so they leave no memories behind unless the user asks for one. Normal chats are reviewed as before, and memories already saved from a temporary chat are not removed.
    
    Fixes #34262
  • fix: replies end in a 400 on vLLM when tool use stops (#34176)
    When tool use stopped for a reply (the tool call limit, the same call failing twice, or a reply cut off in the middle of a tool call), Open WebUI asks the model once more for a final answer, and that request carried an empty tools list. vLLM refuses that with a 400, so the reply ended in that error instead of an answer. The final answer request now keeps the chat's tools and turns tool calls off with tool choice "none", the standard setting for that. Ollama has no tool choice setting, so for Ollama models any request with tool choice "none" now leaves the tools out, which is the only way to keep the model from calling them.
    
    Fixes #34169
  • feat: permission to limit sub-agents to specific users and groups (#34040)
    Sub-agents could only be switched on or off for the whole instance, so once they were on every user could spawn them and an admin had no way to keep the extra model usage to a pilot group. The user permissions now have a Sub-agents switch under Features, both in the default permissions and in each group, next to Memories and working the same way. Users without the permission no longer get the sub-agent tool in their chats, nor the timer tool that is part of the same feature. Admins are not restricted by it, and with sub-agents off in Admin Settings nobody gets them, admins included. The permission is on by default, so existing instances behave as before until an admin turns it off; the default can also be set with the USER_PERMISSIONS_FEATURES_SUBAGENTS environment variable.
    
    Closes #34038
  • fix: sub-agent on a terminal set to one machine per chat works in a machine of its own (#34104)
    A sub-agent could not see the files of the chat that handed it the task, the files it wrote never showed up in that chat, and its extra machine kept running after it finished. It now works in that chat's machine, the same way it already did on a terminal set to one machine per user.
  • fix: tool call arguments get extra spaces when sent back to the model (#33959)
    A tool call the model wrote as compact JSON, as most models do, was sent back to the model with a space added after every comma and colon, in every request after the tool ran. The model now gets its tool call arguments back exactly as it wrote them whenever they were valid JSON, so a model server that caches the model's earlier output can keep using that cache. Arguments that Open WebUI had to repair before the tool could run, such as JSON wrapped in a code block or written with Python-style True and None, still go back in their repaired form.
    
    Fixes #33958
  • fix: the model loses the labels it wrote for its tool calls when Tool Call Labels is on (#33953)
    With Tool Call Labels on, the model writes a short running and completed label for each tool call, and the chat shows them. Whenever the conversation was sent back to the model, both while it was still answering and on later messages, its earlier tool calls were missing those labels, so it saw itself leaving out its own labels and could learn to stop writing labels, which makes the chat fall back to plain tool names. The model now sees its earlier tool calls with the labels it wrote, and the chat shows them as before.
    
    Fixes #33952
  • fix: DeepSeek thinking mode errors when a chat uses skills, knowledge or memories (#33950)
    Starting with 0.13.1, DeepSeek in thinking mode returned the error "The `reasoning_content` in the thinking mode must be passed back to the API." for any chat that uses skills, attached knowledge or memories, even with the connection's Provider set to llama.cpp. Since that release these features reach the model through tool calls behind the scenes, and DeepSeek requires reasoning on every earlier tool call, which these tool calls never have. On connections with Provider set to llama.cpp, Open WebUI now fills in an empty reasoning for any earlier tool call that has none, which DeepSeek accepts, so these chats work again. Connections with Provider set to Default are unchanged: they send no reasoning back, so DeepSeek still needs the llama.cpp setting.
    
    Fixes #33940
  • fix: the turn that compacts the chat still sends the whole history (#33916)
    When a chat crossed the Context Compaction Threshold, the turn that made the summary still sent the model every earlier message with the summary on top, so that request was larger than without compaction and a chat already over the model's context window kept failing. Now that turn sends the summary and only the recent messages, as 0.13.0 did.
    
    Fixes #33915
  • fix: /compact makes the next message larger after a long tool-calling reply (#33912)
    Context compaction can already run partway through a long reply that calls many tools. If /compact was used after such a reply, the next message sent the model every tool call and result from that reply again, so the request grew instead of shrinking and could go past the model's context limit. Now the model gets the same shortened history it got before /compact, plus the new summary. Nothing changes in the saved chat or in what the chat shows.
    
    Fixes #33911
  • fix: a malformed tool call with Tool Search on ends tool use for the rest of the reply (#33872)
    With Tool Search on, when the model sent a broken call for a tool Tool Search had not loaded yet (arguments that were not a JSON object, or a list of tool calls that was empty or in the wrong format), Open WebUI handled it like an unfinished model response and the rest of the reply ran without any tools. Now the model gets a tool error back, like it does for an unknown tool name, and can retry with its tools. Only a model response that really was cut off still ends tool use.
    
    Fixes #33871
  • fix: client IP header placeholders send 127.0.0.1 for automations, timers and sub-agents (#33891)
    When a connection's custom headers use {{USER_IP}} or {{X_FORWARDED_FOR}}, automation runs, timers, sub-agent runs and the model list fetch at startup filled them with 127.0.0.1. A provider that logs or rate-limits per client address then saw these requests as coming from the Open WebUI host. No client sends these requests, so the header is now sent with an empty value for them. Normal chats still send the real client address.
    
    Fixes #33882
  • refac: limit size of version history diffs (#33865)
    Diffing two versions of a skill, tool, function or prompt now refuses inputs above 5000 lines per version. All four history diff views share the same check.
  • feat: client IP placeholders for connection custom headers (#33833)
    Connection custom headers had no way to tell the upstream provider which client a request came from. Adding {{USER_IP}} and {{X_FORWARDED_FOR}} fills in the client address Open WebUI resolves for the request, for example {"X-Real-IP": "{{USER_IP}}"}. Both are empty when there is no client request, such as automations and background jobs. Headers that don't use them are unaffected.
    
    Fixes #33819
  • fix: require a groups claim on token exchange when group management is on (#33846)
    Token exchange now refuses the sign-in with a 403 when group management is on, the user is in at least one group and no groups claim can be read from the provider response or the token, the same way the roles check on that path already does.
  • fix: new chats with a personal terminal reply only "Working directory is unavailable" (#33814)
    A personal terminal, one a user adds in their own Settings > Integrations, is reached by their browser and never by the server. New chats with one got only the error "Working directory is unavailable. Check the terminal connection and path." as their reply, because the server tried to set that terminal's working directory to the folder open in the Files panel itself. The server now does this only for terminals it connects to itself, such as those an admin set up, and the browser keeps setting it for personal terminals as before. Chats with an admin-connected terminal still start in that folder and still show the error when the folder does not exist.
    
    Fixes #33811
  • fix: files and knowledge bases sent through the API reach the model again (#33815)
    API clients that attach a file or knowledge collection in the files field of a chat completion got an answer to the bare question. File Context now defaults to off unless function calling is set to legacy, and API requests that do not come from a chat in the web UI get no tools to open the files either. File Context now defaults to on for those requests, so the file content is used in the answer as before. Chats in the web UI keep letting the model open the files itself.
    
    Fixes #33808
  • fix: MCP OAuth login is lost when the provider has a temporary outage during token refresh (#33805)
    When an MCP tool server uses OAuth and the provider's token endpoint answers with a temporary error (rate limit or 5xx) or cannot be reached while refreshing, the stored session was deleted and the user had to log in again. For providers that rotate refresh tokens that session is the only copy, so one provider blip lost the connection for good. Now these temporary failures leave the session in place and the next call retries, while a refresh the provider actually rejects still removes it.
    
    Fixes #33803
  • fix: skip the knowledge and skill lists when there is nothing to list (#33812)
    With native function calling, the model got a hidden list of the attached knowledge and of the user's skills before every new reply, even when no knowledge was attached and the user had no skills, so every chat spent tokens on two empty lists. A custom pipe function that reads the last message as the user's question got the empty knowledge list instead of the question. Each list is now left out when it is empty, as in 0.13.0.
    
    Fixes #33807