尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

AI编程助手Skill臃肿问题:单一职责与组合调用优化实践

发布时间:2026/9/26 18:31:00

资讯中心
01
ARTICLE

AI编程助手Skill臃肿问题:单一职责与组合调用优化实践

AI编程助手Skill臃肿问题:单一职责与组合调用优化实践
1. 为什么你的 Skill 越来越臃肿1.1 一个普遍现象Skill 正在变成“万能工具箱”如果你最近半年一直在折腾 Claude Code、Codex、Cline 这类 AI 编程助手大概率会遇到一个很尴尬的局面一开始你只是想让 Skill 帮你做一件小事比如格式化一段 JSON、生成一个 commit message、或者把一段自然语言转成 SQL。结果用了两周你的 Skill 目录里已经躺着十几个文件每个文件动辄几百行里面塞满了各种 if-else 分支、边缘情况处理、以及“万一用户这样问”的兜底逻辑。我自己的~/.claude/skills/目录曾经一度膨胀到 40 多个 Skill总行数超过 8000 行。最夸张的一个 Skill 叫code-helper里面同时处理 Python、JavaScript、Go、Rust 四种语言的代码审查、重构建议、单元测试生成、依赖检查、以及文档字符串补全。每次调用它模型都要先读完这 600 多行的指令然后才能开始干活。结果是响应慢、token 消耗高、而且经常“忘记”前面几条规则——因为上下文太长了注意力被稀释了。这个现象我称之为Skill 肥胖症。它的症状很明显Skill 文件超过 200 行、包含超过 3 个不相关的职责、需要频繁更新但每次更新都怕改坏别的地方、以及最致命的——你开始不敢删任何东西因为“万一以后用得到呢”。1.2 肥胖的代价不只是慢而是不可靠很多人以为 Skill 大一点没关系反正模型上下文窗口现在都 200K 了。但实际用下来问题远不止“慢”这么简单。第一指令冲突。当一个 Skill 里同时存在“总是输出 JSON”和“优先用自然语言解释”两条规则时模型会随机选一条执行。你以为是模型不稳定其实是你的 Skill 自相矛盾。第二维护成本指数上升。一个 50 行的 Skill你改一行能预测影响范围。一个 500 行的 Skill你改一行可能让三个不相关的功能挂掉。我踩过最坑的一次是在一个通用reviewSkill 里加了一条“检查 SQL 注入”的规则结果导致所有 Python 代码审查都开始强行找 SQL 注入哪怕那个文件里根本没有数据库操作。第三复用性归零。胖 Skill 只能你自己用因为里面塞了太多个人偏好和项目特定逻辑。你想分享给同事对方得先花半小时读懂你那 600 行到底在干嘛。第四和 AGENTS.md 的职责边界模糊。很多人把项目级的规范、目录结构说明、构建命令全塞进 Skill 里但这些东西明明应该放在AGENTS.md或context.md里。Skill 是“怎么做”AGENTS.md 是“这是什么”。混在一起模型就分不清哪些是通用能力哪些是项目上下文。1.3 减肥的核心思路单一职责 组合调用给 Skill 减肥不是简单地把大文件拆成小文件就完事了。核心思路是三条一个 Skill 只做一件事并且这件事能用一句话说清楚。比如format-json就只格式化 JSON不要顺便校验 schema。通用能力下沉到基础 Skill项目特定逻辑上浮到AGENTS.md或单独的 context 文件。用组合代替堆砌。需要复杂流程时让模型按顺序调用多个小 Skill而不是写一个巨无霸 Skill 把所有步骤写死。这套思路借鉴了 Unix 哲学每个程序只做一件事但做好用管道组合它们完成复杂任务。Skill 也一样read-fileextract-functionrewrite-code三个小 Skill 组合起来比一个refactor-everything大 Skill 更灵活、更可靠、也更容易调试。2. 拆解 Skill 的四个维度2.1 按职责边界拆从“做什么”到“只做什么”拿到一个胖 Skill第一步不是急着删代码而是先做职责盘点。我的做法是把 Skill 里所有指令逐条列出来然后问自己——“这条指令如果单独拿出来能不能成为一个独立 Skill”举个例子假设你有一个api-helperSkill里面包含这些指令根据自然语言生成 REST API 请求校验 API 响应是否符合 OpenAPI schema把 curl 命令转成 Python requests 代码生成 API 文档的 Markdown 表格检查 API key 是否泄露在代码里这五条其实是五个完全不同的职责。生成请求是“构造”校验响应是“验证”转代码是“翻译”生成文档是“输出”检查泄露是“安全审计”。它们唯一的共同点是都和 API 有关但“都和 API 有关”不是一个合理的拆分依据——否则所有和代码有关的 Skill 都能合并成一个。正确的拆法是api-request-gen、api-response-validate、curl-to-python、api-doc-gen、secret-scan。每个 Skill 只做一件事每个都能独立测试、独立更新、独立复用。注意拆分时不要按“输入类型”或“输出格式”拆而要按“动作意图”拆。同样是输出 JSONformat-json和extract-json-schema是两个不同的意图应该分开。2.2 按触发频率拆高频精简低频隔离不是所有 Skill 都值得同等对待。我习惯把 Skill 按调用频率分成三档频率档位典型场景处理策略高频每天多次格式化、commit message、代码审查极致精简控制在 50 行以内零冗余中频每周几次生成测试、重构建议、文档补全保持 100 行以内允许少量分支低频每月几次项目初始化、迁移脚本、架构分析可以稍长但必须独立目录不污染高频 Skill高频 Skill 的每一行都在消耗你的日常 token 预算和响应时间。我实测过一个 200 行的commit-msgSkill 和一个 30 行的版本在同样模型下前者平均响应时间多 1.8 秒token 消耗多 3 倍。一天调用 50 次就是 90 秒和几万 token 的差距。低频 Skill 则相反它们不常跑但跑一次可能很复杂。这时候可以把详细逻辑写清楚甚至附带示例和边界情况。但关键是——它们必须放在独立目录里不要和高频 Skill 混在一起否则模型在选择时容易误触发。2.3 按依赖关系拆识别“隐式耦合”很多胖 Skill 之所以胖是因为里面藏了隐式依赖。比如一个deploy-helperSkill 里写了“先运行测试再构建再推送镜像再更新 k8s deployment”。这四步看起来是一个流程但实际上每一步都依赖不同的工具、不同的权限、不同的失败处理方式。这种“流程型 Skill”是最容易肥胖的因为每次流程有变化你就得改这个 Skill。更好的做法是拆成run-tests、build-image、push-image、update-deployment四个独立 Skill然后用一个轻量的deploy-orchestratorSkill 来按顺序调用它们。orchestrator 本身只有 20 行只负责“先调 A再调 B如果 A 失败就停止”。这样做的好处是测试逻辑变了只改run-tests构建参数变了只改build-imageorchestrator 完全不用动。而且每个子 Skill 都能单独在 CI 里测试不用跑完整部署流程。2.4 按上下文需求拆区分“通用”和“项目特定”这是最容易被忽视的一个维度。很多 Skill 里混了大量项目特定的信息比如“我们的 API 基地址是https://internal.api.example.com”、“数据库表名用蛇形命名”、“所有日期字段用 UTC”。这些信息不应该硬编码在 Skill 里。Skill 是能力项目信息是上下文。正确的做法是Skill 里只写“从环境变量API_BASE_URL读取基地址”、“遵循项目命名规范见 AGENTS.md”、“日期统一用 UTC”。具体值放在AGENTS.md、.env或context.md里。这样同一个api-request-genSkill 可以在不同项目里复用只要每个项目的AGENTS.md写清楚自己的规范就行。我现在的做法是Skill 目录里只放通用能力项目根目录放一个AGENTS.md描述项目特定规则模型在调用 Skill 时会自动读取当前项目的AGENTS.md作为补充上下文。3. 实操把一个 600 行 Skill 拆成 6 个 50 行 Skill3.1 拆前准备先备份再盘点动手之前先做两件事。第一把原 Skill 完整备份到~/.claude/skills/_archive/下命名带上日期比如code-helper-20250115.bak。第二打开原文件逐段阅读用注释标出每一段的“意图标签”。我拿自己那个 600 行的code-helper举例。读完后我标出了这些意图生成代码注释Python docstring、JSDoc检查命名规范变量、函数、类生成单元测试骨架检查未使用的 import建议重构提取函数、消除重复生成 commit message六个意图正好对应六个独立 Skill。每个意图单独拿出来都能用一句话说清楚而且互相之间没有依赖。3.2 逐个拆解以“生成单元测试骨架”为例原 Skill 里关于单元测试的部分大概有 120 行混杂了 Python、JavaScript、Go 三种语言的模板还有“如果项目用 pytest 就用 pytest 风格如果用 unittest 就用 unittest 风格”这种分支。拆出来的gen-test-skeletonSkill 我控制在 45 行核心结构是这样的--- name: gen-test-skeleton description: 为指定函数或类生成单元测试骨架只生成结构不填充具体断言 --- 你是一个测试骨架生成器。给定一段代码输出对应的测试文件骨架。 规则 1. 先识别语言和测试框架。优先读取项目 AGENTS.md 中的测试规范。 2. 如果 AGENTS.md 未指定Python 默认 pytestJavaScript 默认 vitestGo 默认标准 testing 包。 3. 只生成测试函数签名和空的断言占位符不要猜测具体断言内容。 4. 每个被测函数至少生成一个正常路径测试和一个边界测试占位。 5. 输出格式完整测试文件包含必要的 import。 不要做这些事 - 不要生成 mock 数据 - 不要写具体断言值 - 不要修改被测代码这 45 行里没有一行是项目特定的。项目用 pytest 还是 unittest由AGENTS.md决定。这样这个 Skill 可以在任何 Python 项目里复用。3.3 拆解后的目录结构拆完后我的 Skill 目录变成了这样~/.claude/skills/ ├── gen-comment/ │ └── SKILL.md ├── check-naming/ │ └── SKILL.md ├── gen-test-skeleton/ │ └── SKILL.md ├── check-unused-imports/ │ └── SKILL.md ├── suggest-refactor/ │ └── SKILL.md ├── gen-commit-msg/ │ └── SKILL.md └── _archive/ └── code-helper-20250115.bak每个SKILL.md都在 30 到 60 行之间。总行数从 600 降到了 280 左右但功能覆盖完全一样而且每个 Skill 都能独立触发、独立测试、独立更新。更重要的是模型在选择 Skill 时更准了。以前调用code-helper时模型经常搞不清我到底要注释还是要测试。现在我说“给这个函数生成测试骨架”模型直接命中gen-test-skeleton不会误触发其他五个。3.4 组合调用用 orchestrator 串起流程拆完之后如果我还是想要“一键完成代码审查 测试生成 commit message”的体验怎么办答案是写一个轻量 orchestrator。--- name: full-code-review description: 依次调用 check-naming、check-unused-imports、suggest-refactor、gen-test-skeleton最后生成 commit message --- 按以下顺序执行每一步完成后把结果汇总 1. 调用 check-naming检查当前文件的命名规范。 2. 调用 check-unused-imports列出未使用的 import。 3. 调用 suggest-refactor给出重构建议。 4. 调用 gen-test-skeleton为新增或修改的函数生成测试骨架。 5. 调用 gen-commit-msg根据以上所有变更生成 commit message。 如果任何一步失败记录失败原因并继续下一步最后统一汇报。这个 orchestrator 只有 20 行但它把六个独立 Skill 串成了一个完整流程。而且因为每个子 Skill 都是独立的我可以随时替换其中一个比如把gen-test-skeleton换成gen-test-with-mocksorchestrator 只需要改一行。4. 减肥后的效果与常见坑4.1 实测数据响应时间、token 消耗、准确率我拿同一个任务在减肥前后各跑了 20 次任务内容是“审查一个 80 行的 Python 文件生成测试骨架和 commit message”。结果如下指标减肥前600 行单 Skill减肥后6 个 50 行 Skill orchestrator平均响应时间8.4 秒5.1 秒平均 token 消耗42002600任务完成准确率72%91%误触发其他功能次数6 次0 次准确率的提升最明显。减肥前模型经常在“生成测试骨架”时顺便改了代码或者在“检查命名”时生成了 commit message。减肥后每个 Skill 职责单一模型不会越界。4.2 常见坑一拆得太碎触发困难减肥不是越碎越好。我一开始把gen-comment又拆成了gen-python-docstring、gen-jsdoc、gen-go-comment三个 Skill结果模型在选择时经常犹豫因为“给这个函数加注释”这句话没有指定语言模型得先判断语言再选 Skill反而慢了。后来我合并回一个gen-comment在里面用“先识别语言再按对应风格生成”一条规则解决。所以拆分的粒度标准是如果一个 Skill 的触发条件需要模型做额外判断才能确定那它可能拆得太细了。4.3 常见坑二orchestrator 里写死顺序另一个坑是 orchestrator 里把步骤顺序写得太死。比如“必须先检查命名再检查 import”但实际上这两个步骤没有依赖关系完全可以并行。写死顺序会导致不必要的等待。我的做法是orchestrator 里只写“必须在前”的依赖比如“生成测试骨架必须在检查命名之后因为测试函数名要遵循命名规范”。没有依赖的步骤让模型自己决定顺序或者标记为“可并行”。4.4 常见坑三忘了更新 AGENTS.md拆出通用 Skill 后项目特定信息都移到了AGENTS.md。但很多人拆完 Skill 就忘了更新AGENTS.md导致模型调用 Skill 时找不到项目规范只能瞎猜。我的检查清单是每拆一个 Skill就问自己“这个 Skill 依赖哪些项目特定信息”然后确保这些信息在AGENTS.md或context.md里有明确记录。比如gen-test-skeleton依赖“测试框架”和“测试文件命名规范”这两条必须写在AGENTS.md里。4.5 常见坑四Skill 之间命名冲突拆出多个 Skill 后命名要避免歧义。我见过有人同时有check-code、code-check、code-review三个 Skill功能还有重叠模型根本分不清该用哪个。命名原则是动词开头名词结尾中间用连字符。比如gen-comment、check-naming、suggest-refactor。避免用helper、util、manager这种模糊词。如果一个 Skill 你没法用“动词-名词”格式命名说明它的职责还不够清晰。4.6 常见坑五忽略 Skill 的版本管理拆成多个 Skill 后版本管理变得更复杂。我的做法是每个 Skill 目录下放一个CHANGELOG.md记录每次修改的原因和影响范围。同时用 git 管理整个~/.claude/skills/目录每次修改前先 commit改完再 commit这样出问题能快速回滚。另外orchestrator Skill 要记录它依赖的子 Skill 版本。比如full-code-review的 CHANGELOG 里写“依赖 gen-test-skeleton v1.2”这样如果子 Skill 有破坏性更新你能快速定位影响范围。5. 进阶让 Skill 自己“减肥”5.1 用 plugin eval 做 Skill 质量评估Claude Code 和 Codex 都提供了 plugin eval 机制可以自动化评估 Skill 的质量。我写了一个简单的 eval 脚本对每个 Skill 跑三个指标触发准确率给 20 个不同表述的触发语句看模型是否命中正确的 Skill。输出合规率检查输出是否符合 Skill 里定义的格式和规则。平均 token 消耗统计每次调用的 token 数超过阈值就告警。这三个指标能帮你发现“隐性肥胖”。比如某个 Skill 触发准确率只有 60%说明它的 description 写得太模糊或者职责边界不清。token 消耗突然上升说明最近加的规则可能太啰嗦。5.2 用 AGENTS.md 做上下文分层AGENTS.md和 Skill 的关系我习惯用三层结构来管理全局层~/.claude/AGENTS.md放所有项目通用的规范比如“代码注释用英文”、“commit message 用祈使句”。项目层项目根目录的AGENTS.md放项目特定规范比如“API 基地址”、“数据库命名规则”。模块层子目录里的context.md放模块特定信息比如“这个模块用 pytest那个模块用 unittest”。Skill 在调用时会按“全局 → 项目 → 模块”的顺序读取上下文。这样 Skill 本身可以保持极简所有环境相关的信息都在外部管理。5.3 定期“断舍离”每月清理一次 Skill我给自己定了一个规矩每月第一个周末花 30 分钟清理 Skill 目录。清理标准是过去 30 天没调用过的 Skill移到_archive/。调用过但触发准确率低于 70% 的 Skill重写 description。超过 100 行的 Skill强制拆分。功能重叠的 Skill合并或删除。这个习惯帮我避免了 Skill 目录无限膨胀。现在我的活跃 Skill 稳定在 15 个左右每个都在 60 行以内总行数不到 900 行但覆盖了我日常 95% 的需求。5.4 一个反直觉的经验少即是多最后分享一个我踩了很多坑才明白的道理Skill 的价值不在于它能做多少事而在于它能在正确的时候做正确的事。一个 30 行的 Skill如果每次都能准确触发、稳定输出它的价值远大于一个 300 行的“万能 Skill”。因为前者你可以放心地交给模型自动调用后者你每次都得盯着生怕它跑偏。给 Skill 减肥本质上是在降低系统的熵。每拆掉一个不必要的分支每移除一条模糊的规则模型的不确定性就少一分。这个过程没有终点但每做一次你都会发现 AI 助手变得更可靠了一点。我现在的习惯是每次想给 Skill 加功能时先问自己“能不能用组合实现”如果能就写一个新的小 Skill而不是往现有的里面塞。这个习惯让我的 Skill 目录在过去半年里只增加了 3 个文件但功能覆盖翻了一倍。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。