AI & LLM Tools

Open WebUI Pipelines: Setup, Types, and Migration Guide

J
James Eriksson
··14 min read
Learn how to set up, configure, and use Open WebUI Pipelines. This guide covers the 4 pipeline types, practical examples, security risks, and migration to Functions.
TL;DR
  • Open WebUI Pipelines are officially deprecated as of October 29, 2026; migrate to Functions for new projects.
  • Pipelines run on a separate server and support 4 types: Filters (message processing), Pipes (custom workflows), Tools (function calling), and Manifolds (multi-model routing).
  • Setup requires Docker or Python; connect via Admin Panel > Settings > Connections with the Pipelines URL.
  • Security risk: Pipelines execute arbitrary code, so only deploy trusted sources and isolate in containers with resource limits.
  • Troubleshooting: verify the server is running, check the Open WebUI connection URL, confirm pipeline files exist, and look for Python syntax errors in Docker logs.

Open WebUI Pipelines allow you to extend the platform with custom code: filters to process chat messages, pipes for multi-step workflows, and tools for function calling. As of October 2026, Pipelines are officially deprecated and archived. The Open WebUI team recommends migrating to Functions, which offer the same capabilities built directly into the platform without requiring a separate server.

Open WebUI Pipelines Are Deprecated: What You Need to Know

On October 29, 2026, the official Pipelines repository was archived. The README warns: "Do not use Pipelines, not for new setups and not for existing ones." This does not mean Pipelines stop working immediately. Existing deployments will continue to function. But the team is no longer accepting issues or pull requests, and all development has shifted to Functions within the core Open WebUI codebase.

If you have Pipelines running in production, you have two paths forward. First: keep your current setup operational and migrate gradually to Functions as your team develops capacity. Second: switch to Functions immediately if your use cases are straightforward. Functions are simpler to deploy, require no external server, and receive active maintenance.

Why the shift? Functions are faster to develop, easier to debug, and eliminate the operational overhead of running a separate Pipelines service. For teams that do not need the flexibility of arbitrary Python code, Functions cover 95% of real-world use cases. This guide walks you through understanding Pipelines if you inherit them, setting them up if you choose to, and planning your migration to Functions.

Pipelines vs. Functions vs. Tools: Which Should You Use?

Three extension mechanisms exist in Open WebUI, and the terminology confuses almost everyone new to the platform. Pipelines are the legacy system. Functions are the modern standard. Tools are a subset of both. Here is the distinction:

Pipelines run on a separate external server. You write Python code, package it in a Docker container or Git repository, and Open WebUI connects to it via HTTP. Pipelines intercept and modify chat flows: they can filter incoming messages, transform model outputs, call external APIs, or act as entirely custom models. Deprecated as of October 2026.

Functions run inside Open WebUI itself. You write Python code directly in the web interface and it executes in a sandboxed container alongside the chat engine. No external server required. No deployment complexity. Functions replaced Pipelines and are the recommended path for all new work. Actively maintained.

Tools are a subcategory within both Pipelines and Functions. A Tool is a Python function that the chat engine can call directly, similar to function calling in the OpenAI API. If you are building a calculator, a web scraper, or a database query function, you are building a Tool.

If you are starting a new project, use Functions. If you are maintaining Pipelines, plan a migration. If you are reading this to understand someone else's Open WebUI setup, Pipelines are the most likely culprit for that separate server you see running in the background.

Understanding the 4 Pipeline Types

Pipelines come in four flavors. Each solves a different problem. Understanding the type tells you what the Pipeline is doing in the chat flow.

Filter Pipelines intercept messages at two points: inlet (message comes in from the user) and outlet (response comes back from the model). You use Filters to sanitize user input, block toxic messages, remove PII before sending to the model, or clean up the model output before showing it to the user. Filters run synchronously: the chat waits for the filter to finish before proceeding. Example: remove profanity from user input, or strip API keys from model outputs.

Pipe Pipelines act as custom models or routing layers. When a user selects a Pipe, it replaces the normal model inference. Pipes are useful for building multi-step workflows: retrieve documents, rank results, feed them to a model, and return the response. Or: check user permissions, route to specialized models, or run a RAG pipeline. Pipes see the full conversation history and can make decisions based on the thread.

