Skip to content

Latest commit

ย 

History

History
261 lines (211 loc) ยท 11.3 KB

File metadata and controls

261 lines (211 loc) ยท 11.3 KB
author Nexu

Skill ็ณป็ปŸ

ๆ ธๅฟƒๆดžๅฏŸ๏ผš Skill ไธๆ˜ฏ Toolโ€”โ€”ๅฎƒๆ˜ฏไธ€็ป„็›ธๅ…ณ Toolใ€ๆ–‡ๆกฃๅ’Œ่กŒไธบ่ง„ๅˆ™ๆ‰“ๅŒ…ๆˆ็š„่ƒฝๅŠ›ๅ•ๅ…ƒใ€‚Skill ็ณป็ปŸๆŠŠ"100 ไธช Tool ๅกž่ฟ›ๆฏไธช Prompt"ๅ˜ๆˆไบ†"ๆŒ‰้œ€ๅŠ ่ฝฝ็š„่ƒฝๅŠ›่œๅ•"๏ผŒ่Š‚็œๆ•ฐๅƒ Token ๅนถๅคงๅน…ๆๅ‡ Tool ้€‰ๆ‹ฉๅ‡†็กฎ็އใ€‚

ไป€ไนˆๆ˜ฏ Skill๏ผŸ

Tool ๆ˜ฏๆจกๅž‹ๅฏไปฅ่ฐƒ็”จ็š„ๅ•ไธชๅ‡ฝๆ•ฐใ€‚Skill ๆ˜ฏไธ€ไธชๆ‰“ๅŒ…็š„่ƒฝๅŠ›ๅ•ๅ…ƒ๏ผŒๅŒ…ๅซ๏ผš

  • Tool โ€”โ€” ไธ€ไธชๆˆ–ๅคšไธช็›ธๅ…ณ็š„ๅ‡ฝๆ•ฐ Schema ๅ’Œๅค„็†ๅ™จ
  • ๆ–‡ๆกฃ โ€”โ€” ไธ€ไธช SKILL.md ๆ–‡ไปถ๏ผŒ่ฏดๆ˜Žไฝ•ๆ—ถไปฅๅŠๅฆ‚ไฝ•ไฝฟ็”จ่ฟ™ไธช Skill
  • ่กŒไธบ่ง„ๅˆ™ โ€”โ€” ๆจกๅž‹้œ€่ฆ้ตๅพช็š„็บฆๆŸใ€ๆจกๅผๅ’Œๆƒฏไพ‹
skill/
โ”œโ”€โ”€ SKILL.md          # Documentation: when to use, how to use, constraints
โ”œโ”€โ”€ tools.py          # Tool implementations
โ””โ”€โ”€ schema.json       # Tool schemas (or generated from code)

ไพ‹ๅฆ‚๏ผŒไธ€ไธช git Skill ไธๆ˜ฏๆšด้œฒไธ€ไธชๅ•ไธ€็š„ git Toolโ€”โ€”ๅฎƒๆ‰“ๅŒ…ไบ† git_statusใ€git_diffใ€git_commitใ€git_pushใ€git_log๏ผŒๅนถๅŒ…ๅซไบ† commit message ่ง„่Œƒใ€ๅˆ†ๆ”ฏๅ‘ฝๅๅ’Œไฝ•ๆ—ถ้œ€่ฆ็กฎ่ฎคๅ† push ็š„ๆ–‡ๆกฃใ€‚

Skill ไธŽ Tool ็š„ๅŒบๅˆซ

Tool Skill
่Œƒๅ›ด ๅ•ไธชๅ‡ฝๆ•ฐ ไธ€็ป„็›ธๅ…ณๅ‡ฝๆ•ฐ
ๆ–‡ๆกฃ ๅ‚ๆ•ฐๆ่ฟฐ ๅฎŒๆ•ด็š„ SKILL.md๏ผŒๅซ็คบไพ‹ๅ’Œๆƒฏไพ‹
ๅŠ ่ฝฝๆ–นๅผ ๅง‹็ปˆๅญ˜ๅœจๆˆ–ไธๅญ˜ๅœจ ไปŽ่œๅ•ๆŒ‰้œ€ๅŠ ่ฝฝ
Context ๆˆๆœฌ ๆฏไธช Schema ็บฆ 100โ€“200 Token ่œๅ•้กน็บฆ 200 Token + ๅŠ ่ฝฝๅŽ็บฆ 1,000 Token
่กŒไธบ่ง„ๅˆ™ ๆ—  ๅฏๅŒ…ๅซ็บฆๆŸใ€ๅทฅไฝœๆตใ€ๆจกๅผ

