Skip to main content

Overview

Open WebUI provides several extensibility mechanisms to add custom functionality:
  1. Pipelines - Python-based middleware for LLM interactions
  2. Functions/Tools - Native Python functions with code editor
  3. MCP Servers - Model Context Protocol integration

Pipelines Plugin Framework

Pipelines allow you to inject custom logic and Python libraries into Open WebUI’s request/response flow.

What Are Pipelines?

Pipelines act as middleware between Open WebUI and LLM providers, enabling:
  • Rate limiting and usage controls
  • Request/response filtering and modification
  • Custom authentication and authorization
  • Integration with monitoring tools (Langfuse, etc.)
  • Translation services
  • Content moderation and toxic message filtering
  • Custom model routing logic

Repository

Pipelines are maintained in a separate repository: https://github.com/open-webui/pipelines

Getting Started with Pipelines

1. Clone the Pipelines Repository

git clone https://github.com/open-webui/pipelines.git
cd pipelines

2. Install Dependencies

pip install -r requirements.txt

3. Run Pipelines Server

python main.py
The server starts on http://localhost:9099 by default.

4. Connect to Open WebUI

In Open WebUI settings:
  1. Go to Admin SettingsConnections
  2. Set OpenAI API URL to: http://localhost:9099
  3. Pipelines will now intercept requests

Creating a Custom Pipeline

Pipelines are Python classes that inherit from base pipeline types.

Basic Pipeline Structure

from typing import List, Optional
from pydantic import BaseModel

class Pipeline:
    """
    Example pipeline that adds a prefix to all messages
    """
    
    class Valves(BaseModel):
        """Configuration that can be modified via UI"""
        prefix: str = "[Custom] "
        enabled: bool = True
    
    def __init__(self):
        self.name = "Message Prefix Pipeline"
        self.valves = self.Valves()
    
    async def on_startup(self):
        """Called when pipeline initializes"""
        print(f"Pipeline {self.name} started")
    
    async def on_shutdown(self):
        """Called when pipeline shuts down"""
        print(f"Pipeline {self.name} stopped")
    
    async def inlet(self, body: dict, user: Optional[dict] = None) -> dict:
        """
        Modify the request before sending to LLM
        """
        if self.valves.enabled and "messages" in body:
            # Add prefix to the last user message
            if body["messages"]:
                last_message = body["messages"][-1]
                if last_message.get("role") == "user":
                    last_message["content"] = (
                        self.valves.prefix + last_message["content"]
                    )
        
        return body
    
    async def outlet(self, body: dict, user: Optional[dict] = None) -> dict:
        """
        Modify the response after receiving from LLM
        """
        # Process the response here
        return body

Save Your Pipeline

Save the file in the pipelines/ directory:
pipelines/
  examples/
  your_pipeline.py  ← Your custom pipeline
Restart the pipelines server to load your pipeline.

Pipeline Examples

Explore real-world examples in the repository: Rate Limiting:
# pipelines/examples/rate_limit_pipeline.py
# Control user request rates
Translation:
# pipelines/examples/libretranslate_pipeline.py
# Automatic message translation
Content Filtering:
# pipelines/examples/toxic_message_filter_pipeline.py
# Block toxic or harmful content
Usage Monitoring:
# pipelines/examples/langfuse_pipeline.py
# Track usage with Langfuse
Function Calling:
# pipelines/examples/function_calling_pipeline.py
# Custom function/tool execution

Pipeline Methods

Core Methods

  • __init__() - Initialize pipeline and valves
  • on_startup() - Setup code (load models, connect to services)
  • on_shutdown() - Cleanup code
  • inlet(body, user) - Intercept and modify requests
  • outlet(body, user) - Intercept and modify responses

Advanced Methods

  • pipe() - Full control over request/response cycle
  • on_valves_updated() - React to configuration changes

Valves (Configuration)

Valves are pipeline settings that can be modified through the UI:
class Valves(BaseModel):
    api_key: str = ""
    max_tokens: int = 1000
    temperature: float = 0.7
    enabled: bool = True
Users can update these values without modifying code.

Native Python Functions/Tools

Open WebUI includes a built-in code editor for creating Python functions that LLMs can call.

Creating a Function

  1. Navigate to WorkspaceTools
  2. Click Create New Tool
  3. Write your Python function
  4. Save and enable

Function Structure

