The installer
install.py installs, updates, repairs and health-checks the Pipe through Open WebUI's REST API, so it needs your Open WebUI admin email and password. If you'd rather not give a script those, use the manual install: same result.
Applies to: Pipe
Valves: GATEWAY_URL, GATEWAY_TOKEN, AGENT_ID, DEVICE_IDENTITY, STATE_DIR, OWUI_BASE_URL, OWUI_API_KEY, FILE_SERVER_BASE_URL, ENABLE_FILE_SERVER, USE_OWUI_FILES, SEND_STOP_ON_CANCEL
Prerequisites
- A running OpenClaw Gateway, reachable from the machine Open WebUI runs on.
- Admin credentials for your Open WebUI instance.
- Your OpenClaw Gateway API token. This is the value of
gateway.auth.tokenin your OpenClaw config; ask whoever runs your Gateway if you don't have it. uvon the machine running the installer (not inside Open WebUI). The installer needs Python 3.10 or newer, and only talks to Open WebUI: it never connects to the Gateway itself.
If you don't have uv, on the machine that will run the installer:
curl -LsSf https://astral.sh/uv/install.sh | shNo uv? In the repo checkout, this works identically; uv just removes the manual step:
pip install cryptography click rich
python3 install.py installA bare python3 install.py with no subcommand only prints help.
Run the installer
The wizard prompts for everything it needs and says where to find the Gateway token. In the repo checkout:
uv run install.py install --wizardA real run, the Pipe part:
──────────────────────────────────── Login ─────────────────────────────────────
✓ Logged into OWUI as Sam
─────────────────────────────────── Function ───────────────────────────────────
✓ Created pipe function
✓ Activated pipe function
✓ Made pipe function global
──────────────────────────────────── Valves ────────────────────────────────────
! Generated new device identity: 133c1b884175ef2906a0...
! This new identity must be approved once by OpenClaw.
✓ Updated valves: AGENT_ID, DEVICE_IDENTITY, ENABLE_FILE_SERVER,
GATEWAY_TOKEN, GATEWAY_URL, OWUI_BASE_URL, SEND_STOP_ON_CANCEL, STATE_DIR,
USE_OWUI_FILES
─────────────────────────────── Model discovery ────────────────────────────────
✓ Model openclaw_gateway.default and at least one dynamic model are visible
────────────────────────────────── Smoke test ──────────────────────────────────
✓ Smoke test passed
─────────────────────────────── Route smoke test ───────────────────────────────
✓ Route smoke test passed (anthropic/claude-haiku-5-5)uv run resolves cryptography, click and rich into an ephemeral environment, so there is no venv or pip install step. -w is short for --wizard.
The wizard asks for the Open WebUI base URL, admin email and password, the Gateway address (host:port), the Gateway token and the agent id. It only prompts for the email, password and token when they are not already set.
Run it without cloning
On any machine with uv:
uv run https://raw.githubusercontent.com/Eliav2/openclaw-openwebui-integration/main/install.py install --wizardIn that form there is no openclaw_pipe.py next to the script, so the installer downloads the artifact from this repo before deploying it. Point OPENCLAW_PIPE_ARTIFACT_URL at a fork, a pinned tag, or an internal mirror to change that. If the download fails, or returns something that is not the Pipe, the installer stops and tells you to run it from a clone.
The download only happens when there is no repo at all next to the script. A partial checkout with the artifact missing fails loudly instead of deploying main from the internet.
What the no-clone form can't do: skills (it needs the skills/ folder), install_action.py and install_filter.py (they import install.py). For those, use a clone.
Configuration
Only three values are required. Everything else has a working default.
| Required | Flag | |
|---|---|---|
OWUI_EMAIL | --owui-email | Open WebUI admin email |
OWUI_PASSWORD | --owui-password | Open WebUI admin password |
GATEWAY_TOKEN | --gateway-token | gateway.auth.token from your OpenClaw config |
| Optional | Flag | Default |
|---|---|---|
OWUI_URL | --owui-url | http://localhost:8080 |
GATEWAY_URL | --gateway-url | localhost:18789 |
AGENT_ID | --agent-id | main |
OPENCLAW_BRIDGE_STATE_DIR | --state-dir | /data/openclaw-bridge (a directory inside the Open WebUI container; sets the STATE_DIR valve) |
OWUI_API_BASE_URL | --owui-api-base-url | whatever OWUI_URL is. Set it only when the Pipe must reach Open WebUI's API at a different address than you do (sets the OWUI_BASE_URL valve) |
OWUI_API_KEY | --owui-api-key | empty. Only needed if the request bearer token can't be used for media uploads |
FILE_SERVER_BASE_URL | --file-server-base-url | empty. Only needed if you rely on the legacy media fallback |
Flags with no env var:
| Flag | Default | What it does |
|---|---|---|
--wizard, -w | off | Prompt interactively for any missing required values |
--auto-approve / --no-auto-approve | on | Approve a matching pending OpenClaw device when a smoke test reports "pairing required". Only works where the openclaw CLI is installed |
--live | off | Deploy even though E2E_ROOT is set. A shell with E2E_ROOT set belongs to a local E2E sandbox. There, install, repair and healthcheck refuse to run from the host's network namespace, where localhost is the host's real Open WebUI. Inside the sandbox's own namespace they run as usual. install_action.py and install_filter.py take the same flag |
Supply the values as env vars or as flags. uv run install.py install --help lists every flag. Skip the wizard once they are set, in the repo checkout:
export OWUI_EMAIL=admin@example.com
export OWUI_PASSWORD=your-password
export GATEWAY_TOKEN=your-gateway-token
uv run install.py installThat non-interactive form is what you want for CI, config management, or reinstalling after an Open WebUI upgrade.
Python packages inside Open WebUI
The Pipe and the Status Action need websockets and cryptography inside Open WebUI; pydantic already ships with it. Both functions declare the two packages in the requirements: frontmatter field, so Open WebUI pip-installs them itself the first time the function loads. The thinking filter needs neither: it imports only the standard library and pydantic.
If your deployment sets ENABLE_PIP_INSTALL_FRONTMATTER_REQUIREMENTS=false or runs with OFFLINE_MODE, install websockets and cryptography into the Open WebUI image yourself. Otherwise the function fails to load with ModuleNotFoundError: websockets.
Supported Open WebUI and OpenClaw versions: Versions.
What install does
- Log in to Open WebUI.
- Get the Pipe's code. In a clone it rebuilds
openclaw_pipe.pyfromsrc/first, so a stale artifact is never deployed; with no clone it downloads it (see above). - Check whether the Pipe function (
openclaw_gateway) already exists. - If it exists: back up the function and its valves to
backups/, then update the code in place. - If it's new: create the function.
- Make sure it is active and global, switching on only what is off. It never blindly toggles it off first.
- Set the valves. It restores any valve Open WebUI dropped during the update, and keeps every valve it does not manage (see Valves the installer sets).
- Pick the device identity (an Ed25519 key pair): the existing
DEVICE_IDENTITYvalve first, then./.pipe_device_identity.json, and only if neither exists, a new one. It is written to both. - Check that OpenClaw · Default and at least one discovered model are visible in Open WebUI's model list, and stop if not.
- Run an end-to-end smoke test through
/api/chat/completions: it asks the agent to reply with a fixed word. If the reply says pairing required and the localopenclawCLI is available, it approves the matching pending pairing request and tries again. - Run a route smoke test: it picks one discovered (non-default) model and asks the agent which model it is running on, to prove that picking a model in Open WebUI reaches the agent.
The command exits 0 only when both smoke tests pass. The smoke tests are two real messages to your agent, in throwaway chats.
Step 4 is why re-running this is safe: the function is never deleted and recreated, so DEVICE_IDENTITY survives and you never re-approve the device.
Valves the installer sets
Every run of install or repair writes these valves from your env vars, flags and defaults, even when you changed them in the admin panel since:
GATEWAY_URL,GATEWAY_TOKEN,AGENT_ID,STATE_DIR,OWUI_BASE_URLENABLE_FILE_SERVER,USE_OWUI_FILESandSEND_STOP_ON_CANCEL, all set toTrueOWUI_API_KEYandFILE_SERVER_BASE_URL, only when you pass them
So pass the same values on every run. A re-run without GATEWAY_URL sets it back to localhost:18789; one without --state-dir sets STATE_DIR back to /data/openclaw-bridge. If you turned ENABLE_FILE_SERVER off, turn it off again after an update.
DEVICE_IDENTITY and every other valve (DEFAULT_MODEL, MAX_MODELS, AUTO_TITLE and the rest) keep their current values. All valves: Configuration.
Commands
| Command | What it does |
|---|---|
install | Create or update the Pipe function and its valves, then smoke test |
repair | Same as install. Use after a broken or partial setup |
status | Print current state as JSON, change nothing. Exits 0 only when every field is good |
healthcheck | status plus both smoke tests |
skills | Install the agent-side skills. Run it on the Gateway host; it needs no Open WebUI credentials. --force overwrites an existing skill. See agent skills |
status reports function_exists, is_active, is_global, model_visible, has_gateway_url, has_gateway_token, has_device_identity, device_id and device_paired. device_paired asks the local openclaw CLI, so it is only ever true on the Gateway host. On any other machine status and healthcheck exit 1 even when everything works; read the smoke test lines instead.
The companion installers
install_action.pyinstalls the Status Action and mirrors the five shared valves from the Pipe: Status button.install_filter.pyinstalls the thinking filter: thinking control.
Both take only OWUI_URL, OWUI_EMAIL and OWUI_PASSWORD, have install, repair and status but no healthcheck, and must run from a clone.
After the install
- The Gateway holds a new device until you approve it: device pairing.
- Updating, rolling back and uninstalling: update and uninstall.