☰
SKILL编排:用AI给存量代码做一场微创手术
2026/9/26 7:19:30 网站建设 项目流程

大概每个做技术的都会遇到这种场景:手里攥着一套跑了五六年的老系统,业务逻辑缠成一团乱麻,文档早就和代码脱节了。这时候你想用AI帮忙改点东西,结果发现自己处在一种“散装 AI”的状态——这边对话框里问一句“这段逻辑是干嘛的”,那边把生成的代码片段粘进编辑器,再开个新对话让AI帮忙写个单元测试,每个环节都是孤立的,没有任何沉淀,也没有流程约束。AI确实干活了,但产出是碎片化的,改完代码你甚至不知道它改了什么、为什么这么改、有没有把别的地方弄坏。

我最近在存量代码改造上换了一套思路:用 SKILL 把这些零散的AI能力编排成一条有条理的任务流,像做微创手术一样,只切该切的组织,不搞大放疗。这篇文章就把这套做法从头到尾讲一遍,包括SKILL到底怎么定义、编排流程怎么设计、实操中会踩什么坑,全是自己跑过之后的经验。

1. 先把“散装 AI”的病根说清楚

1.1 散装AI的典型症状

我见过太多团队用AI的方式是这样的:开发遇到一个编译报错,把错误信息扔给AI,拿到一段“可能是这么改”的代码,粘进去试试;过一会儿再遇到一个逻辑问题,又打开一个AI对话窗口,重复一遍项目背景,让它生成一段方案。次数多了,每个人手里都有一堆和AI的对话记录,但没有一条被沉淀成可以复用的东西。

这种做法的核心问题有三个。

第一是上下文断裂。每次和AI对话都是从零开始,你需要反复解释项目背景、代码结构、你的约束条件。同一个项目,上午的对话和下午的对话在AI眼里是两个完全不同的世界,它给不出有连续性的建议。这就好比你每天换个新医生看病,每次都要从头讲病情,医生每次都是第一次见到你。

第二是没有边界约束。散装使用AI的时候,你很难让AI明确“什么能改、什么不能碰”。我见过最典型的情况:我只是让AI优化一个函数的时间复杂度,它建议我把整个模块重写一遍,还顺手把配置文件也改了。对存量代码来说,这简直是灾难——你永远不知道AI的“顺手”会波及到哪条业务链路。

第三是结果不可复现。你在对话框里让AI改好了代码,但这个“改好”依赖的是当时的对话上下文、临时编的提示词、碰巧的运气。换个时间、换个人,同样的目标完全得不到同样的结果。对团队协作来说,这种不可复现就意味着经验无法传递,能力无法积累。

1.2 SKILL到底是什么

SKILL本质上是一套标准化的AI技能描述文件,把完成某类任务所需要的提示词、约束规则、参考示例、执行步骤打包成一个可复用的单元。你可以把它理解成给AI写的“岗位说明书”:明确了这个技能叫什么、在什么场景下用、输入是什么、输出是什么、必须遵守哪些规则、按什么步骤执行。

和普通提示词最大的区别在于,SKILL是结构化、可复用、可编排的。一个写好的SKILL可以被反复调用,可以在不同项目中迁移,可以和其他SKILL组合成更复杂的任务流。用开发里的概念来类比,SKILL之于AI智能体,就像函数之于程序、插件之于浏览器、菜谱之于厨师。

举个例子。你不需要每次跟AI说“请你分析这段代码的依赖关系,找出外部依赖、内部耦合、潜在风险点,按表格形式输出”,而是把这段话连同输出格式要求、分析维度定义、注意事项写成一个dependency-analysis/SKILL.md文件。下次需要用的时候,只要在对话里说一句“对src/payment/目录执行依赖分析”就行。

1.3 为什么SKILL特别适合存量代码场景

存量代码最让人头疼的地方在于:它经不起大动干戈。老系统往往没有完善的测试保护,业务规则藏在几千行没人敢动的函数里,依赖关系错综复杂。这种情况下,你需要的不是AI的“创造力”,而是AI的“纪律性”——严格按流程来,只改指定范围,输出可验证的结果。

