zcbot/skills/skill-creator/SKILL.md

5.7 KiB

name description
skill-creator 引导用户创建 / 改造自己的 skill(存进用户私有 `.skills/`,只对自己生效)。当用户说"我想做个自己的 skill / 把某个能力固化下来 / 把 zcbot 的某 skill 改成我要的样子 / 每次都要重复交代同一套规矩"时使用。本 skill 教怎么写 SKILL.md、怎么 fork 内置 skill 再改、怎么写好路由用的 description。用户只是要完成一个具体任务(写本子 / 画图 / 查文献)时不用 —— 那直接走对应 skill。

Skill Creator - 造你自己的 skill

帮用户把"反复要交代的一套做法"沉淀成一个私有 skill,存在他自己的 .skills/ 下,只对他生效,不影响别人也不动内置 skill。

两种来源:

  • 从零写:全新能力,用 save_skill 写一份 SKILL.md。
  • fork 内置再改(最常见):看中某个内置 skill(如 ppt / proposal)但想调规矩,用 fork_skill 整目录拷过来(带它的脚本),再编辑 SKILL.md。

何时用

  • 用户说"我想要个自己的 skill / 自定义 skill / 把这套流程固定下来"
  • 用户说"zcbot 的 X skill 挺好但我想改成 Y" → fork 再改
  • 用户每次任务都要重复交代同一套约束(术语表 / 模板 / 禁忌) → 建议固化成 skill
  • 用户问"skill 怎么写 / SKILL.md 什么格式"

何时不用

  • 用户只是要完成一个具体任务 → 走对应内置 skill,别绕到造 skill
  • 用户要改的是全局行为(所有任务都该这样) → 那是 system prompt / 偏好,不是 skill
  • 一次性的事 → 直接做,不值得固化

关键机制(先讲清楚再动手)

存哪:用户 skill 在私有 .skills/<name>/SKILL.md(与 .memory/ 同级,文件面板里隐藏)。你不用、也不该用 write/shell 去手写这个目录 —— 沙箱 fs 的根不指向那里,跨 host/docker 不可靠。一律用下面两个工具,它们 host 侧直接落到正确位置。

两个工具:

  • save_skill(name, content) — 新建 / 覆盖 .skills/<name>/SKILL.mdcontent 是完整 SKILL.md(含 frontmatter)。写时校验 frontmatter 合法且有 description,不合格直接拒。
  • fork_skill(src, new_name) — 把内置(或用户已有)skill 整目录拷到 .skills/<new_name>/,脚本 / references 一起带过来,frontmatter 的 name 自动改成 new_name

生效时机:造好 / 改好后,下一条消息才生效(registry 每轮重建)。告诉用户造完这条结束,下次发消息就能用了。

覆盖语义(user wins):用户 skill 与内置同名 → 覆盖内置(只对该用户)。想替换内置就用同名,想两个都留就改名(如 ppt-mine)。覆盖会在 skill 列表里显式标 [你的·已覆盖内置],不静默。

工作流

1. 先问清楚要造什么(BLOCKING)

  • 从零还是基于某内置 skill 改?基于改 → 是哪个、想改什么?
  • 这个 skill 解决什么任务?什么时候该触发、什么时候不该?(这决定 description,见下)
  • 要不要带脚本 / 模板?

2a. fork 路径(基于内置改)

  1. fork_skill(src=<内置名>, new_name=<用户起的名>) —— 默认建议改名(如 pptppt-mine),除非用户明确要覆盖内置。
  2. fork 回包会给出 .skills/<new_name>/ 路径。用 read 看 SKILL.md,用 edit 改用户想改的部分(规矩 / 模板 / 默认值)。
  3. 改完告诉用户:下条消息起,<new_name> 就在 skill 列表里了。

2b. 从零路径

  1. 跟用户敲定 name + description + 正文骨架。
  2. save_skill(name, content),content 是完整 SKILL.md。
  3. 若校验报错(缺 description / YAML 坏),按提示修了重存。

3. 写好 description —— 这是最关键的一环

description 是唯一进每轮 skill 列表、决定路由的字段。写糊了的代价不是"skill 不好用",而是误触发 + 稀释列表。规则:

  • 一句话讲清做什么 + 何时用 + 何时别用
  • 触发词(用户会怎么开口),必要时给反例(像不该触发的近义场景)
  • 别写成功能罗列,要写成"路由信号"

照抄内置的结构,比如:

description: 生成 PowerPoint(.pptx)。✅ 触发:PPT / 幻灯片 / slide / deck / .pptx。⛔ 不触发:报告 / 文档 / 纪要(走 documents/proposal)。...

4. SKILL.md 正文骨架(从零时给用户的模板)

---
name: <小写、[a-z0-9_-]、≤64>
description: <路由说明:做什么 + 何时用 + 何时别用 + 触发词>
---

# <标题>

<一句话定位:这个 skill 帮用户做什么>

## 何时用 / 何时不用
- ...

## 工作流
1. ...

## 反模式
- ...

正文要不要分阶段 / 卡 BLOCKING / 带 quality_check,看任务复杂度 —— 简单 skill 几行就够,别硬套。带脚本的:脚本放 .skills/<name>/scripts/,SKILL.md 里用 <skill_dir>/scripts/xxx.py 引(<skill_dir>load_skill 返回头给的路径,host/docker 都对)。

反模式

  • write / shell 手动往 .skills 写 —— 用 save_skill / fork_skill(沙箱 fs 根够不到 .skills,会写错地方)
  • fork 带脚本的内置 skill(ppt/proposal)却只 save_skill 拷了 SKILL.md —— 脚本没带过来,import 必崩;带脚本一律 fork_skill
  • description 写成"很厉害的 PPT skill" —— 没有触发信号,路由抓瞎
  • 默认就覆盖同名内置 —— 除非用户明说要替换,否则改名并存,别悄悄遮掉内置
  • 造完不告诉用户"下条消息才生效",用户当场没看到以为失败
  • 把"所有任务都该遵守的全局规矩"做成 skill —— 那该进偏好 / system prompt

输出

完成后给用户:

  • skill 名 + 路径(.skills/<name>/)
  • 是覆盖内置还是新增 / 并存
  • 一句话:下条消息发什么就能触发它(或让 LLM 自动按 description 路由)