头图

我一度把 Skill 当成一个函数:传参数进去,返回结果出来,完事。按这个理解写的第一个 Skill,描述写得像 API 文档——参数类型、返回值、错误码,一应俱全。结果小艺从来不调它。

我排查了很久,最后发现问题不在代码,在我对"它怎么被叫出来"这件事的理解。Skill 不是"被调用的函数",是"被发现的能力"。这两个说法的差别,就是这一篇要讲的全部。

一、我曾误以为 Skill 是函数

函数是你明确知道名字、主动去调的东西。但用户不会说"调用 meeting-minutes 这个 Skill",他只会说"帮我把刚才那会的讨论理一下"。

系统智能体要做的事,是先听懂这句话的意图,再去一堆已注册的 Skill 里做语义匹配,挑出最合适的那个。匹配靠的不是函数名,而是你写的 SKILL.md 里那段触发场景和描述——那是给机器看的语义说明,不是给人看的接口文档。

我把参数类型写得再规范也没用,因为机器在决定"要不要叫你"的时候,根本还没看到参数那一层。它先看的是:这句话的意图,跟你描述的场景像不像。

所以官方会把 SKILL.md 说成"意图—能力匹配的唯一依据"。你写得像 API 文档,机器反而看不懂。

二、Skill 是"可被发现的能力单元"

我给自己重新下的定义是:Skill 是一个粒度较细、能被小艺语义匹配并调用的能力单元。比如"查订单"“整理会议纪要”“算房贷月供”,都是典型的 Skill 粒度——一件事,说得清,干得完。

它和 Agent 最大的区别在于:Agent 有自主性,会规划、会拆解、会调度;Skill 只负责把一件具体的事干完,它不决定"该不该做",只负责"做"。一个能干活的智能体,背后通常挂着好几个 Skill。

三、触发意图怎么写,决定它能不能被叫出来

这是我最想强调的一点。触发场景要写典型话术(正向示例)和不调用的情况(反向排除),两边都写,缺一不可。

拿后面要做的"会议纪要整理"举例,我会这么写:

  • 调用的情况:“帮我把刚才那会的讨论理一下”“整理成会议纪要”“把这段录音的要点提炼出来”;
  • 不调用的情况:“帮我订个会议室”(意图是预定,不是整理)、“明天几点开会”(意图是查询日程)、“把纪要发给张三”(意图是发送,不是整理)。

写的时候有个笨但有效的办法:把相邻意图全想一遍。用户可能说的、跟你的能力沾边但其实不是你的活,都写进"不调用"里。这些排除项看着是给自己设限,实际是在帮系统做区分——你帮它排除了,它就不会乱叫你。

反面教材是这个:"当用户问问题时调用。"看着省事,实际后果是所有问题都会命中你,误触发率极高——用户体验炸,审核也过不去。你划的边界越清楚,它被正确唤起的比例才越高。

Skill 怎么被叫出来

四、Agent 负责想,Skill 负责干

把分工摆清楚,后面设计就顺了:

Agent 理解模糊需求 → 做规划、拆解步骤 → 调度一个或多个 Skill → 维持多轮对话、把结果组织成人话。

Skill 接收明确参数 → 执行一件具体的事 → 按约定返回结果。

还是第 1 篇那个比方:Agent 是管家,Skill 是管家口袋里的专用工具。用户跟管家说话,管家决定掏哪把工具。你写 Skill 的时候要记住——你是在给管家做工具,不是在跟用户对话。

Agent 与 Skill 的分工

五、平台 Skill 和随包发布的 Skill

最后分清两条落地路径,这决定你选哪种开发方式:

平台 Skill(VibeCoding 生成、平台托管):不用自己搭工程,用自然语言就能生成,适合把已有能力快速外化、做快速原型。周期以分钟计。缺点是深度定制受限。

应用内随包发布的 Skill(手写):跟着你的鸿蒙应用包一起发布,能深度调端侧能力、复用现有业务代码。但要掌握 ArkTS 和鸿蒙智能体框架,周期以天计,而且必须关联 AGC 已上架应用——就是第 2 篇那个硬前置。

我自己的顺序是:先用平台方式验证想法值不值得做,跑通了再用手写方式做正式版。这个顺序最省时间,因为大部分想法其实活不到需要手写那一步。

接下来的两篇,就分别走这两条路——先用 VibeCoding 十分钟搓一个出来,再手写一个正式的。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