Tools Pipelines expose functions that the chat engine can call during conversation. If you configure a Tool, the model learns about it and can invoke it automatically. Example: a web search Tool that the model calls to answer current-events questions, or a database query Tool for looking up customer records. Tools are function-calling aware: you define the function signature and the model figures out when to call it.

Manifold Pipelines are multi-model providers. A Manifold acts as a proxy that presents multiple models as one interface, or routes requests across multiple providers. Example: try the first model, fall back to a second if it errors, or load-balance across instances. Manifolds are the rarest type in practice and require deeper integration.

Most production Pipelines are either Filters (for safety/compliance) or Pipes (for complex workflows).

Setting Up the Pipelines Server

Deploying Pipelines means running a separate Python service. You have two installation paths: Docker (fastest, no Python setup required) or Git plus Python (for development and customization).

Docker Installation

The fastest way to start is Docker. Pull the official image, map a port, and point Open WebUI to it. To access example pipelines, clone the repository at https://github.com/open-webui/pipelines.git to your development machine. The repository is archived (as of October 2026) so you cannot push changes, but you can clone it to run the examples.

Start the Pipelines server with Docker, mapping port 9099 and mounting your examples directory:

docker run -d -p 9099:9099 -v "$(pwd)/examples:/app/examples" ghcr.io/open-webui/pipelines:main

This maps the examples directory into the container. The Pipelines service listens on port 9099. Verify it is running by testing the API endpoint with curl. Make a request to your Pipelines service and you should see a JSON response listing available pipelines (empty at first).

Git and Python Installation (Development)

If you want to write custom pipelines, clone the repository and set up the Python environment. After cloning from the GitHub repository, create a virtual environment:

python3 -m venv venv
source venv/bin/activate

On Windows, use venv\\Scripts\\activate instead.

pip install -r requirements.txt
python3 main.py

The service starts on port 9099. Any Python files in the pipelines/ directory are automatically discovered and loaded.

Connecting to Open WebUI

Once Pipelines is running, connect it to Open WebUI via the admin panel. In Open WebUI, go to Admin Panel > Settings > Connections. Add the Pipelines URL pointing to your service on port 9099 (by default, localhost:9099 for local development). If Pipelines is on a remote server, provide the full hostname or IP address and port.

Open WebUI makes an HTTP request to that endpoint to fetch the pipeline list. If the connection succeeds, you see green and the pipelines appear in the chat interface. If you see red or no pipelines appear, check Docker logs:

docker logs <container_id>

A Practical Filter Pipeline Example: Message Sanitization

Here is a real Filter that blocks profanity and removes emails from user input before the model sees them:

from typing import Optional
from pydantic import BaseModel

class Valves(BaseModel):
    priority: int = 0
    blocked_words: list = ["word1", "word2"]
    remove_emails: bool = True

class Pipeline:
    def __init__(self):
        self.valves = Valves()

    async def inlet(self, body: dict, __user__: dict) -> dict:
        """Runs before the message reaches the model."""
        if "messages" in body:
            last_message = body["messages"][-1]
            text = last_message.get("content", "")
            
            # Block profanity
            for word in self.valves.blocked_words:
                text = text.replace(word, "[REDACTED]")
            
            # Remove emails
            if self.valves.remove_emails:
                import re
                text = re.sub(r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}", "[EMAIL]", text)
            
            last_message["content"] = text
        
        return body

    async def outlet(self, body: dict, __user__: dict) -> dict:
        """Runs after the model responds, before the user sees it."""
        # Remove any API keys or sensitive data from the response
        return body

Valves are configuration parameters you set in the Open WebUI interface without redeploying the pipeline. In this example, a team admin can add blocked words or toggle email removal via the UI. The Pipeline class has two methods: inlet (message in) and outlet (message out). Both are async and must return the modified body.

When you deploy this Filter and select it in a chat, every user message is sanitized before reaching the model. This is useful for compliance (removing PII), safety (blocking known harmful inputs), or cost control (stripping prompts that would confuse the model).

