> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/open-webui/open-webui/llms.txt
> Use this file to discover all available pages before exploring further.

# Functions

> Add Python function calling capabilities to your models

Functions in Open WebUI allow you to extend your language models with custom Python code that can be called during conversations. This enables your models to perform actions, fetch data, and integrate with external services.

## Overview

Functions provide:

* Native Python code execution
* Built-in code editor in the workspace
* Function calling and tool use capabilities
* Filter functions to modify messages
* Admin and user-level configuration

<Note>
  Functions are stored in the database and loaded dynamically at runtime. Admin users can create and manage functions through the web interface.
</Note>

## Creating Functions

### Through the Web Interface

<Steps>
  <Step title="Navigate to Workspace">
    Go to **Workspace → Functions** in the Open WebUI interface
  </Step>

  <Step title="Create New Function">
    Click **Create New Function** and enter:

    * **ID**: Unique identifier (alphanumeric and underscores only)
    * **Name**: Display name for the function
    * **Description**: What the function does
  </Step>

  <Step title="Write Function Code">
    Use the built-in editor to write your Python function:

    ```python theme={null}
    """
    title: Example Function
    description: A simple example function
    author: Your Name
    version: 1.0.0
    """

    class Function:
        def __init__(self):
            pass
        
        def __call__(self, user_message: str, **kwargs) -> str:
            return f"Processed: {user_message}"
    ```
  </Step>

  <Step title="Save and Enable">
    Save the function and toggle it active to make it available
  </Step>
</Steps>

### Via API

Create functions programmatically:

```python theme={null}
import requests

url = "http://localhost:8080/api/functions/create"
payload = {
    "id": "my_function",
    "name": "My Function",
    "content": '''
class Function:
    def __call__(self, user_message: str) -> str:
        return f"Echo: {user_message}"
''',
    "meta": {
        "description": "Echoes the user message",
        "manifest": {}
    }
}

response = requests.post(url, json=payload)
```

## Function Types

Open WebUI supports two main types of functions:

### Action Functions

Perform operations and return results:

```python theme={null}
import requests
from datetime import datetime

class Function:
    def __init__(self):
        self.name = "get_weather"
        self.description = "Get current weather for a city"
    
    def __call__(self, city: str, **kwargs) -> dict:
        # Call weather API
        response = requests.get(
            f"https://api.weather.com/v1/current",
            params={"city": city}
        )
        return response.json()
```

### Filter Functions

Modify messages before and after model processing:

```python theme={null}
class Function:
    type = "filter"  # Mark as filter function
    
    def inlet(self, messages: list, user: dict, **kwargs) -> list:
        """Process messages before sending to model"""
        # Add timestamp to each message
        for msg in messages:
            msg["timestamp"] = datetime.now().isoformat()
        return messages
    
    def outlet(self, messages: list, user: dict, **kwargs) -> list:
        """Process messages after model response"""
        # Log the conversation
        print(f"Conversation for {user['email']}: {len(messages)} messages")
        return messages
```

## Valves Configuration

Valves allow functions to have configurable parameters:

```python theme={null}
from pydantic import BaseModel, Field

class Function:
    class Valves(BaseModel):
        api_key: str = Field(
            default="",
            description="API key for external service"
        )
        temperature: float = Field(
            default=0.7,
            description="Model temperature",
            ge=0.0,
            le=2.0
        )
        max_tokens: int = Field(
            default=1000,
            description="Maximum tokens"
        )
    
    def __init__(self):
        self.valves = self.Valves()
    
    def __call__(self, prompt: str, **kwargs) -> str:
        # Use valve values
        api_key = self.valves.api_key
        temp = self.valves.temperature
        # Your function logic here
        return f"Using temp={temp}"
```

### User Valves

Allow individual users to configure function parameters:

```python theme={null}
from pydantic import BaseModel, Field

class Function:
    class UserValves(BaseModel):
        personal_api_key: str = Field(
            default="",
            description="Your personal API key"
        )
        preferred_language: str = Field(
            default="en",
            description="Preferred response language"
        )
    
    def __init__(self):
        self.user_valves = {}
    
    def __call__(self, user_message: str, __user__: dict, **kwargs) -> str:
        user_id = __user__["id"]
        valves = self.user_valves.get(user_id, self.UserValves())
        
        # Use user-specific configuration
        lang = valves.preferred_language
        return f"Response in {lang}: {user_message}"
```

