diff --git a/.github/workflows/dev-build.yaml b/.github/workflows/dev-build.yaml index e7a912bff6f..d5a45444aac 100644 --- a/.github/workflows/dev-build.yaml +++ b/.github/workflows/dev-build.yaml @@ -6,7 +6,7 @@ concurrency: on: push: - branches: ['arm-runner-test'] # put your current branch to create a build. Core team only. + branches: ['disable-default-agent-skills'] # put your current branch to create a build. Core team only. paths-ignore: - '**.md' - 'cloud-deployments/*' diff --git a/frontend/src/pages/Admin/Agents/DefaultSkillPanel/index.jsx b/frontend/src/pages/Admin/Agents/DefaultSkillPanel/index.jsx index d28f35cf29c..e2505b3ed43 100644 --- a/frontend/src/pages/Admin/Agents/DefaultSkillPanel/index.jsx +++ b/frontend/src/pages/Admin/Agents/DefaultSkillPanel/index.jsx @@ -1,7 +1,15 @@ import React from "react"; import { DefaultBadge } from "../Badges/default"; -export default function DefaultSkillPanel({ title, description, image, icon }) { +export default function DefaultSkillPanel({ + title, + description, + image, + icon, + enabled = true, + toggleSkill, + skill, +}) { return (
@@ -21,10 +29,26 @@ export default function DefaultSkillPanel({ title, description, image, icon }) {
+
{title}

{description} +
+
+ By default, this skill is enabled, but you can disable it if you don't + want it to be available to the agent.

diff --git a/frontend/src/pages/Admin/Agents/index.jsx b/frontend/src/pages/Admin/Agents/index.jsx index e176aeecbc7..605c89348a8 100644 --- a/frontend/src/pages/Admin/Agents/index.jsx +++ b/frontend/src/pages/Admin/Agents/index.jsx @@ -15,14 +15,16 @@ import ImportedSkillConfig from "./Imported/ImportedSkillConfig"; import { Tooltip } from "react-tooltip"; export default function AdminAgents() { + const formEl = useRef(null); const [hasChanges, setHasChanges] = useState(false); const [settings, setSettings] = useState({}); const [selectedSkill, setSelectedSkill] = useState(""); - const [agentSkills, setAgentSkills] = useState([]); - const [importedSkills, setImportedSkills] = useState([]); const [loading, setLoading] = useState(true); const [showSkillModal, setShowSkillModal] = useState(false); - const formEl = useRef(null); + + const [agentSkills, setAgentSkills] = useState([]); + const [importedSkills, setImportedSkills] = useState([]); + const [disabledAgentSkills, setDisabledAgentSkills] = useState([]); // Alert user if they try to leave the page with unsaved changes useEffect(() => { @@ -42,17 +44,31 @@ export default function AdminAgents() { async function fetchSettings() { const _settings = await System.keys(); const _preferences = await Admin.systemPreferencesByFields([ + "disabled_agent_skills", "default_agent_skills", "imported_agent_skills", ]); setSettings({ ..._settings, preferences: _preferences.settings } ?? {}); setAgentSkills(_preferences.settings?.default_agent_skills ?? []); + setDisabledAgentSkills( + _preferences.settings?.disabled_agent_skills ?? [] + ); setImportedSkills(_preferences.settings?.imported_agent_skills ?? []); setLoading(false); } fetchSettings(); }, []); + const toggleDefaultSkill = (skillName) => { + setDisabledAgentSkills((prev) => { + const updatedSkills = prev.includes(skillName) + ? prev.filter((name) => name !== skillName) + : [...prev, skillName]; + setHasChanges(true); + return updatedSkills; + }); + }; + const toggleAgentSkill = (skillName) => { setAgentSkills((prev) => { const updatedSkills = prev.includes(skillName) @@ -93,11 +109,15 @@ export default function AdminAgents() { if (success) { const _settings = await System.keys(); const _preferences = await Admin.systemPreferencesByFields([ + "disabled_agent_skills", "default_agent_skills", "imported_agent_skills", ]); setSettings({ ..._settings, preferences: _preferences.settings } ?? {}); setAgentSkills(_preferences.settings?.default_agent_skills ?? []); + setDisabledAgentSkills( + _preferences.settings?.disabled_agent_skills ?? [] + ); setImportedSkills(_preferences.settings?.imported_agent_skills ?? []); showToast(`Agent preferences saved successfully.`, "success", { clear: true, @@ -143,6 +163,11 @@ export default function AdminAgents() { type="hidden" value={agentSkills.join(",")} /> + {/* Skill settings nav */} {/* Default skills */} { setSelectedSkill(skill); setShowSkillModal(true); }} + activeSkills={Object.keys(defaultSkills).filter( + (skill) => !disabledAgentSkills.includes(skill) + )} /> {/* Configurable skills */} ) : ( - + {defaultSkills?.[selectedSkill] ? ( + // The selected skill is a default skill - show the default skill panel + + ) : ( + // The selected skill is a configurable skill - show the configurable skill panel + )} - setHasChanges={setHasChanges} - {...(configurableSkills[selectedSkill] || - defaultSkills[selectedSkill])} - /> + )} ) : ( @@ -258,6 +303,11 @@ export default function AdminAgents() { type="hidden" value={agentSkills.join(",")} /> + {/* Skill settings nav */}
@@ -268,10 +318,12 @@ export default function AdminAgents() { {/* Default skills list */} !disabledAgentSkills.includes(skill) + )} /> {/* Configurable skills */} ) : ( - + {defaultSkills?.[selectedSkill] ? ( + // The selected skill is a default skill - show the default skill panel + + ) : ( + // The selected skill is a configurable skill - show the configurable skill panel + )} - setHasChanges={setHasChanges} - {...(configurableSkills[selectedSkill] || - defaultSkills[selectedSkill])} - /> + )} ) : ( diff --git a/frontend/src/pages/Admin/Agents/skills.js b/frontend/src/pages/Admin/Agents/skills.js index d7dfddfb7d9..0b73cca675a 100644 --- a/frontend/src/pages/Admin/Agents/skills.js +++ b/frontend/src/pages/Admin/Agents/skills.js @@ -23,21 +23,24 @@ export const defaultSkills = { component: DefaultSkillPanel, icon: Brain, image: RAGImage, + skill: "rag-memory", }, - "view-summarize": { + "document-summarizer": { title: "View & summarize documents", description: "Allow the agent to list and summarize the content of workspace files currently embedded.", component: DefaultSkillPanel, icon: File, image: SummarizeImage, + skill: "document-summarizer", }, - "scrape-websites": { + "web-scraping": { title: "Scrape websites", description: "Allow the agent to visit and scrape the content of websites.", component: DefaultSkillPanel, icon: Browser, image: ScrapeWebsitesImage, + skill: "web-scraping", }, }; diff --git a/server/endpoints/admin.js b/server/endpoints/admin.js index cf3c310d85a..e4e556e57bc 100644 --- a/server/endpoints/admin.js +++ b/server/endpoints/admin.js @@ -374,6 +374,9 @@ function adminEndpoints(app) { case "default_agent_skills": requestedSettings[label] = safeJsonParse(setting?.value, []); break; + case "disabled_agent_skills": + requestedSettings[label] = safeJsonParse(setting?.value, []); + break; case "imported_agent_skills": requestedSettings[label] = ImportedPlugin.listImportedPlugins(); break; @@ -440,6 +443,12 @@ function adminEndpoints(app) { ?.value, [] ) || [], + disabled_agent_skills: + safeJsonParse( + (await SystemSettings.get({ label: "disabled_agent_skills" })) + ?.value, + [] + ) || [], imported_agent_skills: ImportedPlugin.listImportedPlugins(), custom_app_name: (await SystemSettings.get({ label: "custom_app_name" }))?.value || diff --git a/server/models/systemSettings.js b/server/models/systemSettings.js index 402fbf8e575..4a862109fb0 100644 --- a/server/models/systemSettings.js +++ b/server/models/systemSettings.js @@ -24,6 +24,7 @@ const SystemSettings = { "agent_search_provider", "agent_sql_connections", "default_agent_skills", + "disabled_agent_skills", "imported_agent_skills", "custom_app_name", "feature_flags", @@ -40,6 +41,7 @@ const SystemSettings = { "text_splitter_chunk_overlap", "agent_search_provider", "default_agent_skills", + "disabled_agent_skills", "agent_sql_connections", "custom_app_name", @@ -125,6 +127,15 @@ const SystemSettings = { return JSON.stringify([]); } }, + disabled_agent_skills: (updates) => { + try { + const skills = updates.split(",").filter((skill) => !!skill); + return JSON.stringify(skills); + } catch (e) { + console.error(`Could not validate disabled agent skills.`); + return JSON.stringify([]); + } + }, agent_sql_connections: async (updates) => { const existingConnections = safeJsonParse( (await SystemSettings.get({ label: "agent_sql_connections" }))?.value, diff --git a/server/utils/agents/defaults.js b/server/utils/agents/defaults.js index 6154fab6672..093982b791b 100644 --- a/server/utils/agents/defaults.js +++ b/server/utils/agents/defaults.js @@ -4,6 +4,13 @@ const { safeJsonParse } = require("../http"); const Provider = require("./aibitat/providers/ai-provider"); const ImportedPlugin = require("./imported"); +// This is a list of skills that are built-in and default enabled. +const DEFAULT_SKILLS = [ + AgentPlugins.memory.name, + AgentPlugins.docSummarizer.name, + AgentPlugins.webScraping.name, +]; + const USER_AGENT = { name: "USER", getDefinition: async () => { @@ -17,16 +24,9 @@ const USER_AGENT = { const WORKSPACE_AGENT = { name: "@agent", getDefinition: async (provider = null) => { - const defaultFunctions = [ - AgentPlugins.memory.name, // RAG - AgentPlugins.docSummarizer.name, // Doc Summary - AgentPlugins.webScraping.name, // Collector web-scraping - ]; - return { role: Provider.systemPrompt(provider), functions: [ - ...defaultFunctions, ...(await agentSkillsFromSystemSettings()), ...(await ImportedPlugin.activeImportedPlugins()), ], @@ -41,10 +41,29 @@ const WORKSPACE_AGENT = { */ async function agentSkillsFromSystemSettings() { const systemFunctions = []; - const _setting = (await SystemSettings.get({ label: "default_agent_skills" })) - ?.value; - safeJsonParse(_setting, []).forEach((skillName) => { + // Load non-imported built-in skills that are configurable, but are default enabled. + const _disabledDefaultSkills = safeJsonParse( + await SystemSettings.getValueOrFallback( + { label: "disabled_agent_skills" }, + "[]" + ), + [] + ); + DEFAULT_SKILLS.forEach((skill) => { + if (!_disabledDefaultSkills.includes(skill)) + systemFunctions.push(AgentPlugins[skill].name); + }); + + // Load non-imported built-in skills that are configurable. + const _setting = safeJsonParse( + await SystemSettings.getValueOrFallback( + { label: "default_agent_skills" }, + "[]" + ), + [] + ); + _setting.forEach((skillName) => { if (!AgentPlugins.hasOwnProperty(skillName)) return; // This is a plugin module with many sub-children plugins who