Skip to main content
Skills in Open WebUI provide a way to package and share reusable AI capabilities, prompts, and workflows. They enable users to build, organize, and distribute specialized behaviors that can be applied across different conversations and models.

Overview

Skills provide:
  • Reusable AI behaviors and prompts
  • Access control and sharing
  • Version management
  • Search and discovery
  • Import/export functionality
Skills are user-created content that can be shared with specific users, groups, or made available to everyone in your organization.

Creating Skills

Via Web Interface

1

Navigate to Skills

Go to Workspace → Skills in Open WebUI
2

Create New Skill

Click Create New Skill and configure:
  • ID: Unique identifier (lowercase, hyphens allowed)
  • Name: Display name for the skill
  • Description: What the skill does
3

Define Skill Content

Add your skill configuration:
{
  "name": "Code Review Assistant",
  "description": "Provides detailed code reviews",
  "content": {
    "system_prompt": "You are an expert code reviewer...",
    "examples": [
      {
        "input": "Review this function",
        "output": "Here's my analysis..."
      }
    ],
    "parameters": {
      "temperature": 0.7,
      "max_tokens": 2000
    }
  }
}
4

Set Permissions

Configure who can access the skill

Via API

Create skills programmatically:
import requests

url = "http://localhost:8080/api/skills/create"
payload = {
    "id": "code-reviewer",
    "name": "Code Review Assistant",
    "meta": {
        "description": "Performs detailed code reviews",
        "tags": ["coding", "review", "quality"]
    },
    "content": {
        "system_prompt": "You are an expert code reviewer...",
        "temperature": 0.7
    }
}

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

Managing Skills

List All Skills

import requests

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

for skill in skills:
    print(f"{skill['name']}: {skill['meta']['description']}")

Search Skills

Find skills with advanced filtering:
import requests

response = requests.get(
    "http://localhost:8080/api/skills/list",
    params={
        "query": "code review",
        "page": 1,
        "view_option": "all"  # or "personal", "shared"
    }
)

result = response.json()
print(f"Found {result['total']} skills")
for skill in result['items']:
    print(f"- {skill['name']}")

Get Skill by ID

response = requests.get("http://localhost:8080/api/skills/id/code-reviewer")
skill = response.json()

print(f"Name: {skill['name']}")
print(f"Description: {skill['meta']['description']}")
print(f"Write Access: {skill['write_access']}")

Update Skill

import requests

url = "http://localhost:8080/api/skills/id/code-reviewer/update"
payload = {
    "name": "Advanced Code Review Assistant",
    "meta": {
        "description": "Performs detailed code reviews with best practices",
        "tags": ["coding", "review", "quality", "best-practices"]
    },
    "content": {
        "system_prompt": "Updated prompt...",
        "temperature": 0.8
    }
}

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

Toggle Skill

Enable or disable a skill:
response = requests.post(
    "http://localhost:8080/api/skills/id/code-reviewer/toggle"
)

Delete Skill

response = requests.delete(
    "http://localhost:8080/api/skills/id/code-reviewer/delete"
)

Access Control

Skills support granular access control:
import requests

url = "http://localhost:8080/api/skills/id/code-reviewer/access/update"
payload = {
    "access_grants": [
        {
            "principal_type": "user",
            "principal_id": "alice@example.com",
            "permission": "read"
        },
        {
            "principal_type": "user",
            "principal_id": "bob@example.com",
            "permission": "write"
        },
        {
            "principal_type": "group",
            "principal_id": "developers",
            "permission": "read"
        },
        {
            "principal_type": "user",
            "principal_id": "*",  # Public access
            "permission": "read"
        }
    ]
}

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

Permission Levels

  • read: Can view and use the skill
  • write: Can modify the skill configuration

Skill Examples

