把工作流拆成可组合 Skill:PR 自动化的 6 级流水线

Claude 中文知识站 Lv4

前情提要:我接了个任务,给公司 PR 流程做 Claude Code 自动化。

最开始我写了个叫 pr-helper 的 Skill,正文 2,817 字,把所有事儿都放里面——分析 diff、评估风险、写描述、建议测试、生成 changelog、推荐审阅人。一条龙。

跑起来就出事。

为什么单个大 Skill 干不动复杂工作流

三个问题,越用越明显。

第一个,context 膨胀。这个 Skill 触发一次,整个 2.8K 的正文就塞进 context。但实际上每次 PR 需要的能力可能只是其中的一两部分——纯 bugfix 用不到 changelog 建议、纯文档改动用不到测试推荐。全塞进去纯浪费。

第二个,责任混乱。我调优「风险评估」那块想加一些规则,结果改着改着把「描述生成」的格式也改崩了。一个 Skill 干太多事,牵一发动全身。

第三个,失败难排查。一次 PR 自动化挂了,用户反馈「描述写得莫名其妙」。我打开 session log 一看——完蛋,所有步骤都在一个 Skill 里混着执行,根本分不清是哪一步出的问题。

所以我拆了。

6 级流水线是什么样

拆成 6 个独立 Skill,各司其职:

  1. pr-diff-analyze —— 读 diff,抽出「改了什么文件、新增/删除行数、涉及模块、是否修改了依赖」,输出结构化 JSON。
  2. pr-risk-score —— 基于上一步的结构化结果打风险分(0-100),考虑因素包括核心模块、测试覆盖、依赖变更等。
  3. pr-description-gen —— 根据 diff 和风险分生成 PR 描述,包括 Summary、Changes、Testing、Breaking changes 四段。
  4. pr-test-suggest —— 基于 diff 建议要跑哪些测试套件、要不要手动 QA。
  5. pr-changelog-snippet —— 生成一行 changelog 条目(遵循 conventional commits 风格)。
  6. pr-reviewer-recommend —— 根据改动文件的 git blame 历史,推荐 1-3 个合适的审阅者。

每个 Skill 的正文都压到 200-400 字,frontmatter 里清楚写明输入输出格式。

总 token 对比:大 Skill 2,817 → 6 个小 Skill 按需加载平均 600-1,100。而且每个 Skill 可以独立调优、独立测试、独立 rollback

用 slash command 当调度层

六个 Skill 要串起来,得有个编排。我用 slash command 做入口:

1
/pr-autopilot $BRANCH

这个 slash command 的 prompt 模板大致是:

1
2
3
4
5
6
7
8
9
10
11
执行以下流水线,分析分支 $ARGUMENTS 的 PR 改动:

步骤 1:用 pr-diff-analyze 提取 diff 摘要
步骤 2:用 pr-risk-score 对摘要评分
步骤 3:如果 risk >= 60,用 pr-description-gen 生成包含详细 impact 的描述
如果 risk < 60,生成简化描述
步骤 4:用 pr-test-suggest 建议测试
步骤 5:用 pr-changelog-snippet 生成一行 changelog
步骤 6:用 pr-reviewer-recommend 推荐审阅人

每步输出请保留,最后汇总成一个 PR template。

注意第三步那个条件分支——大 Skill 做不到这种清爽的逻辑分流。拆开之后,条件分支是顺手的事。

状态传递这块,我用的是 conversation context 自然流转。前一个 Skill 的 JSON 输出在 context 里,后一个 Skill 从里面读就行。实测下来 agent 处理这种流转很稳,不需要外挂存储。

关于 slash command 的调度写法我之前有篇专门的 slash command 的 5 条设计原则 可以参考。

实测数字

我在 3 个团队跑了 11 周,每周统计:

  • 人工写 PR 描述平均耗时:14 分 8 秒(对 73 个 PR 采样)
  • 拆前大 Skill 自动化:6 分 22 秒(成功率 71.4%,失败就回退人工)
  • 拆后 6 级流水线:3 分 10 秒(成功率 89.7%)

时间省了大半。成功率提升的原因我分析是——每级都专职一件事,出错率低;就算某级挂了,其他级不受影响,部分产出也能用。

