
你有没有遇到过这种情况同一个Agent昨天刚教会它整理项目更新日志今天换个新对话它又像失忆一样从零开始摸索。工具给了、提示词写了甚至把处理步骤直接贴进系统提示里了可换个场景、换个项目一切又要重来。这暴露了一个很本质的问题——我们一直在用对话的方式教一个长期工作的智能体做事却忘了给它一套可以沉淀、复用、进化的能力体系。agent-skills 这个概念最近在圈子里讨论得很热核心思路其实不复杂把Agent能稳定执行的那部分能力从对话上下文里抽离出来固化成结构化的技能文件让Agent按需加载、按流程执行。用我的话说就是别再每次让Agent临时发挥而是给它一本随时能翻的操作手册。这篇文章我会结合自己维护智能体技能库的实际经历从为什么需要技能体系、技能文件怎么组织、手写一个技能的全流程到版本管理、踩坑记录、评估迭代一步步拆开来讲。无论你是刚开始接触Agent开发还是已经把它丢进了生产环境这里面的思路和实践细节应该都能直接借鉴。1. 为什么Agent需要一套独立的技能体系 —— 从重复调用到能力沉淀1.1 同样的事Agent每次都要重新摸索说个真实场景。我维护着一个开源仓库每天都会收到新的issue我习惯让Agent帮我整理当天的issue按类型归类、标出优先级、生成一份简报。第一次用的时候我写了一大段提示词告诉它什么样的算bug、什么样的算需求、优先级怎么判断、输出格式长什么样。效果不错于是我把这段提示词保存下来下次直接粘过去。问题随之而来这段提示词越写越长因为我不断发现新的边界情况。今天发现需要复现步骤的bug要标为高优先级明天又发现带附件图片的issue比纯文字的更紧急。提示词太长之后Agent开始消化不良——有时候漏掉某个规则有时候输出格式直接飘了。更深层的问题是这套规则只有我自己知道。团队里另一位同事想让Agent帮他做同样的事他得重新写一遍。新同事加入得先读一遍我那十几个版本的提示词。等到项目迭代到第三个版本时规则文件已经和提示词混在一起谁也分不清哪个是Agent的行为指令哪个是项目的业务逻辑。我意识到问题的根源不是提示词写得不够好而是缺少一个结构化的载体来承接这些逐渐固化的能力。1.2 技能与工具、插件的本质区别很多人的第一反应是给Agent配工具不就行了给它一个整理issue的函数它直接调用。但工具解决的问题是某一步怎么做比如调GitHub API拉取issue列表、解析markdown表格。它是一段确定的、可执行的代码。而整理当天的issue这件事天然包含多个步骤拉取数据、分类判断、优先级评估、格式化成简报、写入指定位置。每一步都需要单独决策有些决策还得依赖上一步的输出。如果把这整件事塞进一个函数里这个函数会变得极其笨重如果拆成多个函数Agent又需要知道什么时候该调用哪个这个编排逻辑又回到了提示词里。插件的思路更接近扩展能力包但插件通常面向的是平台功能的扩展比如给IDE加一个语法高亮、给浏览器加一个截图快捷键。插件有明确的入口和出口而Agent的技能是一段有弹性的流程入口是用户意图的识别出口是任务目标的达成中间步骤可以根据实际情况动态调整。agent-skills 的思路是第三条路把一个复杂任务定义成一个技能技能内部是一份结构化的说明文档加若干可选的执行动作。Agent识别到这个技能适用时把它当作一套操作规范加载进来按步骤执行。这套规范既替代了冗长的提示词又不像写死的代码那样毫无弹性。1.3 技能要解决的三个核心问题第一一致性。同一类任务无论谁来触发、什么时间触发执行标准都应该是同一套。技能把标准固化下来而不是依赖某一次提示词写得好不好。第二可维护性。规则变了只改技能的某一段描述就行。用不着的技能可以归档新能力可以作为一个新技能加进去不需要去翻旧对话里的临时配置。第三可观测性。技能是结构化的意味着每一次触发、每一步执行、每一次成功或失败都可以被记录和分析。裸的提示词没有这层能力你根本不知道Agent哪一步理解偏了。这三个问题不是某个框架特有的而是所有想把Agent推向实际生产的人都躲不开的。所以无论你用的是哪家模型、哪个Agent平台技能化的思路都能借鉴过来。2. 技能库的基本盘目录结构、SKILL.md 与技能命名规范2.1 一个最小可用技能长什么样以我日常使用的技能目录为例我通常把技能统一放在项目根目录下的 skills/ 文件夹中skills/ ├── collect_changelog/ │ ├── SKILL.md │ ├── scripts/ │ │ ├── fetch_commits.py │ │ └── format_markdown.py │ └── references/ │ └── output_template.md ├── triage_issues/ │ ├── SKILL.md │ └── scripts/ │ └── classify.py └── generate_weekly_report/ ├── SKILL.md └── templates/ └── weekly_report.md每个技能一个独立文件夹至少要有一个 SKILL.md 作为入口其他辅助资源脚本、模板、参考文档按需放置。这个结构有两个好处一是每个技能自包含复制整个文件夹就能共享二是Agent加载技能时能根据 SKILL.md 快速判断这个技能是做什么的、该不该用、怎么用不需要把整个目录都塞进上下文。我在给团队搭技能库时第一条规范就是所有技能强制使用同一目录约定禁止在技能文件夹外散落相关文件。2.2 SKILL.md 里到底该写什么SKILL.md 是技能的核心它的质量直接决定Agent能不能正确触发技能、能不能正确执行。我写的 SKILL.md 至少包含四块内容第一块是 name 和 description。description 最关键它是Agent判断触发条件的依据。写得越具体误触发概率越低。不要只写用于整理问题清单要写清楚适用的任务类型、输入是什么、输出是什么。我会在 description 里放两三个触发示例比如当用户提到整理这周的更新日志时使用同时写上反例比如当用户只是随口询问仓库状态时不触发本技能。第二块是适用场景与边界。明说哪些情况适合用也要明说哪些情况不适合。边界写得越清楚Agent越不会把技能用在错误的地方。比如我之前写的一个技能适用场景是仓库托管在GitHub、issue数量超过20条边界条件写的是如果issue数量小于5条直接手动整理即可无需启动技能。第三块是执行流程。大步骤写清楚先做什么、再做什么、关键判断点在哪、每个步骤的输出怎么传给下一步。我试过两种写法一种是自然语言段落一种是带编号的操作清单。实测下来对执行类任务编号清单的效果明显更好Agent很少跳步对创造性任务自然语言段落更合适能留出发挥空间。第四块是约束与规范。比如所有输出使用中文涉及金额的字段保留两位小数不要修改指定分支以外的代码。这部分是踩坑后不断补充出来的它让技能的执行结果保持稳定。每次出现一次输出格式不符合预期的反馈我都会先检查是不是约束没写到位而不是急着改系统提示词。2.3 技能动作的拆分原则workflow 与 tool_use 的边界技能内部的动作我按这个边界来拆需要调用外部接口、需要访问文件系统、需要执行明确计算逻辑的放在 scripts 里用代码实现需要根据上下文进行判断、比较、选择的放在 SKILL.md 里用自然语言描述处理原则。举个例子整理更新日志技能里从Git历史中拉取某个时间段内所有commit信息是明确操作用脚本实现最合适传入开始时间和结束时间返回结构化数据。而判断哪些commit属于功能开发、哪些属于修bug、哪些属于测试优化这种语义判断我不会写死在代码里而是把分类标准写成描述性规则让Agent在执行时灵活判断。这么设计的原因底层逻辑很简单代码擅长确定性操作自然语言擅长模糊判断。确定性逻辑用代码既能避免Agent每次执行结果飘忽不定也能节省Token模糊判断用自然语言描述规则保留Agent的灵活性。两者结合技能才不会僵硬。我见过不少人把语义判断也硬编码成规则引擎结果维护成本直线上升因为真实世界的判断边界根本列不完。3. 手写一个可落地的技能以批量整理代码仓库更新日志为例3.1 需求拆解不急着写代码先想清楚边界假设我现在要给项目做一个 collect_changelog 技能。第一步不是写 SKILL.md而是想清楚这个任务的边界输入一个时间范围可选默认最近一周、一个目标仓库路径输出一份按类别分组的更新日志markdown格式处理逻辑先拉取commit历史再做语义分类再生成日志文件这个过程中分类最容易有歧义。同一批commitfeat: add login page 毫无疑问是功能fix: user avatar not loading 是修复那chore: update dependencies算什么refactor: split utils into modules又算什么分类规则必须写清楚否则Agent每次分类都可能不稳定。我把分类定义成五类功能、修复、优化、重构、其他。每个类别给出典型示例和边界说明。比如优化限定为性能调优、加载速度改进、资源占用降低重构限定为不改变外部行为的代码结构调整。有了这些界定词Agent的分类稳定性会明显好于没有示范的情况。这个拆解工作大概会花掉整个技能开发的三分之一时间但省下来的调试时间远不止这些。3.2 技能文件夹的完整内容清单collect_changelog 技能的完整文件清单是skills/collect_changelog/ ├── SKILL.md ├── scripts/ │ ├── fetch_commits.py # 拉取指定时间段的commit支持按分支过滤 │ └── generate_report.py # 将分类结果渲染为markdown更新日志 └── references/ └── category_guidelines.md # 分类规则的详细说明与示例SKILL.md 描述整体流程和触发条件fetch_commits.py 只负责和 git 命令行打交道不涉及任何语义判断generate_report.py 接收分类后的commit列表按照模板生成日志category_guidelines.md 里是详细分类示例。脚本建议用标准库或极简依赖实现因为技能库要在不同机器上复用依赖越多越容易在各种环境里翻车。3.3 写 SKILL.md 时的关键措辞描述越具体触发越准确SKILL.md 的 description 我会反复打磨。初稿可能是生成项目更新日志二稿改成从Git仓库获取指定时间段的提交记录按功能、修复、优化、重构、其他五大类整理成更新日志输出到指定文件三稿还要加上触发示例当用户提到整理这周的更新日志生成release notes汇总commit记录等需求时使用。这里的逻辑是Agent触发技能依靠的是 description 和用户指令的语义匹配触发示例能显著提升匹配准确率。只写一句生成更新日志Agent可能在用户只是想简单聊两句的时候就把技能全套加载进来白白浪费上下文加上触发示例和反例后误触发率能降一大截。我做过一个统计优化 description 前后同一个技能的误触发次数降了差不多三分之二。还有一个小细节description 里不要用太多修饰性词汇。比如高效地智能地自动地这类词对Agent理解触发条件没有帮助反而可能干扰语义匹配的权重。直接说做什么、什么时候用、输入输出是什么最有效。3.4 从主Agent到技能内部的多步流程设计技能触发后Agent 执行的主流程我写成这样分析用户指令确认时间范围和仓库路径缺失的按默认值或主动询问调用 fetch_commits.py 获取 commit 列表读取 references/category_guidelines.md 中的分类规则对 commit 逐条分类调用 generate_report.py 渲染 markdown 报告将报告输出给用户并提示是否可以写入文件注意第3步我刻意让它读取分类规则而不是在SKILL.md里内嵌分类示例。原因是SKILL.md 会被Agent全文加载写太长会占用大量上下文references 里的文件是按需读取的只在真正需要分类的时候才加载。这也是技能内部资源组织的一个重要原则——能按需加载就别一股脑塞进去。实际执行时Agent 可能会在步骤2和步骤3之间来回跳几次比如发现 fetch_commits.py 输出的数据格式和预期不符会回头检查脚本参数。这很正常技能流程设计不该是死板的瀑布流只要 Agent 最终能走通并且结果稳定中间的微小折返是可以接受的。4. 技能仓库的组织与管理版本、依赖与多Agent复用4.1 用Git管理技能库的注意事项技能本质上也是代码资产我的习惯是把技能放进单独的Git仓库与主项目仓库分开。原因是技能的变更节奏和主项目不一样——主项目按功能迭代技能按执行行为迭代。混在一起历史记录会变得很乱回滚也容易误伤。在技能仓库里每个技能的开发主线大致是v1.0初版能跑通基本流程v1.1补充分类边界描述修复误分类v2.0把输出模板改成 references 引用SKILL.md 瘦身每条提交信息我都会写清楚改动的影响范围。比如将分类规则迁移到独立引用文件SKILL.md 字数减少约40%这种信息在日后排查问题时非常有价值。另外技能仓库的 README 里我维护了一个技能清单表格列出每个技能的名称、版本、适用场景和负责人避免团队里出现这个技能是谁维护的这种问题。4.2 技能间依赖怎么声明技能之间难免有依赖。最简单的做法是在 SKILL.md 里加一个 dependencies 字段声明依赖的其他技能和版本范围。当Agent加载当前技能时如果发现依赖缺失可以先技能库拉取对应技能再继续执行。需要特别提醒的是依赖关系别设计得太深。我见过有人把技能A依赖技能B、技能B又依赖技能C结果一次触发连锁加载了十几个技能上下文直接爆掉。我的建议是尽量保持技能扁平如果一个技能里涉及复杂的跨领域能力优先拆出来作为独立任务执行而不是层层嵌套。依赖深度控制在两层以内是我实测比较稳妥的阈值。4.3 多场景复用个人助手、团队机器人、流水线Agent技能库的一个显著优势是同一套技能可以在多个场景复用。我在个人开发环境维护的技能库被用在几个地方个人命令行Agent整理更新日志、提交PR前的自查、代码review辅助团队协作机器人自动整理每日站会纪要、自动处理issue triageCI流水线发布前自动生成release notes这几个场景共享同一套技能定义只是执行入口和权限边界不同。实际运行下来维护收益远超维护成本——改一次分类规则三个场景同步生效不用去翻分散在各处的提示词。我算过一笔账技能库投入的维护时间换来的收益大约是原来逐个场景维护提示词的三到四倍。5. 实测中踩过的坑上下文溢出、技能误触发与回退5.1 技能误触发description 写得含糊的后果最典型的翻车案例我给一个 write_commit_message 技能写描述时只写了根据代码变更生成提交信息。结果我发现每当用户提到提交两个字Agent 都尝试触发这个技能——哪怕用户只是在说我提交了一个bug你有空看看。解决这个问题我用的是三个手段组合在 description 里增加明确的触发信号关键词、增加反例描述、补充不适用场景。三点缺一不可。调整后的描述是当用户需要对已修改的代码生成 git commit 信息时使用。仅适用于用户明确表达需要编写或优化提交信息的场景。若用户只是在讨论代码问题、报告提交行为不触发本技能。这种修正在技能上线初期特别重要。我的经验是新技能上线第一周每天都要翻一遍触发日志看到不合理的触发就立刻调整描述。熬过这一周后面就稳定了。5.2 长技能导致上下文被占满技能本身写得越长Agent加载时占用的Token就越多。我踩过一个很具体的坑一个技能文件4000多字其中一半是详细的操作步骤另一半是大量示例。每次触发这个技能光加载它就要消耗大量Token遇到复杂任务加上对话历史上下文很快就紧张了。后来的调整是大动作把不变的静态内容尽量外置到 references/ 等按需加载的位置把动态执行路径留在 SKILL.md 里控制在一两千字以内。这个调整立竿见影触发技能的Token开销降了不少而且因为Agent每次只在需要时去查参考文档反而比一股脑全加载更准确。这背后其实是上下文资源管理的问题。Agent的上下文窗口不是无限的技能体系设计得越精细就越要把上下文留给真正需要实时推理的部分而不是被静态描述占满。5.3 技能内部步骤失败时的回退策略技能是按流程走的但流程中的任何一个步骤都可能失败git历史拉取失败、文件路径不对、格式转换报错。Agent默认的行为通常是直接报错退出但更好的做法是给它一套回退规则。我在 SKILL.md 里加了一段失败处理说明。比如拉取commit失败时先检查仓库路径是否存在确认路径没问题后尝试用轻量级命令重新拉取如果依然失败把错误信息返回给用户并建议检查git仓库状态或权限配置。这套回退规则看起来简单但在生产环境里作用非常大。它能避免Agent因为一个小异常就放弃整个任务也能避免它在同一个地方反复重试浪费Token。我还把失败处理单独作为一个子段落写进 SKILL.md 的标准模板里这样所有技能默认都有一套基本的容错策略而不是每个技能各自为政。5.4 日志与可观测性给技能加 trace技能执行完到底好不好用不能全靠感觉。我在技能库里给每个技能的执行过程加了轻量级日志触发时间、触发的用户指令、技能内部执行了哪些步骤、每步耗时、最终是否成功、Token消耗。这些数据汇总下来就能看到哪些技能被频繁误触发、哪些技能成功率低、哪些步骤消耗过大。这个习惯是我吃了大亏之后养成的。之前有一个技能提示词越写越长但完全无法判断到底是哪一步拖慢了执行速度、哪一步引入了不稳定因素。后来加了日志一眼就看到问题出在一个频繁调用的外部接口上——它平均耗时要占到整个技能执行时间的80%。优化了那个接口之后整个技能的执行时间缩短了一半。所有把技能库用于生产环境的朋友我的建议是可观测性第一时间加越早越好。等出了问题再去补日志往往要牺牲一部分历史数据才能获得足够多的有效样本。6. 技能评估与持续迭代让技能库越用越顺手6.1 评估维度准确率、完成率、耗时、Token消耗技能不是写完就结束了它需要持续评估。我通常从四个维度去看一个技能的健康状况。准确率输出结果是否符合用户预期。这个指标需要人工参与判断我每周抽样一部分执行记录来复核。完成率触发后从头到尾完整跑完的比例可以从日志直接统计。耗时从触发到输出结果的时间如果某个技能耗时异常往往是某个步骤出现了退化。Token消耗技能加载和执行的总Token数这个指标直接关系到成本控制和上下文预留。这四个维度合在一起能比较全面地反映一个技能的真实工作状态。单一维度的优化没有意义比如把 Token 压得很低但完成率掉了一半那就是得不偿失。6.2 回归测试给技能配习题集技能迭代很容易引入修好一个坑又弄坏另一个坑的问题。我的做法是给每个技能配一份回归测试集里面放上典型的输入样例和期望的输出结果。每次改技能先在测试集上跑一遍确认没破坏旧场景。一个技能的测试集不需要太多五八个经典案例就够用关键是要覆盖边界情况。比如分类技能测试集里一定要有既有功能又有修复的混合commit这类不太好分类的样例。我见过有人给技能配了五十多个测试案例维护测试本身的成本反而超过了技能迭代的收益不划算。回归测试的执行也不一定非要自动化。我目前是半自动方式手动触发一轮测试集人工比对输出结果记录在技能仓库的 CHANGELOG 里。等技能数量超过一定规模后可以再引入自动化测试工具。6.3 技能版本更新的灰度策略技能更新最好不要直接全量替换。我踩过新版本技能在A场景表现好在B场景直接翻车的坑当时把一个新的分类规则直接推上去结果旧场景里原本分类准确的commit全被错误地归到了优化这一类。恢复还花了点时间因为有些日志已经被覆盖了。现在的做法是技能描述里增加版本号字段新版本先标记为 beta只有收到明确使用 beta 的指令时才加载新版本跑了一段时间确认各场景稳定后再把正式版本号切到新版本。这个灰度过程听起来有点重但跟一次技能回归失误造成的损失比起来这点成本完全可以接受。尤其是运行在团队协作机器人这类面向多人的场景里一次技能回归失误影响的不只是一个人可能整个团队的自动化流程都会跟着出问题。灰度策略相当于给技能迭代上了一道保险。技能库维护到现在我最深的感觉是它不是一件做完就放在那里的静态资产而是一个需要持续浇水修剪的花园。每次踩坑、每次规则调整、每个新场景的接入都会让技能库变得更成熟。如果你也在带着Agent往生产环境走我的建议是从一开始就用技能化的思路去组织它的能力哪怕前期看着麻烦跑过一两个月之后你会庆幸当初做了这个决定。