# Functions

Source: https://docs.openwebui.com/features/extensibility/plugin/functions

> **⚠️ Critical Security Warning**
>
> **Functions execute arbitrary Python code on your server.** Function creation is restricted to administrators only. Only install from trusted sources and review code before importing. A malicious Function could access your file system, exfiltrate data, or compromise your entire system. For full details, see the [Plugin Security Warning](/features/extensibility/plugin/).

Functions are **modular Python plugins** that extend the capabilities of Open WebUI itself. While [Tools](/features/extensibility/plugin/tools/) give LLMs the ability to call external APIs during inference, Functions change how the platform behaves at a deeper level. They can add entirely new "models" powered by any Python logic, intercept and transform every message flowing through the system, or place interactive buttons directly in the chat UI.

The possibilities are broad: connect a proprietary AI provider, build a smart home controller that responds to natural language, create a database query interface, add real-time translation to every conversation, enforce compliance policies, generate charts from data, or trigger external workflows with a button click. If you can write it in Python, you can turn it into a Function.

Functions are stored in the database as Python source code, dynamically loaded at runtime, and executed server-side. Administrators create and manage them; regular users interact with the results.

---

## Function Types

Open WebUI supports four types of Functions. The type is **auto-detected** from the class name in your Python code, so you never need to configure it manually.

| Type | Class Name | What It Does | How Users See It |
| --- | --- | --- | --- |
| Pipe | class Pipe | Adds a custom model or agent | Appears as a selectable model in the chat sidebar |
| Filter | class Filter | Intercepts data flowing to/from models | Runs transparently as middleware on existing models |
| Action | class Action | Adds interactive buttons to messages | Appears as a clickable button on chat messages |
| Event | class Event | Runs custom logic in response to system events | Runs in the background; no direct UI |

### Pipe Functions

A Pipe registers itself as a new "model" in Open WebUI. When a user selects it and sends a message, the `pipe()` method handles the entire request with no LLM backend required. This makes Pipes incredibly versatile:

- **Model providers**: Integrate APIs that don't follow the OpenAI protocol (Anthropic native, Google Vertex, custom inference servers).
- **Agents & workflows**: Build multi-step agents that call tools, search the web, and reason across multiple turns.
- **Non-LLM interfaces**: Create a smart home controller, a database query tool, a search engine, a calculator, or a code executor. Anything that takes user input and returns a response.
- **Proxies & routers**: Route requests through your own logic, add caching, load balancing, or cost tracking.

A single Pipe can also expose **multiple models** (called a "manifold") by defining a `pipes()` method that returns a list of `{"id": ..., "name": ...}` dictionaries, one per model.

→ **[Pipe Function Guide](/features/extensibility/plugin/functions/pipe)**

### Filter Functions

A Filter sits between the user and the model, intercepting data at three stages:

- **`inlet()`**: Modifies the request **before** it reaches the model (add context, sanitize input, detect language, enforce rate limits, estimate token costs).
- **`stream()`**: Intercepts **streamed chunks** from the model in real time (censor content, replace terms, track token usage).
- **`outlet()`**: Processes the completed response **after** it's generated (log to observability platforms, format citations, append disclaimers, cache responses).

Filters enable powerful cross-cutting concerns like real-time translation, content moderation, prompt injection detection, A/B testing, compliance logging, and PII redaction, all without modifying the underlying model.

Filters can be applied globally (to all models) or attached to specific models. Toggleable filters let users enable/disable them per-chat.

→ **[Filter Function Guide](/features/extensibility/plugin/functions/filter)**

### Action Functions

An Action adds a custom button to the chat message toolbar. When a user clicks it, the `action()` method runs with full access to the event system for real-time UI feedback, user prompts, and confirmations.

Actions can do anything Python can do: summarize or translate a message, copy formatted output, pin important messages, export conversations to external systems, trigger a CI/CD pipeline, send a Slack notification, generate a PDF report, run a code snippet, or kick off an external workflow.

→ **[Action Function Guide](/features/extensibility/plugin/functions/action)**

### Event Functions

_New in Open WebUI 0.10.0._

An Event function runs custom Python in response to **system events** (a user signs up, a chat is deleted, the server starts, configuration changes). Its `event()` method is called for every event and filters on the event name. Event functions can register their own API endpoints and call internal services, which suits them to lifecycle automation, audit logging, signup gating, provisioning, and self-installing plugins.