"""
title: Weather Tool
author: Your Name
version: 1.0.0
"""

import requests
from typing import Optional

def get_weather(
    location: str,
    units: str = "celsius",
    __user__: Optional[dict] = None
) -> str:
    """
    Get current weather for a location.
    
    :param location: City name or coordinates
    :param units: Temperature units (celsius or fahrenheit)
    :return: Weather description
    """
    
    # Your implementation here
    api_key = "your-api-key"
    url = f"https://api.weather.com/v1/current?location={location}"
    
    response = requests.get(url, params={"units": units})
    data = response.json()
    
    return f"Weather in {location}: {data['temperature']}° {units}"

Function Features

  • Type Hints: Use Python type hints for LLM parameter understanding
  • Docstrings: Provide clear descriptions for the LLM
  • User Context: Access __user__ parameter for user information
  • Dependencies: Import standard library or installed packages
  • Error Handling: Implement proper error handling

Installing Dependencies

Functions can use any Python package installed in the Open WebUI environment:
pip install requests aiohttp pandas
Or add to pyproject.toml for permanent installation.

Function Security

Safe Mode: Enable safe mode to deactivate all functions:
export SAFE_MODE=true
RestrictedPython: Functions run in a restricted environment to prevent dangerous operations.

MCP (Model Context Protocol) Servers

MCP servers provide standardized context to LLMs through a protocol.

Configuring MCP Servers

export MCP_SERVERS='{
  "filesystem": {
    "command": "npx",
    "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/files"]
  }
}'

Available MCP Servers

  • Filesystem: File system access
  • Git: Repository interaction
  • GitHub: GitHub API integration
  • Slack: Slack workspace integration
  • PostgreSQL: Database queries
  • Brave Search: Web search
See MCP Documentation for more servers.

Tool/Terminal Servers

Connect external tool servers to Open WebUI.

Configuration

export TOOL_SERVER_CONNECTIONS='[
  {
    "name": "My Tool Server",
    "url": "http://localhost:5000",
    "api_key": "your-api-key"
  }
]'

Terminal Server

Provide terminal access for code execution:
export TERMINAL_SERVER_CONNECTIONS='[
  {
    "name": "Code Runner",
    "url": "http://localhost:8000"
  }
]'

Development Best Practices

Testing

  1. Test locally before deploying
  2. Use the dev environment for iteration
  3. Test with various LLM providers
  4. Validate error handling

Error Handling

async def inlet(self, body: dict, user: Optional[dict] = None) -> dict:
    try:
        # Your logic here
        return body
    except Exception as e:
        print(f"Pipeline error: {e}")
        # Decide: pass through or modify
        return body

Logging

import logging

logger = logging.getLogger(__name__)

async def inlet(self, body: dict, user: Optional[dict] = None) -> dict:
    logger.info(f"Processing request for user: {user.get('name')}")
    # Your logic
    return body

Performance

  • Use async/await for I/O operations
  • Cache expensive computations
  • Avoid blocking operations in pipelines
  • Consider rate limiting for external APIs

Security

  • Validate all user inputs
  • Use environment variables for secrets
  • Implement proper authentication
  • Sanitize outputs before returning
  • Be cautious with code execution

Deployment

Production Pipelines

For production deployments:
# Use Docker
docker run -d -p 9099:9099 \
  -v ./pipelines:/app/pipelines \
  --name pipelines \
  ghcr.io/open-webui/pipelines:main

Environment Variables

export PIPELINES_DIR="./custom_pipelines"
export PIPELINES_PORT="9099"
export PIPELINES_HOST="0.0.0.0"

Examples and Templates

Complete Pipeline Example

See the Pipelines Examples Directory for:
  • Authentication pipelines
  • Rate limiting
  • Content filtering
  • Custom model routing
  • Monitoring integrations
  • Translation services

Function Examples

Check the Open WebUI community for shared functions:

Troubleshooting

Pipeline Not Loading

  1. Check pipeline file syntax
  2. Ensure class is named Pipeline
  3. Verify no import errors
  4. Check pipelines server logs

Function Not Executing

  1. Verify function is enabled
  2. Check for syntax errors in code editor
  3. Ensure dependencies are installed
  4. Review function logs

Performance Issues

  1. Profile slow pipelines
  2. Use async operations
  3. Implement caching
  4. Consider moving logic to background tasks

Resources

Next Steps