AI Agent Skill 上线后,如何持续维护

Skill 上线不是终点,而是它第一次接触真实任务的开始。真正难的工作不是把 SKILL.md 写出来,而是持续回答三个问题:它有没有被正确触发、有没有按预期执行、改完之后有没有伤到旧场景。

本文是「AI Agent 技能(Skill)实战解析」的后续。上一篇讲怎么设计和编写 Skill,这一篇只谈上线之后:如何收集反馈、定位失败、建立评测、管理版本,以及在必要时安全地下线一个 Skill。

Skill 持续维护闭环

本文脉络:
一 为什么 Skill 上线后一定会变
二 先把失败分对类
三 建立最小可用的反馈闭环
四 用评测集守住质量底线
五 版本管理:什么改动算破坏性变更
六 发布策略:从本地验证到灰度上线
七 依赖、兼容性与安全维护
八 什么时候应该拆分、合并或退役
九 一套可执行的维护节奏
十 常见问题

一、为什么 Skill 上线后一定会变

刚写完的 Skill 往往看起来很可靠。示例任务能跑通,规则也没有明显冲突,目录结构干净得像刚装修完的房子。

真实用户一进来,问题就开始了。

有人只说一句「帮我整理一下」,你以为他要写文档,他其实想整理 Excel;有人把一个 200 页 PDF 和一句模糊要求一起丢进来;还有人会在同一次任务里同时触发三个 Skill,让它们争夺工作流的控制权。

这不是模型“不听话”,而是上线前的样本太少。Skill 的行为至少受四类变量影响:

变量 典型变化
用户表达 同一个意图有几十种说法,甚至没有明确关键词
输入材料 文件格式、大小、质量和缺失字段都不可控
运行环境 工具权限、依赖版本、目录结构和网络状态会变化
模型能力 模型升级后,触发判断和指令遵循可能发生漂移

所以我更愿意把 Skill 看成一种行为接口。它虽然不是传统 API,却一样有输入、输出、依赖和兼容性问题。既然是接口,就不能靠“作者感觉应该没问题”来维护。

上线后的目标也不是让它永远不出错。更现实的目标是:

发现失败的速度,比失败扩散的速度快;
修复旧问题时,不制造更大的新问题。

二、先把失败分对类

维护 Skill 最容易踩的坑,是看到一次失败就往 SKILL.md 里补一句规则。补了十几次之后,主文件变成一份充满例外条款的免责声明,Agent 反而抓不住重点。

动手改之前,先判断失败发生在哪一层。

1. 触发失败

该触发时没有触发,或者不该触发时抢了别人的任务。

例如一个技术写作 Skill 只在用户说“博客文章”时触发,但用户说“把这段数据库笔记整理成可发布的长文”时没有触发。这通常是 description 覆盖的表达太窄。

反过来,如果用户只是让 Agent 修改一段 README,它也强行进入完整写作流程,那就是触发范围写得太宽。

这类问题应该改元数据,重点检查:

  • 有没有写清楚“做什么”;
  • 有没有覆盖用户真实使用的措辞;
  • 有没有明确不适用的边界;
  • 是否与其它 Skill 的描述高度重叠。

2. 路由失败

Skill 已经触发,但选错了内部路径。

比如技术写作 Skill 同时支持博客和公众号,用户明确说“发公众号”,Agent 却生成了 Hexo front-matter。这不是触发问题,而是模式判断出了错。

路由失败通常需要改决策条件,而不是增加更多写作规则。

如果目标载体已经明确,直接进入对应模式。
只有在目标载体无法从用户请求和项目上下文判断时,才询问用户。

3. 执行失败

路径选对了,但步骤漏了、顺序错了,或者输出不符合要求。

例如文档生成 Skill 已经选中 .docx 流程,却没有做渲染检查;部署 Skill 修改了配置,却忘了运行构建。这类问题适合增加检查点、脚本或明确的完成条件。

4. 环境失败

网络、权限、依赖、文件路径或外部服务不可用。

环境问题很容易被误诊成指令问题。代理端口没启动时,继续优化“重试规则”没有意义;缺少数据库权限时,往 Skill 里加一句“务必写入数据库”只会让报错更执着。

维护记录里要把这类失败单独标记,因为它们通常需要修工具、配置或部署环境。

