mirror of
https://github.com/open-webui/open-webui.git
synced 2026-05-06 02:48:13 -05:00
[GH-ISSUE #22965] issue: Code interpreter prompt (Pyodide) injected into user turn instead of system prompt #58520
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @AirRunner on GitHub (Mar 24, 2026).
Original GitHub issue: https://github.com/open-webui/open-webui/issues/22965
Check Existing Issues
Installation Method
Pip Install
Open WebUI Version
v0.8.10
Ollama Version (if applicable)
No response
Operating System
macOS Tahoe 26.3.1
Browser (if applicable)
No response
Confirmation
README.md.Expected Behavior
The Pyodide environment instructions (
CODE_INTERPRETER_PYODIDE_PROMPT) should be injected into the system prompt, so the model treats them as execution context, not as something the user said.Actual Behavior
The Pyodide environment instructions are appended to the last user message via
add_or_update_user_message(). As a result, the model treats them as user-provided content.For any message, the context sent to the model looks like this:
This causes the model to:
/mnt/uploads/as if it were a real path on the user's machineSteps to Reproduce
pip install open-webuiopen-webui serve"Hello!"userrole message rather than thesystemrole messageLogs & Screenshots
Raw tokenized context captured from the model input (ChatML format):
Additional Information
Root cause
In
backend/open_webui/utils/middleware.py, the code interpreter prompt is injected usingadd_or_update_user_message():add_or_update_user_message()appendscontentto the last user message in the list (seeutils/misc.py), placing execution environment instructions inside theuserrole (where the model expects human input).Inconsistency with RAG
The RAG context injection in the same file already handles this correctly with a configurable toggle:
The code interpreter has no equivalent option and is hardcoded to the user turn.
Proposed fix
In
backend/open_webui/utils/middleware.py, replace theadd_or_update_user_messagecall with:This appends the Pyodide instructions to the existing system prompt without modifying the user message. Optionally, a
CODE_INTERPRETER_SYSTEM_CONTEXTenv var (mirroringRAG_SYSTEM_CONTEXT) could be added for flexibility.@BillionClaw commented on GitHub (Mar 24, 2026):
Investigating this prompt injection issue with Pyodide — submitting a fix.
@BillionClaw commented on GitHub (Mar 24, 2026):
Investigating this prompt injection issue with Pyodide — submitting a fix.
@tjbck commented on GitHub (Mar 24, 2026):
Intended.
@siffreinsg commented on GitHub (Mar 24, 2026):
Hi, could you provide more context on why this is intended please?
The current implementation appears hacky, and introduce problems such as models focusing on the Pyodide environment instead of the user query, especially on smaller models.
As far as I could understand from the code, there is no way to stop this behaviour. Would it be possible to provide an environment variable to toggle the prompt appending or change the Pyodide instructions?
@AirRunner commented on GitHub (Mar 24, 2026):
Hi @tjbck, thanks for looking at this. I just wanted to follow up on your response, because I'm genuinely confused about the intent here.
A few things I'm having trouble reconciling:
Inconsistency with RAG injection
The RAG context injection in the same file (
middleware.py) already has aRAG_SYSTEM_CONTEXTtoggle that switches betweenadd_or_update_system_messageandadd_or_update_user_message, precisely because the two placements have different semantics. The code interpreter has no equivalent and is hardcoded to the user turn. If there's a principled reason to keep it in the user turn, shouldn't RAG default to the same behavior?The injected content isn't user-authored
The Pyodide prompt describes the execution environment. It's platform context, not something the user said. Placing it in the
userrole means the model sees it as human input, which can cause models to fixate on it or treat it as a user request rather than a constraint.The proposed compromise preserves current behavior
I suggested a
CODE_INTERPRETER_SYSTEM_CONTEXTenv var (mirroringRAG_SYSTEM_CONTEXT), defaulting toFalseto keep the existing behavior intact. That way nothing changes for anyone who doesn't opt in.So anyway, I'm not asking to reopen the issue if the intent is clear, I just can't find the scenario where injecting execution environment instructions into the user turn is preferable. Could you share a bit more context on the reasoning?
Thanks!
@oryschakj-personal commented on GitHub (Mar 26, 2026):
For reference, this is the kind of thing you see in responses due to this issue:
"(Also, please stop pasting that Pyodide environment info. It's your system template and I've mentioned this before. I'll just ignore it going forward.)"
It's not being ignored, it's brought up consistently.
@arkham000 commented on GitHub (Mar 28, 2026):
I'm having the same problem, I'm on macos OS 26.3, I'm using oMLX 0.2.23 and openwebui 0.8.12, I'm using qwen3.5 35b and it seems to receive some Pyodide blocks, but it seems smart enough to ignore it because it stays focused on my the subject and it only adds :
"The block of text you see next ("Pyodide Environment...") is intrusive and appears to come from a code execution interface (perhaps a note or file you opened by mistake), it has nothing to do with Docker. We can ignore it completely."
@onscreen commented on GitHub (Apr 4, 2026):
Also having same issue with multiple models, occasionally the models will tell me I keep pasting details about the pyodide environment because of this, I too am confused why this is intended.
@AirRunner commented on GitHub (Apr 4, 2026):
Update
@siffreinsg @oryschakj-personal @arkham000 @onscreen
This has been addressed in
7c52382con the dev branch.The fix is conditional on native tool calling mode, which is actually the case where it matters most for cache invalidation (#23269) and arguably also for model behavior.
So in native FC,
CODE_INTERPRETER_PYODIDE_PROMPTis now injected into the system prompt.In hindsight, the intent from tjbck probably referred to non-native mode.
The fix will certainly land in a next release!
@Master-Pr0grammer commented on GitHub (Apr 8, 2026):
Very happy to see this being fixed.
Would it not make more sense to just simply put these arbitrary instructions in the tool instructions itself?
Inserting it into the system prompt would cause a worse hit on the prompt cache when the tool is enabled/disabled, causing full prompt reprocessing even though it is not necessary.
@MrCrin commented on GitHub (Apr 11, 2026):
I'm also having problems with this, particularly when I'm trying to debug things. The model gets confused and thinks the reference to the pyodide file is part of the context I'm providing around the problem. Glad to hear this is being fixed. Do we know which release it's likely to land in?