## Managing Functions

### List Functions

```python theme={null}
import requests

response = requests.get("http://localhost:8080/api/functions/")
functions = response.json()
```

### Get Function by ID

```python theme={null}
response = requests.get("http://localhost:8080/api/functions/id/my_function")
function = response.json()
```

### Update Function

```python theme={null}
import requests

url = "http://localhost:8080/api/functions/id/my_function/update"
payload = {
    "content": """# Updated code here""",
    "meta": {"description": "Updated description"}
}

response = requests.post(url, json=payload)
```

### Toggle Function

Enable or disable a function:

```python theme={null}
response = requests.post(
    "http://localhost:8080/api/functions/id/my_function/toggle"
)
```

### Delete Function

```python theme={null}
response = requests.delete(
    "http://localhost:8080/api/functions/id/my_function/delete"
)
```

## Import from URL

Load functions from GitHub or other sources:

```python theme={null}
import requests

url = "http://localhost:8080/api/functions/load/url"
payload = {
    "url": "https://github.com/user/repo/blob/main/my_function.py"
}

response = requests.post(url, json=payload)
function_data = response.json()
```

<Note>
  GitHub URLs are automatically converted to raw URLs. Both `blob` and `tree` URLs are supported.
</Note>

## Function Examples

<Accordion title="Database Query Function">
  ```python theme={null}
  import sqlite3
  from typing import List, Dict

  class Function:
      def __init__(self):
          self.name = "query_database"
          self.description = "Query the local database"
      
      def __call__(self, query: str, **kwargs) -> List[Dict]:
          conn = sqlite3.connect('app.db')
          cursor = conn.cursor()
          
          cursor.execute(query)
          columns = [desc[0] for desc in cursor.description]
          results = [
              dict(zip(columns, row))
              for row in cursor.fetchall()
          ]
          
          conn.close()
          return results
  ```
</Accordion>

<Accordion title="API Integration Function">
  ```python theme={null}
  import requests
  from pydantic import BaseModel, Field

  class Function:
      class Valves(BaseModel):
          api_key: str = Field(default="", description="API Key")
          base_url: str = Field(
              default="https://api.example.com",
              description="API Base URL"
          )
      
      def __init__(self):
          self.valves = self.Valves()
      
      def __call__(self, endpoint: str, params: dict = None, **kwargs) -> dict:
          headers = {"Authorization": f"Bearer {self.valves.api_key}"}
          url = f"{self.valves.base_url}/{endpoint}"
          
          response = requests.get(url, headers=headers, params=params)
          return response.json()
  ```
</Accordion>

<Accordion title="Text Processing Function">
  ```python theme={null}
  import re
  from typing import List

  class Function:
      def __init__(self):
          self.name = "extract_emails"
          self.description = "Extract email addresses from text"
      
      def __call__(self, text: str, **kwargs) -> List[str]:
          email_pattern = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'
          emails = re.findall(email_pattern, text)
          return list(set(emails))  # Remove duplicates
  ```
</Accordion>

## Global vs Local Functions

Functions can be toggled between global and local scope:

```python theme={null}
import requests

# Toggle global scope (available to all users)
response = requests.post(
    "http://localhost:8080/api/functions/id/my_function/toggle/global"
)
```

<Warning>
  Global functions are available to all users. Ensure they don't expose sensitive data or operations.
</Warning>

## Best Practices

1. **Error Handling**: Always wrap function logic in try-except blocks
2. **Type Hints**: Use Python type hints for better documentation
3. **Validation**: Validate inputs before processing
4. **Security**: Never hardcode sensitive credentials
5. **Performance**: Keep functions lightweight and fast
6. **Documentation**: Include clear docstrings and metadata

## Next Steps

* Learn about [Tools](/advanced/tools) for extended functionality
* Explore [Pipelines](/advanced/pipelines) for request/response filtering
* Configure [Skills](/advanced/skills) for reusable capabilities