{
  "id": "code-reviewer",
  "name": "Code Review Assistant",
  "meta": {
    "description": "Provides detailed code reviews with security and performance insights",
    "tags": ["coding", "review", "security", "performance"]
  },
  "content": {
    "system_prompt": "You are an expert code reviewer with deep knowledge of software security, performance optimization, and best practices. When reviewing code:\n\n1. Identify potential bugs and logic errors\n2. Check for security vulnerabilities\n3. Suggest performance improvements\n4. Verify code style and readability\n5. Recommend best practices\n\nProvide specific, actionable feedback.",
    "temperature": 0.7,
    "max_tokens": 2000,
    "examples": [
      {
        "input": "Review this SQL query: SELECT * FROM users WHERE id = '" + userId + "'",
        "output": "⚠️ SQL Injection Vulnerability:\n\nThis code is vulnerable to SQL injection. Use parameterized queries instead:\n\n```python\nquery = 'SELECT * FROM users WHERE id = ?'\ncursor.execute(query, (userId,))\n```"
      }
    ]
  }
}
{
  "id": "technical-writer",
  "name": "Technical Documentation Writer",
  "meta": {
    "description": "Converts technical concepts into clear documentation",
    "tags": ["documentation", "writing", "technical"]
  },
  "content": {
    "system_prompt": "You are a technical writer who excels at creating clear, concise documentation. Your documentation:\n\n- Uses simple language without jargon\n- Includes practical examples\n- Follows a logical structure\n- Anticipates user questions\n- Uses proper formatting (headings, lists, code blocks)\n\nAlways provide complete, ready-to-use documentation.",
    "temperature": 0.8,
    "examples": [
      {
        "input": "Document the API endpoint POST /api/users",
        "output": "# Create User\n\n## Endpoint\n`POST /api/users`\n\n## Description\nCreates a new user account.\n\n## Request Body\n```json\n{\n  \"name\": \"string\",\n  \"email\": \"string\"\n}\n```\n\n## Response\n```json\n{\n  \"id\": \"string\",\n  \"name\": \"string\",\n  \"email\": \"string\"\n}\n```"
      }
    ]
  }
}
{
  "id": "data-analyst",
  "name": "Data Analysis Assistant",
  "meta": {
    "description": "Analyzes data and provides insights",
    "tags": ["data", "analysis", "insights"]
  },
  "content": {
    "system_prompt": "You are a data analyst who helps users understand their data. When analyzing data:\n\n1. Identify key patterns and trends\n2. Calculate relevant statistics\n3. Highlight anomalies\n4. Provide actionable insights\n5. Suggest visualizations\n6. Explain findings in plain language\n\nAlways support your analysis with specific numbers and examples.",
    "temperature": 0.6,
    "max_tokens": 1500,
    "examples": [
      {
        "input": "Analyze this sales data: Q1: $100k, Q2: $150k, Q3: $140k, Q4: $180k",
        "output": "📊 Sales Analysis:\n\n**Total Revenue**: $570k\n**Growth**: 80% year-over-year (Q1 to Q4)\n**Best Quarter**: Q4 ($180k, +28% from Q3)\n**Trend**: Strong upward trajectory with minor Q3 dip\n\n**Insights**:\n- Revenue increased consistently except Q3\n- Q4 shows recovery and strong finish\n- Average quarterly revenue: $142.5k\n\n**Recommendations**:\n- Investigate Q3 dip cause\n- Replicate Q4 success factors"
      }
    ]
  }
}

Import and Export

Export Skills

import requests

response = requests.get("http://localhost:8080/api/skills/export")
skills = response.json()

# Save to file
import json
with open('skills_export.json', 'w') as f:
    json.dump(skills, f, indent=2)

Import Skills

Load skills from exported JSON:
import requests
import json

with open('skills_export.json', 'r') as f:
    skills = json.load(f)

for skill in skills:
    response = requests.post(
        "http://localhost:8080/api/skills/create",
        json=skill
    )
    if response.status_code == 200:
        print(f"✓ Imported: {skill['name']}")

Pagination

When listing skills, use pagination for large result sets:
import requests

def get_all_skills():
    all_skills = []
    page = 1
    
    while True:
        response = requests.get(
            "http://localhost:8080/api/skills/list",
            params={"page": page}
        )
        data = response.json()
        
        all_skills.extend(data['items'])
        
        # Check if there are more pages
        if len(data['items']) < 30:  # PAGE_ITEM_COUNT = 30
            break
        
        page += 1
    
    return all_skills

Best Practices

  1. Clear Naming: Use descriptive IDs and names
  2. Documentation: Include comprehensive descriptions
  3. Tagging: Add relevant tags for discoverability
  4. Examples: Provide usage examples in content
  5. Versioning: Track changes in description
  6. Access Control: Set appropriate permissions
  7. Testing: Test skills before sharing

Use Cases

Team Collaboration

Create shared skills for common team tasks:
  • Code review guidelines
  • Documentation templates
  • Bug triage procedures
  • Customer support responses

Knowledge Management

Capture organizational knowledge:
  • Company-specific terminology
  • Domain expertise
  • Best practices
  • Standard operating procedures

Workflow Automation

Build repeatable AI workflows:
  • Data analysis templates
  • Report generation
  • Content creation
  • Quality assurance checks

Troubleshooting

Skill Not Visible

  • Check access grants include your user/group
  • Verify skill is enabled (not toggled off)
  • Ensure you have read permission
  • Refresh the skills list

Cannot Edit Skill

  • Verify you have write permission
  • Check if you’re the owner
  • Confirm you’re in a group with write access
  • Contact the skill owner or admin

Search Not Finding Skills

  • Try different search terms
  • Check view option (all/personal/shared)
  • Verify skills are properly tagged
  • Ensure skills are enabled

Next Steps

  • Learn about Functions for Python execution
  • Explore Tools for external integrations
  • Configure Memories for long-term context