SKILL恰好能提供这种纪律。你可以把一个存量代码的改造任务拆成多个SKILL,每个SKILL只负责一件具体的事,通过编排让它们按顺序协作。每个SKILL内部都写死了约束条件,AI只能在这个范围内操作,不能越界。这就实现了对存量代码的“微创”——精确定位病灶,小切口介入,尽量减少对周围组织的损伤。

2. 编排设计的核心思路:这台手术怎么切

2.1 为什么“微创”而不是“重构”

我见过不少团队拿到存量代码后的第一反应是想让AI做现代化重构——把老框架换掉、把业务逻辑重塑一遍、顺手把技术债还了。这种冲动我完全理解,但实际在存量代码上这么干,翻车概率极高。

根因在于存量代码的价值往往不是靠“代码质量”体现的,而是靠“已经正确运行了这么多年”体现的。代码里可能藏着很多看起来冗余、过时、甚至不优雅的写法,但它们对应着真实的业务规则、历史兼容策略、边界情况处理。你不知道哪段“垃圾代码”背后链接着一个不能出错的财务计算,也不知道哪段“丑陋写法”是为了规避某个早已没人记得的线上故障。

所以存量代码改造的正确姿势不是重构,而是“微创手术”:在充分理解现状的前提下,找到真正需要改进的局部痛点,用最小干预实现目标,每一步都可回滚、可验证。AI在这里的定位应该是“辅助手术工具”,不是“主治医师”——它提供诊断、操作建议、执行局部改动,但整体方案和审查判断必须有人把关。

2.2 把“手术”拆成三类SKILL角色

一台手术需要术前检查、手术执行、术后护理三个环节。存量代码改造也一样,我把SKILL按职责分成了三类。

诊断类SKILL:负责术前检查。包括代码结构分析、依赖关系梳理、风险点识别、变更影响面评估。这类SKILL的输出是决策依据,帮助你说清楚“哪里需要改、哪里不能碰、改了会影响什么”。

执行类SKILL:负责实际干预。包括局部代码修改、设计模式迁移、API替换、死代码清理。这类SKILL的核心约束是“边界感”——必须在指定的文件、函数、模块范围内操作,不越权修改其他代码。

验证类SKILL:负责术后保障。包括补全单元测试、分析测试覆盖率、执行回归建议、评估改动安全性。这类SKILL的产出是“这次手术是否成功的证据”,而不是一句轻飘飘的“应该没问题”。

这三类SKILL通过编排组合起来,就形成了一条完整的改造流程:先让诊断类SKILL摸清底细,再让执行类SKILL动手修改,最后用验证类SKILL确认改动安全。每个环节的输出都是下一个环节的输入,环环相扣,每一步都有据可查。

2.3 编排方式的选择与取舍

SKILL编排的方式有很多种,我实际使用中觉得最值得关注的是三个维度:执行顺序、分支判断、人工介入点。

执行顺序最简单,就是按“诊断 → 执行 → 验证”的线性流程走。但对复杂的存量代码,执行阶段可能需要多轮迭代——先改A模块,验证通过后再改B模块,这就需要在编排里支持循环和多阶段推进。

分支判断解决的是“不同情况走不同路径”的问题。比如诊断阶段的输出显示某个模块改动风险极高,那就走“保守处理”分支,只做最小修改或者干脆跳过;如果风险可控,就走“正常处理”分支,允许执行类SKILL放手操作。

人工介入点是整个编排里我最看重的东西。AI跑的再顺,也必须有让人喊停、修改、确认的地方。我的做法是在每个SKILL执行完之后都设置一个“审查节点”——AI输出分析结果或修改建议,由我来确认“继续”还是“调整”。这不是不信任AI,而是对存量代码负责任的表现。

3. 实操:给一个存量支付模块做“微创手术”全流程

3.1 第一个SKILL:代码画像与风险评估

我实际改造的是一个老支付模块,代码历史接近六年,好几任开发经手,业务规则没有文档。第一步做的事情是让AI给这个模块画一张“体检报告”,对应的是一个诊断类SKILL。

SKILL文件的核心结构大致长这样:

--- name: payment-module-audit description: 对支付模块进行代码画像和风险评估,输出结构化分析报告 --- # 角色 你是一名有十五年经验的存量系统分析专家,擅长从老代码中还原业务逻辑、识别风险点。 # 任务目标 分析指定目录下的代码,输出: 1. 模块整体结构画像(目录、关键文件、核心类/函数) 2. 外部依赖清单(第三方库、外部服务、配置项) 3. 内部耦合分析(模块间的调用关系、共享状态) 4. 风险区域标记(高风险:涉及资金计算、状态流转;中风险:涉及数据读写;低风险:工具类代码) 5. 可安全修改区域清单 # 输入 - 代码路径:{code_path} - 需要特别关注的业务逻辑:{business_focus} # 约束 - 只做分析,不要给出任何修改建议 - 引用具体代码时注明文件路径和行号 - 不确定的地方标记为 [需人工确认],不要猜测 # 输出格式 按以下Markdown结构输出: ## 模块画像 ## 外部依赖 ## 内部耦合 ## 风险矩阵(表格形式:区域/风险等级/原因/建议动作) ## 可安全修改区域

这个SKILL跑完之后,AI给了一份比较靠谱的体检报告。比如它标记出支付金额计算的核心函数calculateFinalAmount()是高风险区,因为涉及折扣叠加、优惠券校验、四舍五入策略等多重逻辑;同时标记出日志工具类logger.ts是低风险区,可以安全修改。

有了这张风险地图,才知道刀子往哪里下。

3.2 第二个SKILL:约束边界下的代码修改

体检之后进入执行环节。我设计执行类SKILL时的核心原则是:必须在明确边界内操作,每个改动必须给出理由,禁止顺手牵羊。

一个典型的执行SKILL是这样定义的:

--- name: scoped-code-refactor description: 在指定文件/函数范围内执行代码重构,严格限制修改边界 --- # 角色 你是一名保守的代码重构专家,信奉“尽量少改、局部优化、保持行为不变”。 # 任务目标 针对{target_files}中的{target_function},根据需求{change_request}执行代码修改。 # 硬性约束 - 只允许修改{target_files}中与{target_function}直接相关的代码 - 禁止修改其他函数、其他文件、依赖配置、构建配置 - 保持函数的对外签名不变(除非需求明确要求) - 保持错误处理逻辑和边界条件不变 - 每个修改点必须用注释标注:修改原因、涉及需求、风险评估 # 过程要求 1. 先阅读目标函数的完整代码 2. 分析当前实现与需求变更之间的差异 3. 制定最小改动方案 4. 执行修改 5. 输出修改说明清单,包括:改了哪些行、为什么改、潜在影响 # 输出格式 - 修改后的完整函数代码 - 修改点清单(表格:文件/行号/修改前/修改后/修改原因) - 自检报告(是否满足约束、是否有遗留风险) # 禁止事项 - 禁止“顺手”格式化整个文件 - 禁止引入新的第三方依赖 - 禁止重命名已有变量和函数(除非需求要求) - 禁止删除看似“没用”但实际可能被反射/配置引用的代码

这里我特别想强调“保持签名不变”和“禁止顺手格式化”这两条。存量代码里经常有隐形的地方在调用你正在改的函数——比如一个字符串匹配、一个反射调用、一个配置里的函数名。你改了函数签名,可能静默地炸掉一条线上链路。AI不会主动意识到这些,所以必须在SKILL里写死。

实际改造中,这个SKILL帮我完成了一个典型任务:把支付金额计算里的折扣逻辑从“先算总价再套折扣”改成“按商品行项目逐项折扣再汇总”。改动范围被严格限制在calculateFinalAmount()和相关联的三行代码里。AI最终改完还自动标注出了两个风险点:一个涉及精度丢失的场景,一个涉及优惠券与折扣同时生效时的优先级疑问,这两个都被标记为“建议人工确认”。

3.3 第三个SKILL:测试补全与安全验证

手术做完了不能直接缝合下台。存量代码最尴尬的地方是没有测试,改完之后没人能证明“行为保持不变”。所以我设计了验证类SKILL,让AI针对改动点补全测试用例。

