当前位置: 首页 > news >正文

【与我学 ClaudeCode】规划与协调篇 之 Skills:按需加载的领域知识框架

作者:逆境不可逃

技术永无止境

希望我的内容可以帮助到你!!!!!


大家吼 ! 我是 逆境不可逃 今天给大家带来文章《【与我学 ClaudeCode】规划与协调篇 之 Skills:按需加载的领域知识框架》.

Learn-Claude-Code 官方地址 :https://github.com/shareAI-lab/learn-claude-code

Skills 是迭代的第 5 个版本(s05),核心解决系统提示词臃肿、知识加载效率低的问题。它用「两层注入 + 按需加载」的方式,让 Agent 只在需要时加载特定领域的知识,既保证了提示词缓存效率,又避免了无关知识的 token 浪费。

学习路线:s01 > s02 > s03>s04> s05> s06 | s07> s08 > s09 > s10 > s11 > s12


一、问题根源:为什么直接塞系统提示会越用越慢?

当你希望 Agent 遵循特定领域的工作流时(如 Git 约定、测试模式、代码审查清单),传统做法是把所有规则全塞进系统提示词:

  • 10 个 Skill,每个 2000 token,直接占用 20,000 token
  • 大部分知识跟当前任务毫无关系(比如修复 Python Bug 时,Kubernetes 部署的规则完全没用)
  • 每次新增 / 修改 Skill 都会改变系统提示词,导致 Anthropic、OpenAI 的 prompt caching 失效,API 调用成本飙升、响应变慢

二、三大核心设计决策(图片内容详解)

Skills 框架通过三个关键设计,完美解决了上述问题,每个决策都对比了替代方案的缺陷。

1. Skill 通过tool_result注入,而非系统提示词

核心设计:当 Agent 调用load_skill工具时,Skill 的完整内容(SKILL.md正文)会作为tool_result在用户消息中返回,而不是直接注入系统提示词。

两大关键优势

  1. 保持系统提示词可缓存:系统提示词在各轮对话中保持静态,API 提供商的 prompt caching 可以正常工作,大幅降低成本和延迟
  2. 按需注入知识:只有 Agent 需要的 Skill 才会被加载到上下文中,无关知识不会占用 token 空间

替代方案的致命缺陷

把 Skill 直接注入系统提示词实现更简单,也能让模型优先关注这些知识,但会破坏 prompt caching(每次加载新 Skill 都会生成新的系统提示词变体),而且随着 Skill 增多,系统提示词会越来越臃肿。tool_result方案牺牲了一点点注意力优先级,换来了缓存友好和 token 效率。

2. 按需加载 Skill,而非预加载

核心设计:Skill 不会在 Agent 启动时加载,初始只在系统提示词中保留 Skill 的名称和简短描述(来自 YAML frontmatter)。当 Agent 判断需要特定 Skill 时,再调用load_skill工具加载完整内容。

解决的核心问题

  • 保持初始提示词的精简,避免无关知识浪费上下文窗口
  • 让 Agent 「用什么、拿什么」,修复 Python Bug 时不会加载 Kubernetes 部署的 Skill,既省 token 又避免模型被无关指令干扰

替代方案的致命缺陷

预加载所有 Skill 能保证模型随时获取所有知识,但会在无关技能上浪费大量 token,甚至可能超出上下文限制;推荐系统(模型建议技能、人工审批)会增加延迟。懒加载(按需加载)让模型在需要时自助获取知识,是最务实的方案。

3.SKILL.md采用 YAML Frontmatter + Markdown 正文

核心设计:每个SKILL.md文件分为两部分:

  • YAML frontmatter:存储元数据(名称、描述、标签、适用文件 glob 模式),作为「Skill 注册表」的数据源
  • Markdown 正文:存储完整的技能指令、工作流、最佳实践,是按需加载的有效负载

这种分离让你可以列出 100 个 Skill(每个仅需几字节的 frontmatter),而不必一次性加载 100 套完整指令集(每套可能数千 token)。

替代方案的致命缺陷

用单独的元数据文件(skill.yaml+skill.md)也能实现,但会让文件数量翻倍;把元数据嵌入 Markdown(作为标题或注释)需要解析整个文件才能提取元数据。Frontmatter 是 Jekyll、Hugo 等静态站点生成器广泛采用的成熟约定,能让元数据和内容共存,同时又能被单独解析。


三、系统整体架构与工作原理

1. 核心架构:两层注入模型

