星核协同体系 Skill 工程:原子型、工作流型与专属型架构设计
作者:司 & 蝉(执笔)已经过校对修改
日期:2026-04-21
适用平台:CSDN / 技术博客
前言
在多 Agent 协作系统中,"技能"(Skill)是最小的可复用单元。
但并不是所有 Skill 生来平等。在星核协同体系里,我把 Skill 分为三种:原子型 、工作流型 、专属型。
三种形态对应三种不同的持有策略和使用场景。这篇文章讲清楚:
- Skill 的三种分类------每种是什么、为什么这么分
- 枢的 Skill 管理机制------怎么管理skill
- 设计原则------三种 Skill 的共存规范
一、Skill 在体系中的位置
先镇楼:
用户 → 枢(路由层)
↓ sessions_send
司(规划层)
↓ 任务书
磐 / 匠 / 蝉(执行层)
↓ 调用 Skill
[原子型] ← 共享基础设施,所有 Agent 可调用
[工作流型] ← 目标 Agent 私有,组合原子型
[专属型] ← 目标 Agent 私有,自包含,不调用原子型
二、Skill 三种分类
2.1 分类总览
| 分类 | 存储位置 | 持有者 | 是否调用原子型 | 特性 |
|---|---|---|---|---|
| 原子型(共享) | skills/ |
公共使用,按skill使用权限划分 | 否(本身就是原子) | 单一能力,零决策,API Key 自持 |
| 工作流型(私有) | <agent>/skills/ |
目标 Agent 私有 | 是(组合原子型) | 组合多个原子型skill并完成特定复杂任务的工作流 |
| 专属型(私有) | <agent>/skills/ |
目标 Agent 私有 | 否(完全自包含) | 独立实现,不依赖原子型,完全自包含 |
2.2 原子型(共享)
定义:最小的能力单元,只做一件事,职责单一,不包含对其他 Skill 的调用。
存储位置 :skills/(全局共享目录)
持有者:无,但通常由匠负责开发和维护,所有 Agent 均可调用,但依赖skill权限配置(openclaw中给谁配置了谁就可以用)
特征:
| 特征 | 说明 |
|---|---|
| 零决策 | 调用方告诉它做什么,它就做什么 |
| 无状态 | 每次调用独立,不依赖上一次执行结果 |
| API Key 自持 | 每个原子型 Skill 持有自己的 Key,不泄露给调用方 |
| 全局复用 | 可被多个工作流型 Skill 并行调用 |
典型例子:
| Skill | 能力 |
|---|---|
pexels-collector |
从 Pexels 采集视频/图片素材 |
video-link-parser |
解析 B站/抖音/TikTok 视频链接 |
wechat-draft-publisher |
将 HTML 文章发布到微信公众号草稿箱 |
minimax-multimodal-toolkit |
生成图片/音频/视频(MiniMax API 封装) |
pexels-collector 代码示例:
javascript
// skills/pexels-collector/scripts/cli.js(精简版)
const { PexelsClient } = require('./pexels.js')
async function searchVideo(keyword, options = {}) {
const client = new PexelsClient(process.env.PEXELS_API_KEY)
const results = await client.searchVideos({
query: keyword,
per_page: options.count || 10,
orientation: options.orientation || 'vertical',
size: options.size || 'medium'
})
for (const video of results.videos) {
await download(video.video_files[0].link, `${options.output}/${video.id}.mp4`)
}
return { count: results.total_results, files: [...] }
}
module.exports = { searchVideo }
调用方只需要:
bash
node skills/pexels-collector/scripts/cli.js search-video "夏季防晒" \
-n 5 -o ./materials/ --orientation vertical
调用方不需要知道 Pexels API 怎么调,不需要知道视频怎么下载,只知道"给我 5 个防晒相关的竖屏视频素材"。
2.3 工作流型(私有)
定义:将多个原子型 Skill 组合,执行层只需触发一次。
存储位置 :<agent>/skills/(目标 Agent 的私有目录)
持有者 :目标执行层 Agent(如蝉持有 video-production-workflow)
是否调用原子型:是(组合多个原子型)
特征:
| 特征 | 说明 |
|---|---|
| 组合原子型 | 调用多个原子型 Skill 完成复杂任务 |
| 自带执行路径 | 定义了"先做什么、再做什么" |
| 不持有 API Key | 只负责把正确的参数传给原子型 Skill |
| Agent 私有 | 其他 Agent 不能直接调用(除非明确授权,openclaw中操作其他agnet的工作区需要授权) |
典型例子:
| Skill | 持有者 | 组合的原子型 |
|---|---|---|
video-production-workflow |
蝉 | pexels-collector + minimax-multimodal-toolkit + FFmpeg |
aigc_daily_report |
蝉 | aigc-news-collector + minimax-multimodal-toolkit + wechat-draft-publisher |
doc-to-wechat |
蝉 | minimax-multimodal-toolkit(封面图)、wechat-draft-publisher |
video-production-workflow 工作流示例:
yaml
# 工作流定义(SKILL.md 中描述)
name: video-production-workflow
description: >
视频制作工作流 Skill --- 组合 pexels-collector + LLM 文案 + MiniMax TTS + FFmpeg,
实现特定赛道短视频的批量快速生产。
当用户提到视频批量制作、短视频工作流、口播视频生成时触发。
javascript
// 工作流执行逻辑(精简版)
async function produceVideo(topic, options = {}) {
const outputDir = `outputs/${Date.now()}`
mkdirp(outputDir)
// Step1: 素材采集(调用原子型 Skill)
await exec(`node skills/pexels-collector/scripts/cli.js search-video "${topic}" \
-n ${options.count || 10} -o ${outputDir}/materials/ \
--orientation ${options.aspect || 'vertical'}`)
// Step2: 文案生成(调用 LLM API)
const script = await generateScript(topic, options)
writeFile(`${outputDir}/scripts/script.json`, JSON.stringify(script))
// Step3: TTS 配音(调用原子型 Skill)
for (const [i, seg] of script.segments.entries()) {
await exec(`bash skills/minimax-multimodal-toolkit/scripts/tts/generate_voice.sh \
"${seg.text}" -o ${outputDir}/audio/seg_${i}.mp3 --voice-id ${options.voice}`)
}
await exec(`ffmpeg -y -i "concat:${audioFiles.join('|')}" \
-acodec copy ${outputDir}/audio/final.mp3`)
// Step4: 视频拼接(调用 FFmpeg)
await exec(`ffmpeg -y -f concat -safe 0 -i ${outputDir}/filelist.txt \
-i ${outputDir}/audio/final.mp3 \
-vf "scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2" \
-c:v libx264 -preset fast -crf 23 -c:a aac -shortest \
${outputDir}/outputs/final.mp4`)
return `${outputDir}/outputs/final.mp4`
}
执行层只需要:
bash
# 一行命令,触发整个工作流
python -c "
from workflow import produceVideo
print(produceVideo('夏季防晒', {'count': 3, 'aspect': '9:16'}))
"
2.4 专属型(私有)
定义:完全自包含的 Skill,不调用任何原子型 Skill,内部独立实现所有逻辑。
存储位置 :<agent>/skills/(目标 Agent 的私有目录)
持有者:目标执行层 Agent
是否调用原子型:否(完全自包含)
特征:
| 特征 | 说明 |
|---|---|
| 完全自包含 | 所有逻辑内聚在 Skill 内部,不依赖其他 Skill |
| 不调用原子型 | 不调用 skills/ 下的任何共享原子型 |
| Agent 私有 | 专属该 Agent,其他 Agent 不可直接调用 |
| 不可复用 | 逻辑与持有者强绑定,换个 Agent 无法直接用 |
为什么需要专属型?
有些场景下,工作流型 Skill 需要调用的原子型根本不存在------或者调用外部 API 的方式太特殊,不适合做成共享的原子型。
比如:
-
skill-orchestrator :枢专属 skill,管理星核全局 skill 资产,可以扫描、审计、分配、移除各agent的skill
-
task-book :司专属,生成结构化任务书,流程如下:
枢转发需求 → 司 need-analyzer → task-book 生成任务书 ↓ sessions_send 回枢确认 → 司按 DAG(flow节点图) 执行 ↓ 守护层 pass → 典执行 output_route → 司汇报枢 → 交付用户 -
tool-permission-matrix:枢专属 skill,tool的权限管理
-
等等
专属型 vs 工作流型的核心区别:
| 维度 | 工作流型 | 专属型 |
|---|---|---|
| 调用原子型 | ✅ 是 | ❌ 否 |
| 逻辑自包含程度 | 依赖原子型组合 | 完全自包含 |
| 持有位置 | <agent>/skills/ |
<agent>/skills/ |
| 换 Agent 能否直接用 | 部分可(只要原子型存在) | 不可(逻辑强绑定) |
| 适用场景 | 流程可复用、原子型已存在 | 逻辑定制化、无合适原子型 |
三、枢的 Skill 管理机制
Orchestrator Skill 是枢专属的 Skill 管理中枢,基于三个核心脚本实现全链路操作:扫描(scan)、读取(read_config)、变更(patch),以下是流程:
scan → read_config → LLM audit → 枢 review → patch
-
scan:遍历所有存放skill的目录(共享目录+agent工作区下的skills目录),按共享型与 Agent 专属型分类)
-
read_config:读取目前所有agent已经配置的skill
-
audit:审计交叉验证------检查 config 引用与磁盘实际存在是否一致、Skill 与 Agent 职责是否匹配、是否存在孤立 Skill(磁盘有但无任何 Agent 引用)
-
patch:按照审计结果为agent分配或移除skill
通过该专属skill 枢可以更便捷地完成skill管理工作。
四、调用规范与数据流向
4.1 三种 Skill 的协作关系
用户请求
↓
枢(路由判断)
↓ sessions_send
执行层 Agent(持有工作流型/专属型)
↓ 调用
原子型 Skill(共享)← 被工作流型调用
↓ 返回
执行层 Agent
↓
工作流型 Skill(汇总结果)
↓
交付
专属型 Skill 不在这个链条里,它独立运作,不调用任何原子型。
4.2 输出路径规范(由司的任务书定义)
所有 Skill 产出必须写入 outputs/tasks/<task_id>/<agent>/skill-work/ 目录:
outputs/
└── tasks/
└── si-task-2026-0421-002/
└── chan/
└── skill-work/
├── script.json # 工作流产出
├── audio/ # 工作流产出
└── final.mp4 # 工作流产出
4.3 断点续传
原子型 Skill 之间通过文件系统传递数据,不通过内存:
javascript
// Step1 输出素材路径
const materials = await searchVideo(keyword, { output: './materials/' })
// materials = { files: ['./materials/1.mp4', './materials/2.mp4'] }
// Step2 读取素材路径,生成文案
const script = await generateScript(topic, { materials: materials.files })
// Step3 读取文案,生成音频
const audio = await generateVoice(script.segments, { output: './audio/' })
// Step4 读取音频路径,执行拼接
await ffmpeg拼接(materials.files, audio.files)
某个 Step 失败了,从上一个成功的 Step 继续就行------文件系统是最好的断点续传基础。
五、Skill 工程设计原则
| 原则 | 说明 |
|---|---|
| 单一职责 | 原子型 Skill 只做一件事,不多不少 |
| 零决策 | 原子型 Skill 不做业务决策,只执行传入的参数 |
| Key 自持 | 每个 Skill 持有自己的 API Key,不泄露给调用方 |
| 工作流不持 Key | 工作流型 Skill 只编排,不持有任何敏感信息 |
| 专属型独立 | 专属型 Skill 直接调 API,不依赖不存在的原子型 |
| 文件系统传递 | 跨 Step 数据通过文件,不通过内存 |
| 输出路径规范 | 统一写到 outputs/tasks/<task_id>/<agent>/skill-work/ |
| description 即路由 | Skill 的 description 是枢做路由匹配的唯一依据 |
| 可测试 | 每个原子型 Skill 可以独立测试,不依赖工作流 |
六、星核协作体系架构(V4)
变更:
- 新的agent成员加入
- 任务复杂由司处理,复杂程度体现再任务书
- 简化链路,统一输出
层级架构(四层)
入口层 --- 枢(唯一入口,所有需求必经)
规划层 --- 司(任务规划/拆解/派发)
执行层 --- 磐 / 匠 / 蝉 / 探 / 墨狐 / storycraft / 侦
守护层 --- 盾 / 验 / 典
12 个 Agent,各司其职,互不越权。
核心链路(统一版)
用户 → 枢 → 司(need-analyzer + task-book 生成任务书)
↓
枢转发任务书给用户确认
↓
司协调执行层(sessions_send)
↓
执行层产出 → skill-work/
↓
守护层:盾 → 验 → 典
↓
司按 output_route 路由(KB/Skill/Git/Publish/Archive)
↓
枢汇总 → 用户