☰
告别散装AI:用SKILL编排给存量代码做微创手术
2026/9/26 13:33:03 网站建设 项目流程

我一度是个很爱收集提示词的人。收藏夹里躺着八十多个 AI 辅助 Prompt,专门用来处理存量代码的就有二十来个。可真要动手逐行改造那些老模块的时候,这些散装 AI 能力却一个都撑不住场面,我还要花大量时间在多个对话窗口之间“编排”它们协作。后来我换了一套思路——把零散能力装进结构化的 SKILL 里,用一套统一的编排机制去驱动它们,这才算真正给存量代码做起了“微创手术”。这篇文章就把我这一路踩过的坑、总结出的方法完整讲一遍,重点是:它怎么帮你告别“散装 AI”,以及你自己该怎么动手搭。

1. 散装 AI 的尴尬:为什么提示词收藏夹代替不了“会干活的人”

1.1 从一次失败的存量改造说起

之前接手过一套维护了七八年的订单系统,核心模块是用老式风格写的,全局状态散落在各个单例里,前人留下的注释还互相打架。我当时的常规操作是打开某个 AI 助手,粘贴一大段需求,加上“帮我重构这个函数”的尾巴。第一次改造一个库存扣减接口,AI 确实给了一版看着很专业的代码。但导进工程里一跑,单元测试挂了三个,同事小声提醒我:“你有没有想过,这个接口在别的地方是被反射调用的?”

当时我就意识到,问题不在 AI 的能力,而在我的用法。我把 AI 当成了一个“只会接单的临时工”,每次对话都从零开始教它这个项目长什么样、这地方为什么不能动、以前踩过什么雷。它给出的改造建议自然是一次性的、局部的,甚至对代码库产生了错误的全局假设。这就像每次做手术前临时抱佛脚背一遍解剖学,却不带任何病历和手术预案就上台。

1.2 散装 AI 的三个致命伤

日常交流里我常把这类用法叫“散装 AI”,因为它和“散装零食”一样:小包装、随拆随吃、看着选择多,但没有统一的配方和保质期管理。具体落到工程场景,它有三个很要命的伤:

  • 上下文断层。每个对话都是独立会话,项目结构、历史决策、变量命名约定、业务术语,这些最重要的背景知识要么靠你重复粘,要么干脆被模型忽略。模型对“存量代码”的理解只停留在你贴出来的几个片段上。
  • 规范缺失。没人告诉模型这个项目的 API 变更要走什么流程、日志格式是什么、数据库迁移文件要不要一起提交。于是每次生成的代码风格都不一样,甚至会在错误的地方引入新技术栈。
  • 不可复现。这次 AI 生成的方案不错,但你想让它在另一个模块上重来一遍,对不起,得从头再描述一遍需求,或者把刚才的对话记录翻出来手动总结成模板。散装 Prompt 之间没有依赖关系,也没有版本概念。

我见过很多团队折腾了几个月 AI 辅助开发,最后收效甚微,本质上都是栽在这三点上。大家以为缺的是“更好的模型”,其实缺的是把模型能力工程化、流程化的那层胶水。这层胶水,现在的主流做法里,被叫做 SKILL。

2. SKILL 的本质:它把“一次性提示”变成了“可沉淀的职业能力”

2.1 SKILL 在技术体系中的位置

先给 SKILL 一个尽量准确又不绕的定义:SKILL 是一组结构化文件,包括指令文档、参考脚本和元信息,整体挂载到一个 Agent 环境中,让模型在特定任务上能按既定的流程、既定的知识库、既定的质量标准来工作。把它放在架构里看,就很好理解:

  • Prompt(提示词):一次性的给模型下指令。
  • Agent(智能体):能感知上下文、规划拆解、调用工具的自主执行者。
  • SKILL(技能):Agent 在执行任务时可以被动态加载的“专业能力包”。
  • Workflow(编排流程):把多个 Agent、多个 SKILL 串成端到端流水线的逻辑层。

在 Claude Code、Codex、OpenCode 等工具里,基础设施有各自不同的实现,但内核思想已经收敛得非常接近:把过去你写在某个文本文件里的“长 Prompt”,升级成带目录结构、带脚本、带测试样例的“技能包”。Agent runtime 会在需要时把对应的 SKILL 注入到上下文里,而不是让你把一个几千字的规则全部堆在每条消息开头。这个设计本身就是对散装 AI 的一次反向修正。