System prompt (Layer 1 -- always present): +--------------------------------------+ | You are a coding agent. | | Skills available: | | - git: Git workflow helpers | ~100 tokens/skill | - test: Testing best practices | +--------------------------------------+ When model calls load_skill("git"): +--------------------------------------+ | tool_result (Layer 2 -- on demand): | | <skill name="git"> | | Full git workflow instructions... | ~2000 tokens | Step 1: ... | | </skill> | +--------------------------------------+
  • 第一层(低成本):系统提示词中只放 Skill 的名称和简短描述,每个仅需约 100 token,让模型知道「有什么可用」
  • 第二层(按需加载):当模型需要时,通过load_skill工具在tool_result中注入完整的 Skill 内容,仅在需要时占用 token

2. 关键组件与工作流程

(1) SkillLoader:技能加载与解析器
class SkillLoader: def __init__(self, skills_dir: Path): self.skills_dir = skills_dir self.skills = {} self._load_all() def _load_all(self): """递归扫描所有 SKILL.md 文件,解析 frontmatter 和正文""" if not self.skills_dir.exists(): return for f in sorted(self.skills_dir.rglob("SKILL.md")): text = f.read_text() meta, body = self._parse_frontmatter(text) name = meta.get("name", f.parent.name) self.skills[name] = {"meta": meta, "body": body, "path": str(f)} def _parse_frontmatter(self, text: str) -> tuple: """解析 YAML frontmatter(--- 之间的部分)""" match = re.match(r"^---\n(.*?)\n---\n(.*)", text, re.DOTALL) if not match: return {}, text try: meta = yaml.safe_load(match.group(1)) or {} except yaml.YAMLError: meta = {} return meta, match.group(2).strip() def get_descriptions(self) -> str: """第一层:生成系统提示词中的技能列表(仅元数据)""" if not self.skills: return "(no skills available)" lines = [] for name, skill in self.skills.items(): desc = skill["meta"].get("description", "No description") tags = skill["meta"].get("tags", "") line = f" - {name}: {desc}" if tags: line += f" [{tags}]" lines.append(line) return "\n".join(lines) def get_content(self, name: str) -> str: """第二层:返回完整的技能正文,用于 tool_result""" skill = self.skills.get(name) if not skill: return f"Error: Unknown skill '{name}'. Available: {', '.join(self.skills.keys())}" return f"<skill name=\"{name}\">\n{skill['body']}\n</skill>"
(2) 系统提示词初始化
# 第一层:技能元数据注入系统提示词 SYSTEM = f"""You are a coding agent at {WORKDIR}. Use load_skill to access specialized knowledge before tackling unfamiliar topics. Skills available: {SKILL_LOADER.get_descriptions()}"""
(3) 工具注册:load_skill工具
TOOL_HANDLERS = { # 基础工具(bash、read_file 等) "bash": lambda **kw: run_bash(kw["command"]), "read_file": lambda **kw: run_read(kw["path"], kw.get("limit")), "write_file": lambda **kw: run_write(kw["path"], kw["content"]), "edit_file": lambda **kw: run_edit(kw["path"], kw["old_text"], kw["new_text"]), # 新增的技能加载工具 "load_skill": lambda **kw: SKILL_LOADER.get_content(kw["name"]), } TOOLS = [ # 其他工具(略) {"name": "load_skill", "description": "Load specialized knowledge by name.", "input_schema": {"type": "object", "properties": {"name": {"type": "string", "description": "Skill name to load"}}, "required": ["name"]}}, ]
(4) Agent 主循环:处理工具调用
def agent_loop(messages: list): while True: response = client.messages.create( model=MODEL, system=SYSTEM, messages=messages, tools=TOOLS, max_tokens=8000, ) messages.append({"role": "assistant", "content": response.content}) if response.stop_reason != "tool_use": return results = [] for block in response.content: if block.type == "tool_use": handler = TOOL_HANDLERS.get(block.name) try: output = handler(**block.input) if handler else f"Unknown tool: {block.name}" except Exception as e: output = f"Error: {e}" print(f"> {block.name}:") print(str(output)[:200]) results.append({"type": "tool_result", "tool_use_id": block.id, "content": str(output)}) messages.append({"role": "user", "content": results})
(5) 执行流程


四、与 Subagent(s04)的关键变更对比

组件之前(s04 Subagent)之后(s05 Skills)
工具集5 个工具(基础 +task5 个工具(基础 +load_skill
系统提示词静态字符串新增 Skill 描述列表(元数据)
知识库skills/*/SKILL.md文件集合
知识注入方式两层模型:系统提示词(元数据)+tool_result(正文)
核心优化上下文隔离按需知识加载、提示词缓存友好

五、核心优势与创新点

  1. 极致的 token 效率:初始提示词仅加载元数据,完整知识只在需要时注入,大幅降低平均 token 消耗
  2. 缓存友好的系统提示词:系统提示词保持静态,充分利用 API 提供商的 prompt caching,降低成本和延迟
  3. 可扩展的知识管理:新增 / 修改 Skill 只需添加 / 编辑skills/目录下的文件,无需修改代码,也不会破坏缓存
  4. 结构清晰的技能定义:YAML frontmatter + Markdown 正文的模式,兼顾了元数据的可解析性和内容的可读性
  5. 模型自主性与可控性平衡:模型根据任务需求自主决定加载哪些 Skill,系统不强制注入无关知识,同时避免了预加载的臃肿问题

六、运行示例

假设用户输入:"提交本次修改到 Git,遵循项目的提交规范",Agent 的典型执行流程:

  1. 模型查看系统提示词中的技能列表,看到有git技能(描述为「Git workflow helpers」)
  2. 模型判断需要加载git技能,调用load_skill("git")工具
  3. SkillLoader返回git/SKILL.md的完整内容(包含提交规范、Git 命令模板等),作为tool_result加入上下文
  4. 模型根据加载的 Git 技能内容,执行git addgit commit等命令,输出符合规范的提交信息
  5. 后续对话中,git技能的内容会保留在上下文中,无需重复加载(直到对话重置)

七、可扩展方向

  • 技能依赖管理:在 frontmatter 中添加depends_on字段,实现技能之间的依赖加载(如部署技能依赖于 Git 技能)
  • 技能版本控制:为每个 Skill 添加版本号,Agent 可指定加载特定版本的技能
  • 技能过滤:根据当前任务类型(如bugfix/feature)自动推荐相关技能,减少模型选择成本
  • 技能缓存:将常用技能的正文缓存到内存,避免重复读取文件

http://www.jsqmd.com/news/862245/

相关文章:

  • feh主题系统完全指南:如何自定义界面外观和风格
  • 鸿蒙备考题库页面构建:今日计划与题目预览模块的详细解析
  • Kubernete
  • Hello-Agents 第二部分-第九章总结:上下文工程
  • iTorrent完整指南:如何在iPhone上实现专业级种子下载管理
  • Deployment滚动更新与回滚完全指南
  • 技术债的“利息”怎么算?一个让非技术领导也能理解的比喻
  • 如何免费解锁网易云音乐无损音质:5个步骤掌握Netease_url终极工具
  • 远程办公三年,我摸索出一套不被“隐形加班”吞噬的方法
  • 留学生避开算法内卷?2026 欧美大厂极度缺人的无障碍开发蓝海赛道全景拆解
  • 【ElevenLabs新疆话语音落地实战】:20年语音AI专家亲授3大合规适配难点与5步部署清单
  • 简单掌握C++中的函数模板
  • RMAN 全库备份(Full Backup)
  • 如何在Linux系统上安装Realtek RTL8125 2.5GbE网卡驱动:完整配置指南
  • ShareGPT部署完全指南:如何在Vercel上快速搭建自己的分享平台
  • 2026年质量好的亚克力盐浴床高口碑品牌推荐 - 行业平台推荐
  • 2026谷歌I/O炸场:3.5 Flash全面碾压上代旗舰,AI行业彻底变天
  • 如何快速掌握Prism-Samples-Wpf交互性编程:InvokeCommandAction事件驱动开发终极指南
  • 跨国分布式团队协作实录:时区差不是最大障碍,信任才是
  • (二) 1. Q-learning的遗憾界分析-结合置信上界的Q-learning算法
  • 2026 年企业微信社群运营高效工具推荐
  • 机器视觉开发-使用YOLO8预训练模型检测目标
  • Linux的监测程序
  • 如何为 ChocolateyGUI 开发插件:扩展功能与自定义模块指南
  • 从灰蒙蒙到电影级质感:Midjourney 5.2→6.1色彩引擎升级对比实测,4类商业项目调色SOP紧急更新
  • Service与Ingress配置完全指南
  • mPDF实战指南:PHP环境下HTML转PDF的高性能解决方案深度解析
  • Genie入门指南:5分钟快速部署你的第一个大数据作业
  • CANN/asc-devkit C API归约函数文档
  • static-php-cli跨平台构建实战:Linux、macOS、Windows全攻略