前阵子有个创业团队找我做技术咨询,让我看看他们吭哧吭哧写了三个月的 Agent Skill。我心里想,三个月,怎么也得攒下不少家底吧?
结果呢?让他们把跑得最久的几个 Skill 调出来看看。几个人翻了半天,只找到一个用了两周的,其他的,基本写完几天就歇菜了,然后又换新的重写。
这还真不是个例。这些年看过不下十几个团队,九成以上的 Skill 生命周期都没超过一个月。问题出在哪儿?说白了,就是没人按生产级的标准来写这些玩意儿。
今天这篇文章,我就把这两年写 Skill 踩过的坑,还有从无数反面教材里扒出来的教训,总结成六条铁律。每一条,都附上一个真实发生过的案例,希望能让你少走点弯路。
1. 锁死边界,别让 AI 自己猜“该干什么”
反面教材 #1
有个团队写了一个“批量扫描代码漏洞”的 Skill。工程师图省事,没限定扫描范围,心想 AI 这么聪明,肯定能自动识别哪些是项目代码,哪些是第三方库。
结果呢?AI 把 node_modules 里那几万个文件从头到尾扫了个遍。跑了四个小时,CI 机器的 CPU 直接被干满了,最后运维没办法,手动把进程给杀了。
把边界判断交给 AI,它的“理解”可能就是帮你扫平一切。边界必须在代码里写死,别指望 AI 能读懂你的潜台词。
# ❌ 让 AI 自己决定范围
files_to_check = ai_find_all_files('.')
# ✅ 代码锁定范围
SOURCE_DIRS = ['src/', 'lib/', 'tests/']
EXCLUDE_DIRS = ['node_modules/', 'vendor/', '.git/']
files_to_check = []
for d in SOURCE_DIRS:
if not Path(d).exists():
continue # 目录不存在就跳过,不崩
files_to_check.extend(Path(d).rglob('*.py'))
AI 的价值在于“理解意图”,而不是“替你做安全决策”。让它做选择题,你给选项;千万别让它做填空题,因为你根本不知道它会填进去什么。

2. 流程拆成原子步,一步崩了不影响全局
反面教材 #2
另一个团队写了个发布 Skill,一个函数干完所有事:拉代码、编译、打包、上传、发通知。听起来挺简洁,对吧?
结果编译到一半报错了。日志里“拉代码成功”和“编译失败”的信息全混在一起,谁也搞不清到底是代码没拉到,还是编译环境本身就有问题。排查这一个大坑,白白浪费了大半天。
工业级的 Skill,就得一步只做一件事。
步骤 1:前置校验(目录存在?依赖装了?权限够?)
↓ 失败 → 报具体错误,整体跳过
步骤 2:拉取代码(带超时,带重试)
↓ 失败 → 只重试这一步
步骤 3:编译构建(捕获 stdout/stderr)
↓ 失败 → 输出构建日志,不走下一步
步骤 4:制品打包
↓ 失败 → 标记失败,不影响其他步骤
步骤 5:结果汇总
每步独立,好处很明显:哪错了,一目了然,根本不用猜;单步可以重试,不用从头再来;单点故障不会雪崩,一个步骤炸了,不影响其他任务。

3. 所有步骤必须能“优雅失败”
反面教材 #3
见过最离谱的一个 Skill:脚本没找到,然后它执行了 rm -rf {path}。更要命的是,那个 path 变量是空的。
这种代码只写了“成功的路径”,完全没考虑“失败的路径”。这是新手写 Skill 的通病:脑子里只有“一切顺利”的剧本。但生产环境可不惯着你。
# ❌ 只写成功逻辑
def process_script(name):
result = subprocess.run([f'scripts/{name}.sh'], capture_output=True)
return result.stdout
# ✅ 写好失败兜底
def process_script(name):
script_path = f'scripts/{name}.sh'
if not Path(script_path).exists():
log.warning(f'脚本不存在: {script_path}')
return {'status': 'skip', 'reason': '目标不存在'}
try:
result = subprocess.run([script_path], capture_output=True, timeout=30)
if result.returncode != 0:
return {'status': 'fail', 'output': result.stderr}
return {'status': 'ok', 'output': result.stdout}
except subprocess.TimeoutExpired:
return {'status': 'fail', 'reason': '执行超时'}
写每一步的时候,都得逼自己问一句:“万一这步出错了呢?” 只有把所有分支都走通了,代码才算得上是“生产级”。

4. 输出必须结构化,别让下游猜你的意思
反面教材 #4
有个团队写了个“代码覆盖率分析” Skill。输出结果长这样:
检查了 15个文件,大部分覆盖率还行,有几个函数比较低,建议优化一下。
我当时就追问:“哪几个函数?覆盖率具体是多少?你说的‘比较低’是多低?” 结果对方答不上来。因为这是 AI 随手写的回复,每次输出的文本都不一样。
记住,下游系统要的是固定字段、固定格式的数据,不是一段散文。
{
"target": "user_login.py",
"coverage": 72.5,
"status": "warning",
"low_coverage_funcs": ["login_handler", "validate_token"],
"error_msg": ""
}
结构化输出之后,下游可以自动接入 BI 报表、自动触发告警(比如覆盖率低于 60% 就通知)、自动生成趋势图。你的输出,是写给系统和下一个维护它的人看的。

5. 配置参数全抽离,绝不硬编码
反面教材 #5
见过这样的代码吗?
def run():
report_path = '/home/admin/reports/2026/06/07/report.txt'
log_dir = '/var/log/myapp/'
max_retry = 3
下个月想改个目录,或者换个机器部署,就得改代码。这种 Skill 的生命周期,基本等同于“写它的人还在这个组”。
# 全局配置区,一目了然
REPORT_DIR = os.getenv('REPORT_DIR', './reports')
LOG_DIR = os.getenv('LOG_DIR', './logs')
MAX_RETRY = int(os.getenv('MAX_RETRY', '3'))
def run():
report_path = f'{REPORT_DIR}/{datetime.now():%Y/%m/%d}/report.txt'
...
把路径、文件名、阈值、重试次数,全都抽成变量。换环境只需要改配置,完全不用动代码。

6. 版本化,能回滚才是好 Skill
反面教材 #6
有一次线上出了事故,团队想紧急回退到上周那个可靠的 Skill 版本。结果发现——根本没做版本管理。上次改了什么,改对了还是改错了,没人记得。最后只能从头再写一个。
这已经不是技术问题了,而是管理上的缺失。
成熟的做法应该是这样的:
v1.0 — 初始版本:基础扫描功能
v1.1 — 增加并发控制
v1.2 — 修复路径编码 Bug
v2.0 — 重构为异步架构,支持大文件
每次迭代都记录变更点,每次发布都标记版本号。出了事,一条命令就能回滚到上一个稳定版本。
不版本化的 Skill,本质上就是一次性脚本。你不敢轻易改它,因为改坏了你就修不回来。

写在最后
有个团队曾经跟我说,他们对 Skill 的定位就是“让 AI 帮自己干点杂活”。
没错。但杂活也得能 7×24 小时稳定地跑。
你不妨问自己一个问题:如果这个 Skill 明天就要上线,今天你敢不敢不改一行代码就直接部署?
敢的,才叫生产级。不敢的,就一条条对着上面的铁律改。
这六条,每一条都是我和身边的团队用实打实的加班换回来的。以后你写完一个 Skill,在说“搞定了”之前,不妨先对照着看看,自己究竟做到了几条。
