【从零构建AI Code终端系统】06 -- 技能系统:把经验装进书架

06 -- 技能系统:把经验装进书架

每天从零推理同一件事

子代理隔离了中间产物,上下文干净了。但隔离解决不了另一个浪费------重复推理

让模型执行一次代码提交,它从头推理:检查变更、逐文件暂存、写提交信息。这套流程你每天用十次,模型每次从零走一遍------耗 token、路径不同、质量不稳定。人会把反复执行的流程内化为习惯,agent 需要同样的机制:把反复使用的推理路径预编译成指令,用到时直接加载。 一个技能就是一份写给模型看的操作手册。


知识,不是代码

工具和技能容易混淆。工具 = 能力 ------执行命令、读写文件,硬编码在程序里。技能 = 知识------提交规范、审查标准、测试策略,写在纯文本里。

两者的变更节奏完全不同。改一行提交规范不应该需要重新部署;任何人都能写纯文本,不需要编程能力;纯文本天然适配版本控制和团队共享。代码定义机制,文本定义内容,各自以自己的速率演进。


SKILL.md 的结构

技能以目录为单位,每个技能的存放路径遵循固定约定:

复制代码
.agents/skills/<skill-name>/SKILL.md

<skill-name> 就是技能名------小写字母加连字符,1-64 字符,全局唯一。目录名即技能名,SKILL.md 是入口文件。一个项目可以有多个技能,并排放在 .agents/skills/ 下:

复制代码
.agents/skills/
├── commit-workflow/
│   ├── SKILL.md           # 必须:指令 + 元数据
│   ├── scripts/           # 可选:可执行脚本
│   ├── references/        # 可选:参考文档
│   └── assets/            # 可选:模板、资源
├── code-review/
│   └── SKILL.md
└── security-guidance/
    └── SKILL.md

扫描器启动时遍历 .agents/skills/ 下的每个子目录,解析其中的 SKILL.md。目录结构保持一层深度------扁平意味着模型不需要递归查找,人也不需要翻找。

SKILL.md 由 YAML frontmatter 和 Markdown body 两部分组成:

yaml 复制代码
---
name: commit-workflow            # 必需,1-64 字符,小写 + 连字符
description: |                   # 必需,1-1024 字符
  代码提交工作流。用户要求提交代码时激活。
license: MIT                     # 可选
allowed-tools: Bash Read         # 可选,空格分隔,限制可用工具
---

## 提交规范
1. 运行 git status 检查变更
2. 逐文件暂存,不要 git add -A
3. 提交信息使用祈使语气,首行不超过 72 字符

两个必需字段各有职责。name 是唯一标识,扫描和覆盖靠它定位。description 不只描述"做什么",更要说"什么时候用"------模型靠这行描述判断当前任务是否匹配,描述越准确,激活越精准。

Body 部分无格式限制,推荐包含分步指令、输入输出示例和边界情况处理。引用资源文件用相对路径(scripts/lint.sh),与目录结构的扁平原则一致。


三层渐进式披露

20 个技能全量注入约 40K tokens,占窗口 20%,大部分与当前任务无关。解法是按需逐层展开------先看书脊,感兴趣翻目录,确定相关了才读正文:
任务匹配描述
指令引用文件
Metadata

name + description

≈100 tokens/技能
Instructions

完整 SKILL.md body

推荐 <5000 tokens
Resources

scripts/ references/ assets/

按需加载

Metadata。 启动时从所有 SKILL.md 的 frontmatter 提取 namedescription,注入上下文。20 个技能约 2000 tokens------模型扫一眼就知道书架上有什么,几乎不占空间。不相关的技能永远停留在这一层。

Instructions。 模型判断某个技能与当前任务相关时,调用 load_skill 工具,加载完整 body。内容作为工具返回值追加到消息历史,一次性成本。Body 推荐控制在 5000 tokens 以内------太长会稀释上下文,违背"预编译"的初衷。

Resources。 执行 body 中的指令时,才读取 scripts/references/assets/ 下的文件。这些资源从不主动加载,只在指令明确引用时按需获取。

成本曲线很陡:大部分技能停留在第一层(约 100 tokens),少数进入第二层(几千 tokens),资源文件只在执行时才产生开销。


注入位置:追加,不改前缀

技能内容追加到最后一条用户消息的末尾,不修改系统提示词。原因是缓存:大模型 API 普遍支持前缀缓存------请求前缀相同就复用已缓存的 KV 向量。改系统提示词一个字节,缓存全部失效。追加到消息末尾,前缀始终不变,缓存始终命中。

复制代码
beforeModel(state):
    // autoload 技能:每轮直接注入正文,跳过 Metadata 直入 Instructions
    for skill in registry:
        if skill.autoload:
            inject(skill.body)

    // 其余技能:只注入 Metadata 层
    summary = registry
        .filter(s => !s.autoload)
        .map(s => "- {s.name}: {s.description}")

    append_to_last_user_message(summary)

autoload 是一个特殊标记。标记了的技能(如输出风格规范)每轮自动注入完整正文,跳过 Metadata 直接进入 Instructions。适合每次对话都必定用到的基础规范------数量少、体积小,省去模型每次主动加载的开销。


小结

技能把运行时的重复推理转移到编写时。SKILL.md 用 frontmatter 声明身份,用 body 承载指令,用子目录挂载资源。三层渐进式披露------Metadata、Instructions、Resources------确保模型只为真正用到的知识付费。追加注入保护缓存命中率。

但不管书架管理得多精细,对话本身一直在增长------每轮工具调用、每次文件读取都在往窗口里堆东西。窗口终会满,届时需要的不是更聪明的加载,而是压缩。


相关推荐
laplace01233 小时前
第二章 字符串和文本 下
服务器·数据库·python·mysql·agent
枕石 入梦3 小时前
Java 手写 AI Agent:ZenoAgent 实战笔记
人工智能·开源·agent·zenoagent
香芋Yu3 小时前
【从零构建AI Code终端系统】07 -- 记忆管理:窗口满了怎么办
agent·code·claude code·meomry
Lw老王要学习4 小时前
Windows 下 Miniconda 安装与 conda 命令无法识别问题解决指南
windows·llm·conda·agent
feasibility.4 小时前
用OpenClaw做飞书ai办公机器人(含本地ollama模型接入+自动安装skills+数据可视化)
人工智能·科技·机器人·飞书·agi·skills·openclaw
杨天宇ttx18 小时前
Agent 自学指南1 - 别只会"Hi"了:给大模型装上手脚,5分钟变身 Agent
agent
组合缺一20 小时前
赋予 AI Agent “无限续航”:语义保护型上下文压缩技术解析
人工智能·ai·llm·agent·solon·solon-ai
belldeep1 天前
AI agent:介绍 ZeroClaw 安装,使用
人工智能·ai·agent·zeroclaw
XLYcmy1 天前
智能体大赛 实现逻辑 “检索先行”的闭环工作流
数据库·ai·llm·prompt·agent·rag·万方