Refactor skills tool integration and enhance system prompt

- Removed the skills_categories tool from the skills toolset, streamlining the skills functionality to focus on skills_list and skill_view.
- Updated the system prompt to dynamically build a compact skills index, allowing the model to quickly reference available skills without additional tool calls.
- Cleaned up related code and documentation to reflect the removal of skills_categories, ensuring clarity and consistency across the codebase.
This commit is contained in:
teknium1 2026-02-10 19:48:38 -08:00
parent 669545f551
commit 153cd5bb44
4 changed files with 94 additions and 55 deletions

View file

@ -41,7 +41,7 @@ from tools.terminal_hecate import terminal_hecate_tool, check_hecate_requirement
from tools.vision_tools import vision_analyze_tool, check_vision_requirements from tools.vision_tools import vision_analyze_tool, check_vision_requirements
from tools.mixture_of_agents_tool import mixture_of_agents_tool, check_moa_requirements from tools.mixture_of_agents_tool import mixture_of_agents_tool, check_moa_requirements
from tools.image_generation_tool import image_generate_tool, check_image_generation_requirements from tools.image_generation_tool import image_generate_tool, check_image_generation_requirements
from tools.skills_tool import skills_categories, skills_list, skill_view, check_skills_requirements, SKILLS_TOOL_DESCRIPTION from tools.skills_tool import skills_list, skill_view, check_skills_requirements, SKILLS_TOOL_DESCRIPTION
# RL Training tools (Tinker-Atropos) # RL Training tools (Tinker-Atropos)
from tools.rl_training_tool import ( from tools.rl_training_tool import (
rl_list_environments, rl_list_environments,
@ -143,7 +143,7 @@ TOOLSET_REQUIREMENTS = {
"env_vars": [], # Just needs skills directory "env_vars": [], # Just needs skills directory
"check_fn": check_skills_requirements, "check_fn": check_skills_requirements,
"setup_url": None, "setup_url": None,
"tools": ["skills_categories", "skills_list", "skill_view"], "tools": ["skills_list", "skill_view"],
}, },
"rl": { "rl": {
"name": "RL Training (Tinker-Atropos)", "name": "RL Training (Tinker-Atropos)",
@ -432,24 +432,7 @@ def get_skills_tool_definitions() -> List[Dict[str, Any]]:
"properties": { "properties": {
"category": { "category": {
"type": "string", "type": "string",
"description": "Optional category filter (from skills_categories)" "description": "Optional category filter to narrow results"
}
},
"required": []
}
}
},
{
"type": "function",
"function": {
"name": "skills_categories",
"description": "List available skill categories. Call this first to discover what skill categories exist, then use skills_list(category) to see skills in a category.",
"parameters": {
"type": "object",
"properties": {
"verbose": {
"type": "boolean",
"description": "If true, include skill counts per category. Default: false."
} }
}, },
"required": [] "required": []
@ -910,7 +893,7 @@ def get_all_tool_names() -> List[str]:
# Skills tools # Skills tools
if check_skills_requirements(): if check_skills_requirements():
tool_names.extend(["skills_categories", "skills_list", "skill_view"]) tool_names.extend(["skills_list", "skill_view"])
# Browser automation tools # Browser automation tools
if check_browser_requirements(): if check_browser_requirements():
@ -957,7 +940,6 @@ TOOL_TO_TOOLSET_MAP = {
"mixture_of_agents": "moa_tools", "mixture_of_agents": "moa_tools",
"image_generate": "image_tools", "image_generate": "image_tools",
# Skills tools # Skills tools
"skills_categories": "skills_tools",
"skills_list": "skills_tools", "skills_list": "skills_tools",
"skill_view": "skills_tools", "skill_view": "skills_tools",
# Browser automation tools # Browser automation tools
@ -1109,7 +1091,7 @@ def get_tool_definitions(
"vision_tools": ["vision_analyze"], "vision_tools": ["vision_analyze"],
"moa_tools": ["mixture_of_agents"], "moa_tools": ["mixture_of_agents"],
"image_tools": ["image_generate"], "image_tools": ["image_generate"],
"skills_tools": ["skills_categories", "skills_list", "skill_view"], "skills_tools": ["skills_list", "skill_view"],
"browser_tools": [ "browser_tools": [
"browser_navigate", "browser_snapshot", "browser_click", "browser_navigate", "browser_snapshot", "browser_click",
"browser_type", "browser_scroll", "browser_back", "browser_type", "browser_scroll", "browser_back",
@ -1162,7 +1144,7 @@ def get_tool_definitions(
"vision_tools": ["vision_analyze"], "vision_tools": ["vision_analyze"],
"moa_tools": ["mixture_of_agents"], "moa_tools": ["mixture_of_agents"],
"image_tools": ["image_generate"], "image_tools": ["image_generate"],
"skills_tools": ["skills_categories", "skills_list", "skill_view"], "skills_tools": ["skills_list", "skill_view"],
"browser_tools": [ "browser_tools": [
"browser_navigate", "browser_snapshot", "browser_click", "browser_navigate", "browser_snapshot", "browser_click",
"browser_type", "browser_scroll", "browser_back", "browser_type", "browser_scroll", "browser_back",
@ -1391,11 +1373,7 @@ def handle_skills_function_call(function_name: str, function_args: Dict[str, Any
Returns: Returns:
str: Function result as JSON string str: Function result as JSON string
""" """
if function_name == "skills_categories": if function_name == "skills_list":
verbose = function_args.get("verbose", False)
return skills_categories(verbose=verbose)
elif function_name == "skills_list":
category = function_args.get("category") category = function_args.get("category")
return skills_list(category=category) return skills_list(category=category)
@ -1686,7 +1664,7 @@ def handle_function_call(
return handle_image_function_call(function_name, function_args) return handle_image_function_call(function_name, function_args)
# Route skills tools # Route skills tools
elif function_name in ["skills_categories", "skills_list", "skill_view"]: elif function_name in ["skills_list", "skill_view"]:
return handle_skills_function_call(function_name, function_args) return handle_skills_function_call(function_name, function_args)
# Route browser automation tools # Route browser automation tools
@ -1767,7 +1745,7 @@ def get_available_toolsets() -> Dict[str, Dict[str, Any]]:
}, },
"skills_tools": { "skills_tools": {
"available": check_skills_requirements(), "available": check_skills_requirements(),
"tools": ["skills_categories", "skills_list", "skill_view"], "tools": ["skills_list", "skill_view"],
"description": "Access skill documents that provide specialized instructions, guidelines, or knowledge the agent can load on demand", "description": "Access skill documents that provide specialized instructions, guidelines, or knowledge the agent can load on demand",
"requirements": ["skills/ directory in repo root"] "requirements": ["skills/ directory in repo root"]
}, },

View file

@ -550,14 +550,79 @@ def apply_anthropic_cache_control(
# Default System Prompt Components # Default System Prompt Components
# ============================================================================= # =============================================================================
# Skills guidance - instructs the model to check skills before technical tasks # Skills guidance - embeds a compact skill index in the system prompt so
SKILLS_SYSTEM_PROMPT = """## Skills # the model can match skills at a glance without extra tool calls.
Before answering technical questions about tools, frameworks, or workflows: def build_skills_system_prompt() -> str:
1. Check skills_categories to see if a relevant category exists """
2. If a category matches your task, use skills_list with that category Build a dynamic skills system prompt by scanning the skills/ directory.
3. If a skill matches, load it with skill_view and follow its instructions
Returns a prompt section that lists all skill categories (with descriptions
Skills contain vetted, up-to-date instructions for specific tools and workflows.""" from DESCRIPTION.md) and their skill names inline, so the model can
immediately see if a relevant skill exists and load it with a single
skill_view(name) call -- no discovery tool calls needed.
Returns:
str: The skills system prompt section, or empty string if no skills found.
"""
import re
from pathlib import Path
skills_dir = Path(__file__).parent / "skills"
if not skills_dir.exists():
return ""
# Scan for SKILL.md files grouped by category
skills_by_category = {}
for skill_file in skills_dir.rglob("SKILL.md"):
rel_path = skill_file.relative_to(skills_dir)
parts = rel_path.parts
if len(parts) >= 2:
category = parts[0]
skill_name = parts[-2] # Folder containing SKILL.md
else:
category = "general"
skill_name = skill_file.parent.name
skills_by_category.setdefault(category, []).append(skill_name)
if not skills_by_category:
return ""
# Load category descriptions from DESCRIPTION.md files (YAML frontmatter)
category_descriptions = {}
for category in skills_by_category:
desc_file = skills_dir / category / "DESCRIPTION.md"
if desc_file.exists():
try:
content = desc_file.read_text(encoding="utf-8")
# Parse description from YAML frontmatter: ---\ndescription: ...\n---
match = re.search(r"^---\s*\n.*?description:\s*(.+?)\s*\n.*?^---", content, re.MULTILINE | re.DOTALL)
if match:
category_descriptions[category] = match.group(1).strip()
except Exception:
pass
# Build compact index: category with description + skill names
index_lines = []
for category in sorted(skills_by_category.keys()):
desc = category_descriptions.get(category, "")
names = ", ".join(sorted(skills_by_category[category]))
if desc:
index_lines.append(f" {category}: {desc}")
else:
index_lines.append(f" {category}:")
index_lines.append(f" skills: {names}")
return (
"## Skills (mandatory)\n"
"Before replying, scan the skills below. If one clearly matches your task, "
"load it with skill_view(name) and follow its instructions.\n"
"\n"
"<available_skills>\n"
+ "\n".join(index_lines) + "\n"
"</available_skills>\n"
"\n"
"If none match, proceed normally without loading a skill."
)
class KawaiiSpinner: class KawaiiSpinner:
@ -1054,10 +1119,6 @@ class AIAgent:
return f"{face} 🎨 creating '{prompt}'... {time_str}" return f"{face} 🎨 creating '{prompt}'... {time_str}"
# Skills - use large pool for variety # Skills - use large pool for variety
elif tool_name == "skills_categories":
face = random.choice(self.KAWAII_SKILL)
return f"{face} 📚 listing categories... {time_str}"
elif tool_name == "skills_list": elif tool_name == "skills_list":
category = args.get("category", "skills") category = args.get("category", "skills")
face = random.choice(self.KAWAII_SKILL) face = random.choice(self.KAWAII_SKILL)
@ -1635,12 +1696,15 @@ class AIAgent:
base_system_prompt = system_message if system_message is not None else self.ephemeral_system_prompt base_system_prompt = system_message if system_message is not None else self.ephemeral_system_prompt
# Auto-include skills guidance if skills tools are available # Auto-include skills guidance if skills tools are available
has_skills_tools = any(name in self.valid_tool_names for name in ['skills_list', 'skills_categories', 'skill_view']) # Embeds a compact category:names index so the model can match skills
if has_skills_tools: # at a glance and load with a single skill_view(name) call.
has_skills_tools = any(name in self.valid_tool_names for name in ['skills_list', 'skill_view'])
skills_prompt = build_skills_system_prompt() if has_skills_tools else ""
if skills_prompt:
if base_system_prompt: if base_system_prompt:
active_system_prompt = f"{base_system_prompt}\n\n{SKILLS_SYSTEM_PROMPT}" active_system_prompt = f"{base_system_prompt}\n\n{skills_prompt}"
else: else:
active_system_prompt = SKILLS_SYSTEM_PROMPT active_system_prompt = skills_prompt
else: else:
active_system_prompt = base_system_prompt active_system_prompt = base_system_prompt
@ -2277,7 +2341,6 @@ class AIAgent:
'image_generate': ('sparkle', ['🎨', '', '🖼️', '🌟']), 'image_generate': ('sparkle', ['🎨', '', '🖼️', '🌟']),
'skill_view': ('star', ['📚', '📖', '🎓', '']), 'skill_view': ('star', ['📚', '📖', '🎓', '']),
'skills_list': ('pulse', ['📋', '📝', '📑', '📜']), 'skills_list': ('pulse', ['📋', '📝', '📑', '📜']),
'skills_categories': ('pulse', ['📂', '🗂️', '📁', '🏷️']),
'moa_query': ('brain', ['🧠', '💭', '🤔', '💡']), 'moa_query': ('brain', ['🧠', '💭', '🤔', '💡']),
'analyze_image': ('sparkle', ['👁️', '🔍', '📷', '']), 'analyze_image': ('sparkle', ['👁️', '🔍', '📷', '']),
} }

View file

@ -59,7 +59,6 @@ from .image_generation_tool import (
) )
from .skills_tool import ( from .skills_tool import (
skills_categories,
skills_list, skills_list,
skill_view, skill_view,
check_skills_requirements, check_skills_requirements,
@ -158,7 +157,6 @@ __all__ = [
'image_generate_tool', 'image_generate_tool',
'check_image_generation_requirements', 'check_image_generation_requirements',
# Skills tools # Skills tools
'skills_categories',
'skills_list', 'skills_list',
'skill_view', 'skill_view',
'check_skills_requirements', 'check_skills_requirements',

View file

@ -69,7 +69,7 @@ TOOLSETS = {
"skills": { "skills": {
"description": "Access skill documents with specialized instructions and knowledge", "description": "Access skill documents with specialized instructions and knowledge",
"tools": ["skills_categories", "skills_list", "skill_view"], "tools": ["skills_list", "skill_view"],
"includes": [] "includes": []
}, },
@ -142,7 +142,7 @@ TOOLSETS = {
# MoA # MoA
"mixture_of_agents", "mixture_of_agents",
# Skills # Skills
"skills_categories", "skills_list", "skill_view", "skills_list", "skill_view",
# Browser # Browser
"browser_navigate", "browser_snapshot", "browser_click", "browser_navigate", "browser_snapshot", "browser_click",
"browser_type", "browser_scroll", "browser_back", "browser_type", "browser_scroll", "browser_back",
@ -170,7 +170,7 @@ TOOLSETS = {
# Vision - analyze images sent by users # Vision - analyze images sent by users
"vision_analyze", "vision_analyze",
# Skills - access knowledge base # Skills - access knowledge base
"skills_categories", "skills_list", "skill_view", "skills_list", "skill_view",
# Cronjob management - let users schedule tasks # Cronjob management - let users schedule tasks
"schedule_cronjob", "list_cronjobs", "remove_cronjob" "schedule_cronjob", "list_cronjobs", "remove_cronjob"
], ],
@ -185,7 +185,7 @@ TOOLSETS = {
# Vision - analyze images # Vision - analyze images
"vision_analyze", "vision_analyze",
# Skills - access knowledge base # Skills - access knowledge base
"skills_categories", "skills_list", "skill_view", "skills_list", "skill_view",
# Cronjob - let users schedule reminders # Cronjob - let users schedule reminders
"schedule_cronjob", "list_cronjobs", "remove_cronjob" "schedule_cronjob", "list_cronjobs", "remove_cronjob"
], ],
@ -204,7 +204,7 @@ TOOLSETS = {
# Vision # Vision
"vision_analyze", "vision_analyze",
# Skills # Skills
"skills_categories", "skills_list", "skill_view", "skills_list", "skill_view",
# Cronjob management # Cronjob management
"schedule_cronjob", "list_cronjobs", "remove_cronjob" "schedule_cronjob", "list_cronjobs", "remove_cronjob"
], ],