2.2 一个 SKILL 的标准解剖

一个最朴素的 SKILL 目录,往往是这个样子:

refactor-guard/ ├── SKILL.md ├── scripts/ │ └── check_behavior.py └── references/ ├── project_conventions.md └── risk_zones.json

SKILL.md是整个技能包的主配置文件。它分两部分:YAML front matter(用于声明技能名称、描述、适用场景、关联工具,这部分经常会被 Agent 拿来作为检索和加载的依据),以及 Markdown 正文(写清楚这个技能该怎么用、流程是什么、边界在哪、常见禁忌有哪些)。scripts/目录放可供 Agent 调用的辅助脚本,例如检查改动范围、运行静态分析、生成迁移脚本之类的。references/目录则放模型需要查阅的项目级知识,按需加载,而不是一股脑全塞进一次上下文。

我自己的理解是:SKILL 不是提示词套壳,它本质上是在给模型“建职业档案”。提示词是纸上写一段“你是个好员工”,SKILL 是给你一套办公桌:桌上有工作手册、常用工具、历史案例,动工之前你知道先去翻哪个抽屉。

2.3 为什么说“编排”才是 SKILL 和散装提示词的分水岭

单个 SKILL 可以装能力,但它最厉害的点其实在于可以编排。一个针对存量代码改造的场景里,可能有若干个 SKILL 协同工作:一个负责摸底诊断,一个负责生成最小补丁,一个负责行为等价性验证,还有一个负责把改动整理成符合仓库规范的提交。这些技能之间靠明确的输入输出协议衔接,Agent 像一个手术主刀,按顺序调用它们,并根据中间结果动态决定下一步。这才是“微创手术”的意思,不是让 AI 一次性把整块代码重写了一遍,而是让它在一个可控的流程里,对指定病灶做精准处理,每步都有检查点。

搞明白这一点后,后面的操作思路就清楚了:先给存量代码建立风险地图,再按任务拆解成若干 SKILL,最后编排成流水线。下面我从头讲一遍,我是怎么做的。

3. 给存量代码动“微创手术”:SKILL 设计的先决工作

3.1 存量代码的风险地图:先搞清楚哪里能碰、哪里不能碰

设计 SKILL 之前,我最先做的是盘点代码库的风险等级。这个动作听起来像是“分析”,实际很工程化:我把仓库里所有模块按三级分类——高危险区(资金、订单、核心状态机等,改动必须触发人工评审)、中危险区(公共 API、内部服务边界、被跨模块引用的工具函数)、低危险区(组件内部逻辑、局部封装、不影响外部行为的实现细节)。

这一步不能靠直觉,最好用脚本扫一遍。我当时用了一个很简单的分析工具:解析仓库的 import 关系,算出每个文件的被引用数、所在层级、是否被反射或 SPI 机制加载,然后自动落成一份risk_zones.json。这个文件就是我后面 SKILL 的 reference 数据源之一。

之所以强调先做这个,是因为存量代码改造里最大的风险根本不是“AI 生成的代码有问题”,而是 AI 根本不知道它改的地方藏着什么雷。你给它一个函数描述,它能在互联网语料里找到类似函数的改法,但它不知道你们这个项目里这个函数被多少个变态用例日调用了几万次。风险地图就是为了补上这个信息缺口。

3.2 微创原则:把“最小变更 + 行为等价”写进 SKILL 的第一行

做存量改造,我给自己定的铁律是两条:一是“最小变更”,能改一行不改十行,能不动结构绝不动结构;二是“行为等价”,改造前后,对外可观测行为必须一致。这个原则不能只停留在你自己脑子里,要写进 SKILL 的指令文件开头,让它成为 AI 每次执行任务时绕不开的第一约束。

我在每个改造型 SKILL 的SKILL.md里都有一节叫“Golden Rules”,第一条就是这两句话的展开:

## Golden Rules - 禁止为了“代码更优雅”而扩大重构范围。 - 任何改动必须保持原有对外行为,除非任务明确要求改变行为协议。 - 修改涉及高风险区时,必须输出 Human Review Checklist。 - 不允许删除未确认无引用的导出函数、类、配置项。

这条规则的价值在于它会随着技能包一起被注入模型上下文。模型思维中那个“只要代码跑通就行”的惰性,会被这个硬约束给拉回来。后来我实测发现,没有这些显式规则的 SKILL,模型八成会在重构路上越走越远,最后给你交出来一个“新项目”而不是“微创改造”。

