用GitHub Skills给AI编程Agent装上工程纪律:让代码交付更可靠
2026/9/11 3:46:28 网站建设 项目流程

最近复盘团队里一个很有意思的对比:同样用AI编程Agent干活,有人半天生成三个功能模块,代码却让review的同事直挠头;有人半小时产出一个小工具,从目录结构、依赖声明到Git提交信息都规规矩矩。差距不在模型,也不在提示词写得有多华丽,而在你有没有给Agent装上工程纪律。GitHub Skills系统解决的就是这件事——它把工程师日常遵循的规范、流程、检查项,做成Agent能识别、能加载、能按步骤执行的操作规程。这篇文章我会从它解决的问题讲起,拆开一个Skill包的内部构造,聊清楚工程纪律到底是怎么被"编码"进Agent行为的,最后给出一条可以直接上手的装配路径和一个完整的手写示例。

1. AI编程Agent的"有手无脑"困境:代码生成不等于工程交付

1.1 大模型不缺能力,缺的是"交付出可维护代码"的行为约束

很多人第一次接触AI编程Agent时,最大的冲击是它写代码太快了。一个登录接口、一个数据同步任务、一套CRUD页面,几秒钟就能给你吐出来。但真正在真实仓库里跑上几轮之后,你会发现问题不在"能不能写出来",而在"写出来的东西能不能融入现有工程体系"。

我见过太多次这样的场景:Agent接到一个"给用户模块增加导出功能"的任务,直接在一个已有三千行代码的文件末尾追加了一个函数,没有复用里面已有的工具方法,没有考虑异常分支,也没有碰任何测试。代码语法上没问题,但放进项目里,review的人得花十分钟理解它破坏了哪些隐式约定。类似的情况还包括:擅自升级了某个传递依赖的版本、绕过了项目现有的日志规范、生成了和仓库风格完全不一致的命名。

这些问题本质上不是模型能力问题,是行为规范问题。大模型擅长的是从海量数据中学到"一般情况下的代码长什么样",但它看不到你的仓库里"特约了哪些规矩"。于是它默认按通用套路来,而通用套路在这种已经有了几年积累的工程代码库里,经常就是那个"不太对劲"的东西。

1.2 工程纪律不是束缚,是稳定的质量下限

如果说创造力决定了代码的上限,那工程纪律决定的就是下限。在人类组成的团队里,下限靠什么兜住?靠Code Review文化、靠PR模板、靠CI流水线里的测试和lint、靠README和架构文档里写清楚的约定。这些东西的共同特点是:它们都在"代码被合入主线"之前设置了一道闸门。

但到了AI编程Agent这里,闸门很多失效了。Agent不会主动去翻你那份五十页的团队规范文档,也不会因为你没在提示词里写"记得跑测试"就去跑测试。它的默认行为是"尽量高效地完成你直接要求的事情",而那些"你没说但团队约定俗成"的东西,一律不在它的考虑范围内。

这就出现了一个很尴尬的局面:人类成员约定俗成的纪律,在Agent面前因为"不可见"而等于"不存在"。工程纪律要真正约束Agent,必须换一种形态——从"给人读的文档"变成"给Agent执行的操作规程"。

1.3 Skills系统:把"说给人听的规范"翻译成"给Agent执行的操作规程"

GitHub Skills系统提供了一套规范化、结构化的方式来解决这个问题。简单说,Skill就是一个自包含的技能包,里面用一份带格式约束的说明文档(SKILL.md)说清楚"什么场景用、按什么步骤做、有哪些硬性规定",同时可以附带脚本、模板、参考资源,让这些规定可以真实执行、可验证。

你可以把它理解成给Agent发了一本"员工手册":以前是口头交代,Agent听不听全看运气;现在是它在每次动手前都会主动查看的操作规程,并且里面的检查项有脚本兜底,不是一张空头支票。更关键的是,Skill是文件,它可以放进Git仓库做版本管理,团队里每个人、每个CI节点拿到的都是同一份"纪律定义"。

这套思路落地之后,工程纪律不再依赖每个工程师在提示词里的临场发挥,而变成了"代码库自带的基础设施"。下面我拆开一个Skill包,看看它内部到底长什么样。

2. Skills包的内部构造:一份给Agent的"职业规范手册"

2.1 SKILL.md:Agent真正逐字阅读的那几页纸

一个Skill包的核心是SKILL.md。这听上去像一个普通的Markdown文档,但它有别于普通文档的地方在于:Agent会把它当成指令来源,而不是仅供参考的背景信息。这意味着文档里的每句话都可能转化为Agent的动作,所以写作逻辑和写给人看的文档完全不同。