--- name: regression-test-builder description: 针对指定代码改动生成单元测试和回归验证清单 --- # 角色 你是一名测试驱动开发专家,擅长为存量代码补充可靠的回归测试。 # 任务目标 针对代码改动{change_list},生成单元测试代码和回归验证计划。 # 输入 - 改动说明:{change_list} - 被测函数源码:{target_source} - 测试框架:{test_framework} # 要求 1. 测试必须覆盖:正常流程、边界值、异常输入、历史典型场景(如有) 2. 测试用例必须标注“验证目标”,即这个用例在防什么回归 3. 对无法自动测试的场景,给出人工验证清单 # 输出格式 - 测试代码(可直接运行) - 用例说明表(用例名/验证目标/输入/预期输出) - 人工验证清单 # 约束 - 不要为了覆盖率而生成无意义的断言 - 测试代码风格与项目现有测试保持统一 - 如果发现被测函数本身有可疑逻辑,在报告中标注但不擅自修改

这一步产出非常直观:AI生成了十几个测试用例,有几个覆盖的是“折扣叠加”“优惠券阈值边界”“金额精度四舍五入”这类敏感场景。跑完这些测试,才能对这次“微创手术”的效果有底气。

3.4 用编排脚本串起整个流程

三个SKILL各自为战还不够,需要一条逻辑把它们串起来。我用的方式是写一个简单的编排脚本,把输入输出流转起来。核心逻辑大致如下:

# orchestrator.py # SKILL编排器:串联诊断、执行、验证三个阶段 # 仅作示意,实际使用时按所用工具调整API调用 from skill_runner import run_skill # 伪代码,表示调用SKILL的执行入口 def orchestrate_payment_refactor(): # 阶段一:诊断 audit_result = run_skill( "payment-module-audit", code_path="src/payment/", business_focus="金额计算、优惠折扣" ) # 输出:体检报告,包含风险矩阵和可修改区域 # 人工审查点:确认风险矩阵,批准修改范围 approved_scope = human_review(audit_result) if not approved_scope: print("手术方案未通过,终止流程") return # 阶段二:执行(支持多轮迭代) for target in approved_scope.get("targets", []): change_list = run_skill( "scoped-code-refactor", target_files=target["files"], target_function=target["function"], change_request=target["request"] ) # 人工审查点:确认改动清单无越界 if not human_review(change_list): print(f"跳过目标 {target['function']}") continue # 阶段三:验证 test_result = run_skill( "regression-test-builder", change_list=change_list, target_source=read_source(target["files"]), test_framework="pytest" ) # 执行测试并记录结果 run_tests(test_result) print("存量模块微创手术完成")

这个编排流程的精髓在于两个人工审查点:一个在诊断之后,确认“手术方案”可不可行;一个在执行之后,确认“实际改动”有没有越界。AI干活,人把关,这是存量代码改造能安全推进的关键保障。

4. 常见问题与排查技巧实录

4.1 SKILL没生效,AI依然“自由发挥”

这是我最开始频繁遇到的情况。写好了SKILL文件,也明确说要调用这个技能,但AI给出的回答还是泛泛的、不受约束的。排查之后发现问题出在两点。

第一,SKILL文件的描述信息不够明确。AI选择技能的时候主要是靠name和description来判断何时该用哪个SKILL。如果描述写得太宽泛,比如“分析代码并给出建议”,AI可能在一个需要纯诊断的场景里也顺手给出修改建议。我的解决方法是把description写得更具象,明确触发场景和适用边界。

第二,提示里没有明确引用SKILL名称。在多数支持SKILL的AI工具里,如果你只说“帮我分析这段代码”,AI不一定自动匹配到已加载的技能文件。更稳妥的写法是直接点名:“调用 payment-module-audit 技能,对src/payment/目录做代码画像”。点名之后,AI才会按技能文件里的约束执行。

4.2 存量代码上下文太大,塞不进模型窗口

老模块经常是几千行甚至上万行代码,全部塞进上下文不现实。这个问题我的解法组合拳是:先用诊断类SKILL只读取目录结构和关键文件,产出高层次的概览;再对具体要改的函数单独提取源码喂给执行类SKILL。

相当于先拍一张X光片确定病灶位置,再做局部活检,而不是把整个人体都摊开来看。实践中,诊断类SKILL的输入可以是“目录树 + 关键文件列表”,输出是“哪些文件值得深读”;然后再针对这几个文件做精读分析。这样能在有限上下文里层层聚焦,不会被无关代码淹没。

