Access 300+ AI models through OpenRouter directly inside Open WebUI — with provider routing, reasoning tokens, streaming, fallbacks, and cache control out of the box.
Models from OpenAI, Anthropic, Google, Meta, Mistral, DeepSeek and more — each with its provider icon.
<think> blocks streamed in real time with configurable effort levels.
Sort, prefer, exclude and require parameters across providers per request.
- Features
- Requirements
- Installation
- Usage
- Configuration
- Architecture
- Development
- Contributing
- Troubleshooting
- FAQ
- License
- Manifold pipe — exposes all OpenRouter models as native Open WebUI models in the model selector.
- Provider routing — sort by
price,throughput, orlatency; prefer or exclude specific providers; enforcerequire_parameters. - Reasoning tokens —
<think>blocks streamed in real time with configurable effort (low,medium,high). - Streaming — full SSE streaming with mid-stream error handling and automatic
<think>closure on error. - Model fallbacks — automatic failover to one or more backup models via
FALLBACK_MODELS. - Middle-out compression — fits long prompts within context windows (
transforms: ["middle-out"]). - Cache control — Anthropic-style
cache_controlinjection on the longest message chunk. - Citations —
[n]references from web-search-enabled models are converted to markdown links. - Provider icons — 22 provider logos synced directly into Open WebUI's model database.
- Retry logic — exponential backoff with jitter on timeout and connection errors.
- FREE_ONLY mode — filter to show only free-tier models (
:freesuffix or0/0pricing). - Pre-flight validation — invalid API keys are caught at model-fetch time, not after sending a message.
- Open WebUI ≥ 0.4.0 running locally or in Docker.
- OpenRouter API key — free account, key starts with
sk-or-. - Python ≥ 3.10 (managed by Open WebUI; no separate install needed for the pipe).
Search for "OpenRouter Pipe" on openwebui.com and install it directly from the community hub — no copy-paste required.
- Copy the full content of
openrouter_pipe.py. - In Open WebUI, navigate to Admin Panel → Functions.
- Click + Add Function (or Import).
- Paste the code and save.
- Enable the function using the toggle.
- Click the ⚙️ Valves icon and enter your
OPENROUTER_API_KEY.
All OpenRouter models will appear in the model selector immediately.
Note: You can also set
OPENROUTER_API_KEYas a server environment variable instead of entering it in Valves.
git clone https://github.com/sena-labs/Open-WebUI-Pipe-OpenRouter.git
cd Open-WebUI-Pipe-OpenRouter
pip install -r requirements.txt
python test_pipe.py # 252 tests — verify everything is greenAll behavior is controlled through Valves in the Open WebUI admin panel. Every valve accepts an environment variable fallback (see Configuration).
| Goal | Valves to set |
|---|---|
| Show only OpenAI and Anthropic models | MODEL_PROVIDERS = openai,anthropic |
| Show only free models | FREE_ONLY = true |
| Use DeepSeek for reasoning | select deepseek/deepseek-r1, INCLUDE_REASONING = true |
| Route cheapest provider first | PROVIDER_SORT = price |
| Add a fallback model | FALLBACK_MODELS = anthropic/claude-3.5-sonnet |
When INCLUDE_REASONING is enabled (default), the pipe requests reasoning tokens from models that
support them. The internal reasoning appears inside <think>…</think> blocks before the main
response.
Set REASONING_EFFORT to low, medium, or high to control how much compute the model
allocates to reasoning. Leave it empty to let the model decide.
Models with web-search capabilities return citation annotations. The pipe automatically converts
[1], [2] references to [[1]](url) markdown links and appends a numbered Citations:
section at the end of the response.
Every valve accepts an environment variable fallback. The table below lists both.
| Valve | Env Var | Default | Description |
|---|---|---|---|
OPENROUTER_API_KEY |
OPENROUTER_API_KEY |
"" |
Your OpenRouter API key |
OPENROUTER_BASE_URL |
OPENROUTER_BASE_URL |
https://openrouter.ai/api/v1 |
API endpoint |
| Valve | Env Var | Default | Description |
|---|---|---|---|
INCLUDE_REASONING |
OPENROUTER_INCLUDE_REASONING |
true |
Request reasoning tokens (<think> blocks) |
REASONING_EFFORT |
OPENROUTER_REASONING_EFFORT |
"" |
Effort level: low, medium, high, or empty |
| Valve | Env Var | Default | Description |
|---|---|---|---|
MODEL_PREFIX |
— | None |
Custom prefix for model names (e.g. 🔥 ) |
MODEL_PROVIDERS |
OPENROUTER_MODEL_PROVIDERS |
ALL |
Provider filter (e.g. openai,anthropic). ALL means no filter |
INVERT_PROVIDER_LIST |
OPENROUTER_INVERT_PROVIDER_LIST |
false |
Treat MODEL_PROVIDERS as an exclusion list |
FREE_ONLY |
OPENROUTER_FREE_ONLY |
false |
Show only free-tier models |
| Valve | Env Var | Default | Description |
|---|---|---|---|
PROVIDER_SORT |
OPENROUTER_PROVIDER_SORT |
"" |
Sort: price, throughput, latency |
PROVIDER_ORDER |
OPENROUTER_PROVIDER_ORDER |
"" |
Preferred providers (comma-separated) |
PROVIDER_IGNORE |
OPENROUTER_PROVIDER_IGNORE |
"" |
Excluded providers (comma-separated) |
REQUIRE_PARAMETERS |
OPENROUTER_REQUIRE_PARAMETERS |
false |
Only use providers that support all request parameters |
DATA_COLLECTION |
OPENROUTER_DATA_COLLECTION |
allow |
Data policy: allow or deny |
| Valve | Env Var | Default | Description |
|---|---|---|---|
FALLBACK_MODELS |
OPENROUTER_FALLBACK_MODELS |
"" |
Fallback model IDs (comma-separated) |
ENABLE_MIDDLE_OUT |
OPENROUTER_ENABLE_MIDDLE_OUT |
false |
Middle-out compression for long prompts |
ENABLE_CACHE_CONTROL |
OPENROUTER_ENABLE_CACHE_CONTROL |
false |
Inject Anthropic cache_control on the longest message |
SYNC_PROVIDER_ICONS |
OPENROUTER_SYNC_ICONS |
true |
Sync provider icons into Open WebUI's model database |
| Valve | Env Var | Default | Description |
|---|---|---|---|
REQUEST_TIMEOUT |
OPENROUTER_REQUEST_TIMEOUT |
90 |
HTTP timeout in seconds |
MAX_RETRIES |
— | 2 |
Auto-retry count on transient errors |
The pipe implements the Manifold pattern: one pipe entry point that surfaces multiple models.
| Layer | Files | Responsibility |
|---|---|---|
| Entry points | Pipe.pipes(), Pipe.pipe() |
Model listing and chat routing |
| Payload | _prepare_payload() |
Sanitize OWUI internals, inject routing and reasoning |
| Transport | _retryable_request() |
Retry wrapper with exponential backoff |
| Streaming | _stream_response() |
SSE parser, <think> management, mid-stream errors |
| Non-streaming | _non_stream_response() |
JSON response, body-level error detection |
| Enrichment | _inject_cache_control(), _insert_citations() |
Post-processing |
Open-WebUI-Pipe-OpenRouter/
├── openrouter_pipe.py # Main pipe source — install this in Open WebUI
├── function.json # Open WebUI community manifest
├── test_pipe.py # Unit test suite (252 tests)
├── integration_test.py # Live API integration tests (47 tests)
├── TESTING.md # Manual pre-release checklist
├── SECURITY.md # Security policy
├── CONTRIBUTING.md # Contribution guidelines
├── CHANGELOG.md # Version history
├── LICENSE # MIT License
├── requirements.txt # Python dependencies
└── .github/
├── workflows/
│ └── tests.yml # CI pipeline (Python 3.10–3.13)
└── ISSUE_TEMPLATE/
├── bug_report.yml
└── feature_request.yml
The pipe strips these Open WebUI-internal keys before forwarding to OpenRouter:
_OWUI_INTERNAL_KEYS = {
"chat_id", "title", "task", "task_id", "features", "citations",
"metadata", "files", "tool_ids", "session_id", "message_id"
}It also removes user when sent as a dict (Open WebUI format) since OpenRouter expects a string.
python test_pipe.py # Unit tests (252 tests)
python integration_test.py # Live API tests (requires OPENROUTER_API_KEY)The unit test suite covers: valve defaults, payload preparation, streaming and non-streaming
responses, retry logic, citation injection, model listing, and pipe() routing.
Contributions are welcome. See CONTRIBUTING.md for the full playbook.
Set your API key in Admin Panel → Functions → OpenRouter Pipe → Valves (⚙️), or set the
OPENROUTER_API_KEY environment variable on the server and restart Open WebUI.
Your key is incorrect or malformed. Retrieve a valid key from
openrouter.ai/keys — it should start with sk-or-.
Wait a moment and retry. MAX_RETRIES only retries on network timeouts and connection failures —
HTTP 429 errors are returned immediately. Consider upgrading your OpenRouter plan for higher limits.
Add credits at openrouter.ai/credits.
Increase REQUEST_TIMEOUT in Valves (default: 90 seconds), or try a faster model. Some large
reasoning models can take over a minute for complex prompts.
- Verify your API key is valid (a single "error" model appears if it is not).
- If
MODEL_PROVIDERSis set, confirm the provider names are lowercase:openai,anthropic,google. - If
FREE_ONLYis enabled, some providers may have no free models — try disabling it. - Set
MODEL_PROVIDERS = ALLto show the full catalog.
Some models may be temporarily unavailable. Try a different model or check status.openrouter.ai.
Q: Does this work with Open WebUI's native tool calling?
A: Open WebUI manages tool calling in an iterative loop: when the pipe's response contains
tool calls, Open WebUI executes them, appends the results as role: "tool" messages, and
re-invokes the pipe with the updated thread. The pipe forwards the full message list to
OpenRouter on each invocation. Whether a model can generate tool calls depends on
OpenRouter's provider support for that model.
Q: Why does FREE_ONLY include models without a :free suffix?
A: Some models are listed as free on OpenRouter without carrying a :free suffix in their
ID. The pipe uses a two-pass check: first it looks for the :free suffix, then it falls
back to inspecting the pricing.prompt and pricing.completion fields returned by the
OpenRouter /models endpoint — if both are 0, the model is treated as free.
Q: Can I use multiple provider filters at once?
A: MODEL_PROVIDERS accepts a comma-separated list (e.g. openai,anthropic). Enable
INVERT_PROVIDER_LIST to turn it into an exclusion list instead.
Q: How do fallback models work?
A: FALLBACK_MODELS adds extra model IDs to the models array in the OpenRouter request. If the
primary model fails, OpenRouter automatically tries the next one. Non-streaming responses include
a "Responded by: model-id" attribution when a fallback handled the request.
This project is licensed under the MIT License — see the LICENSE file for details.