openwebui/functions/computer_link_filter.py) is the only integration point between Open WebUI and the Computer Use Server. Two jobs:
inlet()— when theai_computer_usetool is active, fetch the server-baked system prompt over HTTP and inject it into the conversation.outlet()— decorate assistant messages that contain sandbox file URLs with a markdown preview link and an archive-download link. On patched Open WebUI builds the preview link auto-promotes to an inline artifact. On stock builds it stays a clickable link — either way the user reaches the preview without a rebuild.
Installation
- Open WebUI → Admin Panel → Functions → New Function.
- Paste the entire contents of
openwebui/functions/computer_link_filter.py. - Save; toggle the function Active and Global for every model.
- Override any Valve if needed — defaults work end-to-end as long as the Computer Use Server is reachable at
http://localhost:8081(or yourORCHESTRATOR_URL).
Valves reference
Two URL roles
v4.0.0 removed the old “twoFILE_SERVER_URL” footgun. There is now one public URL owned by the server (PUBLIC_BASE_URL), delivered to the filter via the X-Public-Base-URL response header on /system-prompt. The filter has no public-URL Valve.
See Open WebUI integration for the full embedding checklist.
How the preview gets rendered
outlet() appends a markdown link [🖥️ Open preview]({PUBLIC_BASE_URL}/preview/{chat_id}) to every assistant message that references a sandbox file.
- Stock Open WebUI: link stays a link. User clicks it → preview opens in a new tab.
- Patched Open WebUI (our
docker-compose.webui.ymlbuild):fix_preview_url_detectionsees/preview/{chat_id}in the message text and pushes a synthetic<iframe>intohtmlGroups.fix_artifacts_auto_showthen auto-opens the side panel. No click.
v4.1.0 breaking change. Earlier versions embedded a raw fenced
<iframe> block in messages. That was a foot-gun (the patch’s !htmlGroups.some(o=>o.html) guard skipped detection when the block was present). v4.1.0 uses only the markdown link + the patch. PREVIEW_MODE="artifact" and "both" were removed — re-seed Valves after upgrading.System prompt injection
INJECT_SYSTEM_PROMPT=True (default): when the ai_computer_use tool is active and chat_id is present, the filter HTTP-fetches {ORCHESTRATOR_URL}/system-prompt and injects it into the system message. 5-minute LRU cache, stale-cache fallback on transport failure. The X-Public-Base-URL response header is cached alongside the prompt so outlet() can build browser-facing links without its own Valve.
Non-http(s) schemes on ORCHESTRATOR_URL are rejected to block file:// / ftp:// information-disclosure paths.
Archive button
ARCHIVE_BUTTON="on" (default): when an assistant message contains at least one URL matching {PUBLIC_BASE_URL}/files/{chat_id}/..., outlet() appends a markdown link to /files/{chat_id}/archive. The endpoint streams a zip of every file the sandbox has written for the chat. The append is idempotent — safe to re-run outlet() on the same body.
Troubleshooting
Preview shows “connection refused” or a blank framePUBLIC_BASE_URLmust be reachable from the user’s browser. No Valve for this — flows from server env.docker compose ps— iscomputer-use-serverhealthy?curlthe iframe’ssrc=directly — SPA HTML should come back as HTTP 200.
- The assistant message must contain at least one URL matching
{PUBLIC_BASE_URL}/files/{chat_id}/...(or a<details type="tool_calls">block referencing a browser tool). No trigger, no decoration. chat_idmust reachoutlet()via__metadata__. Restart Open WebUI after toggling Valves if the model didn’t re-init.PREVIEW_MODE="button"ORARCHIVE_BUTTON="on". Bothoff=outlet()returns body unchanged.
docker-compose.webui.yml), or live with the click.
“Non-http scheme” error in logs
ORCHESTRATOR_URL is set to file:// / ftp://. Fix by pointing at http:// or https://.
See also
- System prompt reference — six MCP-native tiers
- Open WebUI integration — embedding checklist