4.3 AI改完出现“附带伤害”

有次让AI给一个数据导出模块加字段映射,它倒是规规矩矩改了目标函数,但为了“让代码更整洁”,自作主张把同一个文件里的另一个函数也重新格式化了一遍,还改了变量名。这种“附带伤害”在散装AI里几乎不可能被发现,因为你不会一行行去比对diff。

SKILL编排帮我解决了这个问题:执行类SKILL的“禁止事项”里明确写了“禁止格式化整个文件”“禁止重命名已有变量”,同时要求输出每个修改点的前后对照。再加上执行后的人工审查节点,基本能把“顺手改”这种东西拦住。

我还给自己加了一条硬规矩:SKILL执行完之后,必须跑一次git diff全量检查。一眼扫过去,如果改动行数远超预期,直接git checkout回退,不容商量。

4.4 SKILL写得太死,反而没法复用

另一个极端是SKILL里的约束条件写得太具体,比如把某个支付函数的名字、某个业务字段的值写死在技能描述里。这个SKILL的确能管好这个模块,但换个项目就完全用不了。

我的经验是做一个“抽象度”的取舍:把通用的流程性约束写进SKILL,把具体的项目参数通过输入项传递。比如上面那个执行类SKILL,“保持函数签名不变”“禁止修改指定范围以外代码”“输出修改清单”这些是通用约束,要写死;而“目标是哪个文件、改哪个函数、需求是什么”这些都是每次调用时传入的参数,不要写死。

这样SKILL才能在团队和项目间流动,积累成真正的资产,而不是一次性工具。

4.5 问题排查速查表

现象排查方向解决方案
AI不按SKILL约束执行技能描述太宽泛、提示未点名具化description,提示中直接引用技能名称
输出格式不符合要求SKILL中输出格式定义不够严格在SKILL中给出明确的Markdown模板
上下文不足导致遗漏输入信息不完整将大任务拆成多轮,逐层聚焦
改动范围超出预期缺少边界约束在SKILL中用“禁止事项”写死红线
测试补全覆盖率低缺少历史场景数据补充业务规则作为测试设计输入
SKILL在其他项目不可用参数写死在技能描述中将项目参数改为调用时传入的变量
AI在分析阶段主动改代码角色定位不清晰在SKILL“角色/任务目标/约束”中强调只分析不修改

5. 把SKILL编排变成团队的基础设施

我用这套方法论跑通了一个存量支付模块的改造之后,最大的感受是:SKILL编排解决的不只是“AI干活效率”的问题,更是“团队经验沉淀”的问题。散装AI时代,每个人和AI的协作经验都躺在各自的对话记录里,人一走、经验就没了。SKILL把经验固化成了文件,放进了仓库,任何人都能复用和迭代。

现在我会建议团队做三件事。

第一,建一个SKILL目录。把团队日常用到的高频技能全部整理成SKILL文件,按“诊断类/执行类/验证类”或者“代码分析/测试生成/文档编写”这样的维度建目录,纳入版本管理。每个SKILL都记录更新历史,评审过、踩过坑的都写在里面。

第二,每个改造任务强制走编排流程。哪怕是改一个很小的函数,也按照“先诊断、再执行、后验证”的顺序走,不允许跳过步骤直接让AI改代码。这个“强制”并不是官僚主义,而是给小改动也建立安全网。

第三,定期迭代SKILL内容。SKILL不是一次写死的东西。我每次用完都会顺手更新技能文件——这次遇到什么新坑,就在“禁止事项”里补一条;这个输出格式不好用,就调整一下模板。经过几轮迭代,SKILL会越磨越顺手,越来越像团队的“体外大脑”。

最后分享一个我个人主观的判断标准:如果你发现自己还在反复复制粘贴同样的一段提示词给AI,那你就是还在过“散装AI”的日子。把它写成一个SKILL文件,放进编排流程里,你省下的不只是那点敲字的力气,而是为每一次AI交互建立起了质量和安全的底线。这一步迈出去,AI才算真正开始帮团队——而不是帮倒忙。

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

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

立即咨询