大家都在安装skill,用skill,那是否知道如何设计一个skill呢?更进一步你设计的skill是否足够好呢?怎么判断好不好呢?

以我今天写代码过程中,写skill 的一个案例的说明这件事情吧,带你经历"需求分析 → 初版设计 → 反思 → 深度优化"的渐进之旅。这不只是一次重构,更是一次关于 Skill 该怎么写 的认知升级。

阅读完本文你会收获:

  1. 从零开始设计一个 Skill 的完整实战流程

  2. 理解 Skill 的三层渐进式架构和核心设计原则

  3. 掌握判断"哪些逻辑该用脚本、哪些该交给 Agent"的决策框架

  4. 获得一个可复用的 Skill 质量评估 checklist

  5. 当然,最后也能够知道如何判断一个Skill是否设计的好


一个重复到让人厌烦的工作流

我自己是一个研发,又在实践vibecoding,迭代速度就更快了,那么重复的流程出现的频次也会更多。而日常开发有一个固定流程:改完代码后,得走一遍 Git 工作流——从 master 拉新分支、写规范的 commit message、push 到远程、在 GitLab 上创建 MR。

这个流程本身不复杂,但每次都得敲一堆命令,很麻烦:

git checkout master
git pull origin master
git checkout -b feature/待办列表可见时间从7天改为20天
# ... 改代码 ...
git add .
git commit -m "feat(all): p66_6666 待办列表已完成可见时间从7天改为20天"
git push -u origin feature/待办列表可见时间从7天改为20天
# 然后打开浏览器,去 GitLab 手动创建 MR,填标题、填描述...

这不正好适合做成一个 Skill 吗? 让 Agent 来搞定这些重复劳动——用户只需要说一句话描述需求,剩下的全自动化。


开始动手设计 Git 工作流 Skill

说干就干。分析一下这个 Skill 需要处理什么:

  1. 收集信息:需求描述、任务号、类型(feat/fix/refactor)

  2. 字符串处理:从 Git remote URL 提取 project_id、生成分支名、拼接 commit message

  3. Git 操作:创建分支、commit、push

  4. GitLab API:通过 MCP 工具创建 MR

其中第 2 步涉及字符串处理,有固定的规则。作为一个"合格的工程师",自然想到——写脚本来处理。于是初版 Skill 长这样:

git-workflow-automator/
├── SKILL.md                            # 210 行指令
├── scripts/
│   ├── parse_project_id.py             # 48 行,正则提取 project_id
│   ├── generate_branch_name.py         # 35 行,拼接分支名
│   └── generate_commit_message.py      # 42 行,拼接 commit message
└── references/
    ├── commit_message_spec.md
    └── branch_naming_spec.md

三个脚本分别做什么?

parse_project_id.py:正则提取

# 从 Git remote URL 中提取 project_id
# 输入:http://git.wondershare.cn/xxx/xxxv.git
# 输出:xxxx/xxx

import re, sys
url = sys.argv[1]
patterns = [
    r'[:/]([^/]+/[^/]+?)(?:\.git)?$',   # HTTP/SSH
]
for p in patterns:
    m = re.search(p, url)
    if m:
        print(m.group(1))
        break

generate_branch_name.py:字符串拼接

# 输入:type=feat, description=嵌入AI助手应用
# 输出:feature/嵌入AI助手应用

type_map = {"feat": "feature", "fix": "fix", "refactor": "refactor"}
prefix = type_map.get(sys.argv[1], "feature")
print(f"{prefix}/{sys.argv[2]}")

generate_commit_message.py:格式化

# 输入:type=feat, task_id=p66_6666, description=嵌入AI助手应用
# 输出:feat(all): p66_6666 嵌入AI助手应用

print(f"{sys.argv[1]}(all): {sys.argv[2]} {sys.argv[3]}")

三个脚本加起来 125 行代码。整个 Skill 总共 335 行(SKILL.md 210 行 + 脚本 125 行),目录结构清晰,脚本有输入有输出,规范、完整、工程化。

跑一下,能用。Agent 按照 SKILL.md 的指令收集信息,调脚本处理字符串,执行 Git 命令,创建 MR——全流程跑通了。完美 ✅

需求满足了。但这个 Skill 设计得到底好不好?


等一下——这个 Skill 真的设计得好吗?

功能上没问题,确实能完成任务。但"能用"和"设计得好"是两回事。

回想一下那三个脚本做的事:

  • parse_project_id.py:从 URL 提取路径

  • generate_branch_name.py:按规则拼接字符串

  • generate_commit_message.py:按模板格式化文本

等等,这些不就是字符串处理吗?而 Agent 的核心能力恰恰就是语言处理——它天生就擅长这个。

“现在 Agent 能力比较厉害了,这些过程,Agent 是否都能通过 GitLab MCP 工具 + 命令行一次完成?而不是通过脚本?”