่ฟ™ไธชๅŒบๅˆซๅฏน Token ็ปๆตŽๅพˆ้‡่ฆใ€‚ไธ€ไธชๆœ‰ 80 ไธช Tool ็š„ Harness ๆฏๆฌก API ่ฐƒ็”จไป… Schema ๅฐฑ่ฆ่Šฑ็บฆ 12,000 Tokenใ€‚ไธ€ไธชๆœ‰ 15 ไธช Skill ๅ’Œ 300 Token ่œๅ•็š„ Skill ็ณป็ปŸๅชๅŠ ่ฝฝ้œ€่ฆ็š„้ƒจๅˆ†ใ€‚

SKILL.md ๆ ผๅผ

SKILL.md ๆ–‡ไปถๆ˜ฏ Skill ็š„ไฝฟ็”จๆ‰‹ๅ†Œใ€‚ๆจกๅž‹ๅœจ Skill ่ขซๅŠ ่ฝฝๆ—ถ่ฏปๅ–ๅฎƒ๏ผš

# Git Operations

## When to Use
- User asks to check, commit, or push code changes
- You need to inspect file history or diffs
- Resolving merge conflicts

## Available Tools
- `git_status` โ€” Show working tree status
- `git_diff` โ€” Show changes (staged or unstaged)
- `git_commit` โ€” Commit staged changes with a message
- `git_push` โ€” Push commits to remote
- `git_log` โ€” Show recent commit history

## Conventions
- Always run `git_status` before committing
- Use conventional commit messages (feat:, fix:, docs:)
- Never force-push without explicit user approval
- Commit message should be under 72 characters

## Examples
To commit and push:
1. `git_status` โ†’ review what's changed
2. `git_diff` โ†’ verify the changes are correct
3. `git_commit("feat: add user auth middleware")`
4. `git_push`

่ฟ™ไธชๆ ผๅผ็ป™ไบ†ๆจกๅž‹่ถณๅคŸ็š„ไธŠไธ‹ๆ–‡ๆฅๆญฃ็กฎไฝฟ็”จ Skill๏ผŒ่€Œไธ้œ€่ฆๆŠŠๆ‰€ๆœ‰็Ÿฅ่ฏ†ๅกž่ฟ› Tool ๆ่ฟฐ้‡Œใ€‚

Skill ่œๅ•ๆจกๅผ

ไธ่ฆๅœจๅฏๅŠจๆ—ถๅŠ ่ฝฝๆ‰€ๆœ‰ Tool๏ผŒ่€Œๆ˜ฏ็ป™ๆจกๅž‹ๅ‘ˆ็Žฐไธ€ไธช็ดงๅ‡‘็š„ๅฏ็”จ Skill ่œๅ•ใ€‚ๆจกๅž‹่ฏปๅ–่œๅ•๏ผŒๅ†ณๅฎš้œ€่ฆๅ“ชไธช Skill๏ผŒ็„ถๅŽๅŠ ่ฝฝๅฎƒ๏ผš

SKILL_MENU = """Available skills (use load_skill to activate):

- file_ops: Read, write, search, and edit files in the workspace
- git: Version control โ€” status, diff, commit, push, log
- web: HTTP requests, web search, URL fetching
- shell: Execute shell commands in a sandbox
- database: SQL queries, schema inspection, migrations
- calendar: Create events, check availability, manage schedules
- email: Read inbox, send emails, search messages
- image: Generate and analyze images
"""

่œๅ•ๅช่Šฑ็บฆ 150 Tokenใ€‚ๅŠ ่ฝฝไธ€ไธช Skill ๅขžๅŠ ๅ…ถ SKILL.md๏ผˆ็บฆ 500โ€“1,000 Token๏ผ‰ๅ’Œ Tool Schema๏ผˆ็บฆ 200โ€“800 Token๏ผ‰ใ€‚ๅฏนๆฏ”้ข„ๅ…ˆๅŠ ่ฝฝๆ‰€ๆœ‰ Tool๏ผš

็ญ–็•ฅ                        Token ๆ•ฐ (8 ไธช Skill๏ผŒ็บฆ 60 ไธช Tool)
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
ๅ…จ้ƒจ้ข„ๅ…ˆๅŠ ่ฝฝ:                ~12,000 tokens (ๆฏๆฌก้ƒฝๆ˜ฏ)
Skill ่œๅ• + ๅŠ ่ฝฝ 2 ไธช:     ~150 + ~2,400 = ~2,550 tokens
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
่Š‚็œ:                       ๆฏ่ฝฎ็บฆ 9,450 tokens (78%)

ๅœจ 30 ่ฝฎ Session ไธญ๏ผŒ่Š‚็œ็บฆ 280K Tokenโ€”โ€”ๆŒ‰ API ๅฎšไปท็ฎ—ๆ˜ฏๅฎžๆ‰“ๅฎž็š„้’ฑใ€‚