5. 预期本身不合理

还有一类失败最隐蔽:Skill 忠实地执行了规则,但规则本身已经过时。

例如最初要求所有任务都生成详细计划,后来发现简单改字也要先列五步计划,成本远大于收益。这时应该删规则,而不是教模型“在简单任务里把计划写短一点”。

一句经验:能删掉一条错误规则,就不要再补三条例外。

三、建立最小可用的反馈闭环

不需要一上来就做复杂的可观测平台。一个 Skill 刚上线时,维护者真正需要的只有少量高质量信号。

1. 每次失败至少记录什么

建议保留以下字段:

字段 用途
用户原始请求 判断触发和路由是否合理
被触发的 Skill 与版本 确认问题来自哪一版
选择的内部路径 区分触发失败和路由失败
最终结果 查看实际偏差,而不是只看报错
用户修正 用户改了什么,往往比“满意/不满意”更有价值
失败分类 触发、路由、执行、环境或规则问题
是否可复现 决定能否加入回归评测

注意隐私边界。日志里可能包含代码、客户数据、文档内容和账号信息。能记录结构化摘要,就不要默认保存完整输入;必须保存时,要明确访问权限和保留期限。

2. 别只收集差评

只看失败案例会把 Skill 越改越保守。维护者还需要知道它在哪些场景表现稳定,否则很容易为了修一个边缘问题,把主流程改坏。

我通常会同时保留三类样本:

黄金样本:必须一直做对的核心任务
事故样本:线上真实失败,修复后加入回归集
边界样本:容易误触发、输入缺失或多 Skill 冲突的任务

黄金样本保证“基本盘”不退化,事故样本保证同一个坑别踩两次,边界样本则专门测试那些看起来不像正常用户、但偏偏每天都会出现的输入。

3. 用户修正是最值钱的反馈

“结果不好”信息量很低。“不要改原文结构,只修复术语错误”就具体得多。

如果同一种修正反复出现,不要急着把用户的话原样追加到 Skill。先问:

  • 这是通用规则,还是某个项目的偏好?
  • 应该放在 SKILL.md,还是项目级指令?
  • 能不能变成一个自动检查,而不是自然语言提醒?
  • 它是否会与现有规则冲突?

Skill 不是所有反馈的垃圾桶。

四、用评测集守住质量底线

没有评测集的 Skill,维护方式通常是“改完跑一个示例,感觉好多了”。这种感觉非常不可靠。

最小评测集不需要几百条。先选 15~30 个有代表性的任务,就能拦住大量回归。

1. 评测什么

Skill 的评测至少分四层:

层级 评测问题 示例指标
触发 该用时用了,不该用时没用吗 触发准确率、误触发率
路由 是否选择了正确模式和参考资料 路由准确率
过程 是否执行关键步骤 检查点通过率
结果 最终产物是否可用 构建成功、格式正确、人工评分

只评最终文本容易掩盖过程问题。一次构建成功,可能只是模型碰巧生成了正确配置;如果它没按要求检查仓库状态,下次就可能覆盖用户改动。

2. 把模糊要求变成可判定条件

“文章写得专业”很难自动评测,但可以拆成:

  • front-matter 是否包含必需字段;
  • 是否有 <!-- more -->
  • 主章节是否使用中文编号;
  • 是否引用了不存在的内部链接;
  • 构建是否通过;
  • 是否出现禁用的套路化表达。

能用脚本判定的,不要全交给另一个模型打分。模型评审适合判断表达质量、事实一致性等开放问题;文件存在、字段完整、命令成功这些事情,确定性检查更便宜也更可信。

3. 每次线上事故都要变成回归样本

一次故障只有进入评测集,才算真正修完。

建议给案例一个稳定编号:

id: TW-017
title: 明确要求公众号时误走博客模式
input: "把这篇内容改成微信公众号文章"
expected:
mode: wechat
must_not_contain:
- "categories:"
- "<!-- more -->"

以后无论改 description、工作流还是参考资料,都重新跑这条。否则三个月后很可能有人“优化结构”时把旧问题重新放回来。

五、版本管理:什么改动算破坏性变更

Skill 也应该有版本号。不是为了看起来专业,而是为了回答一个实际问题:线上失败到底发生在哪一版?