这个灵魂拷问一出来,我立刻意识到:我给 Agent 写了三个它根本不需要的"拐杖"

这就好比你雇了一个英语八级的翻译,然后给他一本英汉词典说"查这个词"。他不需要词典,他本来就会。

但光靠直觉说"不需要"还不够。要回答"这个 Skill 到底哪里设计得不好",得先真正理解 Skill 的本质。


回到原点:Skill 到底是什么?

如何一句话解释 Skill?

Skill 是给 AI Agent 用的"岗位手册"

就像你给新员工写一份 SOP(标准操作流程),告诉他"遇到这种情况,按这个步骤做"。Agent 天生就是个"通才",什么都知道一点但没有深入的领域知识。Skill 就是把特定领域的知识打包喂给它,让它变成"专才"。

常说的三层渐进式加载是怎么回事?

这是 Skill 系统最精妙的设计。不是一股脑把所有信息塞给 Agent,而是分三层按需加载:

第 3 层:Bundled Resources

第 2 层:SKILL.md 正文

第 1 层:元数据

Agent 判断匹配

需要详细信息时

name + description
~100 词,始终在上下文中

工作流程 + 指令
触发后才加载,≤500 行

scripts/ + references/ + assets/
按需加载或直接执行

类比一下:

层级 类比 作用
第 1 层 名片 Agent 扫一眼就知道这个 Skill 干什么、什么时候用
第 2 层 操作手册 具体步骤和规则,触发后才翻开
第 3 层 工具箱 辅助脚本、参考文档,需要时才拿出来

为什么要这么设计?因为 上下文窗口是公共资源。Agent 同时可能有 22 个 Skill(我们项目就是),如果每个都把完整内容塞进去,光 Skill 就占满了上下文。三层设计让 Agent 用最小的上下文开销,完成最精准的能力匹配。

description 字段是非常重要的

因为 description 是 Skill 被触发的唯一机制

Agent 靠 description 判断"这个 Skill 跟当前任务有关系吗?"。一个好的 description 应该包含:

  • 做什么(功能描述)

  • 什么时候用(触发场景)

  • 关键词(用户可能说的话)

看个对比:

差的 description 好的 description
内容 “Git 工作流工具” “通过对话收集用户需求信息后,自动执行完整 Git 工作流包括创建新分支、生成规范 commit message(包含任务号如 p66_6666)、推送代码、创建 GitLab MR。当用户说开始新需求、创建分支、提交代码、发 MR 时使用。”
效果 Agent 不确定什么时候该用 Agent 精准匹配到

第 3 层的 scripts 什么时候该用?

这是这次实战过程中的关键问题。Skill 系统有一个核心原则叫 “自由度匹配任务脆弱性”。翻译成大白话:

越是不能出错的事,越要用脚本(低自由度);越是需要灵活判断的事,越要交给 Agent(高自由度)。


带着理解回来:诊断初版 Skill 的问题

适合 Agent 原生(高自由度)

字符串提取与拼接

自然语言理解

格式转换

规则应用与判断

适合脚本(低自由度)

数据库操作

文件系统批量操作

加密/哈希计算

精确的数值计算

用一个决策表来判断:

判断维度 用脚本 ✅ 用 Agent 原生 ✅
出错后果 不可逆(删数据、改文件) 可重试(生成文本、调 API)
确定性要求 必须 100% 精确 95% 就够用
LLM 能力覆盖 超出语言处理范畴 就是语言处理本身
环境依赖 需要特定 runtime/库 不需要额外依赖
复杂度 算法/数学密集 规则/模式匹配

现在理解了这个原则,回头审视初版的三个脚本:

Agent 天生就会

脚本做的事

正则匹配

字符串拼接

格式化输出

从 URL 中提取路径

按规则拼接字符串

按模板格式化文本

脚本 出错后果 确定性 LLM 覆盖 结论
parse_project_id.py 可重试 95% 够用 ✅ 完全覆盖 不需要
generate_branch_name.py 可重试 95% 够用 ✅ 完全覆盖 不需要
generate_commit_message.py 可重试 95% 够用 ✅ 完全覆盖 不需要

三个全部判定为"不需要"。问题不在于脚本本身的质量,而在于它们不该存在。

除了脚本多余,初版还有一个隐蔽的问题:交互示例中写了"直接回车使用默认"、“[回车]”。但用户跟 Agent 交互是通过聊天,不是终端——没有"回车"这个动作。Skill 中的交互示例直接影响 Agent 的行为模式,写了"回车",Agent 就会说出"请按回车"这种在聊天场景下莫名其妙的话。

诊断结果:初版 Skill 有两个设计缺陷——

  1. 用脚本做了 Agent 原生能力就能搞定的事(违反"能力优先"原则)

  2. 交互示例不匹配实际使用场景(终端语言 vs 聊天语言)


