【与我学 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 个工具(基础 + task 5 个工具(基础 + 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)自动推荐相关技能,减少模型选择成本
  • 技能缓存:将常用技能的正文缓存到内存,避免重复读取文件
相关推荐
奋斗的老史5 小时前
LangChain4j + Elasticsearch 实现企业级向量存储(支持混合检索、元数据过滤)
elasticsearch·langchain4j
大信说财务5 小时前
发票管理的技术底座:从架构支撑到可信归档
大数据·软件·财务管理·数电票·发票
AIDF20265 小时前
动态大模型 Prompt 生成技术解析
服务器·llm·prompt·agent
嗯、.5 小时前
Agent 路由架构的一次尝试:LangGraph + Swarm Handoff + 小模型 Router
人工智能·python·swarm·langgraph·multi-agent·model-routing
luyu007_0076 小时前
鲁渝能源全功率无线充电为巡检机器人筑牢能源底座
人工智能·安全·机器人·能源
学困昇6 小时前
Linux 动静态库制作与原理:从 .a、.so 到 ELF 加载一次讲透
linux·运维·服务器·c语言·开发语言·c++·人工智能
一切皆是因缘际会6 小时前
从概率拟合到内生心智:七层投影架构重构AGI数字生命新范式
大数据·数据结构·人工智能·重构·架构·agi
Jump 不二6 小时前
AI Agent Skill 系统架构全解析:SKILL 规范与框架实现
人工智能·语言模型·系统架构
青衫客366 小时前
从操作系统到 Agent OS:多智能体系统运行原理的底层类比与架构思考
架构·agent