Skill ๆณจๅ†Œ่กจๅฎž็Žฐ

import json
from pathlib import Path
from dataclasses import dataclass, field

@dataclass
class Skill:
    name: str
    description: str
    doc: str                           # Contents of SKILL.md
    tools: list[dict] = field(default_factory=list)        # Tool schemas
    handlers: dict = field(default_factory=dict)            # name โ†’ callable

class SkillRegistry:
    """Registry with on-demand skill loading."""

    def __init__(self, skills_dir: str):
        self.skills_dir = Path(skills_dir)
        self._catalog: dict[str, Skill] = {}
        self._active: dict[str, Skill] = {}
        self._scan()

    def _scan(self):
        """Scan the skills directory and build the catalog."""
        for skill_dir in self.skills_dir.iterdir():
            if not skill_dir.is_dir():
                continue
            skill_md = skill_dir / "SKILL.md"
            schema_file = skill_dir / "schema.json"
            if not skill_md.exists():
                continue

            doc = skill_md.read_text()
            # Extract first line after "# " as description
            first_heading = ""
            for line in doc.splitlines():
                if line.startswith("# "):
                    first_heading = line[2:].strip()
                    break

            schemas = []
            if schema_file.exists():
                schemas = json.loads(schema_file.read_text())

            self._catalog[skill_dir.name] = Skill(
                name=skill_dir.name,
                description=first_heading,
                doc=doc,
                tools=schemas,
            )

    def get_menu(self) -> str:
        """Generate the skill menu for the model."""
        lines = ["Available skills (use load_skill to activate):\n"]
        for name, skill in self._catalog.items():
            status = " [loaded]" if name in self._active else ""
            lines.append(f"- {name}: {skill.description}{status}")
        return "\n".join(lines)

    def load_skill(self, name: str) -> str:
        """Load a skill, making its tools available."""
        if name not in self._catalog:
            return f"Error: Unknown skill '{name}'. Check the skill menu."
        if name in self._active:
            return f"Skill '{name}' is already loaded."

        skill = self._catalog[name]
        self._active[name] = skill
        tool_names = [t["name"] for t in skill.tools]
        return (
            f"Loaded skill '{name}' with {len(skill.tools)} tools: "
            f"{', '.join(tool_names)}\n\n"
            f"Documentation:\n{skill.doc}"
        )

    def unload_skill(self, name: str) -> str:
        """Unload a skill to free up context space."""
        if name not in self._active:
            return f"Skill '{name}' is not loaded."
        del self._active[name]
        return f"Unloaded skill '{name}'."

    def get_active_schemas(self) -> list[dict]:
        """Return tool schemas for all currently loaded skills."""
        schemas = []
        for skill in self._active.values():
            schemas.extend(skill.tools)
        # Always include the meta-tools
        schemas.append({
            "name": "load_skill",
            "description": "Load a skill by name to activate its tools",
            "parameters": {
                "type": "object",
                "properties": {
                    "name": {"type": "string", "description": "Skill name from the menu"}
                },
                "required": ["name"],
            },
        })
        return schemas

    def dispatch(self, tool_name: str, arguments: dict) -> str:
        """Dispatch a tool call to the appropriate skill handler."""
        if tool_name == "load_skill":
            return self.load_skill(arguments["name"])

        for skill in self._active.values():
            if tool_name in skill.handlers:
                try:
                    return str(skill.handlers[tool_name](**arguments))
                except Exception as e:
                    return f"Error: {type(e).__name__}: {e}"

        return f"Error: Tool '{tool_name}' not found. Is the skill loaded?"

่–„ Harness + ๅŽš Skill

ๆžถๆž„ๅŽŸๅˆ™๏ผšHarness ๅบ”่ฏฅๆ˜ฏ่–„็š„โ€”โ€”ๅชๆœ‰ Agentic Loopใ€Context ็ป„่ฃ…ๅ’Œ Skill ๆณจๅ†Œ่กจใ€‚ๆ‰€ๆœ‰้ข†ๅŸŸไธ“ไธš็Ÿฅ่ฏ†้ƒฝๆ”พๅœจ Skill ไธญ๏ผš

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Harness๏ผˆ่–„๏ผ‰                                    โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚
โ”‚  โ”‚ Agentic  โ”‚  โ”‚  Context   โ”‚  โ”‚    Skill     โ”‚ โ”‚
โ”‚  โ”‚  Loop    โ”‚  โ”‚ Assembler  โ”‚  โ”‚  Registry    โ”‚ โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                      โ”‚ ๆŒ‰้œ€ๅŠ ่ฝฝ
     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
     โ–ผ                โ–ผ                โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  git    โ”‚    โ”‚  file_ops  โ”‚    โ”‚  web      โ”‚