→ **[Event Function Guide](/features/extensibility/plugin/functions/event)**

---

## How Functions Work

### Type Detection

When you save a Function, Open WebUI scans the Python source code for a top-level class named `Pipe`, `Filter`, `Action`, or `Event`. The first match determines the function type. You never need to manually set the type because it's inferred from the code.

```
# This is detected as a Pipe function:class Pipe:    async def pipe(self, body: dict) -> str:        return "Hello from my custom model!"# This is detected as a Filter function:class Filter:    async def inlet(self, body: dict) -> dict:        return body
```

### Module Loading & Caching

The Python source code is loaded via `exec()` into a temporary module namespace. Once loaded, the module is cached in memory (`request.app.state.FUNCTIONS`) and only reloaded when the source code changes. Four legacy prefixes are rewritten on the way in, `from utils`, `from apps`, `from main` and `from config`, each gaining an `open_webui.` prefix. The rewrite is a plain text replacement over the whole file, so those strings are also changed inside docstrings and prompt text. Creating or saving a function stores the rewritten source. Loading a function applies the rewrite to the code it runs and leaves the stored source as it is.

### When a Function Fails to Load

A function fails to load when its code raises while it is being executed: a syntax error, an `import` that fails, an exception raised while the class is constructed or a file with no `Pipe`, `Filter`, `Action` or `Event` class in it.

- **Saving in the editor** executes the new code before storing it. Code that fails to load is refused: the Python error shows in the editor, the new source is not written and the version already saved stays active and keeps running. Fix the code and save again. A failed `requirements` install is refused the same way.
- **Outside the editor**, the code is executed again every time the module is loaded, for example after a restart. When that fails, Open WebUI switches the function to **inactive** to keep it from failing on every request, and logs `Error loading module: <function id>: <the error>`. A package that was installed into the container by hand and never added to `requirements` is the usual cause, since it is gone after a restart. Fix the code, then switch the function back on in **Admin Panel > Functions**.

### Frontmatter

A triple-quoted docstring at the top of the file is parsed as YAML frontmatter for metadata:

```
"""
title: My Custom Function
author: your_name
author_url: https://github.com/your_name
version: 1.0.0
icon_url: https://example.com/icon.svg
required_open_webui_version: 0.4.0
requirements: requests, beautifulsoup4
"""
```

| Field | Purpose |
| --- | --- |
| title | Display name in the admin UI |
| author / author_url | Attribution metadata |
| version | Version identifier |
| icon_url | Icon displayed next to the function name (use a URL, not base64) |
| required_open_webui_version | Minimum compatible Open WebUI version |
| requirements | Comma-separated list of pip packages to auto-install |

