都在用Skill,那你知道好的Skill应该长啥样吗?—— 1次Skill优化实录
本文通过一个Git工作流自动化Skill的设计优化案例,探讨了如何设计高质量的Skill。作者最初设计了包含三个脚本的Skill(共335行代码),随后反思发现这些字符串处理任务本可由Agent原生完成。文章深入分析了Skill的三层架构(元数据、指令手册、资源工具),提出"自由度匹配任务脆弱性"原则:精确操作适合脚本,灵活判断应交给Agent。最后提供了Skill质量评估ch
大家都在安装skill,用skill,那是否知道如何设计一个skill呢?更进一步你设计的skill是否足够好呢?怎么判断好不好呢?
以我今天写代码过程中,写skill 的一个案例的说明这件事情吧,带你经历"需求分析 → 初版设计 → 反思 → 深度优化"的渐进之旅。这不只是一次重构,更是一次关于 Skill 该怎么写 的认知升级。
阅读完本文你会收获:
-
从零开始设计一个 Skill 的完整实战流程
-
理解 Skill 的三层渐进式架构和核心设计原则
-
掌握判断"哪些逻辑该用脚本、哪些该交给 Agent"的决策框架
-
获得一个可复用的 Skill 质量评估 checklist
-
当然,最后也能够知道如何判断一个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 需要处理什么:
-
收集信息:需求描述、任务号、类型(feat/fix/refactor)
-
字符串处理:从 Git remote URL 提取 project_id、生成分支名、拼接 commit message
-
Git 操作:创建分支、commit、push
-
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,而是分三层按需加载:
类比一下:
| 层级 | 类比 | 作用 |
|---|---|---|
| 第 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 原生 ✅ |
|---|---|---|
| 出错后果 | 不可逆(删数据、改文件) | 可重试(生成文本、调 API) |
| 确定性要求 | 必须 100% 精确 | 95% 就够用 |
| LLM 能力覆盖 | 超出语言处理范畴 | 就是语言处理本身 |
| 环境依赖 | 需要特定 runtime/库 | 不需要额外依赖 |
| 复杂度 | 算法/数学密集 | 规则/模式匹配 |
现在理解了这个原则,回头审视初版的三个脚本:
| 脚本 | 出错后果 | 确定性 | LLM 覆盖 | 结论 |
|---|---|---|---|---|
parse_project_id.py |
可重试 | 95% 够用 | ✅ 完全覆盖 | 不需要 |
generate_branch_name.py |
可重试 | 95% 够用 | ✅ 完全覆盖 | 不需要 |
generate_commit_message.py |
可重试 | 95% 够用 | ✅ 完全覆盖 | 不需要 |
三个全部判定为"不需要"。问题不在于脚本本身的质量,而在于它们不该存在。
除了脚本多余,初版还有一个隐蔽的问题:交互示例中写了"直接回车使用默认"、“[回车]”。但用户跟 Agent 交互是通过聊天,不是终端——没有"回车"这个动作。Skill 中的交互示例直接影响 Agent 的行为模式,写了"回车",Agent 就会说出"请按回车"这种在聊天场景下莫名其妙的话。
诊断结果:初版 Skill 有两个设计缺陷——
-
用脚本做了 Agent 原生能力就能搞定的事(违反"能力优先"原则)
-
交互示例不匹配实际使用场景(终端语言 vs 聊天语言)
动手优化:删掉脚本,用指令代替
诊断清楚了,动手很干脆——直接删掉整个 **scripts/** 目录,把脚本逻辑转化为 SKILL.md 中的自然语言指令;同时把所有"回车"改为"回复’默认’"。最终的样子是下面这个样子。

重构前 vs 重构后
脚本逻辑 → 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 在整个过程中做了什么?
注意标了"原生能力"的三步——这就是原来三个 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 的原生能力,只在超出其能力范围时才引入外部脚本。
这不是"脚本无用论"。数据库操作、文件系统批量处理、加密计算——这些该用脚本还是得用脚本。关键是 匹配:把对的工具用在对的地方。
如果有所收获,别忘记点个赞
更多推荐




所有评论(0)