โ”‚  skill  โ”‚    โ”‚  skill     โ”‚    โ”‚  skill    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

่ฟ™็งๅˆ†็ฆปๆœ‰ๅฎž้™…ๅฅฝๅค„๏ผš

  • Skill ๅฏ็งปๆค โ€”โ€” ไธบไธ€ไธช Harness ๅ†™็š„ Skill ๅœจๅฆไธ€ไธชไธญไนŸ่ƒฝ็”จ
  • Skill ๅฏๆต‹่ฏ• โ€”โ€” ็‹ฌ็ซ‹ๆต‹่ฏ• Tool ๅ’Œ Schema
  • Skill ๅฏ็ป„ๅˆ โ€”โ€” ๆจกๅž‹่‡ช็„ถๅœฐๅ‘็Žฐๅฆ‚ไฝ•็ป„ๅˆๅทฒๅŠ ่ฝฝ็š„ Skill
  • Harness ไฟๆŒ็ฎ€ๅ• โ€”โ€” ้€š่ฟ‡ๆทปๅŠ  Skill ๆฅๅขžๅŠ ่ƒฝๅŠ›๏ผŒ่€Œไธๆ˜ฏไฟฎๆ”นๆ ธๅฟƒ

ๅธธ่ง้™ท้˜ฑ

  • ๅฏๅŠจๆ—ถๅŠ ่ฝฝๆ‰€ๆœ‰ Skill โ€”โ€” ่ฟ่ƒŒไบ† Skill ็ณป็ปŸ็š„ๅˆ่กทใ€‚็”จ่œๅ•ๆจกๅผๆŒ‰้œ€ๅŠ ่ฝฝใ€‚
  • ๅทจๅž‹ Skill โ€”โ€” ไธ€ไธชๆœ‰ 30 ไธช Tool ็š„"ไธ‡่ƒฝ" Skill ๅชๆ˜ฏๆขไบ†ไธช้ฉฌ็”ฒ็š„ๅ…จ้‡ๅŠ ่ฝฝ้—ฎ้ข˜ใ€‚ไฟๆŒ Skill ่š็„ฆ๏ผšๆฏไธช 3โ€“8 ไธช Toolใ€‚
  • ็ผบๅฐ‘ SKILL.md โ€”โ€” ๆฒกๆœ‰ๆ–‡ๆกฃ็š„ Tool ่ฟซไฝฟๆจกๅž‹็Œœๆต‹ไฝฟ็”จๆƒฏไพ‹ใ€‚SKILL.md ไธๆ˜ฏๅฏ้€‰้กน๏ผ›ๅฎƒๆ˜ฏ Skill ็š„ๅคง่„‘ใ€‚
  • ๆฒกๆœ‰ๅธ่ฝฝๆœบๅˆถ โ€”โ€” ๅฆ‚ๆžœๆจกๅž‹ๅŠ ่ฝฝไบ†ไบ”ไธช Skill ๅดๆ— ๆณ•ๅธ่ฝฝ๏ผŒContext ไผšๅพˆๅฟซๅกซๆปกใ€‚ๅง‹็ปˆๅœจ load_skill ๆ—ๆไพ› unload_skillใ€‚
  • Skill ๅ’Œ Tool ๅ‘ฝๅๆททๆท† โ€”โ€” ๅฆ‚ๆžœ Skill ๅซ git ไธ”ๅŒ…ๅซไธ€ไธชๅซ git ็š„ Tool๏ผŒๆจกๅž‹ๅฏ่ƒฝไผšๆŠŠ Skill ๅๅฝ“ Tool ๅๆฅ่ฐƒ็”จใ€‚็”จไธๅŒ็š„ๅ‘ฝๅ๏ผšSkill ๅซ git๏ผŒTool ๅซ git_statusใ€git_diff ็ญ‰ใ€‚

ๅปถไผธ้˜…่ฏป

  • OpenClaw Skills Architecture โ€” ไธ€ไธช็”Ÿไบง็บง Skill ็ณป็ปŸ๏ผŒๅซ Skill ่œๅ•ๅ’ŒๆŒ‰้œ€ๅŠ ่ฝฝ
  • Anthropic: Tool Use Guide โ€” Tool ่ฎพ่ฎกๆœ€ไฝณๅฎž่ทต๏ผŒๅŒๆ ท้€‚็”จไบŽ Skill
  • Model Context Protocol: Tools โ€” ่ทจ Harness Tool/Skill ไบ’ๆ“ไฝœ็š„ๅผ€ๆ”พๆ ‡ๅ‡†