只要是经常和AI对话的人,应该都碰到过这种场景:同一个任务,你上回才手把手教过它怎么干,换个会话窗口,它又原样犯傻。我在做Agent类项目时,最让人崩溃的从来不是模型理解力不够,而是它永远记不住“你做事的方法”。你让它按项目维度写日报,它写了;过两天你想让它按同样的逻辑写周报,它又退回通用模板,仿佛上次什么都没发生。
后来我接触到一个思路,叫做 Agent-Skills,翻译过来就是“智能体技能”。它的目标很直接:把AI与人协作过程中形成的稳定工作方式,封装成可复用、可调用的技能模块,让AI不用你再反复教。这篇文章我会从实际问题出发,聊Agent-Skills解决什么问题、内部怎么设计、怎么写、怎么上线,以及我在落地过程中踩过的几个坑。如果你也在做Agent应用,或者只是希望AI助手更懂你的习惯,这篇内容应该对你有用。
1. 为什么AI总在“重复教三遍”——从会话记忆到技能沉淀
1.1 会话隔离:每次对话都是重新认识
很多用户默认AI能记住历史对话,但实际情况是:模型本身是无状态的。所谓“记忆”,要么靠当前上下文窗口里的内容,要么靠外部系统临时注入。你新建一个会话,本质上就是一次“重新认识你”的过程。
我见过最普遍的用法,是把一套固定指令存在某个文档里,每次开新对话前先粘贴一遍。有人管这个叫“人肉Skill”。短期看确实能用,但它有三毛病。第一,容易忘,你总有手边没带模板的时候;第二,会过时,模板在团队群聊里更新了一版,你本地粘贴的还是老的;第三,不灵活,你想让它在特定条件下才生效,粘贴式指令根本做不了条件分支。
这时候你才会意识到,问题本质不在模型能力,而在于我们把“工作方式”这种本该结构化的东西,当成了一次性的对话消息去传递。会话隔离之下,AI永远只有短期记忆。一次教完、一次生效,这个思路在单次对话里没错,但它无法沉淀,无法复用。
1.2 记忆库的局限:记住事实不等于记住方法
后来主流的解法是给AI配记忆库,用向量化存储的方式把用户偏好、历史结论放进去,下次对话时检索注入。这个方案确实解决了部分问题,但它的定位在实践中更偏“记住事实”。比如它擅长记住“张三喜欢简洁回复”“这个项目的验收标准是XX”,要它表达一整套执行流程,就非常吃力。
我打个比方:记忆库像一本笔记本,记录的是“上次聊了什么、结论是什么”;而工作方式更像一本操作手册,记录的是“遇到什么情况、按什么顺序、做什么动作、最后产出什么样子”。笔记本不能代替操作手册,因为前者回答“知道什么”,后者回答“怎么做”。
这也解释了为什么很多团队的Agent做完记忆增强之后,依然需要反复调教:因为记忆库补上的是知识层,不是流程层。而真正让AI稳定复现你工作方式的,恰恰是后者。这两个东西要分开存、分开管,否则就全挤在一堆向量里,检索出来的东西可解释性极差。
1.3 Skill的本质:把“怎么做”封装成可复用的行为模块
Agent-Skills的思路,就是专门补上“怎么做”这一层。它把一个稳定、可重复的工作方式,拆成一段结构化的技能描述,包括触发条件、执行步骤、约束规则和输出格式,然后以独立模块的形式挂载到Agent上。AI一旦命中触发条件,就按这套流程执行,而不是临时发挥。
你可以把它理解成给AI发了一本岗位手册。比起让AI每次从零猜你的喜好,更可靠的方案是让它学会一套SOP。而且因为Skill是独立模块,它可以存在本地、可以放进团队共享库、可以按项目加载、可以单独迭代。一个人的工作习惯,就这样变成了可以被组织和工具继承的资产,而不是随会话一起消失。
到这里,你已经能看出Agent-Skills的定位:它介于Prompt、Memory和Fine-tuning之间。比Prompt更持久,比Memory更强调流程,比Fine-tuning更轻量、更容易理解。接下来我讲讲更具体的设计问题。
2. 拆解一个Skill:设计层面的四个关键组件
2.1 从Prompt到Skill:从“说教”到“程序化”
还是从最熟悉的Prompt说起。传统Prompt解决的是“这一次任务怎么干”,它通常是一段自然语言,描述背景、要求、输出格式。问题在于,你写了A任务,AI就只按A任务的方式干活;稍微换个说法问,它可能又飘了,表现非常不稳定。
Skill和Prompt最关键的分水岭在于:Skill把工作方式“程序化”了。它不只是一段更好的提示词,而是一个有边界、有条件、有步骤、有工具依赖的结构化单元。你可以同时准备几十个Prompt,但它们之间是散的;而Skill更像把这些Prompt做成了可插拔的功能模块,一个模块就是一件完整的事。
2.2 四个核心组件:触发条件、执行步骤、输出契约、工具依赖
在设计Skill的时候,我习惯先拆四个部分,缺一不可。
首先是触发条件。它决定AI在什么情况下启动这个Skill。这里有个重要原则:条件要写“可判断的话”。比如“当用户要求生成日报或周报时”就是可判断的;而“当用户需要帮助时”这种万能句式,几乎是无效条件,因为任何对话都满足它,Skill就失去了特异性。
其次是执行步骤。这一步把工作方式拆成有序动作,是Skill的骨架。动作描述要具体到AI能直接执行。举例来说,“第一步,从对话记录中提取项目名称和完成事项;第二步,按项目维度汇总;第三步,单列风险项”。步骤如果不清晰,AI就会自由发挥,你得到的输出每次都不一样。
第三是输出契约,也就是“长什么样才叫完成”。包括标题格式、段落顺序、语气风格、字段结构。这里我特别推荐一个技巧:给例子比给形容词有效。比如你想让它突出风险,不要只写“要突出风险”,而是写“风险项一律用‘风险:’开头,并在每项后面附上影响范围”。
第四是工具依赖。很多Skill不是纯文本任务,它要调用搜索、读写文件、执行代码、发送消息。Skill里必须显式声明需要哪些工具,以及调用边界。比如“只允许读取项目目录下的文档,禁止修改文件”。这一步不仅影响执行效果,更直接影响安全边界。
2.3 一个可参考的Skill结构示例
下面用YAML写了一个“周报生成Skill”的最小结构,你可以直接拿来改:
skill_name: weekly_report_generator version: 0.1 description: - 当用户要求生成周报或周工作总结时启用 trigger: intent: ["周报", "周总结", "week review"] context_required: ["本周聊天记录", "项目列表"] steps: - step: 1 action: "提取本周所有项目相关的对话片段" method: "从当前上下文与记忆库中检索" - step: 2 action: "按项目维度聚合完成事项" method: "每个项目一个小节,事项按时间倒序" - step: 3 action: "识别风险与阻塞项" method: "包含未完成原因、影响范围、需要谁协调" - step: 4 action: "生成输出" method: "遵循output_format" output_format: title: "本周工作汇报" sections: - "项目进展" - "风险与阻塞" - "下周计划" style: "先结论后细节,每条不超过三行" warning: "不要在开头写'本周工作整体平稳'这类空话" tool_dependencies: required: ["memory_search"] forbidden: ["file_write"]这个示例里有几个细节值得琢磨。description我刻意写成“可以判断的话”,让AI能够在多个触发词之间准确匹配;steps里标了method,避免AI在步骤内部自由发挥;output_format里写了负面清单,这比只说“要写得具体”有效得多;tool_dependencies里的forbidden字段用于限制权限,防止它生成周报的时候顺手改文件。
2.4 为什么四个组件就够了
我见过不少设计者给Skill加了大量复杂字段,有场景描述、人员角色、例子库、评分表,等等。从我实际跑下来的感受是,四组件是一个平衡点:触发条件解决“什么时候生效”,执行步骤解决“按什么顺序做”,输出契约解决“做成什么样”,工具依赖解决“能碰什么不能碰什么”。这四个维度正好覆盖了Agent执行一个任务需要的全部决策面。再加字段,维护成本会明显上升,普通人很难持续维护一套过于复杂的Skill。宁可复杂在内容里,不要复杂在结构上。
3. 手写一个Skill的完整流程:从识别需求到上线挂载
3.1 第一步:先观察,不要急着写
我最初犯的错误,是凭想象去写Skill。结果不是场景假想就是粒度失控,写出来的东西根本用不起来。后来我换了一个更笨但更有效的方法:先记录。回看过去两周自己和AI的对话,把重复出现的任务类型列出来,再逐个判断它值不值得做成Skill。
判断标准我浓缩成三条:一组字段。候选任务至少每周出现一次;执行流程基本稳定;输出结果可以被明确判断好坏。三条都满足才值得写。我常用一个经验值:同一件事如果你反复教AI超过三次,或者教完还是不满意,那么这就是Skill的候选。反之,一次性的任务不要投入。
下面是我实际用过的一个筛选表示例,方便你对照:
| 候选任务 | 出现频率 | 流程稳定性 | 输出可验收 | 是否值得做Skill |
|---|---|---|---|---|
| 周报生成 | 高 | 稳定 | 是 | 值得 |
| 竞品动态整理 | 高 | 稳定 | 是 | 值得 |
| 代码审查 | 中 | 较稳定 | 是 | 值得 |
| 头脑风暴 | 低 | 不稳定 | 否 | 不值得 |
3.2 第二步:写一个“异常具体”的第一版
开始写第一版时,我建议先别管格式好不好看,最重要是把每个动作写到AI能理解。这里有一个很实用的句式:动作加对象加条件。不要写“整理项目信息”,而要写“从对话记录中提取项目名称、负责人、当前状态”;不要写“分析风险”,而要写“找出延期超过三天的任务,标记为高风险”。
术语统一也是这阶段容易踩的坑。同一个东西从头到尾要叫同一个名字。“项目”就一直是“项目”,不要一会儿叫“项目”,一会儿叫“任务”“案子”。AI对术语漂移非常敏感,同一个概念三个叫法,它就会在步骤里来回横跳,输出结构也会跟着乱。
3.3 第三步:测试时不要只看输出,要看过程
Skill写完一定要测,但大多数人只测“输出对不对”。我建议同时测三件事:触发准不准、步骤稳不稳、边界清不清晰。具体操作是:先给它一个明显该触发的问题,看它是否正确启动;再连测三次同样的输入,看输出结构是否一致——Skill的核心价值就是稳定性;最后给它一个模棱两可的问题,看它是否会在不该触发的时候硬套流程。
我有一个很痛的教训。某个Skill测试阶段输出完美,但上线之后一旦遇到“用户没有提供足够信息”的情况,就开始编造内容去填充模板。后来检查发现,是步骤里少写了一条“信息不足时先向用户确认,不要猜测”。边界处理必须写进Skill里,否则AI在不确定时,倾向于“硬着头皮完成”而不是“停下来问”,这在生成类任务里是致命的。
3.4 第四步:挂载到Agent工作流
Skill写好后,挂载方式有很多种,主要看你的Agent架构。轻量做法是放在系统提示词里作为附加指令,适合个人使用;标准做法是注册到Agent的工具列表,由路由模块根据用户意图动态加载;更重的做法是做成外部技能库,通过检索匹配后再把Skill文本注入上下文。
我目前最常用的方案,就是“检索后注入”。Agent先判断用户请求与哪些Skill相关,只把匹配的Skill内容注入上下文,而不是把所有技能一股脑塞进去。好处是上下文不会被无关内容占满,内存效率高,也能同时加载多个Skill。你可以在路由层给每个Skill打标签,比如“周报”“日报”“复盘”,标签与用户意图的匹配度,直接决定加载优先级。
3.5 一个完整运行示例:从请求到输出
为了让你更直观地理解,我跑了一个模拟用例。
用户输入:“帮我写这周的周报,这周主要在搞登陆模块重构和性能优化。”
Agent内部处理如下:
- 路由模块识别到“周报”关键词,命中weekly_report_generator,加载Skill。
- 检查上下文,发现本周对话记录里有登陆模块的重构讨论、性能优化的排查记录,满足context_required。
- 按steps顺序执行:提取项目片段、按项目维度聚合、识别风险项。
- 输出时套用output_format,标题为“本周工作汇报”,包含“项目进展”“风险与阻塞”“下周计划”三个部分。
最终输出大致是:
标题: 本周工作汇报 项目进展: - 登陆模块重构: - 完成 OAuth 流程替换 - 完成会话有效期策略调整 - 性能优化: - 定位接口慢查询根因 - 优化索引方案,P50 响应时间下降 40% 风险与阻塞: - 风险:OAuth 切换涉及旧数据迁移,影响范围较大,需要数据组配合。 下周计划: - 完成迁移脚本联调 - 启动性能回归测试这个例子看着简单,但它验证了两件事:技能确实按照预设的步骤和格式在工作,而且在不额外提示的情况下,AI会主动区分项目、聚合风险,而不是用一套通用模板敷衍你。
4. 让Skill真正“活”起来:版本管理、团队复用与冲突处理
4.1 Skill不是一次性产物,它需要版本迭代
Skill写完并不是结束。团队规范会变,工具会变,AI的底座模型也会升级。我见过有人一份Skill用半年不更新,结果新模型推理能力更强,反而被旧Skill里的冗余指令拖累了输出质量,该发挥的地方发挥不出来。
建议给每个Skill加版本号,并且记录变更历史。每次改动只改一个点,改完重跑一遍回归测试。哪怕只改了一条输出格式要求,都要验证它不影响步骤执行。版本号不只是追溯工具,更是团队协作的锚点。你说“周报Skill升到0.3了”,别人立刻知道改了哪块,减少了大量沟通成本。
4.2 从个人习惯到团队技能库
当你在团队里推广Agent-Skills,你会发现它带来的不只是效率提升,还有一致性。以前写竞品分析,每个人交上来的格式五花八门;现在共用同一个竞品分析Skill,结构统一,评审的人看着省力,新成员上手也更快。
团队技能库一定要分工维护。每类业务指定一个负责人,更新权限不要对所有人放开。否则就会出现“这个Skill加了一段要求,那个Skill又把要求删了”的混乱。我见过比较稳的流程是:个人先在自己的空间里写Skill,跑顺手之后再提交到团队库,评审通过后统一发布。新版本发布时保留回滚入口,一旦出问题能立刻切回旧版本。这套流程很接近代码库的发布机制,Skill本质上也值得被当作代码来管。
4.3 多Skill冲突:优先级和细粒度设计
当AI同时加载多个Skill时,冲突几乎不可避免。典型场景是“周报Skill”要求输出包含“下周计划”,而“日常助手Skill”要求一切回答尽量简短。两个指令同时生效,AI就会犹豫,输出往往两头不靠。
解决思路是给Skill加两级控制。第一级,在Skill内部写清楚“本Skill优先于通用指令”;第二级,在挂载顺序上让更具体的Skill排在后面,后面的覆盖前面的。这样做的好处是分层清晰:通用Skill负责对话礼仪,具体Skill负责业务动作,各管一层。冲突出现时调整优先级就好,不要试图在一个Skill里塞下所有情况,那会回到过度泛化的老路。
4.4 如何衡量技能库是否健康
技能库运行一段时间后,总会有一些Skill很少被触发。我现在的习惯是定期看使用数据,频率很低的Skill要么改触发条件,要么直接归档。衡量健康度我只看三个指标:触发次数、成功率、维护成本。成功率可以看输出是否被用户二次修改,二次修改率高于三成,就说明这个Skill的描述不够准确。维护成本看变更频率,一个Skill频繁改动,往往是因为边界没想清楚,而不是团队需求不稳定。
5. 踩坑实录:我在落地Agent-Skills时遇到的四个典型问题
5.1 第一个坑:过度泛化,一个Skill想管所有事
我最早写过一个“文档处理Skill”,本意是让它处理所有文档类任务。结果会议纪要场景表现很好,改需求文档时各种乱来。原因在于文档类型差异太大,会议纪要是高度结构化的,需求文档是开放式的,用一套步骤约束所有类型,AI只能在不同的文档之间生硬套模板。
教训是:Skill粒度一定要小。宁可一个场景一个Skill,也不要试图做一个应对所有情况的超级Skill。判断粒度是否合适,看触发条件就知道了:如果触发条件里列了八九种场景,明显就是太泛了,需要拆。拆开之后每个Skill都轻,维护起来也简单,测试时也能更精准地定位问题。
5.2 第二个坑:静态指令失效,Skill不知道上下文已经变了
这个坑特别隐蔽。Skill里写了“提取本周所有项目任务”,但如果这一周根本没有新任务,AI就会从旧记录里翻出过时内容硬填,看起来有条理,实际上是错的。还有一次,用户原本在A项目,临时切到B项目,Skill仍然按照A项目的模板输出,因为它在设计时没有考虑到用户语境会切换。
后来我在Skill模板里加入动态变量占位符,每次调用时由Agent从上下文中提取真实值填充。比如不要写“提取本周所有项目任务”,而是写“提取当前活跃项目列表,从下文中的项目字段动态读取”。同时增加一条检查规则:如果关键字段没有对应数据,禁止猜测,必须返回提示让用户补充。这一行看起来简单,实际避免了一大批“表面正确、实则编造”的输出。
5.3 第三个坑:工具权限失控,Skill会“顺手”做过头
当Skill绑定工具调用时,权限边界必须显式声明。我遇到过一个例子:有同事写了个“自动归档邮件”Skill,本意是把指定邮件移到归档文件夹。结果因为工具调用条件写得不精确,Agent把收件箱里所有匹配关键词的邮件都归档了,其中还有几封没处理的。
事后我们加了一条硬规则:凡是涉及修改、删除、发送这类操作的Skill,必须增加确认步骤。Agent先输出将要执行的动作清单,等用户确认后再真正调用工具。这个确认机制虽然降低了自动化程度,但换来了安全边界,我认为非常值得。尤其在直接操作外部系统的场景里,宁可多一次确认,也不要让AI在无人监督的情况下完成破坏性动作。
5.4 我的判断标准:什么时候值得写Skill,什么时候不值得
最后分享我现在用来判断“要不要写Skill”的标准,其实就三条:重复频率、流程稳定性、输出可验收性。如果一件事每周至少出现一次,流程步骤基本不变,输出结果能被明确判断好坏,那就值得写;反过来,如果是一件从未做过的新任务、流程随时会变、好坏标准自己也说不清,那么普通对话解决就好,不要强行Skill化。
按这个标准,你可能不需要很多Skill。我见过有人一口气建了几十个Skill,最后日常在用的不到五个。Skill的核心价值从来不是数量,而是在真正高频且需要一致性的任务上,把人的工作方式稳定下来。它最好的状态是,你以为它不存在,但它每次都在用同一种章法帮你把事情做完。这也是我做了这么多Agent项目之后,对Agent-Skills最真实、最朴素的一点体会。