5.3 Skills 技能系统设计 — 项目知识的持久化与复用 本节导读:深入理解 Agent Skills 系统的设计原理与编写方法,掌握如何将项目知识编码为可复用的技能包,让循环每次运行都能自动获取正确的上下文。 学习目标 理解 Skills 的结构和组成 掌握 Skills 编写的核心原则和最佳实践 学会设计触发方式(显式调用 vs 自动匹配) 理解 Skills 与 Plugin 的关系 核心概念 Addy Osmani 对 Skills 的精准描述:"A skill is how you stop re-explaining the same project context every session like a goldfish.
本节导读:深入理解 Agent Skills 系统的设计原理与编写方法,掌握如何将项目知识编码为可复用的技能包,让循环每次运行都能自动获取正确的上下文。
Addy Osmani 对 Skills 的精准描述:"A skill is how you stop re-explaining the same project context every session like a goldfish. It's that intent written down on the outside."(Skill 是你不再像金鱼一样每次会话都重新解释项目上下文的方法。它就是把意图写在外面。)
Skills 解决的是循环工程中的"意图债务"(Intent Debt)——Agent 每次启动都从零开始,如果你不在外部写清楚项目的约定、规范和历史,Agent 就只能猜测。
# .claude/skills/api-design.md ## 概述 API 设计技能:帮助 Agent 设计 RESTful API。 ## 元数据 description: API 端点设计、路由结构、请求响应格式规范 ## 项目约定 - RESTful 路由命名: /api/v{version}/{resource} - 成功响应格式: { "success": true, "data": {...}, "meta": {...} } - 错误响应格式: { "success": false, "error": { "code": "ERR_xxx", "message": "..." } } - 分页: ?page=1&limit=20,响应包含 meta.page, meta.totalPages ## 错误码规范 | 错误码 | HTTP 状态码 | 含义 | |--------|------------|------| | ERR_VALIDATION | 400 | 请求参数验证失败 | | ERR_AUTH | 401 | 未授权 | | ERR_FORBIDDEN | 403 | 权限不足 | | ERR_NOT_FOUND | 404 | 资源不存在 | | ERR_CONFLICT | 409 | 资源冲突 | | ERR_RATE_LIMIT | 429 | 请求频率超限 | ## 不要做 - 不要在 URL 中使用动词(用 /users 而不是 /getUsers) - 不要返回裸数组(始终包裹在 data 对象中) - 不要在响应中暴露内部 ID(使用 UUID) ## 参考文件 - docs/api-standards.md - examples/user-api-example.json
""" skill_manager.py - Skills 管理器 """ import os import re from dataclasses import dataclass from typing import List @dataclass class Skill: name: str description: str content: str path: str class SkillManager: """Skills 管理和匹配系统""" def __init__(self, skills_dir: str): self.skills_dir = skills_dir self.skills: List[Skill] = [] self.load_skills() def load_skills(self): """加载所有 Skills""" if not os.path.exists(self.skills_dir): return for skill_file in os.listdir(self.skills_dir): if skill_file.endswith('.md'): path = os.path.join(self.skills_dir, skill_file) with open(path, 'r') as f: content = f.read() # 从内容中提取描述 description = self._extract_description(content) name = skill_file.replace('.md', '') self.skills.append(Skill( name=name, description=description, content=content, path=path )) print(f"加载了 {len(self.skills)} 个 Skills") for s in self.skills: print(f" - {s.name}: {s.description[:50]}...") def _extract_description(self, content: str) -> str: """从 SKILL.md 中提取描述""" # 查找 description: 行 for line in content.split('\n'): if line.strip().startswith('description:'): return line.split(':', 1)[1].strip() return "" def match(self, task_description: str) -> List[Skill]: """根据任务描述匹配最相关的 Skills""" scored = [] for skill in self.skills: score = self._compute_relevance( task_description, skill.description ) if score > 0.3: # 相关度阈值 scored.append((skill, score)) # 按相关度排序 scored.sort(key=lambda x: x[1], reverse=True) return [s for s, _ in scored] def _compute_relevance(self, task: str, description: str) -> float: """计算任务与 Skill 的相关度""" task_keywords = set(task.lower().split()) desc_keywords = set(description.lower().split()) overlap = task_keywords & desc_keywords if not desc_keywords: return 0.0 return len(overlap) / len(desc_keywords) def get_skill_content(self, skill_name: str) -> str: """获取指定 Skill 的完整内容""" for skill in self.skills: if skill.name == skill_name: return skill.content return "" # 使用 manager = SkillManager(".claude/skills") matched = manager.match("设计用户注册的 REST API") for s in matched: print(f"匹配: {s.name} -> 加载 {len(s.content)} 字节知识")
class SkillCombiner: """Skill 组合器:将多个简单 Skill 组合为复杂能力""" def combine_for_task(self, task: str, skills: List[Skill]) -> str: """为任务组合相关 Skills""" combined = f"# 组合指令集: {task}\n\n" # 按 Skill 优先级排列 for i, skill in enumerate(skills, 1): combined += f"\n## Skill {i}: {skill.name}\n" combined += skill.content[:2000] + "\n" combined += "---\n" # 添加冲突解决规则 combined += "\n## 冲突解决规则\n" combined += "当多个 Skill 的指令冲突时:\n" combined += "1. 安全相关的指令优先\n" combined += "2. 更具体的指令优先于通用指令\n" combined += "3. 禁止事项优先于建议事项\n" return combined
A:用 Agent 会搜索的关键词来写。Osmani 的建议是"a tight boring description beats a clever one"(紧凑无聊的描述胜过聪明的描述)。例如,"API 端点设计、路由结构、请求响应格式规范" 比 "让你的 API 更优雅" 好得多——前者在任务提到"API设计"时会被正确匹配。
A:拆分为多个 Skill。每个 Skill 应该聚焦于一个特定领域。例如,将一个包含所有 API 规范的巨大 Skill 拆分为:api-routing.md、api-errors.md、api-auth.md。Agent 会根据任务自动匹配需要的 Skill 子集。
A:Skill 是作者格式,Plugin 是分发格式。Skill 就是一个文件夹(SKILL.md + 可选脚本和资源),你在自己的项目中编写和使用。当你想跨项目共享或打包分发时,把一个或多个 Skill 打包成 Plugin。Claude Code 和 Codex 都支持 Plugin 格式的安装和管理。
本节深入介绍了 Agent Skills 系统的设计与编写方法。Skills 是循环工程的"项目大脑"——它们将项目知识编码为 Agent 可以自动读取的格式,消除了"意图债务"。关键收获:无聊但精确的描述胜过聪明但模糊的描述。
下一节我们将探讨企业级 Agent 运行时的设计。
关键词:Loop Engineering, Skills, Agent Skills, SKILL.md, 插件, 项目知识, 意图债务, Claude Code, 教程, 实战