[GH-ISSUE #24852] Filter outlet replace/status events do not update first assistant message with Native tools + streaming #123722

Open
opened 2026-05-21 03:11:42 -05:00 by GiteaMirror · 3 comments
Owner

Originally created by @gerpervaz on GitHub (May 17, 2026).
Original GitHub issue: https://github.com/open-webui/open-webui/issues/24852

Check Existing Issues

  • I have searched for any existing and/or related issues.
  • I have searched for any existing and/or related discussions.
  • I have also searched in the CLOSED issues AND CLOSED discussions and found no related items (your issue might already be addressed on the development branch!).
  • I am using the latest version of Open WebUI.

Installation Method

Docker

Open WebUI Version

latest main/stable as of 2026-05-17

Ollama Version (if applicable)

N/A - using vLLM OpenAI-compatible backend

Operating System

Ubuntu Linux with Open WebUI running in Docker

Browser (if applicable)

Chromium and Chrome

Confirmation

  • I have read and followed all instructions in README.md.
  • I am using the latest version of both Open WebUI and Ollama.
  • I have included the browser console logs.
  • I have included the Docker container logs.
  • I have provided every relevant configuration, setting, and environment variable used in my setup.
  • I have clearly listed every relevant configuration, custom setting, environment variable, and command-line option that influences my setup (such as Docker Compose overrides, .env values, browser settings, authentication configurations, etc).
  • I have documented step-by-step reproduction instructions that are precise, sequential, and leave nothing to interpretation. My steps:
  • Start with the initial platform/version/OS and dependencies used,
  • Specify exact install/launch/configure commands,
  • List URLs visited, user input (incl. example values/emails/passwords if needed),
  • Describe all options and toggles enabled or changed,
  • Include any files or environmental changes,
  • Identify the expected and actual result at each stage,
  • Ensure any reasonably skilled user can follow and hit the same issue.

Expected Behavior

When a Filter modifies the assistant message in outlet, or emits frontend events such as replace, status, notification, or execute, the currently visible assistant message should update immediately, including on the first assistant response of a new chat.

This is especially important for safety/validation filters that block invalid tool or code-interpreter results. The user should not keep seeing a streamed answer that the filter has already invalidated.

Actual Behavior

On the first assistant response of a new chat, the Filter runs and the message content is replaced in the persisted chat state, but the visible UI keeps showing the original streamed assistant response.

The replacement becomes visible after leaving and re-entering the chat. It also works correctly when pressing Regenerate, and in subsequent conversation turns.

Events emitted from outlet such as replace, status, notification, and execute do not appear to update the first rendered assistant message. The same filter behavior is visible on regenerate / later turns.

Steps to Reproduce

  1. Run Open WebUI from Docker using the latest available version.
  2. Configure an OpenAI-compatible backend, e.g. vLLM, with a model that supports Native / Agentic tool calling.
  3. Enable streaming.
  4. Enable Native / Agentic Code Interpreter or any Native tool path that produces tool/function_call_output messages.
  5. Create a Filter whose outlet replaces the final assistant message when a tool/code execution result is invalid. The filter also emits replace, status, and notification events.
  6. Start a brand-new chat.
  7. Send a prompt that triggers tool/code execution and intentionally fails, for example a Code Interpreter request that runs: print(broken_variable_123)
  8. Observe that the filter replaces the persisted assistant content with a failure notice, but the first visible assistant message in the UI still shows the original streamed model response.
  9. Leave and re-enter the chat, or press Regenerate.
  10. Observe that the replacement/failure notice is now visible and frontend notifications/status can appear.

Minimal filter logic:

async def outlet(self, body, __event_emitter__=None, __user__=None):
    messages = body.get("messages", [])
    assistant = next((m for m in reversed(messages) if m.get("role") == "assistant"), None)
    if assistant:
        replacement = "FILTER_REPLACED: final assistant response was blocked"
        assistant["content"] = replacement
        if __event_emitter__:
            await __event_emitter__({"type": "replace", "data": {"content": replacement}})
            await __event_emitter__({"type": "status", "data": {"description": replacement, "done": True, "hidden": False}})
            await __event_emitter__({"type": "notification", "data": {"type": "warning", "content": replacement}})
    return body

The same issue is reproducible with a more realistic filter that only blocks failed execute_code / code_interpreter results.

Logs & Screenshots

Observed structured assistant output includes Native function calls and function_call_output messages. In the failing case, Open WebUI receives a tool/code result with stderr, e.g. NameError or SyntaxError, and the filter replaces the final assistant message.

The persisted chat content is changed correctly. After reload / leaving and re-entering the chat, the replacement is visible.

Browser console showed no actionable client-side error related to this issue during the reproduction. Docker/container logs do not show a backend crash; the issue appears to be frontend state/render lifecycle behavior for the first streamed assistant message.

Screenshots available for attachment:

  1. Screenshot first response.png — first assistant response keeps showing the original streamed response despite failed execution / guard replacement.
  2. Screenshot succeded response after regeneration.png — after regeneration, the guard replacement and notification are visible.

I attempted to attach these screenshots through the GitHub issue form. If they are not visible as attachments below, I can attach them manually after submitting or in a follow-up comment.

Image Image

Additional Information

This appears specific to the first assistant message lifecycle under Native tool calling + streaming. The same Filter behavior works on Regenerate and later turns.

This may be related to streamed chat completion snapshots overwriting frontend events emitted from outlet, or to the first assistant message component not yet being subscribed to outlet-emitted events.

Relevant backend/model configuration:

  • Backend: vLLM OpenAI-compatible API
  • Model: Qwen/Qwen3.6-35B-A3B-FP8
  • Tool mode in Open WebUI: Native / Agentic function calling
  • Streaming: enabled
  • vLLM flags include:
    • --enable-auto-tool-choice
    • --tool-call-parser qwen3_coder
    • --reasoning-parser qwen3

The issue does not appear to be that tool calling fails. Native tool calls and function_call_output messages are produced correctly. The issue is that a Filter outlet replacement/event emitted after the first streamed assistant message is not reflected in the visible UI until reload/regenerate/subsequent turns.

Use case: a safety filter validates Code Interpreter / execute_code results. If execution fails or returns no verifiable stdout/result, the filter replaces the final answer to prevent the model from presenting fabricated results. When the first visible streamed answer is not updated, users may trust an invalid response until they reload the chat.

Originally created by @gerpervaz on GitHub (May 17, 2026). Original GitHub issue: https://github.com/open-webui/open-webui/issues/24852 ### Check Existing Issues - [x] I have searched for any existing and/or related issues. - [x] I have searched for any existing and/or related discussions. - [x] I have also searched in the CLOSED issues AND CLOSED discussions and found no related items (your issue might already be addressed on the development branch!). - [x] I am using the latest version of Open WebUI. ### Installation Method Docker ### Open WebUI Version latest main/stable as of 2026-05-17 ### Ollama Version (if applicable) N/A - using vLLM OpenAI-compatible backend ### Operating System Ubuntu Linux with Open WebUI running in Docker ### Browser (if applicable) Chromium and Chrome ### Confirmation - [x] I have read and followed all instructions in `README.md`. - [x] I am using the latest version of **both** Open WebUI and Ollama. - [x] I have included the browser console logs. - [x] I have included the Docker container logs. - [x] I have **provided every relevant configuration, setting, and environment variable used in my setup.** - [x] I have clearly **listed every relevant configuration, custom setting, environment variable, and command-line option that influences my setup** (such as Docker Compose overrides, .env values, browser settings, authentication configurations, etc). - [x] I have documented **step-by-step reproduction instructions that are precise, sequential, and leave nothing to interpretation**. My steps: - Start with the initial platform/version/OS and dependencies used, - Specify exact install/launch/configure commands, - List URLs visited, user input (incl. example values/emails/passwords if needed), - Describe all options and toggles enabled or changed, - Include any files or environmental changes, - Identify the expected and actual result at each stage, - Ensure any reasonably skilled user can follow and hit the same issue. ### Expected Behavior When a Filter modifies the assistant message in outlet, or emits frontend events such as replace, status, notification, or execute, the currently visible assistant message should update immediately, including on the first assistant response of a new chat. This is especially important for safety/validation filters that block invalid tool or code-interpreter results. The user should not keep seeing a streamed answer that the filter has already invalidated. ### Actual Behavior On the first assistant response of a new chat, the Filter runs and the message content is replaced in the persisted chat state, but the visible UI keeps showing the original streamed assistant response. The replacement becomes visible after leaving and re-entering the chat. It also works correctly when pressing Regenerate, and in subsequent conversation turns. Events emitted from outlet such as replace, status, notification, and execute do not appear to update the first rendered assistant message. The same filter behavior is visible on regenerate / later turns. ### Steps to Reproduce 1. Run Open WebUI from Docker using the latest available version. 2. Configure an OpenAI-compatible backend, e.g. vLLM, with a model that supports Native / Agentic tool calling. 3. Enable streaming. 4. Enable Native / Agentic Code Interpreter or any Native tool path that produces tool/function_call_output messages. 5. Create a Filter whose outlet replaces the final assistant message when a tool/code execution result is invalid. The filter also emits replace, status, and notification events. 6. Start a brand-new chat. 7. Send a prompt that triggers tool/code execution and intentionally fails, for example a Code Interpreter request that runs: print(broken_variable_123) 8. Observe that the filter replaces the persisted assistant content with a failure notice, but the first visible assistant message in the UI still shows the original streamed model response. 9. Leave and re-enter the chat, or press Regenerate. 10. Observe that the replacement/failure notice is now visible and frontend notifications/status can appear. Minimal filter logic: ```python async def outlet(self, body, __event_emitter__=None, __user__=None): messages = body.get("messages", []) assistant = next((m for m in reversed(messages) if m.get("role") == "assistant"), None) if assistant: replacement = "FILTER_REPLACED: final assistant response was blocked" assistant["content"] = replacement if __event_emitter__: await __event_emitter__({"type": "replace", "data": {"content": replacement}}) await __event_emitter__({"type": "status", "data": {"description": replacement, "done": True, "hidden": False}}) await __event_emitter__({"type": "notification", "data": {"type": "warning", "content": replacement}}) return body ``` The same issue is reproducible with a more realistic filter that only blocks failed execute_code / code_interpreter results. ### Logs & Screenshots Observed structured assistant output includes Native function calls and function_call_output messages. In the failing case, Open WebUI receives a tool/code result with stderr, e.g. NameError or SyntaxError, and the filter replaces the final assistant message. The persisted chat content is changed correctly. After reload / leaving and re-entering the chat, the replacement is visible. Browser console showed no actionable client-side error related to this issue during the reproduction. Docker/container logs do not show a backend crash; the issue appears to be frontend state/render lifecycle behavior for the first streamed assistant message. Screenshots available for attachment: 1. `Screenshot first response.png` — first assistant response keeps showing the original streamed response despite failed execution / guard replacement. 2. `Screenshot succeded response after regeneration.png` — after regeneration, the guard replacement and notification are visible. I attempted to attach these screenshots through the GitHub issue form. If they are not visible as attachments below, I can attach them manually after submitting or in a follow-up comment. <img width="1375" height="937" alt="Image" src="https://github.com/user-attachments/assets/97e88486-a76c-4725-bad1-3c29414ac149" /> <img width="1540" height="768" alt="Image" src="https://github.com/user-attachments/assets/4a4ea4fa-4ecc-4c4a-9c67-c2d6f2fb84a9" /> ### Additional Information This appears specific to the first assistant message lifecycle under Native tool calling + streaming. The same Filter behavior works on Regenerate and later turns. This may be related to streamed chat completion snapshots overwriting frontend events emitted from outlet, or to the first assistant message component not yet being subscribed to outlet-emitted events. Relevant backend/model configuration: - Backend: vLLM OpenAI-compatible API - Model: Qwen/Qwen3.6-35B-A3B-FP8 - Tool mode in Open WebUI: Native / Agentic function calling - Streaming: enabled - vLLM flags include: - `--enable-auto-tool-choice` - `--tool-call-parser qwen3_coder` - `--reasoning-parser qwen3` The issue does not appear to be that tool calling fails. Native tool calls and `function_call_output` messages are produced correctly. The issue is that a Filter `outlet` replacement/event emitted after the first streamed assistant message is not reflected in the visible UI until reload/regenerate/subsequent turns. Use case: a safety filter validates Code Interpreter / execute_code results. If execution fails or returns no verifiable stdout/result, the filter replaces the final answer to prevent the model from presenting fabricated results. When the first visible streamed answer is not updated, users may trust an invalid response until they reload the chat.
GiteaMirror added the bug label 2026-05-21 03:11:42 -05:00
Author
Owner

@owui-terminator[bot] commented on GitHub (May 17, 2026):

⚠️ Missing Issue Title Prefix

@gerpervaz, your issue title is missing a categorising prefix (e.g. bug:, feat:, docs:).

Please update the title to lead with one of:

  • bug: bug report or error
  • feat: feature request or enhancement
  • docs: documentation issue
  • question: usage question
  • help: support request

Example: bug: Login fails when the password contains special characters

<!-- gh-comment-id:4472639425 --> @owui-terminator[bot] commented on GitHub (May 17, 2026): # ⚠️ Missing Issue Title Prefix @gerpervaz, your issue title is missing a categorising prefix (e.g. `bug:`, `feat:`, `docs:`). Please update the title to lead with one of: - **bug**: bug report or error - **feat**: feature request or enhancement - **docs**: documentation issue - **question**: usage question - **help**: support request Example: `bug: Login fails when the password contains special characters`
Author
Owner

@owui-terminator[bot] commented on GitHub (May 17, 2026):

🔍 Related Issues Found

I found some existing issues that might be related. Please check if any of these are duplicates or contain helpful solutions:

  1. 🟢 #24714 issue: Filter outlet-modified assistant content is persisted in chat_message.content but lost from chat.chat history after reload
    This is the closest match: it reports that outlet-modified assistant content is persisted but not reflected consistently in the chat UI/history after reload. Your issue differs in that the problem shows up immediately on the first streamed assistant message, but both point to outlet changes not being properly reflected in the visible chat state.
    by etiennegnome · bug

  2. 🟣 #14221 issue: Streaming breaks (disables) with native tool calling
    This earlier native-tool-calling bug shows that streaming behaves incorrectly when native tools are enabled. While it is not about outlet events specifically, it is related to the same tool-calling + streaming path that your issue says triggers the stale first assistant render.
    by rvkwi · bug


💡 If your issue is a duplicate, please close it and add any additional details to the existing issue instead.

This comment was generated automatically. React with 👍 if helpful, 👎 if not.

<!-- gh-comment-id:4472639838 --> @owui-terminator[bot] commented on GitHub (May 17, 2026): <!-- terminator-bot:related-issues-reply --> 🔍 **Related Issues Found** I found some existing issues that might be related. Please check if any of these are duplicates or contain helpful solutions: 1. 🟢 [#24714](https://github.com/open-webui/open-webui/issues/24714) **issue: Filter outlet-modified assistant content is persisted in chat_message.content but lost from chat.chat history after reload** *This is the closest match: it reports that outlet-modified assistant content is persisted but not reflected consistently in the chat UI/history after reload. Your issue differs in that the problem shows up immediately on the first streamed assistant message, but both point to outlet changes not being properly reflected in the visible chat state.* *by etiennegnome · `bug`* 2. 🟣 [#14221](https://github.com/open-webui/open-webui/issues/14221) **issue: Streaming breaks (disables) with native tool calling** *This earlier native-tool-calling bug shows that streaming behaves incorrectly when native tools are enabled. While it is not about outlet events specifically, it is related to the same tool-calling + streaming path that your issue says triggers the stale first assistant render.* *by rvkwi · `bug`* --- 💡 If your issue is a duplicate, please close it and add any additional details to the existing issue instead. *This comment was generated automatically.* React with 👍 if helpful, 👎 if not.
Author
Owner

@gerpervaz commented on GitHub (May 21, 2026):

Thanks, I checked the related issues.

#24714 is very close and may share the same underlying synchronization problem between Filter outlet() changes and the chat state used by the UI/history.

The main difference is the timing and visible surface:

  • #24714: the outlet-modified content is visible immediately after generation, but is lost after navigating away/reloading the chat.
  • This issue: the outlet-modified content is persisted and becomes visible after leaving/re-entering, but the first streamed assistant message in a new chat does not update immediately. The user keeps seeing the stale streamed response that the Filter has already replaced/invalidated.

So I think this is not a pure duplicate unless maintainers want to track all Filter outlet synchronization issues in #24714. It may be the same family of bug, but this report specifically covers the first-message visible render path with Native tools + streaming.

#14221 seems more general and older: streaming behavior with native tool calling. It is related context, but it does not cover Filter outlet replacement/status events or the stale first assistant render.

<!-- gh-comment-id:4505806073 --> @gerpervaz commented on GitHub (May 21, 2026): Thanks, I checked the related issues. #24714 is very close and may share the same underlying synchronization problem between Filter `outlet()` changes and the chat state used by the UI/history. The main difference is the timing and visible surface: - #24714: the outlet-modified content is visible immediately after generation, but is lost after navigating away/reloading the chat. - This issue: the outlet-modified content is persisted and becomes visible after leaving/re-entering, but the first streamed assistant message in a new chat does not update immediately. The user keeps seeing the stale streamed response that the Filter has already replaced/invalidated. So I think this is not a pure duplicate unless maintainers want to track all Filter outlet synchronization issues in #24714. It may be the same family of bug, but this report specifically covers the first-message visible render path with Native tools + streaming. #14221 seems more general and older: streaming behavior with native tool calling. It is related context, but it does not cover Filter outlet replacement/status events or the stale first assistant render.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/open-webui#123722