[PR #21275] [CLOSED] feat: add Agent Skills system with semantic activation and script execution #49054

Closed
opened 2026-04-30 01:22:46 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/open-webui/open-webui/pull/21275
Author: @dathtd119
Created: 2/9/2026
Status: Closed

Base: devHead: feat/agent-skills


📝 Commits (1)

  • 5b54584 feat: add Agent Skills system with semantic activation and script execution

📊 Changes

20 files changed (+2981 additions, -101 deletions)

View changed files

📝 backend/open_webui/config.py (+18 -0)
backend/open_webui/internal/migrations/019_add_skills.py (+66 -0)
📝 backend/open_webui/main.py (+23 -1)
backend/open_webui/models/skills.py (+260 -0)
backend/open_webui/routers/skills.py (+285 -0)
📝 backend/open_webui/utils/middleware.py (+609 -99)
backend/open_webui/utils/skills_executor.py (+216 -0)
backend/open_webui/utils/skills_external_bridge.py (+357 -0)
src/lib/apis/skills/index.ts (+295 -0)
📝 src/lib/components/admin/Users/Groups/Permissions.svelte (+32 -0)
📝 src/lib/components/chat/Chat.svelte (+5 -0)
src/lib/components/workspace/Skills.svelte (+412 -0)
src/lib/components/workspace/Skills/SkillEditor.svelte (+288 -0)
📝 src/lib/constants/permissions.ts (+4 -1)
📝 src/lib/stores/index.ts (+1 -0)
📝 src/routes/(app)/workspace/+layout.svelte (+14 -0)
📝 src/routes/(app)/workspace/+page.svelte (+2 -0)
src/routes/(app)/workspace/skills/+page.svelte (+5 -0)
src/routes/(app)/workspace/skills/create/+page.svelte (+26 -0)
src/routes/(app)/workspace/skills/edit/+page.svelte (+63 -0)

📄 Description

Pull Request Checklist

  • Target branch: dev
  • Description: Provided below
  • Testing: Manually tested all features on a live instance (port 3001) with real models (gemini-3-flash, gpt-5.3-codex)
  • Code review: Self-reviewed, follows existing access control and module patterns (Tools, Functions, Knowledge)
  • Title Prefix: feat:

Changelog Entry

Description

Adds a native Agent Skills module to Open WebUI — a first-class workspace module alongside Models, Knowledge, Prompts, and Tools.

Skills are reusable prompt+script bundles that can be mounted from external directories (e.g. ~/.claude/skills) and auto-activate based on user message context. When a skill includes executable scripts (.py/.sh), they run automatically via subprocess and their output is injected into the LLM's system prompt.

This enables Open WebUI to act as an agent platform where domain-specific capabilities (DevOps, databases, web search, etc.) are loaded dynamically based on conversation context — without MCP or external tool servers.

Added

  • Backend model (models/skills.py): Skill SQLAlchemy model with access_control (matching Tools pattern: None=public, {}=private, custom group/user permissions), activation config, effects, priority, is_active
  • DB migration (019_add_skills.py): Peewee migration creating skill table
  • Router (routers/skills.py): Full CRUD + toggle + export + external sync endpoints with has_access/has_permission checks and BYPASS_ADMIN_ACCESS_CONTROL support
  • External bridge (utils/skills_external_bridge.py): Scans mounted directories for SKILL.md/plugin.json files, extracts metadata, discovers bundled scripts, and upserts into DB on startup
  • Script executor (utils/skills_executor.py): Runs .py/.sh scripts via subprocess.run() with timeout (30s default), output limit (10KB), stdin=/dev/null, sandbox cwd=/tmp
  • Semantic activation (utils/middleware.py): Three activation modes — always, auto (keyword/regex rules), semantic (LLM-based intent matching with token-overlap fallback). Skills auto-execute scripts when triggered.
  • Config (config.py): USER_PERMISSIONS_WORKSPACE_SKILLS_ACCESS, _IMPORT, _EXPORT permission keys (default False — admin-managed, skills still activate for all users via public access_control)
  • Frontend: Workspace Skills UI (Skills.svelte, SkillEditor.svelte), API client (apis/skills/index.ts), workspace layout tab, group permissions toggles

Changed

  • main.py: Register skills router, add startup external skills sync
  • middleware.py: Add skill activation pipeline in process_chat_payload (between system prompt setup and folder handling)
  • config.py: Add skills permission entries to DEFAULT_USER_PERMISSIONS
  • Workspace layout/page: Add Skills tab (gated by workspace.skills permission)
  • Group permissions UI: Add Skills toggles

Fixed

  • N/A (new feature)

Security

  • Scripts run with restricted environment (only PATH, HOME, LANG, API keys passed through)
  • External skill directories mounted read-only
  • All endpoints enforce access control via has_access() / has_permission()
  • Script execution: stdin=/dev/null, timeout enforcement, output truncation

Breaking Changes

  • None. New feature, no existing behavior modified.

Additional Information

Architecture

~/.claude/skills/ (mounted RO)
    │
    ├─ tavily/search/SKILL.md + scripts/search.sh
    ├─ databases/SKILL.md + scripts/db_backup.py
    └─ devops/SKILL.md + scripts/docker_optimize.py
    
    ↓ (startup sync)
    
[skill table in DB] ← CRUD via /api/v1/skills/
    
    ↓ (chat request)
    
middleware.py:
  1. Collect active skills (explicit + always + auto + semantic)
  2. For skills with scripts → subprocess.run() → capture output
  3. Inject skill prompt + execution output into system message
  4. LLM sees enriched context

Testing performed

Test Model Result
Shell script execution (Tavily search) gemini-3-flash Real API results injected
Python script skill (databases) gemini-3-flash Prompt injected, script help text returned
No skill triggers (unrelated topic) gemini-3-flash Clean response, no skill tags
Specific skill auto-triggers (Dockerfile) gemini-3-flash Only devops skill activates
Explicit skill_ids override gemini-3-flash Forced skill loads correctly
Non-admin user access gemini-3-flash Skills tab hidden, skills still activate in chat
84 external skills sync on startup N/A All discovered and persisted

Contributor License Agreement

By submitting this pull request, I confirm that I have read and fully agree to the Contributor License Agreement (CLA), and I am providing my contributions under its terms.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/open-webui/open-webui/pull/21275 **Author:** [@dathtd119](https://github.com/dathtd119) **Created:** 2/9/2026 **Status:** ❌ Closed **Base:** `dev` ← **Head:** `feat/agent-skills` --- ### 📝 Commits (1) - [`5b54584`](https://github.com/open-webui/open-webui/commit/5b54584312847b10552a7ea2ffff70a659983380) feat: add Agent Skills system with semantic activation and script execution ### 📊 Changes **20 files changed** (+2981 additions, -101 deletions) <details> <summary>View changed files</summary> 📝 `backend/open_webui/config.py` (+18 -0) ➕ `backend/open_webui/internal/migrations/019_add_skills.py` (+66 -0) 📝 `backend/open_webui/main.py` (+23 -1) ➕ `backend/open_webui/models/skills.py` (+260 -0) ➕ `backend/open_webui/routers/skills.py` (+285 -0) 📝 `backend/open_webui/utils/middleware.py` (+609 -99) ➕ `backend/open_webui/utils/skills_executor.py` (+216 -0) ➕ `backend/open_webui/utils/skills_external_bridge.py` (+357 -0) ➕ `src/lib/apis/skills/index.ts` (+295 -0) 📝 `src/lib/components/admin/Users/Groups/Permissions.svelte` (+32 -0) 📝 `src/lib/components/chat/Chat.svelte` (+5 -0) ➕ `src/lib/components/workspace/Skills.svelte` (+412 -0) ➕ `src/lib/components/workspace/Skills/SkillEditor.svelte` (+288 -0) 📝 `src/lib/constants/permissions.ts` (+4 -1) 📝 `src/lib/stores/index.ts` (+1 -0) 📝 `src/routes/(app)/workspace/+layout.svelte` (+14 -0) 📝 `src/routes/(app)/workspace/+page.svelte` (+2 -0) ➕ `src/routes/(app)/workspace/skills/+page.svelte` (+5 -0) ➕ `src/routes/(app)/workspace/skills/create/+page.svelte` (+26 -0) ➕ `src/routes/(app)/workspace/skills/edit/+page.svelte` (+63 -0) </details> ### 📄 Description ## Pull Request Checklist - [x] **Target branch**: `dev` - [x] **Description**: Provided below - [x] **Testing**: Manually tested all features on a live instance (port 3001) with real models (gemini-3-flash, gpt-5.3-codex) - [x] **Code review**: Self-reviewed, follows existing access control and module patterns (Tools, Functions, Knowledge) - [x] **Title Prefix**: `feat:` ## Changelog Entry ### Description Adds a native **Agent Skills** module to Open WebUI — a first-class workspace module alongside Models, Knowledge, Prompts, and Tools. Skills are reusable prompt+script bundles that can be mounted from external directories (e.g. `~/.claude/skills`) and auto-activate based on user message context. When a skill includes executable scripts (`.py`/`.sh`), they run automatically via subprocess and their output is injected into the LLM's system prompt. This enables Open WebUI to act as an agent platform where domain-specific capabilities (DevOps, databases, web search, etc.) are loaded dynamically based on conversation context — without MCP or external tool servers. ### Added - **Backend model** (`models/skills.py`): `Skill` SQLAlchemy model with `access_control` (matching Tools pattern: `None`=public, `{}`=private, custom group/user permissions), `activation` config, `effects`, `priority`, `is_active` - **DB migration** (`019_add_skills.py`): Peewee migration creating `skill` table - **Router** (`routers/skills.py`): Full CRUD + toggle + export + external sync endpoints with `has_access`/`has_permission` checks and `BYPASS_ADMIN_ACCESS_CONTROL` support - **External bridge** (`utils/skills_external_bridge.py`): Scans mounted directories for `SKILL.md`/`plugin.json` files, extracts metadata, discovers bundled scripts, and upserts into DB on startup - **Script executor** (`utils/skills_executor.py`): Runs `.py`/`.sh` scripts via `subprocess.run()` with timeout (30s default), output limit (10KB), `stdin=/dev/null`, sandbox `cwd=/tmp` - **Semantic activation** (`utils/middleware.py`): Three activation modes — `always`, `auto` (keyword/regex rules), `semantic` (LLM-based intent matching with token-overlap fallback). Skills auto-execute scripts when triggered. - **Config** (`config.py`): `USER_PERMISSIONS_WORKSPACE_SKILLS_ACCESS`, `_IMPORT`, `_EXPORT` permission keys (default `False` — admin-managed, skills still activate for all users via public `access_control`) - **Frontend**: Workspace Skills UI (`Skills.svelte`, `SkillEditor.svelte`), API client (`apis/skills/index.ts`), workspace layout tab, group permissions toggles ### Changed - `main.py`: Register skills router, add startup external skills sync - `middleware.py`: Add skill activation pipeline in `process_chat_payload` (between system prompt setup and folder handling) - `config.py`: Add skills permission entries to `DEFAULT_USER_PERMISSIONS` - Workspace layout/page: Add Skills tab (gated by `workspace.skills` permission) - Group permissions UI: Add Skills toggles ### Fixed - N/A (new feature) ### Security - Scripts run with restricted environment (only PATH, HOME, LANG, API keys passed through) - External skill directories mounted read-only - All endpoints enforce access control via `has_access()` / `has_permission()` - Script execution: `stdin=/dev/null`, timeout enforcement, output truncation ### Breaking Changes - None. New feature, no existing behavior modified. ## Additional Information ### Architecture ``` ~/.claude/skills/ (mounted RO) │ ├─ tavily/search/SKILL.md + scripts/search.sh ├─ databases/SKILL.md + scripts/db_backup.py └─ devops/SKILL.md + scripts/docker_optimize.py ↓ (startup sync) [skill table in DB] ← CRUD via /api/v1/skills/ ↓ (chat request) middleware.py: 1. Collect active skills (explicit + always + auto + semantic) 2. For skills with scripts → subprocess.run() → capture output 3. Inject skill prompt + execution output into system message 4. LLM sees enriched context ``` ### Testing performed | Test | Model | Result | |------|-------|--------| | Shell script execution (Tavily search) | gemini-3-flash | ✅ Real API results injected | | Python script skill (databases) | gemini-3-flash | ✅ Prompt injected, script help text returned | | No skill triggers (unrelated topic) | gemini-3-flash | ✅ Clean response, no skill tags | | Specific skill auto-triggers (Dockerfile) | gemini-3-flash | ✅ Only devops skill activates | | Explicit skill_ids override | gemini-3-flash | ✅ Forced skill loads correctly | | Non-admin user access | gemini-3-flash | ✅ Skills tab hidden, skills still activate in chat | | 84 external skills sync on startup | N/A | ✅ All discovered and persisted | ## Contributor License Agreement By submitting this pull request, I confirm that I have read and fully agree to the Contributor License Agreement (CLA), and I am providing my contributions under its terms. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-04-30 01:22:46 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/open-webui#49054