☰
AI Agent技能实战:用Markdown构建可复用的工作流指令包
2026/10/14 9:47:51 网站建设 项目流程

1. 先说清楚:给 AI 代理和工作流用的“skills”到底是什么

“skills”这个词在开发圈里最近出现的频率实在太高了,但真正把它讲明白的人不多。先说我的结论:所谓的 skills,指的是一种高度结构化的能力描述文件,通常以 Markdown 为承载格式,把一个任务从“目标定义、执行步骤、关键参数、注意事项、可调用的工具清单”全部写清楚。它既不是一段随手贴给 AI 的提示词,也不是一个写死逻辑的脚本,而是介于两者之间、让 AI 代理能读懂并反复执行的一套“工作指令包”。

我举个例子。假设你每天都要做代码审查,以前的做法是把审查规范复制粘贴到对话框里,让模型照着看。问题是提示词会超出上下文,而且每次都要重写一遍。而如果用 skills 的思路,你只需要在项目里维护一份code-review/SKILL.md,里面写清审查的目标、要检查的维度、禁止放过的红线、输出报告的格式,然后让 AI 代理按需加载这份能力说明。这样无论是本地编辑器、命令行工具还是 CI 流水线调用,拿到的都是同一套标准流程,不会因为换了个入口就行为漂移。

适合谁来学?我认为这篇文章更适合那些已经用过 AI 辅助编程,但觉得输出不够稳定的人;也适合团队里负责沉淀工程规范、想让 AI 工具真正融入交付流程的技术负责人。如果你还停留在“每次复制粘贴提示词”的阶段,那么把提示词升级成 skills,就是一次效率的质变。

需要先明确的是,skills 并不解决所有问题。它解决的核心痛点是“任务知识的复用”和“执行过程的可控性”。它不负责代替你思考,不负责自动写出所有代码,真正做的是把你脑子里的隐性经验显性化,变成 AI 代理可以稳定调用的“操作手册”。这也是为什么我接下来会重点讲结构设计和踩坑,而不是单纯罗列几个模板让你照抄——因为你真正需要的不是一段文本,而是一套“如何设计能力说明”的方法。

2. 为什么用 Markdown 写 skills,而不是脚本或者纯提示词

在我最早尝试做技能打包的时候,也走过不少弯路。最开始我自然想到的是脚本——既然要让机器干活,那就写个 Python 脚本把步骤固化下来。但这个方向很快就撞墙了:脚本擅长的是确定性的流程,比如“读文件、调接口、生成报告”,但 AI 代理处理的任务大多是非确定性的,你需要让模型在理解上下文之后自己决定细节,脚本根本写不出这种灵活性。

后来我又试过纯提示词,把一段很长的指令塞进系统提示里。这种方式最大的问题是不可维护。提示词不是模块化的,你想改某一条检查规则,就得在几千字的文本里定位;不同任务之间的公共逻辑也没法复用,每个提示词都是孤岛。更麻烦的是,提示词没有办法挂载参考资料和工具调用,AI 只能凭训练数据里的记忆去“猜”,结果就是有时候执行得对,有时候执行得离谱。

Markdown 写 skills 恰好补上了中间的缺口。它有几个其他格式替代不了的优势:

  • 可读性和可解析性兼顾。人对 Markdown 很熟悉,AI 对 Markdown 的解析也特别稳定,front matter 区域可以用来放结构化元数据,正文区域可以写自由格式的说明,两边各取所需。
  • 天然适配文件系统。一个技能就是一个文件夹,里面有说明文档、参考文件、脚本子目录,用 Git 管理版本非常方便,换设备、多人协作都不是问题。
  • 可以渐进式增强。最开始你可以只写一个SKILL.md,描述清楚任务步骤;用着用着发现某些步骤需要工具调用,再在元数据里声明allowed-tools;再复杂一点还可以加references目录挂业务文档。这种从简到繁的演进路径,是脚本和纯提示词都给不了的。

还有人会问,用 YAML 或者 JSON 纯结构化不好吗?纯结构化的问题是它严重限制了表达能力。你真正常需要的是“这段让模型自己判断,那段让模型严格按照模板输出”,这种需求在纯结构化的配置里几乎没法优雅表达。Markdown 的自由文本能让你用自然语言补充边界条件和判断标准,模型在这种模式下理解得更准确。

