Skill Development Guide
This document provides technical implementation details for the Skill system, including architecture, Provider development, and API reference.
Basic Concepts: Please read Skill System Concepts first to understand the basic concepts.
Skill Implementation by Shell Typeβ
The Skill system has different implementations for different Shell types:
| Shell Type | Skill Loading Method | Characteristics |
|---|---|---|
| Chat | Dynamic loading (load_skill tool) | LLM calls on-demand, prompt injection |
| ClaudeCode | Pre-deployed to filesystem | Downloaded to ~/.claude/skills/ at task startup |
Chat Shell Skill Flowβ
Loading Flowβ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 1. Task Start - ChatConfigBuilder builds configuration β
β β Extract skill metadata from Ghost.spec.skills β
β β Inject skill summaries into system prompt β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 2. System Prompt Contains: β
β "## Available Skills β
β - **skill_name**: description (call load_skill to use)" β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 3. LLM Decides to Load Skill β
β β Calls load_skill(skill_name="xxx") tool β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 4. LoadSkillTool Executes β
β a. Find Skill (user private first, then public) β
β b. Extract full prompt from SKILL.md β
β c. Load Provider dynamically (public skills only) β
β d. Register tools with SkillToolRegistry β
β e. Cache loaded skill for session β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Implementation Detailsβ
-
ChatConfigBuilder (
chat_shell/chat_shell/services/chat_service.py)- Extracts skill metadata from Ghost configuration
- Builds skill_names and skill_configs for the session
-
System Prompt Injection
append_skill_metadata_prompt()injects skill summaries- Format:
- **{skill_name}**: {description}
-
LoadSkillTool
- Built-in tool called by LLM
- Session-level caching prevents duplicate loading
- Dynamic Provider loading for public skills only
Claude Code Skill Flowβ
Loading Flowβ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 1. Task Start - ClaudeCodeAgent Initialization β
β β Get skills list from bot_config β
β β Call _download_and_deploy_skills() β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 2. SkillDownloader Downloads Skills β
β a. Call Backend API to query skill info β
β GET /api/v1/kinds/skills?name={skill_name} β
β b. Download skill ZIP package β
β GET /api/v1/kinds/skills/{skill_id}/download β
β c. Extract to skills directory β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 3. Skills Deployment Complete β
β - Docker mode: ~/.claude/skills/ β
β - Local mode: {task_config_dir}/skills/ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 4. Claude Code SDK Uses Skills β
β - SDK automatically reads SKILL.md from skills directory β
β - User-selected skills get emphasis prompt added β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Mode Differencesβ
| Feature | Docker Mode | Local Mode |
|---|---|---|
| Skills Directory | ~/.claude/skills/ | {task_config_dir}/skills/ |
| Cache Strategy | Clear and redeploy each time | Preserve existing, only download new |
clear_cache | true | false |
skip_existing | false | true |
Key Componentsβ
-
SkillDownloader (
executor/services/api_client.py)- Downloads skill ZIP packages from Backend API
- Extracts to specified directory
- Supports cache strategy configuration
-
ModeStrategy (
executor/agents/claude_code/mode_strategy.py)- Defines
get_skills_directory()to get skills directory - Defines
get_skills_deployment_options()to get deployment options
- Defines
-
User-Selected Skills Emphasis (
executor/agents/claude_code/claude_code_agent.py)_build_skill_emphasis_prompt()generates emphasis prompt for user-selected skills- Prompt prefix encourages model to prioritize using these skills
Skill Provider Systemβ
Providers allow Skills to define custom tools that are dynamically loaded at runtime (Chat Shell only).
Provider Interfaceβ
from abc import ABC, abstractmethod
from typing import Any, Optional
from langchain_core.tools import BaseTool
class SkillToolProvider(ABC):
"""Base class for Skill tool providers."""
@property
@abstractmethod
def provider_name(self) -> str:
"""Unique identifier for the provider."""
pass
@property
@abstractmethod
def supported_tools(self) -> list[str]:
"""List of tool names this provider supports."""
pass
@abstractmethod
def create_tool(
self,
tool_name: str,
context: SkillToolContext,
tool_config: Optional[dict[str, Any]] = None,
) -> BaseTool:
"""Create a tool instance."""
pass
Example Provider Implementationβ
from chat_shell.chat_shell.skills.provider import SkillToolProvider
from chat_shell.chat_shell.skills.context import SkillToolContext
class MermaidToolProvider(SkillToolProvider):
@property
def provider_name(self) -> str:
return "mermaid"
@property
def supported_tools(self) -> list[str]:
return ["render_mermaid"]
def create_tool(
self,
tool_name: str,
context: SkillToolContext,
tool_config: Optional[dict[str, Any]] = None,
) -> BaseTool:
config = tool_config or {}
from .render_mermaid import RenderMermaidTool
return RenderMermaidTool(
task_id=context.task_id,
subtask_id=context.subtask_id,
ws_emitter=context.ws_emitter,
render_timeout=config.get("timeout", 30.0),
)
Provider Configuration in SKILL.mdβ
---
description: "Diagram visualization"
provider:
module: provider # Python module name (without .py)
class: MyToolProvider # Provider class name
tools:
- name: tool_name
provider: provider_name
config:
timeout: 30
dependencies:
- chat_shell.chat_shell.tools.pending_requests
---
SkillToolRegistryβ
The SkillToolRegistry (chat_shell/chat_shell/skills/registry.py) manages:
- Provider registration and lookup (singleton, thread-safe)
- Dynamic Provider loading from ZIP packages
- Tool instance creation for skills
Security Considerationsβ
β οΈ Important: Only public Skills (user_id=0) can load dynamic code from providers. User-uploaded Skills can only provide prompt content. This prevents malicious code execution from user uploads.
Database Storageβ
Tablesβ
| Table | Purpose |
|---|---|
kinds | Skill CRD metadata (like other CRDs) |
skill_binaries | ZIP package binary storage |
skill_binaries Schemaβ
CREATE TABLE skill_binaries (
id INT PRIMARY KEY AUTO_INCREMENT,
kind_id INT NOT NULL, -- References kinds.id
binary_data LONGBLOB NOT NULL, -- ZIP package content
file_size INT NOT NULL, -- File size in bytes
file_hash VARCHAR(64) NOT NULL, -- SHA256 hash
created_at DATETIME,
FOREIGN KEY (kind_id) REFERENCES kinds(id) ON DELETE CASCADE
);
API Endpointsβ
| Endpoint | Method | Description |
|---|---|---|
/skills/upload | POST | Upload Skill ZIP package |
/skills | GET | List current user's Skills |
/skills/unified | GET | List user + public Skills |
/skills/public/list | GET | List public Skills |
/skills/public | POST | Create public Skill (admin only) |
/skills/invoke | POST | Get Skill prompt content |
/skills/{skill_id} | GET | Get Skill details |
/skills/{skill_id}/download | GET | Download Skill ZIP package |
/skills/{skill_id} | PUT | Update Skill |
/skills/{skill_id} | DELETE | Delete Skill (checks references) |
/api/tasks/{task_id}/skills | GET | Get task-associated Skills (used by Claude Code) |
Key Source Filesβ
Chat Shellβ
| File | Purpose |
|---|---|
chat_shell/chat_shell/skills/registry.py | SkillToolRegistry singleton |
chat_shell/chat_shell/skills/provider.py | SkillToolProvider base class |
chat_shell/chat_shell/skills/context.py | SkillToolContext for tool creation |
chat_shell/chat_shell/tools/skill_factory.py | Skill tool factory |
Executor (Claude Code)β
| File | Purpose |
|---|---|
executor/services/api_client.py | SkillDownloader and fetch_task_skills |
executor/agents/claude_code/claude_code_agent.py | _download_and_deploy_skills implementation |
executor/agents/claude_code/mode_strategy.py | ModeStrategy base class |
executor/agents/claude_code/docker_mode_strategy.py | Docker mode strategy |
executor/agents/claude_code/local_mode_strategy.py | Local mode strategy |
Backendβ
| File | Purpose |
|---|---|
backend/app/schemas/kind.py | Skill CRD schema definition |
backend/app/models/skill_binary.py | SkillBinary SQLAlchemy model |
backend/app/api/endpoints/kind/skills.py | REST API routes |
backend/app/services/skill_service.py | SkillValidator for ZIP validation |
Frontendβ
| File | Purpose |
|---|---|
frontend/src/apis/skills.ts | API client functions |
frontend/src/features/settings/components/SkillListWithScope.tsx | Skill list with scope selector |
frontend/src/features/settings/components/skills/SkillManagementModal.tsx | Skill management dialog |
frontend/src/features/settings/components/skills/SkillUploadModal.tsx | Skill upload dialog |
Built-in Skillsβ
Located in backend/init_data/skills/:
| Skill | Description |
|---|---|
mermaid-diagram | Diagram visualization using Mermaid.js |
wiki_submit | Wiki submission capability |
Skill Lifecycleβ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 1. Create Skill β
β - User uploads ZIP package β
β - Validate SKILL.md format and extract metadata β
β - Store in kinds table and skill_binaries table β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 2. Configure Association β
β - Add skill name to Ghost.spec.skills[] β
β - Ghost is referenced by Bot β
β - Bot is referenced by Team β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 3. Runtime Loading β
β Chat Shell: β
β - Skill metadata injected into system prompt β
β - LLM calls load_skill() on demand β
β - Provider loaded and tools registered β
β β
β Claude Code: β
β - Download skill ZIP packages at task startup β
β - Extract to skills directory β
β - Claude Code SDK automatically reads and uses β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 4. Update/Delete β
β - Update: Upload new ZIP, metadata updated β
β - Delete: Check Ghost references first, reject if referenced β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Provider Development Best Practicesβ
- Follow the interface - Implement all abstract methods
- Handle errors gracefully - Return meaningful error messages
- Use context properly - Access task_id, subtask_id, ws_emitter from context
- Configure timeouts - Set reasonable timeouts in tool_config
Related Documentationβ
- Skill System Concepts - Basic concepts and usage
- Core Concepts - Overview of all CRD types
- YAML Specification - Complete YAML format reference