动手优化:删掉脚本,用指令代替

诊断清楚了,动手很干脆——直接删掉整个 **scripts/** 目录,把脚本逻辑转化为 SKILL.md 中的自然语言指令;同时把所有"回车"改为"回复’默认’"。最终的样子是下面这个样子。

image.png

重构前 vs 重构后

重构后

SKILL.md
210 行

references/
2 个规范文档

重构前

SKILL.md
210 行

scripts/
3 个 Python 文件

parse_project_id.py
48 行

generate_branch_name.py
35 行

generate_commit_message.py
42 行

references/
2 个规范文档

脚本逻辑 → SKILL.md 指令的转化示例:

parse_project_id.py(48 行 Python)变成了 SKILL.md 中的 6 行自然语言:

### 第 2 步:自动解析项目信息

执行命令获取 GitLab project_id:
  git remote get-url origin
  # 示例输出:http://git.wondershare.cn/xxx.git

从 URL 中提取 project_id:xxxx

就这么简单。Agent 看到这段指令后,完全知道该怎么做——因为"从 URL 中提取路径"就是 LLM 的基本能力。

量化对比

指标 重构前 重构后 变化
SKILL.md 行数 210 行 210 行 持平
脚本文件 3 个(125 行) 0 个 -100%
总代码量 335 行 210 行 -37%
外部依赖 Python 3 runtime 零依赖
维护点 4 个文件 1 个文件 + 2 个 ref -50%
功能完整性 无变化

重点看最后一行:功能没有任何损失


实战验证:完成全流程

重构后立刻做了一次真实验证——把之前的代码修改(待办列表可见时间从 7 天改为 20 天)走一遍完整流程:

User: 帮我把刚才的修改走一下 git 流程

Agent: 好的!请描述这次需求是什么?

User: 待办列表已完成可见时间从7天改为20天

Agent: 任务号是多少?(直接回复"默认"使用 p66_6666,或输入具体任务号)

User: 默认

Agent: 这是新功能(feat)、修复(fix)还是重构(refactor)?

User: feat

Agent:
✅ 已更新 master 分支到最新
✅ 已创建分支:feature/待办列表可见时间从7天改为20天
✅ 已提交:feat(all): p66_6666 待办列表已完成可见时间从7天改为20天
✅ 已推送到远程
✅ MR 已创建:http://git.wondershare.cn/xxxxxx/xxxxx/-/merge\_requests/95

Agent 在整个过程中做了什么?

GitLab MCP Git Agent 用户 GitLab MCP Git Agent 用户 描述需求 理解需求,提取 type/description git remote get-url origin 从 URL 提取 project_id(原生能力) 生成分支名(原生能力) checkout master && pull checkout -b feature/xxx 生成 commit message(原生能力) add && commit && push create_merge_request() 反馈完整结果

注意标了"原生能力"的三步——这就是原来三个 Python 脚本做的事,现在 Agent 自己就完成了,不需要任何外部脚本。


回头看:这次优化带来的两个洞察

洞察 1:Agent 的能力边界在移动

两年前,让 LLM 做正则提取可能不太靠谱。但今天的 Agent?从 http://git.wondershare.cn/xxxx/xxxxx.git\ 中提取 xxx/xxxxxx 这种事,它闭着眼睛都能做对。

启示:定期重新评估 Skill 中的脚本——Agent 能力在持续增长,昨天需要脚本辅助的事,今天可能已经不需要了。

洞察 2:"指令即代码"的思维转变

传统思维:逻辑 = 代码。新思维:对 Agent 来说,清晰的自然语言指令就是"代码"

# 这就是"代码"
从 URL 中提取 project_id:匹配域名后的路径部分,去掉 .git 后缀

Agent 读到这行指令,执行结果跟 48 行 Python 正则脚本完全一致。而且这行"代码"更好维护——任何人一看就懂。


总结:Skill 质量评估 checklist

基于这次优化经历,提炼出一个评估 Skill 质量的 checklist:

# 检查项 评判标准
1 脚本必要性 每个脚本是否在做 Agent 原生能力覆盖不了的事?
2 自由度匹配 脆弱操作用脚本,灵活操作用指令?
3 description 质量 包含"做什么 + 什么时候用 + 关键词"?
4 上下文效率 SKILL.md ≤ 500 行?信息密度够高?
5 交互方式一致 交互示例匹配实际使用场景(聊天 vs 终端)?
6 外部依赖 是否引入了不必要的 runtime 依赖?
7 零功能损失 优化后功能完整性是否得到保证?

一个核心原则

能力优先——先用 Agent 的原生能力,只在超出其能力范围时才引入外部脚本。

这不是"脚本无用论"。数据库操作、文件系统批量处理、加密计算——这些该用脚本还是得用脚本。关键是 匹配:把对的工具用在对的地方。


如果有所收获,别忘记点个赞

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