diff --git a/backend/open_webui/routers/memories.py b/backend/open_webui/routers/memories.py
index e8546b9efd..db2bf5e238 100644
--- a/backend/open_webui/routers/memories.py
+++ b/backend/open_webui/routers/memories.py
@@ -18,11 +18,6 @@ log = logging.getLogger(__name__)
router = APIRouter()
-@router.get("/ef")
-async def get_embeddings(request: Request):
- return {"result": await request.app.state.EMBEDDING_FUNCTION("hello world")}
-
-
############################
# GetMemories
############################
@@ -165,7 +160,7 @@ async def reset_memory_from_vector_db(
user=Depends(get_verified_user),
):
"""Reset user's memory vector embeddings.
-
+
CRITICAL: We intentionally do NOT use Depends(get_session) here.
This endpoint generates embeddings for ALL user memories in parallel using
asyncio.gather(). A user with 100 memories would trigger 100 embedding API
diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py
index 586a261103..d65e231302 100644
--- a/backend/open_webui/utils/middleware.py
+++ b/backend/open_webui/utils/middleware.py
@@ -2099,9 +2099,10 @@ async def process_chat_payload(request, form_data, user, metadata, model):
# Skills: inject manifest only — model uses view_skill tool to load full content on-demand
user_skill_ids = form_data.pop("skill_ids", None) or []
- model_skill_ids = model.get("info", {}).get("meta", {}).get("skills", [])
+ model_skill_ids = model.get("info", {}).get("meta", {}).get("skillIds", [])
all_skill_ids = list(set(user_skill_ids + model_skill_ids))
+ available_skills = []
if all_skill_ids:
from open_webui.models.skills import Skills as SkillsModel
@@ -2348,6 +2349,7 @@ async def process_chat_payload(request, form_data, user, metadata, model):
{
**extra_params,
"__event_emitter__": event_emitter,
+ "__skill_ids__": [s.id for s in available_skills],
},
features,
model,
diff --git a/backend/open_webui/utils/tools.py b/backend/open_webui/utils/tools.py
index bce57dc266..7e8520a1ac 100644
--- a/backend/open_webui/utils/tools.py
+++ b/backend/open_webui/utils/tools.py
@@ -508,7 +508,7 @@ def get_builtin_tools(
)
# Skills tools - view_skill allows model to load full skill instructions on demand
- if is_builtin_tool_enabled("skills"):
+ if extra_params.get("__skill_ids__"):
builtin_functions.append(view_skill)
for func in builtin_functions:
diff --git a/src/lib/components/workspace/Models/ModelEditor.svelte b/src/lib/components/workspace/Models/ModelEditor.svelte
index a47d738f79..05d17ddaf6 100644
--- a/src/lib/components/workspace/Models/ModelEditor.svelte
+++ b/src/lib/components/workspace/Models/ModelEditor.svelte
@@ -12,6 +12,7 @@
import Tags from '$lib/components/common/Tags.svelte';
import Knowledge from '$lib/components/workspace/Models/Knowledge.svelte';
import ToolsSelector from '$lib/components/workspace/Models/ToolsSelector.svelte';
+ import SkillsSelector from '$lib/components/workspace/Models/SkillsSelector.svelte';
import FiltersSelector from '$lib/components/workspace/Models/FiltersSelector.svelte';
import ActionsSelector from '$lib/components/workspace/Models/ActionsSelector.svelte';
import Capabilities from '$lib/components/workspace/Models/Capabilities.svelte';
@@ -89,6 +90,7 @@
let knowledge = [];
let toolIds = [];
+ let skillIds = [];
let filterIds = [];
let defaultFilterIds = [];
@@ -166,6 +168,14 @@
}
}
+ if (skillIds.length > 0) {
+ info.meta.skillIds = skillIds;
+ } else {
+ if (info.meta.skillIds) {
+ delete info.meta.skillIds;
+ }
+ }
+
if (filterIds.length > 0) {
info.meta.filterIds = filterIds;
} else {
@@ -293,6 +303,7 @@
});
toolIds = model?.meta?.toolIds ?? [];
+ skillIds = model?.meta?.skillIds ?? [];
filterIds = model?.meta?.filterIds ?? [];
defaultFilterIds = model?.meta?.defaultFilterIds ?? [];
actionIds = model?.meta?.actionIds ?? [];
@@ -736,6 +747,10 @@