可以沿用语义化版本的思路:

PATCH:修正文案、补充示例,不改变既有流程
MINOR:新增可选能力、模式或参考资料,旧用法仍然有效
MAJOR:改变触发边界、默认行为、输出契约或依赖要求

下面这些改动,我会按破坏性变更处理:

  • 原来默认生成草稿,现在默认直接写文件;
  • 原来允许自主发布,现在必须等待用户确认;
  • 修改输出文件名或目录;
  • 删除一个已公开的模式;
  • 更换必须安装的工具;
  • 改变与其它 Skill 的职责边界。

1. 保留变更记录

不必写成大型项目的发布公告,但至少说明:

## 1.3.0 - 2026-07-27

### Added
- 新增 PDF 输入的归一化流程

### Changed
- 只有目标载体不明确时才询问博客/公众号模式

### Fixed
- 修复“技术长文”没有触发 Skill 的问题(TW-021)

变更记录最重要的不是“改了什么文件”,而是“用户能观察到的行为发生了什么变化”。

2. 不要悄悄改变输出契约

如果下游脚本依赖 Skill 生成的文件名、字段或目录结构,一个看似无害的重命名也可能让整条工作流断掉。

维护时应把稳定部分明确成契约,例如:

输入契约:接受 Markdown、Word、PDF
输出契约:生成一个 UTF-8 Markdown 文件
路径契约:写入 source/_posts/
验证契约:交付前必须通过 Hexo 构建

契约之外的措辞和内部步骤可以灵活优化;契约变更则需要升大版本、迁移说明或兼容期。

六、发布策略:从本地验证到灰度上线

直接修改所有用户正在使用的 Skill,然后观察有没有人报错,是最省事也最昂贵的发布方式。

更稳妥的流程是:

修改草案
→ 静态检查
→ 回归评测
→ 影子运行
→ 小范围灰度
→ 全量发布
→ 观察与回滚

1. 静态检查

先检查那些不需要模型运行的问题:

  • frontmatter 是否合法;
  • name 是否与目录一致;
  • 引用的文件和脚本是否存在;
  • 相对路径是否正确;
  • 是否出现互相冲突的指令;
  • 主文件是否膨胀到难以阅读;
  • 示例中是否残留密钥和真实用户数据。

2. 影子运行

影子运行的意思是:新版 Skill 读取真实任务并生成结果,但不把结果交给用户,也不执行写操作。维护者只比较新旧版本的决策和产物。

它尤其适合验证触发逻辑。因为“新版会不会抢走别的 Skill 的任务”,靠离线构造几个例子很难看全。

3. 灰度与回滚

如果运行平台支持版本选择,先让少量用户或内部任务使用新版。观察指标没有明显恶化,再逐步扩大。

每次发布都应保留一个能快速切回的稳定版本。回滚条件要提前写清楚,例如:

核心任务成功率下降超过 5%
误触发率连续两小时超过 3%
出现未经确认的外部写操作
构建失败率明显上升

别等事故发生后再开会讨论“这算不算严重”。

七、依赖、兼容性与安全维护

Skill 自身可能只是一组 Markdown,但它依赖的世界一直在变。

1. 建一张依赖清单

至少记录:

依赖类型 例子 维护动作
模型 默认模型、上下文长度 模型升级后跑完整评测
工具 浏览器、Shell、文档渲染器 跟踪接口和权限变化
外部服务 GitHub、Slack、Cloudflare 检查认证、限流和 API 版本
项目约定 目录、构建命令、模板 仓库变更时同步 Skill
参考资料 官方文档、规范 定期检查链接和版本

最常见的维护事故不是 Skill 主文件写错,而是它引用的脚本改了参数,或者项目已经换了构建命令。

2. 模型升级必须重跑评测

新模型通常更强,但“更强”不等于“行为完全兼容”。

它可能更主动地调用工具,也可能更少询问用户;过去必须写得很细的步骤,新模型已经能自己推断;过去一句话就能约束住的边界,新模型反而会做更远的扩展。

所以模型升级应当被当成一次依赖升级,而不是免费性能提升。

3. 定期做安全审查

