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
Navigate to Skills
Go to Workspace → Skills in Open WebUI
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
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
}
}
}
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\n 1. Identify potential bugs and logic errors \n 2. Check for security vulnerabilities \n 3. Suggest performance improvements \n 4. Verify code style and readability \n 5. Recommend best practices \n\n Provide 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\n This code is vulnerable to SQL injection. Use parameterized queries instead: \n\n ```python \n query = 'SELECT * FROM users WHERE id = ?' \n cursor.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\n Always 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 \n Creates 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\n 1. Identify key patterns and trends \n 2. Calculate relevant statistics \n 3. Highlight anomalies \n 4. Provide actionable insights \n 5. Suggest visualizations \n 6. Explain findings in plain language \n\n Always 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' ] } " )
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
Clear Naming : Use descriptive IDs and names
Documentation : Include comprehensive descriptions
Tagging : Add relevant tags for discoverability
Examples : Provide usage examples in content
Versioning : Track changes in description
Access Control : Set appropriate permissions
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