3.3 针对存量场景的三个 SKILL 需求拆解

给一个具体的存量代码库做微创改造,我最终拆出了三个 SKILL,职责非常清晰:

结构化诊断这个技能负责低风险扫描和风险盘点:识别出改造范围内的函数复杂度、依赖关系、调用链上所有危险点,输出每个改动的风险等级和影响范围。它生成的是手术前的“影像报告”。

最小补丁生成这个技能负责在给定风险等级和约束下,产出只针对目标逻辑的最小 diff,并且给出每处改动的理由,如果某处改动需要触碰高风险区,它会强制生成一个人工确认点。

行为等价验证这个技能负责拿改造前后的行为做对比,比如通过录制接口输入输出、跑回归用例、做静态语义检查,验证黑盒层面没有行为漂移。一旦发现可疑差异,立即阻断并回到最小补丁生成环节。

这三个 SKILL 是后面编排流水线的基础。接下来我直接手把手展示其中一个 SKILL 是怎么写出来的,完全照抄也能用。

4. 实操:从零编写一个“存量代码微创改造”SKILL

4.1 SKILL 目录结构与 YAML frontmatter 写法

我以“最小补丁生成”这个 SKILL 为例。先建目录,名字叫patch-craft。目录内部长这样:

patch-craft/ ├── SKILL.md ├── scripts/ │ ├── extract_diff.py │ └── detect_risk.py └── references/ ├── risk_zones.json └── commit_conventions.md

SKILL.md的 front matter 很关键,我这样写:

--- name: patch-craft description: 在给定存量代码上生成最小、行为等价的修改补丁。优先输出最小 diff,强制高风险改动的人工程确认。 when_to_use: 当任务需要对已有函数/模块做逻辑修复、局部重构,且必须保持对外行为不变时。 source_files: [SKILL.md, references/risk_zones.json, references/commit_conventions.md] allowed_tools: [bash, read_file, write_file, apply_patch] ---

这里when_to_use字段是 Agent 在任务匹配时决定要不要加载这个技能包的依据。我见过很多人忽略这段,结果 Agent 乱加载技能,把不相关的能力注入上下文,既浪费 token 又干扰决策写得越精准越好。

4.2 核心指令文件 SKILL.md 的关键段落设计

front matter 下面是正文,我按执行步骤来组织。正文里最需要花心思的是三个段落:

第一段是“适用范围与禁区”。我会明确写清楚这个 SKILL 绝不允许做什么,比如不允许重命名被外部引用的符号、不允许跨函数搬移逻辑、不允许修改公共 API 签名只允许在函数内部做等价变换。

第二段是“执行流程”,我会把它写成 Agent 可以直接遵照的操作序列。核心是一个五步流程:

  1. 读取references/risk_zones.json,确认目标文件风险等级,若为高危,先把流程图跳到人工程确认步骤。
  2. 读取目标函数完整实现和所有调用点,梳理输入输出契约。
  3. 生成最小补丁,要求 diff 的行数必须少于原函数行数的 30%,超过则重新审视改造范围。
  4. 运行scripts/check_behavior.py对改造前后行为做等价性检查。
  5. 输出变更说明,若触碰到风险区,生成 Human Review Checklist 并停止自动提交。

第三段是“输出格式”。我要求所有改造决定的输出必须是结构化格式,包含“变更行数”、“行为等价验证结果”、“风险区触碰情况”、“解释说明”。这一步很重要,因为后面编排层全靠这个结构化输出决定流水线走向。如果 SKILL 输出是自由文本,后面让 Agent 用另一套逻辑解析,就非常脆。

4.3 配套验证脚本和风险数据的作用

我把行为等价检查脚本写得很朴素,没有上什么重型符号执行工具,用的是“契约快照 + 类型签名对比”的思路。脚本会做三件事:

  • 提取目标函数的输入类型、输出类型、异常抛出列表。
  • 对比改造前后这两个接口描述是否完全一致。
  • 如果在仓库里发现了针对该函数的单测或接口录制,则把输入样本喂给改造前后两个版本,对比输出。

这脚本不可能证明“行为绝对等价”,但在工程上已经能拦掉 90% 的“改坏了但编译没问题”场景。真正凶险的存量代码往往没有测试,所以这个脚本还提供--snapshot模式:不依赖历史测试数据,而是基于当前行为做一次“现状快照”,改造后把快照里的样本重新跑一遍。术语上叫做“基于现状的特征验证”,说白了就是先把现状当契约,再验证你没有破坏它。