重点检查:

  • 是否可能泄露环境变量、凭证或用户文件;
  • 外部内容能否通过提示注入改变工作流;
  • 写操作是否有清晰授权边界;
  • 删除、覆盖、发布等动作是否可恢复;
  • 日志是否记录了不必要的个人或业务数据;
  • 引用的脚本和依赖是否来自可信来源。

尤其要警惕“为了减少确认步骤”而不断放宽权限。流畅和失控之间,有时只差一句“默认直接执行”。

八、什么时候应该拆分、合并或退役

不是所有维护都应该继续往原 Skill 里加内容。

1. 该拆分的信号

  • 主文件越来越长,大量章节只服务于特定场景;
  • 触发描述需要列出互不相关的任务;
  • 不同模式使用完全不同的工具和产物;
  • 修改一个模式时,经常让另一个模式回归;
  • 用户只想用其中一部分,却每次加载整套规则。

先考虑把细节拆到 references/。如果连触发条件、流程和产物都不同,再拆成独立 Skill。

2. 该合并的信号

  • 两个 Skill 总是一起触发;
  • 职责边界需要反复向模型解释;
  • 输入输出几乎相同,只差少量参数;
  • 用户根本分不清应该点哪个。

Skill 不是越多越好。数量多到需要另一个 Skill 来解释“该用哪个”,通常说明分类出了问题。

3. 该退役的信号

  • 平台已经原生提供同等能力;
  • 长期没有真实调用;
  • 维护成本明显高于带来的收益;
  • 依赖已停止维护或存在安全风险;
  • 新 Skill 已完整覆盖旧能力。

退役不要直接删除。先标记 deprecated,给出替代方案和迁移时间;观察没有剩余调用后,再停止分发。涉及输出格式变化时,还要保留读取旧格式的兼容窗口。

九、一套可执行的维护节奏

维护最怕“有空再看”。下面这套节奏不重,但足以让一个中小规模 Skill 保持健康。

每周

  • 查看新增失败和用户修正;
  • 给失败分类,合并重复问题;
  • 把可复现事故加入回归集;
  • 修复高频且影响核心流程的问题。

每次发布

  • 更新版本号和变更记录;
  • 跑静态检查与完整回归;
  • 检查输出契约是否变化;
  • 记录依赖版本;
  • 确认回滚版本可用;
  • 观察发布后的错误率与人工反馈。

每月

  • 清理重复、冲突和已经失效的规则;
  • 检查外部链接、脚本和工具接口;
  • 复盘误触发率和任务成功率;
  • 审查日志字段与权限;
  • 评估是否需要拆分、合并或退役。

可以把这份清单直接放进 Skill 仓库:

## Release Checklist

- [ ] 新失败已分类
- [ ] 事故样本已加入回归集
- [ ] 核心评测全部通过
- [ ] 输出契约无意外变化
- [ ] 依赖与安全检查完成
- [ ] CHANGELOG 已更新
- [ ] 回滚版本可用
- [ ] 灰度指标正常

真正成熟的 Skill,不是规则最多,而是每条规则都能解释自己为什么存在。

十、常见问题

问题 回答要点
Skill 多久更新一次合适? 不要按日历强行发版。高影响故障立即修,普通改进攒成小版本;即使没有发版,也应定期检查依赖和反馈。
用户说“不好用”,应该立刻改吗? 先拿到原始请求、实际结果和用户修正,确认失败类型。单个偏好不一定适合上升为全局规则。
评测集需要多少案例? 先从 15~30 个高价值案例开始,覆盖核心、事故和边界场景。数量不是目标,能拦住真实回归才是。
可以只靠另一个模型评审吗? 不建议。格式、文件、命令和构建结果优先用确定性检查;模型评审留给表达质量和语义一致性。
SKILL.md 越写越长怎么办? 通用流程留在主文件,场景细节拆到 references/;如果触发条件和产物也不同,再拆成多个 Skill。
模型升级后需要改 Skill 吗? 不一定要改,但必须重跑评测。先用结果证明兼容,再决定删规则还是补约束。
如何判断维护是否有效? 看核心任务成功率、误触发率、人工修正率、平均修复时间和回归数量,而不是看新增了多少规则。
旧 Skill 可以直接删除吗? 不要。先标记废弃、提供替代方案和迁移期,确认没有剩余调用后再下线。