从单个 Skill 到技能组:协同开发需要考虑哪些问题
多个 Skill 协同,重点已经不再是单个 SKILL.md 怎么写,而是研究:
多个职责独立的 Skill,如何像一组服务或函数一样,被正确调度、传递数据、处理失败并最终完成任务。

可以把整个技能组理解成一个工作流系统:
| 技能组设计 | 开发中的对应概念 |
|---|---|
| Skill | 函数、服务或任务节点 |
| 调度 Skill | Workflow Engine / Orchestrator |
| description | 路由条件和能力注册 |
| references | 依赖配置和领域规则 |
| 共享文件 | 持久化状态和数据协议 |
| Skill 交接 | 函数调用或消息传递 |
| QA Skill | 测试和质量门禁 |
| 发布 Skill | 最终副作用和交付 |
一、技能职责设计
1. 每个 Skill 只负责一个阶段
多个 Skill 能协同的前提,是每个 Skill 的职责足够清楚。
例如一个完整任务可以拆成:
1需求确认
2→ 任务规划
3→ 内容生成
4→ 质量检查
5→ 产物发布每个阶段由一个独立 Skill 负责。
最常见的问题是职责重叠:
1规划 Skill 顺手生成内容
2生成 Skill 又重新调整规划
3检查 Skill 检查时直接改变目标
4发布 Skill 发布前重新加工内容一旦每个 Skill 都能修改所有内容,整个技能组就无法预测。
需要为每个 Skill 定义:
- 它读取什么;
- 它负责什么;
- 它修改什么;
- 它不负责什么;
- 什么条件下算完成;
- 完成后交给谁。
可以统一成一个职责声明:
1输入:
2处理:
3输出:
4允许修改:
5禁止修改:
6完成条件:
7下游 Skill:二、调度设计
1. 谁负责决定下一个 Skill
多个 Skill 不能只依赖“执行完以后随便调用另一个 Skill”。
需要有一个明确的调度角色。
调度方式主要有三种。
固定流水线
1Skill A
2→ Skill B
3→ Skill C
4→ Skill D适合步骤固定、分支较少的任务。
优点是简单、稳定,缺点是灵活性有限。
条件路由
1Skill A
2 ├── 条件满足 → Skill B
3 ├── 信息不足 → Skill C
4 └── 检查失败 → 返回 Skill A适合存在审核、重试和人工确认的任务。
中央调度
1 ┌→ Skill A
2用户请求 → 调度 Skill ─→ Skill B
3 └→ Skill C调度 Skill 负责:
- 判断当前任务状态;
- 选择需要调用的 Skill;
- 检查调用前置条件;
- 决定是否继续;
- 处理失败和回退;
- 判断整个任务是否完成。
技能数量较多、分支复杂时,应使用中央调度,避免 Skill 之间相互随意调用。
2. 调度 Skill 不做具体业务
调度 Skill 只负责:
1判断
2选择
3交接
4记录不应该同时负责生成内容、修改文件或发布结果。
否则它会迅速变成一个包含所有逻辑的超级 Skill。
三、上下游数据协议
1. Skill 之间不能只传自然语言
如果上一个 Skill 只说:
已经规划好了,接下来可以开始执行。
下一个 Skill 仍然不知道:
- 规划结果在哪里;
- 当前任务是什么;
- 哪些内容已经确认;
- 哪些内容不能修改;
- 当前处于什么状态。
多个 Skill 协同时,需要一份明确的数据协议。
例如:
1taskId: task-001
2status: planned
3currentStage: planning
4nextStage: generating
5
6input:
7 source: source.md
8
9result:
10 planFile: plan.md
11
12constraints:
13 confirmed: true
14 allowReplan: false上游 Skill 写入结果,下游 Skill 按字段读取,而不是重新理解全部历史对话。
2. 区分业务数据和执行状态
共享数据中至少包含两部分:
1业务数据
2执行状态业务数据是任务本身的内容:
1主题
2规划
3正文
4图片
5发布地址执行状态描述流程运行到哪里:
1当前阶段
2完成时间
3执行结果
4失败原因
5重试次数
6下一个节点两者不要混在一起。
四、状态机设计
多个 Skill 配合时,不能只通过“文件是否存在”判断任务进度。
需要定义明确的状态:
1pending
2→ planning
3→ planned
4→ generating
5→ generated
6→ reviewing
7→ approved
8→ publishing
9→ published失败状态可以单独定义:
1review_failed
2publish_failed
3blocked
4cancelled每个 Skill 只允许执行合法的状态转换:
1规划 Skill:
2pending → planning → planned
3
4生成 Skill:
5planned → generating → generated
6
7检查 Skill:
8generated → reviewing → approved
9generated → reviewing → review_failed
10
11发布 Skill:
12approved → publishing → published这样可以防止:
- 规划未确认就开始生成;
- 检查未通过就直接发布;
- 已发布内容被重复发布;
- 失败任务被误认为完成。
五、交接设计
1. Skill 完成后必须留下交接记录
一个 Skill 执行完成,不能只回复一句“已经完成”。
至少要记录:
1完成了什么
2生成了哪些产物
3修改了哪些文件
4当前状态是什么
5下一个 Skill 是什么
6下一个 Skill 需要读取什么
7是否存在待确认项可以统一交接格式:
1handoff:
2 from: planning
3 to: generating
4 status: ready
5
6artifacts:
7 - plan.md
8
9confirmed:
10 - scope
11 - structure
12
13pending: []
14
15constraints:
16 allowPlanChange: false2. 下游 Skill 先验证交接条件
下游 Skill 启动后,不应该立即执行。
它需要先检查:
- 上游状态是否完成;
- 必要文件是否存在;
- 数据结构是否正确;
- 是否还有待确认项;
- 当前 Skill 是否有权修改这些产物。
这和函数调用前的参数校验类似。
六、共享产物设计
1. 明确唯一事实来源
同一个数据不能同时存在多个未经同步的版本。
例如规划信息同时存在于:
1聊天记录
2plan.md
3task.json
4文章 Frontmatter后续 Skill 不知道应该相信哪一份。
必须规定唯一事实来源:
1聊天记录:用于交互
2状态文件:用于调度
3业务文件:用于最终内容
4交接记录:用于阶段传递下游 Skill 只读取指定来源。
2. 区分中间产物和最终产物
1中间产物:
2分析结果
3任务规划
4检查报告
5临时提示词
6
7最终产物:
8正式文章
9生成图片
10发布页面
11发布地址中间产物可以被后续 Skill 更新,最终产物默认不应被随意覆盖。
七、质量门禁设计
多个 Skill 协同不能只有生产节点,还需要检查节点。
1生成 Skill
2→ QA Skill
3 ├── 通过 → 进入发布
4 └── 失败 → 返回生成 SkillQA Skill 应该输出结构化结果:
1result: failed
2
3checks:
4 structure: passed
5 content: failed
6 format: passed
7
8issues:
9 - location: section-2
10 reason: 缺少具体实现
11 action: 补充输入、处理和输出
12
13retryFrom: generatingQA 不应该只给一个笼统评价,也不应该在没有记录的情况下直接大幅修改产物。
八、失败、重试和回退设计
多个 Skill 一定会出现部分成功:
1规划成功
2内容生成成功
3检查成功
4发布失败这时不能从头重新执行。
每个 Skill 都要定义:
- 失败后是否可以重试;
- 最大重试次数;
- 从哪个状态恢复;
- 已有产物是否可以复用;
- 是否需要回退上游;
- 什么情况下交给用户处理。
例如:
1工具调用超时
2→ 当前 Skill 重试
3
4输入数据缺失
5→ 返回上游补充
6
7质量检查失败
8→ 返回生成 Skill 局部修改
9
10发布权限不足
11→ 暂停任务,等待用户处理
12
13状态文件损坏
14→ 停止执行,不猜测状态九、幂等性设计
同一个 Skill 可能因为重试、重复触发或人工操作执行多次。
因此需要提前定义:
1重复执行是跳过、覆盖、更新,还是创建新版本?常见处理方式:
- 根据
taskId判断是否已经执行; - 根据内容哈希判断产物是否变化;
- 已完成状态默认跳过;
- 修改文件前读取当前版本;
- 发布前检查远程是否已经存在;
- 外部操作记录唯一请求 ID。
尤其是发布、上传、创建 Issue、发送消息等带副作用的操作,必须考虑幂等性。
十、权限和副作用设计
不同 Skill 应该拥有不同的操作权限。
例如:
| Skill 类型 | 允许操作 |
|---|---|
| 分析 Skill | 只读 |
| 规划 Skill | 修改规划文件 |
| 生成 Skill | 创建业务产物 |
| 检查 Skill | 读取产物、生成检查报告 |
| 发布 Skill | 修改外部系统 |
| 调度 Skill | 更新状态和交接记录 |
不要让所有 Skill 都能:
- 修改全部文件;
- 覆盖最终产物;
- 发布外部内容;
- 删除历史记录。
副作用越大的 Skill,前置条件应该越严格。
十一、可观测性设计
技能组运行后,要能够回答:
- 当前运行到哪一步;
- 哪个 Skill 正在执行;
- 上一步生成了什么;
- 为什么选择当前分支;
- 哪个检查没有通过;
- 失败发生在哪里;
- 是否执行过重试;
- 最终修改了哪些外部数据。
建议为每次任务保存执行记录:
1taskId: task-001
2status: reviewing
3currentSkill: quality-check
4startedAt: 2026-07-24T10:00:00Z
5updatedAt: 2026-07-24T10:05:00Z
6
7history:
8 - skill: planning
9 status: success
10 output: plan.md
11
12 - skill: generating
13 status: success
14 output: article.md
15
16 - skill: quality-check
17 status: running这相当于工作流系统的运行日志。
十二、版本兼容设计
多个 Skill 独立演进后,会出现协议不兼容:
1上游输出 schema v2
2下游仍按 schema v1 读取共享数据应该增加版本:
1schemaVersion: 1Skill 也可以声明:
1accepts:
2 - schemaVersion: 1
3
4produces:
5 schemaVersion: 1当结构升级时,需要明确:
- 是否兼容旧版本;
- 是否提供迁移;
- 不兼容时是否停止执行;
- 哪些 Skill 必须同时升级。