典型的SKILL.md会包含一段frontmatter,用来声明技能名称和描述。描述字段尤其关键,因为它决定了Agent在什么情况下会把这个Skill拉出来用。描述写得太宽,Agent会在跟技能不相干的场景里频繁误触发;写得太窄,Agent该用时又找不到它。比较合适的写法是在描述里明确"适用范围"和"不适用范围"两件事。

正文部分则通常包含:这个技能的目标、适用的输入、执行步骤、硬性约束、完成后的验收标准。这些内容越具体越好。比如"检查代码风格"这种表述就不合格,合格的是"运行仓库根目录下的npm run lint,确认所有通过后,在提交信息中附上lint结果摘要"。

2.2 scripts与resources:让约束可执行

SKILL.md里的自然语言写得再详细,Agent的执行仍然可能出现偏差。真正的兜底是脚本。一个规范的Skill包通常会带一个scripts目录,里面放可执行的检查脚本。Agent按SKILL.md的指示去调用脚本,脚本返回通过或失败的结果,失败时还会附带具体的错误信息,Agent再根据这些信息修改代码。

这个设计非常像人类团队里的CI:光靠Code Review时说"请你注意规范"是不够的,得有一个跑起来就会红灯的检查工具。对Agent来说,脚本给了它一个明确的外部反馈信号,而不必完全依赖模型自己"感觉行不行"。

resources目录则存放模板、配置样例、参考文档。比如一个"生成新组件"的Skill,resources里可以放组件目录的标准结构和一份符合团队风格的示例代码。Agent在创建新组件时直接参照这些资源,比让它凭空发挥稳定得多。

2.3 发现与加载:Skill是怎么被"找到"的

Skills的存放遵循一套约定。不同AI编程工具对目录路径的命名略有差异,但逻辑相通:可以放在用户级别的全局技能目录,也可以放在仓库内部的.local/skills或.skills这类目录里。放在用户级目录意味着所有项目都能用,适合放通用的、跨仓库的技能;放在仓库目录则只对该仓库生效,适合放高度定制化的工程规范。

加载机制通常是:Agent在启动任务时扫描这些目录,读取每个Skill的frontmatter描述,把它纳入自己的"可用工具集合"。之后当用户提的需求与某个Skill描述的场景匹配时,Agent就会在回复中自动加载并遵循该SKILL.md中的流程。这个"按需自动发现"的机制,决定了Skill描述质量的优先级非常高——你在SKILL.md里写不清楚的边界,Agent就会用它的"自由意志"替你决定,而它替你做的决定,常常就是产生工程混乱的起点。

3. 工程纪律的三大编码机制:约束、编排与反馈闭环

3.1 显式约束:"禁止做什么"比"应该做什么"更容易被执行

我早期写过一批Skills,一开始通篇都是"应该"句式:应该写测试、应该更新文档、应该遵循现有风格。实际跑下来发现效果有限,因为Agent天然倾向于"完成用户可见的功能",而那些"应该"往往属于不可见的质量项,优先级天然靠后。后来我把大量"应该"改成了"禁止"和"必须",效果立刻不一样。

比如这样一段:"禁止修改package-lock.json或yarn.lock;禁止在src之外的目录创建新文件;所有对外接口必须保持向后兼容,如果需要破坏性变更,必须先在方案中说明并等待用户确认。"这类显式约束在SKILL.md里优先级最高,Agent在每一步动作前都会拿它对照一遍,违反后会停下来说明情况。人类团队里这叫"红线",Agent的Skill里同样需要红线,而且必须写得非常明确,不给解释空间。

有个经验是:一条约束如果不能用一条命令或一个静态检查来判断是否违反,那它大概率执行不到位。所以凡是能用脚本验证的约束,一定要配合脚本使用,这才是真正的"可执行纪律"。

3.2 流程编排:用checklist接管模糊任务

工程纪律的另一层含义是"流程顺序不能乱"。人类工程师拿到一个任务会先看需求、再探索现有代码、然后设计方案、写代码、自测、提交。但Agent如果没有任何流程约束,它经常跳步骤:还没看现有实现就开写,写完不跑测试就提交。

所以我在Skill里会强制编排流程。一个典型的实现类任务被拆成了六个阶段:理解需求、探索相关代码、输出实现方案、编写代码、运行验证、整理提交说明。每个阶段都有一个明确的输入和输出,并且要求Agent在当前阶段完成之前,不得进入下一阶段。

