设计 AI Skill 的一些思路和踩过的坑

前言
最近一年多,AI 应用的重心在慢慢从“单次对话”转向“让模型自主完成一个完整任务”。不管是 Anthropic 的 Agent Skills 开放标准、Context Engineering 概念的兴起,还是各种 agent 框架的迭代,大家都在探索同一件事:怎么让模型在复杂任务里稳定地做对。
我们在这个过程里陆续做了十几个 Skill,覆盖深度研究、文档解读、专业写作、邮件助手、数据分析、会议总结这些场景。一开始也是写长 prompt,觉得讲得够清楚就能跑通。后来发现完全不是这么回事。
这篇想整理一下过程中的一些思考,权当一份实践记录。
一、遇到的一个核心问题
先说一下我们碰到的具体困难。
模型本身的能力是够的——不管是 Claude 还是 GPT 系列,在单轮任务上表现已经很好了。但一到多轮、多步骤、需要跨工具操作的场景,就很容易出现一种“稳定的错误”。
不是偶尔答错一个知识点,而是换个用户、换份材料还会再犯的那种错误。比如:
- 会议总结里,把“我建议下周上线”写成了“决定下周上线”
- 深度研究里,前面做了多源交叉验证,最后综合成四条结论时每条只剩一个链接,验证的证据链丢了
- 数据分析里,两组数据 JOIN 之后忘了检查基数变化,结果重复计算了
- PDF 解读里,只读了前面 20 页和最后一页,就声称“已完整阅读”
我们翻过 Anthropic 的一些工程文章,他们对此也有类似的观察——模型在长上下文里存在“注意力稀释”的问题,上下文越长,精确回忆具体信息的能力就越弱。同时,模型在压缩和综合的过程中,倾向于把一些细微但重要的区别给磨平。
这就引出了我们后来设计 Skill 时最关注的一个问题:在这个任务里,哪些区别是一旦被抹平就会出错的?
二、从失败反向推导
如果先想清楚这个问题,后面的设计路径会顺很多——从失败往回推,而不是从理想流程往下排。
先看:出错了,到底是哪种信息丢了?
拿几个常见的错误来分析:
| 表面看到的错误 | 本质上是哪种信息在处理中丢了 |
|---|---|
| 提议被写成了决定 | 说话行为的类型——是建议还是决议——没被区分 |
| 邮件发错了人 | 收件人里 To、Cc、Bcc 的角色和权限边界被合并了 |
| 分析结果数量对不上 | 数据连接时的粒度变化没有被记录 |
| 论文结论被夸大 | 研究设计的限制和可推断范围在压缩中被省略了 |
| PDF 漏读了中段内容 | 文档的结构和阅读覆盖状态没有留下来 |
| 多源研究退化成一个引用 | 主张和证据之间“多对多”的关系被简化成“一对一” |
| 抓取失败的来源被当成不可信 | 访问状态和来源质量的区分被合并了 |
这个分析的好处是,它不让你停在一句“模型不够仔细”上。你会被推到更具体的地方:这个错误发生了,是不是因为某个信息在处理过程中被弄丢了?如果是,这种信息能不能被显式地保存下来?
然后做:把容易丢的信息变成“必须保存的状态”
面对“会议里把提议写成决定”,加一句“注意区分提议和决定”不太管用——在长任务的后半段,这句提醒早就被压到上下文深处了。
我们试下来比较有效的方式,是把这些容易丢的东西变成显式的状态字段。比如会议场景,不是写一条规则,而是定义一个结构:
- 发言原文是什么
- 是建议、讨论、还是决议
- 谁做出的
- 有没有被后续讨论修改或撤回
- 在原始材料里的具体位置
每个具体任务里都可以这样拆。PDF 解读需要“覆盖状态”——哪些页读了、哪些没读、哪些需要视觉核验。数据分析需要“转换日志”——每一步处理前后数据量的变化。
这背后的想法其实挺朴素:如果一种信息的丢失会导致错误,那就别让它只活在流动的对话里,给它一个固定的位置。
关键判断:哪些信息值得建模?
当然不是所有信息都需要这样处理。我们一般用三个问题筛一下:
- 丢了它,结果会错吗?
- 工具调用失败后,要靠它来恢复吗?
- 最终结果在审计时,需要拿它来对照吗?
三个都否的话,就不用专门建模。否则 Skill 文件会越写越长,反而找不到重点。
状态机的顺序,按依赖关系排
设计流程时,我们不先预设“这个任务应该分几步”。而是把关键判断列出来,逐个问:这个判断要成立,得先知道什么?
比如解读一篇论文——想评价结论,得先理解研究设计。想理解研究设计,得先确认读的是哪个版本。想确认版本,得先拿到论文全文和出版信息。想对统计结果提出质疑,得先核对具体数字。
这些前置关系排出来,步骤顺序就自己出现了:
确认身份 → 获取全文 → 了解结构 → 逐段阅读 → 重建论证 → 评估证据 → 核验 → 输出
这样排出来的流程,每个步骤都有它不得不存在的理由——不是装饰,而是因为后面的步骤依赖它。
责任有跃迁的地方,多加一道确认
还有一个我们比较关注的点:任务里有些动作只是读取和分析,有些动作会改变现实状态。
读邮件 → 写草稿 → 真正发送
看会议记录 → 提取待办 → 创建任务
分析数据 → 得出结论 → 修改生产数据
这些箭头连起来看着很自然,但其实每跨一次,责任的边界就变了。我们后来养成了一个习惯:在这些跃迁点上,多问一句“这里需要确认吗”。 比如邮件 Skill 里会把 draft 和 send 明确分开,会议 Skill 里会把 summary 和 task creation 拆成不同阶段。
控制力度按风险来,不是按篇幅来
不是所有规则都该写死。一个简单的判断思路:
- 错误后果严重、模型在这个点上判断不稳定 → 硬规则,比如“不得伪造引用”“Bcc 不得泄露”“高风险结论必须有足够证据”
- 多种做法都可以、依赖具体上下文判断 → 给原则和启发,比如搜索用什么关键词、报告怎么组织、需要几个例子支撑
一刀切地严格,Skill 会变得僵化。一刀切地宽松,又会回到原点。每一处控制力度都可以单独思考。
三、Skill 的整体结构
上面这些思路落地之后,一个 Skill 大致由这几个部分构成:
- 触发条件:什么时候该用,什么时候不该用
- 用户会怎么用它:从哪些角度进入、期望什么结果
- 任务里的关键对象:哪些信息需要被显式追踪
- 执行步骤和顺序:按前置依赖排出来的状态机
- 质量底线:什么情况下结果不可接受
- 失败后的恢复方式:工具出错、来源冲突、无法访问怎么办
- 输出格式:结果里哪些字段必须保留、哪些可以灵活处理
写出来的文件结构大概是三层:
- name + description——模型随时能看到,只管判断“这个 Skill 该不该触发”
- SKILL.md——触发后加载,放核心规则、状态机、质量要求和交付格式
- references——只在特定类型或风险等级出现时按需加载
这样简单任务不会被复杂的流程拖慢,复杂任务也有足够的参考信息。
用代码来类比的话——Skill 更像函数里的参数校验和边界条件,而不是主逻辑。主逻辑让模型自己发挥,Skill 负责说“在这个场景下,有哪些坑你别踩、有哪些状态你别丢”。
四、踩过的几个坑
做 Skill 的过程中有些反复出现的问题,记一下。
1. 把所有东西塞进一个长 prompt
一开始很容易这么干——觉得讲得越详细越好。但实际跑起来,长 prompt 里的细节越多,模型反而越容易漏掉真正重要的规则。而且每次对话都加载全文,token 成本也大。
后来改成按需加载:主文件只放不可绕过的规则,具体操作指南放在单独的 reference 里,模型自己判断什么时候读。
2. 规范写得很严谨,但运行时根本没执行
有的 Skill,SKILL.md 看起来很完整,但实际跑的时候,Workflow 走的是另一套硬编码逻辑。规范归规范,执行归执行。
解决方式是给 Workflow 定义清楚它必须返回哪些字段、引用哪些位置。不只是“把做完的结果给我”,而是有固定的交接格式。
3. 为了显得完整而塞功能
有些 Skill 其实用纯文字指导就够了,但总觉得“差个脚本不够完整”,就硬加一段 Python。实际上这些任务的核心难点是判断而不是机械执行——文档解读难在有没有漏页、表格有没有错位,不难在能不能提取文本;研究难在搜什么、什么时候停,不难在搜索本身。
脚本只在一种情况下值得加:同一段代码被反复重写、操作机械且容易出错、平台原生能力搞不定。
4. 把“没找到”写成“不存在”
这个听起来像小问题,但影响很大。搜索结果为空、访问失败、来源声明被其他证据反驳、信息客观上不存在——这四种情况的含义完全不同。我们在 Skill 里专门区分了这几个状态,结果的质量明显有提升。
5. 固定验证次数或来源数量
早期我们试着定“每个结论至少 3 个来源”“验证 2 次”这种硬数字。跑下来发现简单问题成本过高,复杂问题又不够。后来改成按主张的风险等级动态分配——影响结论的关键主张多验证,背景信息一笔带过就行。
五、怎么知道 Skill 有没有用
我们试下来比较实用的评估方式分三层。
第一层是结构检查——frontmatter 对不对、reference 文件能不能找到、有没有 TODO 和无关文件。这个可以自动化。
第二层是把自己遇到的失败场景整理成一组检查项,每次改完 Skill 都过一遍。比如“全文覆盖声明有没有覆盖记录”“OCR 出来的关键数字有没有视觉核验”“多源证据在综合后有没有变成单源”。
第三层是用真实的用户表达来测。不是说“测试一下 coverage ledger 是否完整”,而是说“帮我看懂这份 180 页财报,重点判断现金流有没有恶化”。跟真实场景越接近,测试越有意义。
如果测出来某个错误反复出现,改的时候有个原则我们觉得挺重要:改通用机制,不改某一道题。 不写“欧盟 AI 法案必须引用 EUR-Lex”,而写“涉及权威法律原文时,重要主张不能只引用聚合站点”。前者修一个 case,后者修一类问题。
六、Skill 不是独立存在的
做了十几个 Skill 之后,有一个感受越来越明显:Skill 之间是可以串联的。
比如一个典型的分析链路:
PDF Skill 把文档内容提取出来、检查有无漏页
→ 论文解读 Skill 重建论证、评价证据质量
→ 深度研究 Skill 补充外部研究和领域现状
→ 数据分析 Skill 复核论文里的数据
→ 专业写作 Skill 组织成完整报告
每个 Skill 解决一个环节的问题,组合起来可以覆盖比较长的任务链。
另外,Skill 也不一定要独立存在。如果只是某类任务的一个子场景(比如“董事会会议”只是“会议总结”的一种类型),做成 reference 就够了,不需要单独成 Skill。判断标准是:这个场景有没有独特的对象模型、独特的风险、独特的状态需要追踪?有就值得独立,没有就不需要。
结语
这套方法是踩坑踩出来的一点经验整理,还在持续调整中。
回头想,贯穿整个过程的核心思路其实就一条:做 Skill 的时候多问“在这个任务里,什么信息一旦丢了就会出错”,少问“模型应该按几步来执行”。 前面是找问题,后面是排步骤——先把该保护的信息找到,顺序和结构自然会跟着出来。
如果你也在折腾 Skill 或者 Agent,希望能有点参考。