更隐蔽的好处是 API 成本:拆前平均每 PR 花 $0.0412(因为一次性把 2.8K 正文读进去,还要全走一遍逻辑),拆后 $0.0193(按需加载 + 每级 context 都小)。53% 的降幅。

这跟 context window 预算策略 里讲的原则是一致的:按需加载永远比一次性加载省

失败恢复:中间哪级挂了怎么续跑

拆成流水线的另一个好处,就是失败时能精确定位重试。

我给每个 Skill 的输出都加了一个标准化的 status 字段:

1
2
3
4
5
{
"status": "ok",
"step": "pr-risk-score",
"output": { ... }
}

或者失败时:

1
2
3
4
5
6
{
"status": "failed",
"step": "pr-test-suggest",
"reason": "无法识别测试框架",
"partial_output": { ... }
}

调度层发现某级 failed,就有几种处理策略:

  • 跳过:这级不是关键路径(比如 reviewer 推荐挂了,继续把描述生成完)。
  • 重试:这级可能是偶发问题,retry 一次。
  • 降级:用一个更简单的 fallback 逻辑代替。
  • 中断:关键路径挂了,整条停下来让人工介入。

我给 pr-description-gen 配的是「重试 1 次后降级到简化模板」——因为这是最关键的一级,不能完全挂;但又不能无限重试浪费钱。

有一次线上 pr-risk-score 连续挂了 4 次,我一查发现是某类特殊 PR(只改了 LICENSE 文件)让它的判定规则懵圈。查出来之后修 Skill 正文,只改一个文件,其他 5 个 Skill 纹丝不动。这就是拆分带来的可维护性

拆分原则:什么时候该拆

不是所有 Skill 都该拆。我的经验法则:

信号一:这个 Skill 正文超过 1,500 字。多半意味着它在干多件事。
信号二:用户反馈里出现「它有时候这块做得好有时候那块做得差」。典型的职责混合征兆。
信号三:你改一个小地方要反复看整份 Skill 才能确定不会影响别处。耦合过高。
信号四:不同路径的输入只需要 Skill 的一部分能力。按需加载的收益明显。

反过来,如果一个 Skill 本来就 300 字、专职一件事、逻辑顺序固定,就别折腾拆了。

拆分的隐性成本

说点公平的——拆成流水线不是白拿收益。

调度复杂度上去了。原来一个 Skill 能搞定的,现在要写 slash command 编排逻辑。新人接手需要先理解整条链路。

调试多了一层。debug 时不仅要看某个 Skill 出了什么问题,还要看调度层有没有把状态正确传下去。

版本兼容要注意。如果 Skill A 的输出格式变了,Skill B 要跟着更。我后来给每个 Skill 加了个 output_schema 版本字段,就是为了这个。

所以这是个 trade-off。小工作流(2-3 步以内)没必要拆,一个 Skill 搞定就行。真正复杂的工作流(5 步以上、有条件分支、跨领域)拆分的收益才会显现。

一个顺便的发现

拆成小 Skill 之后,我发现很多 Skill 可以跨工作流复用。

比如 pr-diff-analyze 不只 PR 自动化用,code review 的 slash command 也能用;pr-reviewer-recommend 能被「指派 bug 修复人」的 slash command 调用。

这就像搭乐高——小积木比大积木通用性强得多。拆到最后,我手头攒了 40 多个「原子 Skill」,组合起来能搭出十几个工作流。

小结

「可组合」这个词说烂了,但真放到 Skill 设计上,确实是个好思路。单个 Skill 小而专,组合起来解决复杂问题,比写一个巨型 Skill 健康得多。

下次你写到第三段 ## 如果...那么... 的时候,停一下,想想是不是该拆了。

延伸
Skill 拆完之后随之而来的问题是:这么多 Skill 怎么测、怎么保证改一个不挂另一个?我给生产环境的 23 个 Skill 搭了 CI,跑回归测试。这篇讲具体做法:Skill 也需要 CI:我给 23 个 Skill 写了回归测试
  • 标题: 把工作流拆成可组合 Skill:PR 自动化的 6 级流水线
  • 作者: Claude 中文知识站
  • 创建于 : 2026-04-18 14:52:00
  • 更新于 : 2026-04-19 09:21:00
  • 链接: https://claude.cocoloop.cn/posts/skill-workflow-chains/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论