这个设计模仿的是飞行员的checklist文化。飞行员起飞前会逐项检查仪表,不是因为每检查一次飞机就更安全一点,而是因为人类在熟悉任务中容易跳过关键步骤。Agent的"越熟练越自信"问题更严重,因为它生成代码的过程几乎不带自我怀疑。流程编排等于在它的默认行为模式外面加了一层轨道,让它必须按顺序走。

3.3 反馈闭环:执行-检查-纠错,取代"差不多就行"

Agent在生成长段代码时,最大的问题是缺少一个诚实的"自检信号"。它不会自己感觉到"这段代码可能有隐患"——模型的输出是基于概率生成的,不是基于验证的。所以必须在Skill里内置反馈机制。

具体做法是在SKILL.md的每个关键节点嵌入检查指令:写完模块后先运行单元测试,看到输出结果后,如果有失败项就要定位失败原因并修复,再重新运行,直到全绿才能继续。这个循环强调"Agent必须读取脚本输出并基于输出行动",而不是"运行一下脚本然后忽略结果"。

真正执行起来你会发现,加了这样一个反馈闭环,Agent的代码质量提升非常明显。原因不复杂:大模型其实知道很多代码问题,但它默认不会主动去检查;一旦Skill强制它把检查结果纳入下一步的考量,它能识别和修复大量前面"蒙着眼"写出来的问题。纪律在这里起到的作用,就是逼它把已知的验证知识派上用场。

4. 从"能跑"到"靠谱":给Agent装配Skills的实操路径

4.1 装配前先盘点:你的仓库缺哪条纪律

在动手配置Skills之前,建议先花半小时盘点自己的仓库当前最缺哪种纪律。方法很简单:翻最近十个合并的PR,看看review里面最常见的评论集中在哪几类。如果评论总是"这个改动影响到了其他使用方""缺少测试""提交信息不规范",那这几件事就是你的Agent首先需要被约束的方向。

用最小的投入解决最痛的问题。这个思路在引入工程纪律时要特别强调。你有可能会想一口气把文档、测试、风格、安全、提交规范全部塞给Agent,但这样的Skill包多半会被Agent选择性忽略——因为它要遵守的东西太多了,反而没有一个是强约束。与其这样,不如先挑一个最痛的点,把它做成一个完整的Skill,跑顺了再加下一个。

4.2 一套最低成本的"角色纪律"配置

结合我的实践,一个新建仓库如果要用Agent持续开发,最低限度应该配备以下几类Skills。这里我用表格列出,方便对照自己的情况选择。

场景推荐Skill核心约束推荐脚本
提交前检查代码变更规范跑lint、跑测试、确认无残留调试日志lint脚本、test脚本
提交信息Conventional Commit规范校验提交信息格式、scope必须与变更模块对应commit-msg校验脚本
文档同步README/API文档更新对外接口变更时同步更新文档文档完整性检测脚本
依赖管理依赖变更审批禁止擅自升级依赖版本,必须说明升级理由依赖diff检查脚本
新文件生成模块创建规范新文件必须放置到约定目录,遵循命名规范目录结构校验脚本

配置的方式很简单:把写好的SKILL.md和脚本放进仓库的.skills目录,或者用户级技能目录,然后在Agent的对话里直接要求它"在处理任务时自动加载对应Skill"即可。多数工具都支持在启动时扫描本地Skills目录,甚至可以在项目根目录加一个说明,让进入项目的Agent主动加载。

4.3 我踩过的三个坑:描述过宽、约束过载、缓存滞后

第一个坑是Skill描述写得过宽。我给一个仓库写了"仓库规范"Skill,frontmatter里的描述是"适用于这个仓库的所有开发任务"。结果Agent在几乎每个任务里都会加载它,导致每次响应都先输出一大段规范摘要,反而拖慢了主流程。后来我把描述改成"适用于涉及src目录下公共模块改动的任务",触发频率立刻正常了。经验是:描述里最好写清楚"什么类型任务不需要使用本Skill",负向排除对Agent的帮助比正向描述更大。

第二个坑是单份SKILL.md里堆了超过二十条硬性约束。这种Skill看起来非常严谨,但Agent实际执行时记不住那么多,经常捡了前面几条丢了后面几条。后来我做了拆分:一份Skill只聚焦一个行为主题,比如"依赖管理规范"只处理依赖变更的审批流程,"代码提交规范"只处理提交信息的检查。多个主题用多个Skill文件,比一份大而全的文件有效得多。

第三个坑是缓存问题。有些工具会缓存已加载的Skill列表,修改SKILL.md后可能不会立即生效。我自己就遇到过改了描述但Agent还在用旧版本的场景,排查半天才意识到是缓存没刷新。现在每次调整Skill内容后,我都会重启会话或者主动触发一次重新扫描,确认加载的是新版本再继续。