> **Automatic Dependency Installation**
>
> When `requirements` is specified in the frontmatter, Open WebUI automatically installs the listed packages via `pip` the first time the function loads. This is controlled by the [`ENABLE_PIP_INSTALL_FRONTMATTER_REQUIREMENTS`](/reference/env-configuration#enable_pip_install_frontmatter_requirements) environment variable (enabled by default).

---

## Installing Functions

### From the Community Library

1. Browse the [Community Function Library](https://openwebui.com/search).
2. Click **Get** on the function you want.
3. Enter your Open WebUI instance URL (e.g., `http://localhost:3000`).
4. Click **Import to Open WebUI**. You'll be redirected to the Function Editor.
5. Review the code, then click **Save**.

> **warning**
>
> Always review the source code before importing. Community functions are user-contributed and **run directly on your server**.

### From a URL

1. Go to **Admin Panel > Functions**.
2. Click **Import from URL** and paste a link to the Python file.
- GitHub URLs are automatically converted to raw file URLs.
3. Review and save.

### Create Manually

1. Go to **Admin Panel > Functions**.
2. Click **Create**.
3. Enter an ID (alphanumeric and underscores only), name, and description.
4. Write your Python code in the editor.
5. Click **Save**. The function type is auto-detected from your code.

---

## Managing Functions

### Admin Controls

Functions are managed from **Admin Panel > Functions**. The page is hidden when [`ENABLE_FUNCTIONS`](/reference/env-configuration#enable_functions) is set to `False`. Each function has the following controls:

| Control | Description |
| --- | --- |
| Active toggle | Enables or disables the function. Disabled functions are not loaded or executed. |
| Global toggle | When enabled, the function applies to all models automatically. Available for Filters and Actions. |
| Valves (⚙️ gear icon) | Opens the admin-configurable settings for this function. |
| Export / Delete | Export the function as a file or remove it. |

### Version history

Functions keep a version history that works like the one for tools: the version picker next to **Back**, **Compare to current**, **Set as Production** and **Delete**. See [Version history](/features/extensibility/plugin/tools#version-history) for the details. For functions:

- Only admins can open and change versions.
- **Production** is the version that is running.
- Valves and the **Active** and **Global** switches belong to the function itself and keep their current values when you change versions. When the current Valves do not fit an older version's code, setting it as Production is refused with **Current Valves are incompatible with this code** and the running version stays in place.

The same actions are available over the API, admin only: `GET /api/v1/functions/id/{id}/history` (paged with `?page=`), `GET /api/v1/functions/id/{id}/history/{history_id}`, `GET /api/v1/functions/id/{id}/history/diff?from_id=...&to_id=...`, `DELETE /api/v1/functions/id/{id}/history/{history_id}` and `POST /api/v1/functions/id/{id}/update/version` with `{"version_id": "..."}`. A save through `POST /api/v1/functions/id/{id}/update` accepts an optional `commit_message`.

### Translating a function

The globe selector in the function editor stores a name, a description, valve labels and per-action labels for each language, so an action button under a reply can read in the user's own language. See [Translations](/features/administration/translations).

### Assigning Functions to Specific Models

Instead of making a Filter or Action global, you can attach it to specific models:

1. Go to **Workspace → Models**.
2. Edit the target model.
3. In the **Filters** or **Actions** section, select the functions you want to attach.

This allows different models to use different filters. For example, you might apply a content-moderation filter only on public-facing models.

### Toggleable Filters

Filters can be made user-toggleable by setting `self.toggle = True` in `__init__`. When toggleable, users see an on/off switch in the chat input area and can enable or disable the filter per-conversation. Filters without `self.toggle` are always-on when active.

---

## Valves & UserValves

Functions support a two-tier configuration system built on [Pydantic](https://docs.pydantic.dev/):

| Level | Class Name | Who Configures | Where |
| --- | --- | --- | --- |
| Admin | Valves | Administrators only | Admin Panel > Functions > ⚙️ |
| User | UserValves | Any user | Chat interface, per-function |

**Valves** are ideal for API keys, model endpoints, and global behavior settings. **UserValves** let individual users customize behavior (e.g., their preferred language, output format, or personal API key).

Both are defined as nested Pydantic `BaseModel` classes inside your `Pipe`, `Filter` or `Action` class. An `Event` class can carry `Valves` too, but never `UserValves`, since event handlers run without a user. The admin-configured values are stored in the database and loaded automatically at runtime. When Valves hold secrets, an administrator can [encrypt them at rest](/features/extensibility/plugin/development/valves#encrypting-valve-values-at-rest).

→ **[Valves Development Guide](/features/extensibility/plugin/development/valves)**

---

## Functions vs Tools: When to Use Which

| Use Case | Use a... | Why |
| --- | --- | --- |
| Give the LLM access to live data (weather, stocks, APIs) | Tool | Tools are called by the model during inference |
| Add a model provider with a non-OpenAI API | Pipe Function | Pipes register as models in the sidebar |
| Build a non-LLM interface (search, databases, smart home) | Pipe Function | Pipes handle the entire request without needing an LLM |
| Build a multi-step agent with custom logic | Pipe Function | Pipes control the full request/response cycle |
| Translate, moderate, or redact content in real time | Filter Function | Filters intercept every message transparently |
| Log requests to an observability platform | Filter Function | Inlet/outlet filters see all traffic |
| Rate-limit or enforce usage policies | Filter Function | Inlet filters can reject requests before the model |
| Add a button to export, summarize, or share messages | Action Function | Actions appear on the message toolbar |
| Trigger an external workflow from the chat UI | Action Function | Actions run arbitrary Python on click |

---

## Development Resources

| Guide | Description |
| --- | --- |
| Pipe Function Guide | Build custom models, agents, and non-LLM interfaces |
| Filter Function Guide | Intercept, translate, moderate, and log messages |
| Action Function Guide | Add buttons for export, workflows, and interactive tasks |
| Event Function Guide | Run custom logic in response to system events |
| Valves | Configure functions with admin and user settings |
| Events | Send real-time updates to the UI |
| Reserved Arguments | __user__, __event_emitter__, __metadata__, and more |
| Rich UI | Embed interactive HTML/JS content in responses |