risk_zones.json的数据来自目录扫描脚本,生成后我不会频繁改动,除非有模块被重新定性。SKILL 引用它,等于给模型一份“哪些地方带电”的现场地图,这是散装 Prompt 时代最常见却最容易漏掉的信息。

5. 编排层实战:用 workflow 把诊断、手术、复检三个 SKILL 串成流水线

5.1 编排时的数据约定:每个 SKILL 输入输出如何对齐

有了三把独立的手术刀,还得把它们装进一个手术流程里。这一步,本质就是 SKILL 编排。我第一次做的时候犯了个很蠢的错:三个 SKILL 的输出格式各自为政。诊断输出 Markdown 表格,补丁生成输出 JSON,验证脚本又只打印文本。到了 Agent 想拿诊断结果去驱动补丁生成的时候,根本没法稳定解析。

后来我痛定思痛,给所有 SKILL 定了一套统一的数据交换格式,核心是三个字段:

{ "target": "文件路径:函数名", "risk_level": "high | medium | low", "action_required": "auto_patch | human_review | block" }

每个 SKILL 任务完成后都要输出一个包含以上字段的标准信封(envelope),再加上各自业务数据。诊断 SKILL 的信封里带findings,补丁 SKILL 的信封里带diff和rationale,验证 SKILL 的信封里带verification_status。这样编排层的流转逻辑就非常干净:上一个 SKILL 的信封,决定下一个 SKILL 的触发条件和参数配置。

5.2 一条完整流水线示例

我最终实际跑通的流水线大致是这一步序列,每一步之间都有明确的转移条件:

  1. 传入“目标函数 + 期望修复说明”,编排层先调用诊断 SKILL。
  2. 诊断 SKILL 输出风险等级。如果高风险,流水线直接转人工评审,不让任何自动补丁继续往下走。
  3. 中低风险进入补丁生成 SKILL,输出最小 diff 和改动理由,同时如果改动边界跨了公共函数,也会追加一个human_review标记。
  4. 验证 SKILL 拿到 diff 和原函数,跑行为等价检查;结果通过就进入下一环,不通过就把失败信息反馈回补丁生成 SKILL,让它基于具体验证失败样本重新调整。
  5. 最终的补丁、验证报告、人工程确认单一起打包,交给库的审阅接口分段提交。

这套流程跑起来之后,我比较大的感受是:它把“AI 自己决定怎么改”变成了“AI 按流程决定怎么改”。前一种模式里模型太自由,动不动就会顺便“优化”周边代码;后一种模式每个 SKILL 的边界都很窄,任何越界行为都会被后面的验证或编排逻辑拦下来。

5.3 编排顺序的取舍:哪些步骤必须串行,哪些可以跳步

关于编排顺序,我总结了一个经验:涉及接口签名、全局状态、公共 API 的改动,三个阶段——诊断、补丁、验证——缺一不可,必须串行;如果是函数内部实现细节的局部重写,那么诊断阶段可以少跑一些跨模块分析,直接从文件内依赖分析开始,能省不少 token和时间。

还有一个容易忽略的点:编排层不能只做“顺序调用”,它必须有回环能力。我上面的流程里,验证失败会反馈回补丁生成,这就是一个典型的回环。如果编排只是线性流程,遇到验证失败就只能整条流水线崩掉;有了回环机制,它会在两三轮之内自动迭代收敛,大多数问题并不需要人工介入。

我尝试配置工作流时用了不少现成的 agent 编排工具,它们对 SKILL 的原生支持程度不一。有的支持子任务节点和显式的技能绑定,有的只能靠自定义函数把技能夹带进去。我的建议是,别被工具牵着走,先把数据交换信封定下来,工具只负责执行逻辑,技能之间的协议只要稳定,换哪家 Agent 框架都能迁。

6. 实测中踩过的坑:SKILL 编排不是写完了就自动好用

6.1 坑一:多轮对话里 SKILL 指令被后文覆盖,Agent 突然“失忆”

我印象最深的一次翻车,发生在一次连续改造了四个模块的长任务里。前三个模块都顺顺利利,到第四个模块时,模型开始不按SKILL.md里限制的最小变更原则来,擅自把整个函数改造成了生成器风格,还美其名曰“提升了迭代效率”。排查很久之后,我才意识到是多轮上下文里模型对 SKILL 指令的注意力衰减了。