5. 团队级技能治理:让Skills成为团队的工程公约

5.1 把Skills放进仓库:克隆即获得工程公约

如果Skills只停留在个人层面,那它解决的是你个人用Agent的体验;要让整个团队受益,最直接的办法是把Skills作为仓库的一部分进行版本管理。新成员克隆仓库后,本地工具自动扫描到仓库级Skills,从第一天起就会受到同样的约束。这比让新人自己去看团队文档然后凭理解执行要可靠得多。

把Skills放进仓库还有一个额外的好处:它随着PR一起演进。任何一个Skill的修改都可以走代码评审流程。以前"改团队规范"要起草文档、发公告、等大家自觉执行;现在改一个Skill,PR合并之后,所有用Agent开发的成员自然就切到了新流程。规范升级从"靠人传话"变成了"改代码、合代码"。

这类仓库里建议至少包含三层内容:Skill定义文件本身、配套的校验脚本、以及一个简短的使用说明。说明里不需要写过程流程,只需要告诉使用者"这个仓库自带哪些Agent技能、放在哪个目录、遇到问题找谁"。

5.2 与CI形成"双闸门":Agent预检,流水线终审

Skill的存在并不能替代CI,正确的姿势是形成一个"双闸门"机制。Agent在本地开发时通过Skill做预检,尽可能在提交之前把问题拦掉;CI流水线在代码推到远端后做终审,跑完整的测试、构建、安全扫描。两道闸门各管一段:Skill负责"帮Agent写对",CI负责"确认代码确实没问题"。

这个机制在实际运行中对开发节奏的改善很明显。以前Agent生成的PR经常在CI阶段红灯,然后要来回提交好几次才能过;现在Skill里已经内置了"提交前必须本地跑过测试"的约束,很多基础错误在Agent阶段就被修正了,CI红灯数量大幅下降,人也轻松很多。

需要注意的是,Skill脚本和CI脚本尽量复用同一套检查核心,避免两边规则不一致。如果Skill里说"禁止修改lock文件",而CI里没有对应检查,那这条纪律就是软约束,时间长了Agent还是会越界。把同一套规则做成一个脚本,Skill调用它,CI也调用它,才能保证口径一致。

5.3 治理纪律:Skills本身也需要被维护

Skills不是写完就一劳永逸的。随着仓库结构变化、依赖升级、团队规范调整,Skill内容也会逐渐过时。最常见的腐化现象是:仓库已经改用新测试框架了,Skill里还写着旧的测试命令;或者团队早就废弃了某个目录,Skill还在强制生成文件到那里。

维护Skills的最省力方式是给它设一个"定期体检"的节奏。我实践下来比较有效的方法是:每个迭代周期结束时,顺手把Agent在这期间犯过、且被CI拦下的错误类型整理一次,看哪些错误是因为Skill覆盖不到导致的,哪些是因为Skill描述不准确导致的。把这些结论沉淀回Skill更新里,形成一个小闭环。

另外,Skill的变更记录最好和代码一样留痕。在仓库的release note或CHANGELOG里加一行"更新了提交信息校验规则",成本很低,但能避免很久以后大家对着一个Skill文件不知道它为什么长成这个样子。

6. 从零手写一个最小可用的Skill:完整过程复盘

6.1 明确边界:给"规范提交信息"写一份操作规程

前面讲的都是框架,这一节用一个能直接上手的例子走完整流程。假设团队的痛点很具体:Agent生成的PR提交信息格式混乱,有的不写scope,有的没按Conventional Commits来。我们来做一个"规范提交信息"的Skill。

先明确边界:这个Skill只负责一件事,就是在Agent生成提交信息之前,先校验提交信息是否符合团队约定的格式。不涉及代码风格、不涉及测试,目的是让Skill足够聚焦,触发起来更精准。

6.2 完整的Skill目录与SKILL.md

首先建立目录结构,放进仓库的.skills目录下:

.skills/ └── conventional-commit/ ├── SKILL.md └── scripts/ └── check-commit-msg.sh

SKILL.md的内容大致长这样:

--- name: conventional-commit description: 在生成Git提交信息时使用。适用于编写或修改提交信息、PR标题和PR描述的场景。不适用于代码实现、代码审查或问题排查。若提交信息已符合Conventional Commits规范且包含正确的scope,则无需使用本Skill。 ---
# Conventional Commit 规范 本Skill确保Agent生成的Git提交信息严格遵循Conventional Commits格式。 ## 使用步骤 1. 先查看最近的提交历史,了解仓库正在使用的scope命名约定。 2. 分析本次变更的模块归属,选择最贴近的scope;如果现有scope都无法覆盖,使用`*`并说明原因。 3. 按以下格式生成提交信息:

( ):

type必须是以下值之一:feat、fix、docs、style、refactor、perf、test、build、ci、chore。 scope必须从仓库已有的scope列表中选取。 subject使用祈使句、不超过80个字符、首字母小写。 ## 硬性约束 禁止生成没有scope的提交信息。 禁止使用`feat`之外的type描述非功能性改动。 禁止在subject中使用中文标点。 禁止在提交信息正文中出现协作者姓名或邮箱。 ## 验收标准 提交信息必须通过scripts/check-commit-msg.sh的校验。脚本返回非零退出码时,根据错误输出修正后重新生成。

这份文档的关键是把"禁用情况"写进了描述,又通过验收标准把"必须通过脚本校验"固化为强约束。仅靠自然语言时,Agent可能觉得"得写个scope,大概差不多就行";有了脚本兜底,过不了就是过不了。

6.3 一个可执行的commit-msg校验脚本

配套脚本的作用是把SKILL.md里的验收标准变成可以执行的检查。下面是一个简单的bash脚本示例,它做的事情是:读取提交信息文件,用正则检查格式,输出错误并返回失败退出码。

#!/usr/bin/env bash COMMIT_MSG_FILE="${1:-/dev/stdin}" MSG="$(cat "$COMMIT_MSG_FILE")" TYPE_PATTERN='^(feat|fix|docs|style|refactor|perf|test|build|ci|chore)\(' SCOPE_PATTERN='^[a-z][a-z0-9-]*\):' SUBJECT_PATTERN='^[a-z0-9].{0,80}$' if ! grep -qE "$TYPE_PATTERN" <<< "$MSG"; then echo "错误:type必须是 feat/fix/docs/style/refactor/perf/test/build/ci/chore 之一,并且必须带scope括号。" echo "示例:feat(user-service): add email verification" exit 1 fi if ! grep -qE "${TYPE_PATTERN}${SCOPE_PATTERN}" <<< "$MSG"; then echo "错误:scope只能包含小写字母、数字和中划线,且必须以右括号结尾。" echo "示例:fix(auth): handle token expiry" exit 1 fi if ! grep -qE ": [a-z0-9]" <<< "$MSG"; then echo "错误:subject必须以小写字母或数字开头。" exit 1 fi if ! awk "NR==2 { exit } /^.{81,}$/ { print \"错误:subject不能超过80个字符\" > \"/dev/stderr\"; exit 1 }" <<< "$MSG"; then exit 1 fi echo "提交信息格式校验通过" exit 0

这个脚本不需要多复杂,关键是它给Agent提供了一个确定性的通过标准。当SKILL.md里写了"必须通过脚本校验"时,Agent就会去调用这个脚本,拿到失败输出后修改提交信息,再重新跑,直到退出码为0。

6.4 实测、反例与迭代

写完SKILL.md和脚本之后,我在测试仓库里放了几条典型的错误提交信息来验证效果。第一条是"fix login bug",因为缺少scope被脚本拦下,Agent根据错误提示改成了"fix(auth): correct login redirect"。第二条是"FEAT: 新增接口",type大小写和中文标点都不符合,Agent也通过脚本反馈修正了。

真正有价值的验证不光是看Skill能不能拦截错误,还要看Agent在完全没被提示的情况下会不会自动加载它。我在一个干净会话里直接要求Agent"提交刚才的改动",发现它扫描仓库后主动将conventional-commit纳入执行流程,说明Skill的自动发现机制是通的。

这个小而完整的示例可以直接扩展成一套团队纪律库。比如再写一个"测试先行"Skill,强制Agent每次新增功能前先补齐测试用例再动手实现;再写一个"变更日志"Skill,要求Agent在涉及对外接口变更时自动更新CHANGELOG。每个Skill独立演进,聚合起来就是一棵完整的纪律树。

我在实际项目中跑通这套流程之后的体会是:GitHub Skills系统真正解决的,不是让Agent写出更强的代码,而是让它在无人盯守的情况下,也按同一个稳定的标准把事情做完。模型的能力用户在持续提升,但工程纪律不会自动伴随能力提升出现——它需要被显式定义、结构化承载、持续维护,最终才能成为团队默认的工作方式。对任何把AI编程Agent放在真实生产仓库里的团队来说,这件事的优先级,应该排在更换"更强模型"之前。

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

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

立即咨询