2025-12-29 10:03:23 +00:00
|
|
|
# Development
|
|
|
|
|
|
|
|
|
|
Learn how to develop plugins and contribute to OpenWebUI Extras.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Getting Started
|
|
|
|
|
|
|
|
|
|
<div class="grid cards" markdown>
|
|
|
|
|
|
|
|
|
|
- :material-book-open-page-variant:{ .lg .middle } **Plugin Development Guide**
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
The comprehensive guide covering everything from getting started to advanced patterns and best practices.
|
|
|
|
|
|
|
|
|
|
[:octicons-arrow-right-24: Read the Guide](plugin-guide.md)
|
|
|
|
|
|
2025-12-29 11:47:54 +00:00
|
|
|
- :material-file-document-edit:{ .lg .middle } **Documentation Guide**
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
Learn how to write and contribute documentation using MkDocs and Material theme.
|
|
|
|
|
|
|
|
|
|
[:octicons-arrow-right-24: Read the Guide](documentation-guide.md)
|
|
|
|
|
|
2025-12-29 10:03:23 +00:00
|
|
|
- :material-github:{ .lg .middle } **Contributing**
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
Learn how to contribute plugins, prompts, and documentation to the project.
|
|
|
|
|
|
|
|
|
|
[:octicons-arrow-right-24: Contribution Guide](../contributing.md)
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Plugin Types Overview
|
|
|
|
|
|
|
|
|
|
OpenWebUI supports three main plugin types:
|
|
|
|
|
|
|
|
|
|
| Type | Purpose | Entry Method |
|
|
|
|
|
|------|---------|--------------|
|
|
|
|
|
| **Action** | Add buttons to messages | `action()` |
|
|
|
|
|
| **Filter** | Process messages | `inlet()` / `outlet()` |
|
|
|
|
|
| **Pipe** | Custom model integration | `pipe()` |
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Quick Start Templates
|
|
|
|
|
|
|
|
|
|
### Action Plugin
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
"""
|
|
|
|
|
title: My Action
|
|
|
|
|
author: Your Name
|
|
|
|
|
version: 1.0.0
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
class Action:
|
|
|
|
|
async def action(self, body: dict, __event_emitter__=None):
|
|
|
|
|
await __event_emitter__({"type": "notification", "data": {"content": "Hello!"}})
|
|
|
|
|
return body
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Filter Plugin
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
"""
|
|
|
|
|
title: My Filter
|
|
|
|
|
author: Your Name
|
|
|
|
|
version: 1.0.0
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
class Filter:
|
|
|
|
|
async def inlet(self, body: dict, __metadata__: dict) -> dict:
|
|
|
|
|
# Process before LLM
|
|
|
|
|
return body
|
|
|
|
|
|
|
|
|
|
async def outlet(self, body: dict, __metadata__: dict) -> dict:
|
|
|
|
|
# Process after LLM
|
|
|
|
|
return body
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Pipe Plugin
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
"""
|
|
|
|
|
title: My Pipe
|
|
|
|
|
author: Your Name
|
|
|
|
|
version: 1.0.0
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
class Pipe:
|
|
|
|
|
def pipes(self):
|
|
|
|
|
return [{"id": "my-model", "name": "My Model"}]
|
|
|
|
|
|
|
|
|
|
def pipe(self, body: dict):
|
|
|
|
|
return "Response from custom pipe"
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Core Concepts
|
|
|
|
|
|
|
|
|
|
### Valves Configuration
|
|
|
|
|
|
|
|
|
|
Valves allow users to configure plugins through the UI:
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
|
|
|
|
class Action:
|
|
|
|
|
class Valves(BaseModel):
|
|
|
|
|
api_key: str = Field(default="", description="API Key")
|
|
|
|
|
enabled: bool = Field(default=True, description="Enable plugin")
|
|
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
self.valves = self.Valves()
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Event Emitter
|
|
|
|
|
|
|
|
|
|
Send notifications and status updates:
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
# Notification
|
|
|
|
|
await __event_emitter__({
|
|
|
|
|
"type": "notification",
|
|
|
|
|
"data": {"type": "success", "content": "Done!"}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
# Status update
|
|
|
|
|
await __event_emitter__({
|
|
|
|
|
"type": "status",
|
|
|
|
|
"data": {"description": "Processing...", "done": False}
|
|
|
|
|
})
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### User Context
|
|
|
|
|
|
|
|
|
|
Access user information:
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
user_name = __user__.get("name", "User")
|
|
|
|
|
user_id = __user__.get("id")
|
|
|
|
|
user_language = __user__.get("language", "en-US")
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Best Practices
|
|
|
|
|
|
|
|
|
|
1. **Async Operations**: Always use `async/await` for I/O operations
|
|
|
|
|
2. **Error Handling**: Catch exceptions and notify users
|
|
|
|
|
3. **Status Updates**: Provide feedback during long operations
|
|
|
|
|
4. **Configuration**: Use Valves for customizable options
|
|
|
|
|
5. **Documentation**: Include clear docstrings and README files
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Resources
|
|
|
|
|
|
|
|
|
|
- [Full Development Guide](plugin-guide.md)
|
|
|
|
|
- [Plugin Examples](https://github.com/Fu-Jie/awesome-openwebui/tree/main/plugins)
|
|
|
|
|
- [OpenWebUI Documentation](https://docs.openwebui.com/)
|