后来我采取的机制是,给 SKILL 的执行流程加一道“自我检查点”:每完成一个函数的修改,在输出中强制附带一条“Golden Rules 确认标记”,列出本次改动是否触碰风险区、是否保持等价。别小看这一步,它迫使模型在每个关键节点重新回溯一遍它的行为准则,而不是被后文的用户指令、自己的推理内容带跑偏。这招实测比什么“系统提示词必须放在最前面”都管用。

6.2 坑二:验证脚本和改造动作之间的死锁

有一阵子,我的流水线陷入了“验证失败 → 重新生成补丁 → 又验证失败”的死循环。原因很无语:行为等价检查脚本太严格,它对比了目标函数在新旧版本里的字节码行号信息,而这恰恰会因为增量编译产生噪音。于是它每次上报“行为变化”,逼着补丁生成 SKILL 反复改,越改越差。

这个坑的根源是“验证器和被测对象耦合太紧”。解决方法也比较痛快:把等价性判断维度收敛回可观察契约和数据样本,删掉行号、变量名这类实现细节层面的比对。工程上叫“不要用实现细节做黑盒验证”,但在 SKILL 编排里,它更像是一个修掉循环依赖的设计问题。现在我的所有验证脚本都有明确条款:只比较输入输出行为,不比较实现特征。

6.3 坑三:存量代码里的隐蔽依赖,SKILL 上下文装不下

风险地图再周全,也有覆盖不到的地方。存量代码最大的特点就是“这里有一层看不见的魔法”,反射调用、动态 import、配置文件里配的处理器类名……这些依赖,静态分析只能抓个大概。有一回 SKILL 很自信地认为某个废弃函数没有被任何地方引用,建议删除,结果上线当晚那段路径被一个运行时动态加载的插件触发了。

在那之后,我在“补丁生成”SKILL 里加入了一条新的禁区规则:任何关于“无引用”的判断,必须给出证据文件来源,且不允许仅凭静态扫描结果判定高风险对象为可删除。宁可保守留废代码,也不要让“微创手术”变成“截肢手术”。这个规则把不少无谓的激进删改挡住了。

6.4 从排错到机制:给 SKILL 加“强制检查点”

经历了上面几次坑,我把“强制检查点”变成了所有改造型 SKILL 的统一标配。简单来说,它是一组必须执行的中间检查步骤,不跳步、不合并、不留到最后一次性做。三个阶段各有检查点:

  • 动手前:确认风险区状态、确认是否有隐藏依赖证据。
  • 动手中:每完成一文件改动,强制运行局部静态检查,并输出变更行数占比。
  • 动手后:强制运行行为等价快照验证和人工复审清单生成。

这些检查点让整个改造过程可控了很多。虽然每次任务会因此多消耗一些 token,但它换回的是可追溯性和安全感。在存量代码上做自动改造,我宁可多花 20% 的算力成本,也不愿意上线后再花 10 倍时间回溯定位是谁改错了哪一行。

7. 我的个人体会:SKILL 编排的投入产出比因人而异,但长期值得

做这套东西做下来,我最想分享的体会是:SKILL 编排不是买来即用的东西,它更像是一种工程纪律。你得先接受“前期搭框架很烦、但后期收益是复利”这个规律。

如果你只是偶尔拿 AI 改一两个脚本,那确实没必要搭这么重的体系,几条精心调过的 Prompt 也能应付。但如果你像我一样,要在一套没有测试、没有文档、全局状态满天飞的存量代码上长期做改进,那这套 SKILL 编排体系带来的回报会非常明显。最直接的变化是,你不再需要每次重新教 AI 这个项目是什么,风险地图和变更规范都在技能包里躺着,换什么模型都能保持同一套工作底线。

另外,我个人的一个实用建议是:不要一开始就想把 SKILL 体系设计得完美。第一次可以先只做一个诊断 SKILL + 一个验证脚本,拿一个低风险模块跑通闭环,再逐步加更多专家技能和编排节点。过程很像搭积木,底层的数据交换协议一旦稳住了,往上叠再多的技能都不怕散。别忘了那句话:好的编排不是让你控制每一个动作,而是让每一层都只做它最擅长的事,然后靠协议把它们缝合起来。照着这个思路走,你也能告别“散装 AI”,给存量代码做出一台真正的微创手术床。

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

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

立即咨询