A Practical Pipe Pipeline Example: Custom RAG Workflow

A Pipe is more complex: it replaces the entire model call. Here is a Pipe that retrieves documents, ranks them, and feeds them to the model as context. This pattern demonstrates how to build RAG (Retrieval-Augmented Generation) systems where relevant documents are pulled in before the model generates a response:

from typing import Optional
import httpx

class Pipeline:
    def __init__(self):
        pass

    async def pipe(self, body: dict, __user__: dict) -> dict:
        """Custom model replacement."""
        
        # Extract the user query
        messages = body.get("messages", [])
        user_query = messages[-1]["content"] if messages else ""
        
        # Connect to your vector database service
        vector_db_endpoint = "your-vector-db-service-endpoint"
        
        async with httpx.AsyncClient() as client:
            response = await client.post(
                f"{vector_db_endpoint}/search",
                json={"query": user_query, "top_k": 5}
            )
            docs = response.json()["results"]
        
        # Rank and format context
        context = "\\n".join([d["text"] for d in docs[:3]])
        
        # Inject context into the prompt
        system_prompt = f"You are a helpful assistant. Use this context:\\n{context}\\n\\n"
        
        # Call the selected model with augmented prompt
        model = body.get("model")
        
        return {
            "status": 200,
            "body": {
                "choices": [{"message": {"content": "RAG response here"}}]
            }
        }

A Pipe sees the incoming request body, which includes the model name, messages, temperature, and other parameters. The Pipe can decide to call a different model, augment the prompt, retrieve external data, or handle the entire request itself. In this example, the vector_db_endpoint would point to services like Weaviate, Milvus, or Pinecone running on your network. The code retrieves relevant documents, formats them as context, and injects them into the prompt before the model generates a response.

Security: Why Arbitrary Code Execution Matters

Pipelines run Python code on your server. That code can read files, make network requests, delete data, or consume resources. If you load a Pipeline from an untrusted source, you are running arbitrary code on your infrastructure.

This is not a bug; it is by design. Pipelines are powerful precisely because they allow arbitrary computation. But it comes with responsibility. Here is how to manage the risk:

Vet the source. Only run Pipelines from creators you trust. Read the code before deploying. Look for file system access, network calls to unknown endpoints, or loops that could hang the system.

Run in isolation. Deploy the Pipelines server in its own container with limited permissions. Do not run it as root. Restrict network access: Pipelines should only reach the databases and APIs it explicitly needs. Use a firewall to block outbound traffic except to whitelisted endpoints.

Limit resource consumption. Set memory and CPU limits on the Pipelines container. A runaway loop should not crash the host. Use Docker with resource flags:

docker run -d -p 9099:9099 --memory="1g" --cpus="2" ghcr.io/open-webui/pipelines:main

Monitor and log. Watch for Pipelines that consume excessive resources, make unexpected network requests, or error frequently. Logs are your first clue that a Pipeline is misbehaving. Enable audit logging in Open WebUI to track which Pipelines were invoked and by whom.

Consider Functions instead. If the code comes from external sources, consider Functions instead of Pipelines. Functions run in a more controlled environment and are easier to audit because the code is visible in the Open WebUI interface, not hidden in a Docker image.

Troubleshooting: Why Pipelines Aren't Showing Up

"Pipelines not detected" is the most common issue. Here is the diagnostic flow.

Step 1: Verify Pipelines server is running. Test the service endpoint to confirm it responds. You should see a JSON response, even if it is an empty list. If you get connection refused, the server is not running. Check Docker logs:

docker ps

Is the container running? Check the output:

docker logs <container_id>

Step 2: Check the Open WebUI connection. In Admin Panel > Settings > Connections, verify the Pipelines URL is correct. If you see a red error icon, Open WebUI cannot reach Pipelines. Common causes: wrong hostname, port mismatch, or firewall blocking. If Pipelines runs on another machine, use the full hostname or IP address and port instead of localhost.

Step 3: Check pipeline files exist. If the connection is green but no pipelines appear, the pipelines/ directory is empty or contains syntax errors. SSH into the Pipelines container or check the mounted volume:

docker exec <container_id> ls -la /app/pipelines/

If the directory is empty, mount the examples directory:

docker run -d -p 9099:9099 -v "$(pwd)/examples:/app/pipelines" ghcr.io/open-webui/pipelines:main

Step 4: Check Python syntax. A Pipeline with a syntax error fails silently. Pipelines does not validate Python at startup. It loads pipelines when they are first requested. Check Docker logs for import errors:

docker logs <container_id> | grep -i error

Step 5: Check imports and dependencies. If a Pipeline imports a library that is not installed, it fails when you try to use it. Add dependencies to a requirements.txt in the Pipeline's directory or install them in the Docker image at build time. The standard image includes httpx, requests, pydantic, and a few others. If you need additional packages, build a custom image or mount a requirements.txt and pip install inside the container.

Frequently Asked Questions

Open WebUI Pipelines not detected: why?

The Pipelines server is not reachable by Open WebUI, or the server is running but the pipelines directory is empty. Test the URL in Admin Panel > Connections and check Docker logs for errors. Verify the pipelines/ directory contains Python files with no syntax errors.

Are Open WebUI Pipelines the same as plugins?

No. Plugins extend the Open WebUI interface itself (adding buttons, modifying the UI). Pipelines extend the chat logic and data flow. If you are building custom models or filters, use Pipelines (now deprecated) or Functions (modern). If you are building UI extensions, use Plugins.

What is the difference between a Pipe and a Filter pipeline?

A Filter runs at the inlet (before the model) or outlet (after the model) and does not replace the model. A Pipe replaces the entire model call and returns the response itself. Use Filters for message processing. Use Pipes for custom workflows or RAG pipelines.

Can I use LangChain in a Pipeline?

Yes. LangChain can be installed as a dependency and imported in your Pipeline code. However, Pipelines are deprecated, so new LangChain integrations should use Functions instead. If you need LangChain, migrate to Functions soon.

Why are Pipelines deprecated if they are so powerful?

Functions offer most of the power with less operational overhead. Running a separate Pipelines server requires Docker, networking, resource management, and monitoring. Functions run inside Open WebUI, eliminating that complexity. For teams that do not need arbitrary code execution on a separate service, Functions are simpler and more maintainable.

How do I migrate from Pipelines to Functions?

Move your Python code from the Pipeline class into a Function. Inlets become pre-processing logic; outlets become post-processing logic; Pipes become the main function body. Functions have a slightly different API, but the core logic translates directly. Test each function in the Open WebUI interface before removing the Pipelines server.

Do Functions have the same arbitrary code execution risk as Pipelines?

Functions run in a sandboxed container and cannot access the host file system or perform unconstrained network calls. This is safer than Pipelines, which run with the permissions of the Docker container. Functions are the recommended choice if you are concerned about security.

The Bottom Line

Open WebUI Pipelines are deprecated as of October 2026. If you are setting up Open WebUI today, use Functions instead. If you maintain Pipelines, they continue to work, but plan a migration to Functions when your team has capacity.

Pipelines are powerful because they allow you to extend Open WebUI with arbitrary Python code: filters for safety and compliance, pipes for complex workflows, tools for function calling. Setting them up requires Docker, a separate server, and monitoring. The 4 pipeline types solve different problems: Filters process messages, Pipes replace the model call, Tools enable function calling, and Manifolds multiplex across models.

Security is the main tradeoff. Pipelines can run malicious code if you load untrusted sources. Isolate them in containers, vet the source code, and monitor resource consumption.

For teams that want the extensibility of Pipelines without the operational burden, Opsily's managed Open WebUI service handles infrastructure and scaling. You focus on your custom logic, not server management. Start at https://console.opsily.com or explore our hosting options at /hosting/open-webui/hosted-open-webui.

Skip the complexity. Use managed Open WebUI.
Opsily hosts Open WebUI with automatic scaling, backups, and security—no pipeline server to manage.
Get Started Free

Ready to self-host your own apps?

One server. Multiple apps. No per-app fees.

Get started →