我个人的建议是:元数据用 YAML(放在 front matter 里),操作说明用 Markdown,工具调用用可执行文件或命令描述。这个组合不是为了让格式好看,而是让“人写的东西”和“AI 读的东西”都能在同一个文件里各得其所。你在维护技能文件的时候,先想到的是人能不能看懂,其次才是 AI 能不能执行,顺序搞反了后面一定会出问题。

3. 技能文件的目录设计与元数据规范

说到落地,第一步是确定目录结构。别看 skills 只是一个文件夹,结构设计得好不好,直接决定了它后期能长多大、能不能规模化。我自己常用的标准结构是这样:

skills/ └── code-review/ ├── SKILL.md ├── scripts/ │ ├── collect_changes.py │ └── format_report.py ├── references/ │ ├── security_checklist.md │ ├── style_guide.md │ └── common_bugs.md └── examples/ ├── good.review.md └── bad.review.md

一个技能文件夹至少要有SKILL.md,这是主入口文件。scripts目录放可执行的辅助脚本,references目录放参考资料,examples目录放输入输出示例。不要把所有东西都堆在SKILL.md里,否则文件会越来越大,最后模型加载的时候很吃力,人也很难维护。

SKILL.md的元数据部分是我最强调的。front matter 字段设计得好,AI 代理才能精准判断“这个技能适不适合当前场景”。我这里给出一份经过多次调整的元数据模板,你可以直接复用:

--- name: code-review description: 对代码变更进行系统性审查,覆盖安全漏洞、性能问题、可读性和测试覆盖,输出结构化审查报告。适用于本地分支、PR/MR 代码评审场景,不适用于整体项目架构评估。 version: 1.2.0 trigger: review, code review, 审查代码, mr, pr allowed-tools: - git - rg - python - gh workflow: - collect_changes - scan_security - check_performance - verify_tests - generate_report avoid: - 在未获取完整变更列表前就给出结论 - 修改用户代码 - 生成未经请求的重构建议 - 审查范围超出当前变更 output: format: markdown sections: [overview, issues, severity_summary, suggestions] ---

每个字段我都踩过坑,挑几个关键的说说。

description字段必须明确写出“适用范围”和“不适用范围”。原因是 AI 代理在自主决定调不调用某个技能时,主要就看这段描述。你写得含糊,它就会在无关场景里误用。比如只写“用于代码审查”,它可能在你请求架构评审的时候也加载进来,白白浪费上下文还误导输出。

trigger字段用来定义触发词,对应自然语言里的常见表达。这个字段不需要面面俱到,把高频说法覆盖掉就行。我见过有人把几十种表达都列进去,最后反而出错,因为代理会为了触发而机械匹配关键词。精准匹配远胜于穷举罗列。

workflow字段定义执行的步骤序列,每个步骤对应一个更细的子任务。这样做的好处是,代理能按照既定顺序推进而不是自由发挥。但注意,这个字段不要写成伪代码,写清楚“做什么”就行,“怎么做”在正文里展开。

avoid字段是我的独家心得。大多数人写技能文件只写“应该做什么”,不写“不应该做什么”。但模型执行任务时,很多错误恰恰是“多做了”而不是“没做到”。明确列出禁止行为,能让输出稳定性大幅提升。比如代码审查技能里写上“不修改用户代码”,代理就真的不会越权动手改文件,这个字段省过我好几次返工。

4. 从零写一个可以复用的技能:以“代码审查技能”为例

光讲理论容易飘,我直接带你走一遍完整流程。就以第 3 节结构里的 code-review 技能为例,目标是让它真能被 AI 代理稳定执行,而不是纸面上好看。

第一步,先定义审查的目标和边界。我在SKILL.md的正文开头会写一段总纲,说明这个技能的定位:单次变更审查、关注增量不关注存量、输出分级问题清单。这段话不光是给代理看的,也是给调用这个技能的人看的,双方对齐预期。

第二步,把工作流里的五个阶段分别写清楚。以scan_security为例,我不会只写“检查安全漏洞”五个字,而是会写出一条条具体的检查线索:

### scan_security 重点检查以下安全问题: 1. 注入类风险:SQL 拼接、shell 命令拼接、eval 使用。识别所有来自用户输入的变量是否经过验证或转义。 2. 认证与授权缺失:接口是否缺少鉴权校验、越权访问路径是否暴露。 3. 敏感信息泄露:硬编码密钥、token、密码、连接串是否进入代码库。 4. 依赖风险:新增的第三方依赖版本是否存在已知漏洞。 - 使用 `pip-audit` 或 `npm audit` 命令自动检测,并把结果纳入最终报告。 - 不要求逐条分析 CVE,只标记高危或可直接利用的问题。

这样写的好处是,代理拿到了可执行的检查准则,而不是一句空洞的“注意安全”。模型在推理时会把每条线索当做一个待验证的命题,逐项去代码里找证据,输出质量会高很多。

第三步,把工具调用的方式固化。比如收集变更文件列表,我会在scripts/collect_changes.py里写好脚本,然后SKILL.md的工作流里这样描述:

### collect_changes 1. 如果当前目录是一个 Git 仓库,先运行 `git status --porcelain` 获取变更文件列表。 2. 对于未提交的变更,使用 `git diff <file>` 获取具体差异。 3. 对于已经提交的变更,使用 `git log --oneline -5` 定位最近提交,然后用 `git diff HEAD~1` 获取差异。 4. 如果没有任何变更,输出提示“未检测到代码变更”,终止流程。

我强调一下,这里的关键是让代理拿着命令去执行而不是自己推断。如果你不告诉它用 git 命令,模型可能靠训练数据里的记忆去“猜”变更内容,那结果必然是灾难性的。每一条工作流指令都应该是可验证、可执行、可回溯的。

第四步,写示例。examples/good.review.md和bad.review.md各放一份。好的审查报告样例应该展示理想的输出格式,包括问题分级、代码引用、修改建议;差的样例则展示常见错误,比如泛泛而谈、没有代码引用、给出重构建议却说不清收益。这一步很多人会忽略,但实际上示例是模型理解任务预期的最快路径,比你写十行说明都管用。

第五步,把avoid字段里的内容展开。在正文末尾我会加一段带编号的边界说明,比如“不要超出当前变更范围去评价历史代码”,“每个问题必须附带文件路径和行号,否则视为无效”。这些约束会和 front matter 里的avoid字段形成呼应,给模型双重提醒。

完成这些之后,你的技能就已经具备实际使用价值了。但注意,这只是一个初始版本,真正的坑还在后面——下面几节我会说说接入方式、迭代维护以及我实际踩过的那些哭笑不得的问题。

5. 技能的接入方式:本地 CLI、IDE、CI 流水线

一个技能文件写出来不能只躺在仓库里,得能被不同的入口调用。我实际用下来,接入方式有三个层次,你可以根据自己的场景选。

第一层是本地 CLI。最简单的做法是把skills目录放在项目的根目录下,AI 代理启动时自动扫描该目录,把SKILL.md的元数据加载进来。具体实现可以用一个小脚本去遍历目录,读取 front matter,构建技能索引:

# 构建技能索引的命令示例 find ./skills -name "SKILL.md" | while read file; do echo "发现技能: $file" head -20 "$file" | grep "^name\|^description" done

这里不用搞太复杂。你只需要让代理知道有哪些技能可用、各自适用什么场景,真正的内容在真正被调用时才加载,避免占用上下文窗口。我见过有人试图把所有技能一次性全部读入上下文,结果模型还没开始干活先被几万字说明淹没,效果反而很差。

第二层是集成进 IDE。以当前主流的 AI 编程插件为例,它们大多支持自定义指令目录,你只要在插件配置里把skills目录指向项目的技能文件夹,就能在交互对话中直接触发。这一层的价值在于,开发者写代码时可以用自然语言唤起技能,比如输入“审查一下这段代码”,代理就会去匹配code-review技能的触发词,然后按流程执行。体验上跟日常使用 AI 编程助手没有区别,但背后运行的是一套标准化流程而不是自由发挥的提示词。

第三层是 CI 流水线。这一层比较高级,适合团队级应用。你可以写一个独立的命令行工具,输入一个变更范围,输出一份审查报告,然后在 GitLab CI 或 GitHub Actions 里加一个 Job 去调用它:

review-job: stage: test script: - python skills/code-review/scripts/collect_changes.py --output changes.json - python skills/code-review/scripts/run_review.py --input changes.json --output review.md artifacts: paths: - review.md

这样每次 MR 或 PR 都会自动产出审查报告,开发者不用自己去问 AI,报告就已经挂在流水线上了。当然,这个方案的维护成本不低,脚本要写得足够稳定,否则 AI 生成内容的格式问题会频繁打断流水线。我更推荐的做法是:脚本只负责收集输入和格式化输出,中间的“判断过程”交给本地 AI 代理通过调用技能完成,形成人机协作而不是全自动。

接入方式的选择,核心原则是“让技能离使用场景越近越好”。本地 CLI 适合个人开发者,IDE 集成适合前端开发或日常编码,CI 流水线适合团队质量管理。不要一上来就追求全渠道接入,先在一个场景里跑顺,再逐步扩展。

6. 维护、测试与迭代:一份技能的生命周期管理

技能文件不是写完就结束的,它和代码一样需要持续维护。我见过太多人把技能写完之后就再也没动过,几个月后运行效果明显下降,然后就得出结论“skills 没用”。其实问题出在缺少迭代机制上。

先说测试。技能测试最有效的方式是 dry-run,也就是用固定的示例输入去跑一遍完整流程,然后检查输出是否符合预期。比如 code-review 技能,我会准备三个测试用例:一个包含明显 SQL 注入的代码片段、一个包含性能问题的函数、一个规范但有小瑕疵的实现。跑完之后看输出报告能不能准确识别出这三个问题,有没有误报、漏报。测试脚本可以用 pytest 或者简单的 shell 断言。

我不想把自动化测试说得太玄乎。对你个人使用而言,更现实的方案是每次遇到“执行效果明显不对”的情况,把输入和输出记录下来,然后反推是技能的哪个环节出了问题。这个反推的过程就是在做测试。

具体来说,有五个维护动作是你需要定期做的:

  • 版本管理。为每个技能维护版本号,front matter 里的version字段每次实质修改都要递增。修改日志可以用一行话写在SKILL.md的末尾,方便追溯。
  • 描述校准。AI 代理误调技能或漏调技能,大概率是description写得不准。每当你发现误调,第一件事就是改写描述,不是去改正文。
  • 工作流精简。如果某个流程跑下来模型总在某个环节卡住,多半是步骤分解得太粗或者太细。太粗会导致模型自由发挥,太细会导致上下文爆炸。反复试几次,找到那个刚好能引导而不束缚的粒度。
  • 示例更新。examples目录只要有好的实际输出案例,就整理进去。它是模型学习最快的素材,一定不要只用初始版本里的那几个。
  • 工具声明对齐。allowed-tools字段如果声明了某个工具,技能正文里就必须有对应的调用方式说明,否则声明就是空的,甚至会造成歧义。

维护还有一个不太被注意的维度:技能之间的边界。当你的技能数量超过五个,相互之间就可能出现功能重叠。比如你有个code-review技能,又有个security-scan技能,那审查代码时该调用哪个?我在实践中会专门维护一份INDEX.md,记录每个技能的边界和关联关系,遇到重叠就收敛到一个技能里,避免代理在多个技能之间来回摇摆。

版本管理和变更控制这块,强烈建议用 Git 单独建一个仓库存放技能资产,每次修改走 MR 评审。技能文件改坏了不像代码改坏了那样有明显报错,它的错误是隐性的——模型某天突然输出质量下降,你可能很久都定位不到原因。有 Git 历史,你就能对比不同版本的技能文件,快速锁定改动点。

7. 我踩过的坑

这部分我挑几个真实遇到过的坑,应该能帮你省下不少调试时间。

第一个坑是描述写得太“大”。我一开始给某个技能写描述时写的是“用于项目分析”,结果代理几乎在每次对话里都把这个技能加载进来,因为只要聊到项目相关话题,它就觉得匹配,导致上下文被大量无关内容撑爆。后来我把描述改成了“用于对完整代码仓库进行架构分析,识别模块边界和数据流;不适用于单文件级代码审查”,误调率立刻大幅下降。写描述宁可窄一点,让代理漏调几次,也好过错调占用上下文。

第二个坑是工具调用太贪心。总想让技能看起来强大,于是往allowed-tools里塞了一堆工具,写正文时又要求逐个调用。实际上模型在长流程里每多一次工具调用就多一层出错风险,尤其是一些 CLI 工具的输出格式不完全可控,解析失败会直接中断整个流程。我的经验是:一个技能只用最核心的两三个工具,多余的工具需求通过拆分技能而不是堆在单个技能里解决。

第三个坑是过度结构化。有段时间我心血来潮,想把技能的每一个步骤都做成独立的 YAML 块,配上条件分支和循环逻辑。结果是文件变得无比复杂,维护成本飙升,然而执行效果并没有变好。原因在于 AI 代理的能力优势就是理解自然语言后的灵活推理,你把它硬掰成伪代码执行器,反而废掉了它的长处。技能文件应该在“给出清晰边界”和“保留推理空间”之间找平衡。

第四个坑和上下文管理有关。技能引用参考资料时,不要直接把大段参考资料粘贴到SKILL.md里,尤其是那些完整的公司规范文档、年度总结之类的东西。正确做法是放进references目录,在正文中只写“需要时参考references/style_guide.md中的第三章命名规范,重点检查类名和函数名是否符合规则”。让代理按需读取,而不是全量加载。

第五个坑是忽略示例的更新。技能刚创建时写的示例,往往跟实际业务场景有偏差,而且随着代码风格演进,示例本身会过时。建议每个月抽一点时间检查examples目录,把日常执行中特别成功的输出案例补充进去,把带误导性的旧示例替换掉。示例的时效性直接影响模型的输出风格,长期不更新,技能会慢慢“水土不服”。

最后一个坑,就是不要用技能去做它不擅长的事。比如代码审查技能,你拿去让它评估整个项目的技术栈迁移方案,它可能还是按审查单行的方式去逐文件扫,最后给出一堆不痛不痒的优化建议。技能本身就是“特定任务的高压舱”,你用错了场景,得到的自然是错位的结果。判断场景匹不匹配,先看技能描述里的适用范围,再看触发词,两个都对得上才调用。

8. 从个人技能到团队技能资产

技能如果只服务于个人,那它的价值是有限的。真正的分水岭,是把它变成团队共用的知识资产。我帮某支团队搭建过一套完整的技能体系,核心的经验可以压缩成三句话:技能来源于实践,沉淀于文档,更新于评审。

团队场景下,第一个要解决的问题是“谁来写技能”。我的做法是,不要求每个人一开始就写出完美的技能文件,而是鼓励把日常实操中重复出现的问题记录下来。比如团队约定每次代码评审都要检查日志脱敏,那就在某次评审后把它写进 code-review 的检查清单里。技能的初稿可以粗糙,关键是要形成“从实践中来,回实践中去”的闭环。

第二个问题是“怎么保证技能质量”。单人维护很容易陷入视角盲区。团队里我会给技能设置评审机制:任何技能文件的变更都要经过 at least 一个人的 review,重点检查description是否准确、workflow是否可执行、avoid是否覆盖已知高频问题。这个评审不需要复杂流程,一个 MR 评论就够。

第三个问题是“怎么让技能被用起来而不是吃灰”。很多团队花大力气写了技能资产,最后发现代理根本不触发,因为执行者不信任技能的产出质量。要让团队用起来,必须得有耐心打磨技能直到它稳定输出有价值的结果。这个过程急不来,但我可以给一个指标:某个技能被调用十次,其中至少有七次产出被采用,这个技能就算合格了。低于这个比例,说明技能本身有问题,需要回到测试环节去调整。

技能资产沉淀下来之后,还有一个好处是新人上手成本大幅降低。以前新人要问东问西才能搞明白团队的代码审查规范,现在直接看技能文件就行,里面写的都是已经固化的标准做法。这也是我坚持用 Markdown 而不是内部 Wiki 的原因——技能文件和代码同仓库、同版本、同评审流程,它的更新节奏和代码同步,不会出现文档写了但代码早就变了的情况。

我在实际使用中的体会是,写技能这个动作本身,就是在逼你把你脑子里的隐性知识翻出来,重新整理成可表达、可传播的显性规则。这个过程一开始有点难受,但收益是长期的。当你发现某天早上打开电脑,代理按你自己定义的标准流程把活干完,而你只需要做一次审核的时候,你就明白前面那些功夫没有白费。最后说一个我最常提醒自己的原则:技能文件是写给你的同事和未来的自己看的,AI 代理只是那个执行者。人看不顺眼的东西,机器执行起来也不会好到哪里去。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询