工坊手册
三大工坊的使用与开发维度:创意工坊(recipe/flow)、技能工坊(skill workshop)、技能锻造(forge)、技能审批(proposals)、交换所工坊(broker)。 来源
OPERATION.md§19–§20、§37–§38、src/bridge/routes/skill_forge.py、skill_proposals.py、skill_workshop.py、agent_recipes.py、flow_templates.py。
目录
- 技能锻造 SkillForge
- SKILL.md 格式规范
- Skill 改动审批 SkillProposals
- 技能工坊 SkillWorkshop
- 创意工坊 CreativeWorkshop(Recipe)
- 创意工坊 CreativeWorkshop(Flow)
- Recipe 编译 / 干跑 / E2E 测试
1. 技能锻造 SkillForge
组件:SkillForgeModal.vue
入口:ChatStage 多选消息(Shift/Ctrl)→ 顶部批量操作条 → 锻造 Skill
1.1 后端 API(src/bridge/routes/skill_forge.py)
| 端点 | 阶段 | 说明 |
|---|---|---|
POST /derive_io | Phase 1 快速路径 | 一次 LLM rewrite → 解析 INPUTS/OUTPUTS/TRIGGER 行 → ~30-40s |
POST /propose | Phase 1 完整版 | rewrite + tool_select + denoise + params + mock + summary → ~12min |
POST /repropose | Phase 1 重提 | 用户锁定 I/O 后重新生成 summary |
POST /build_and_preview | Phase 2 | 完整链:denoise → tool_select → params → mock → summary → generate → validate → repair |
POST /preview | Phase 2 旧 | 生成 SKILL.md + 验证 |
POST /revise | 修订 | agent 模式工具循环(read/grep/edit/validate/finish) |
POST /commit | 提交 | 持久化 SKILL.md + 刷新 skill_registry.json |
GET /revise/inflight | 查询 | 正在修订中的 skill_id 列表 |
GET /revise/terminal/<skill_id> | 查询 | 消费已完成的修订结果 |
1.2 3 步向导流程
Step 1 — params(参数确认)
- 前端
POST /derive_io→ 后端一次 LLM rewrite(workspace/skills/prompts/forger_rewrite.md)→ 解析 intent 的INPUTS:/OUTPUTS:/TRIGGER:行 → 返回{intent, inputs, outputs, trigger, skill_id_seed} - 显示三个可编辑区域:
- 输入列表:每行
{name, type, description},可增删改 - 输出列表:同上
- 触发场景:文本输入
- 输入列表:每行
- 用户改动后出现浮动按钮:
- ✕ 撤回:恢复 LLM 原稿(baselineInputs/baselineOutputs/baselineTrigger)
- ✓ 应用:
POST /repropose→ 后端用锁定的 I/O 重新生成 summary
Step 2 — review(审阅)
POST /build_and_preview→ 后端跑完整链 → 返回{skill_md, errors, skill_id, summary}- 显示完整 SKILL.md 预览(markdown 渲染)
- 可编辑:
skill_id:snake_case,^[a-z][a-z0-9_]{0,63}$scope:global/agent/recipe(agent 绑定 recipe 时默认 recipe)overwrite:同名覆盖开关
- 若有
errors,红色列表展示:input_missing:锁定的输入名在 SKILL.md 中找不到output_missing:锁定的输出名在 SKILL.md 中找不到script_still_invalid:嵌入式脚本 I/O 合约不匹配pipeline_validator_crashed:管道验证器异常
- 可输入
user_guidance→POST /revise→ agent 模式修订
Step 3 — commit(提交)
- 点 提交 →
POST /commit→ 写入目标目录:global→workspace/skills/<skill_id>/SKILL.mdagent→workspace/agents/agent_<id>/skills/<skill_id>/SKILL.mdrecipe→workspace/agent_recipes/<recipe_id>/skills/<skill_id>/SKILL.md
- 刷新
skill_registry.json(rebuild_skill_registry) - 若 registry 未收录(description 为空导致 indexer 跳过),回退注入 placeholder entry
- 清除
dense_recall缓存
1.3 Phase 1 vs Phase 2 数据流
Phase 1 (derive_io):
用户选择消息 → POST /derive_io → 一次 LLM rewrite → 解析 I/O
用户确认/编辑 I/O → (可选) POST /repropose → LLM 重新 summary
Phase 2 (build_and_preview):
POST /build_and_preview →
Round 1: denoise (trace 去噪)
Round 2: tool_select + params (并行)
Round 3: mock (模拟输入)
Round 4: summary (摘要)
Round 5: generate (完整 SKILL.md)
→ validate (结构验证) + repair (修复一次)
→ I/O name presence check
→ per-script I/O validate + repair
→ pipeline gate
→ 返回 {skill_md, errors}2. SKILL.md 格式规范
2.1 基本结构
---
skill_id: my_skill
description: 一句话描述
version: 1.0
tags:
category: productivity
trigger_scenarios:
intent:
- 用户说"帮我生成报告"
condition:
- agent 有访问报表系统的权限
---
## Skill Inputs
```json
{
"type": "object",
"properties": {
"report_type": {"type": "string", "description": "报告类型"},
"date_range": {"type": "string", "description": "日期范围"}
},
"required": ["report_type"]
}Skill Outputs
{
"type": "object",
"properties": {
"report_content": {"type": "string"},
"file_path": {"type": "string"}
}
}Step 1: 收集数据
Input Schema (JSON):
{"properties": {"query": {"type": "string"}}, "required": ["query"]}指令: 用 search 工具搜索相关信息... Output Schema (JSON):
{"properties": {"results": {"type": "array"}}}Step 2: 生成报告
...
### 2.2 验证规则(`SkillForger.validate()`)
1. **拓扑验证**:Metadata → Skill Inputs → Skill Outputs → Steps → 顺序正确
2. **字段名精确匹配**:Step Input Schema 的属性名必须与 SKILL 级别 Inputs 或上游 Step Outputs 匹配(无 fallback)
3. **工具步 I/O 1:1 SET 匹配**:每个 tool 步的 Input Schema 必须是目标工具参数的子集;Output Schema 必须是工具返回值的子集
### 2.3 验证器端点POST /api/skills/forge/preview → {skill_md, errors} POST /api/skills/forge/commit → 先 validate,再 pipeline_gate,最后写入
**pipeline gate**(`_validate_skill_source`):检查完整数据流合约——每个 step input 必须能从前序 step output 或 skill input 解析到,每个 step output 必须被下游消费或作为 skill output 输出。
### 2.4 嵌入式脚本验证
SKILL.md 内的 ` ```python ` / ` ```bash ` 等代码块(≥300 字节)会被提取并验证 I/O 合约:
- 脚本必须从 `skill_inputs` 读取输入
- 脚本必须将结果写入 `skill_outputs`
- 验证失败 → 一次 LLM repair 尝试
- repair 后仍失败 → `script_still_invalid` error
### 2.5 修订模式(`POST /revise`)
用户给出 `user_guidance` → `SkillReviseAgent` 工具循环:
- `read_skill`:读取当前 SKILL.md
- `grep_skill`:搜索内容
- `edit_skill`:编辑 SKILL.md
- `validate_skill`:调用验证器
- `finish`:完成修订
最多 `MAX_TURNS` 轮。修订后执行 placeholder 展开 + 最终 gate。
---
## 3. Skill 改动审批 SkillProposals
**组件**:`SkillApprovalsView.vue`
**入口**:Desktop → **Skill 改动审批** 图标(`skill-approvals` app)
**后端**:`src/bridge/routes/skill_proposals.py`
### 3.1 API 端点
| 端点 | 说明 |
|---|---|
| `GET /api/skill_proposals` | 列出所有待审批提案(不含 body,只发元数据) |
| `GET /api/skill_proposals/count` | 待审批数量(用于 DialogList badge) |
| `GET /api/skill_proposals/<pid>` | 完整提案(含 current_body + proposed_body) |
| `POST /api/skill_proposals/<pid>/approve` | 批准 → 写入 `workspace/skills/` |
| `POST /api/skill_proposals/<pid>/reject` | 拒绝 → 归档到 `rejected/` |
### 3.2 审批队列存储
- 队列位置:`workspace/manager/skill_proposals/pending/`
- 每个提案一个 JSON 文件:`{proposal_id}.json`
- 字段:`proposal_id`, `target_agent_id`, `skill_id`, `target_path`, `created_at`, `trigger`, `current_body`, `proposed_body`, `run_id`, `report_path`
### 3.3 触发条件
agent 的 `skill_auto_apply=False`(默认值)→ agent 通过 `manager_review_tools.apply_agent_updates` 提出的 SKILL.md 修改进入审批队列。
### 3.4 界面交互
- 列表:每条显示来源 agent(`agentName(agentId)`)、`skill_id`、`created_at`
- 展开 diff:`current_body` vs `proposed_body` 并排对比
- **批准**:`approve_proposal(pid)` → 写入 SKILL.md
- **拒绝**:输入 reason → `reject_proposal(pid, reason)` → 移入 `rejected/`
- 自动刷新:6 秒轮询(`store.loadPendingSkillProposals()`)
---
## 4. 技能工坊 SkillWorkshop
**组件**:`SkillWorkshop.vue`(顶层)+ 子组件
**入口**:Desktop → **技能调用工坊** 图标(`skill-workshop` app)
**针对**:长流程 + 需要分步骤反馈的 manager-only skill
### 4.1 后端 API(`src/bridge/routes/skill_workshop.py`)
| 端点 | 说明 |
|---|---|
| `GET /api/skill_workshop/skills` | 列出有 `has_form_component` 的 manager skill |
| `POST /api/skill_workshop/upload` | multipart 上传参考图/视频/音频 |
| `GET /api/skill_workshop/asset?path=...` | 读取 session/run 目录下的文件 |
| `POST /api/skill_workshop/rewrite` | LLM 改写 storyboard(chunked,按 token 预算分桶) |
| `POST /api/skill_workshop/run` | 启动 runner(后台线程) |
| `GET /api/skill_workshop/run/<run_id>/status` | 轮询 status.json |
| `GET /api/skill_workshop/run/<run_id>/images` | 列出所有参与图片(角色参考 + 关键帧) |
| `POST /api/skill_workshop/run/<run_id>/regenerate_image` | 重新生成单张图片 |
| `POST /api/skill_workshop/run/<run_id>/approve_images` | 图片审核通过 → 进入 clip_review |
| `GET /api/skill_workshop/run/<run_id>/clips` | 列出每段 clip 状态 |
| `POST /api/skill_workshop/run/<run_id>/clips/<idx>/generate` | 生成单段 clip |
| `POST /api/skill_workshop/run/<run_id>/concat_final` | 拼接所有 clip → final.mp4 |
| `GET /api/skill_workshop/draft` | 读取续传草稿 |
| `POST /api/skill_workshop/draft` | 保存续传草稿 |
| `GET /api/skill_workshop/history/<skill_id>` | 历史 run 列表 |
| `GET /api/skill_workshop/history/<skill_id>/<run_id>` | 单次 run 详情 |
### 4.2 状态机(6+ 阶段)pick → compose → review → running → image_review → clip_review → done ↘ error ↕ history (从 pick 或 done 进入)
| 阶段 | 组件 | 说明 |
|---|---|---|
| `pick` | 主页面 | 已注册 manager skill 列表 + **历史记录**按钮 |
| `compose` | `GenerateVideoForm.vue` / `EditVideoForm.vue` | 输入表单:主题/时长/角色/场景/参考图 |
| `review` | `StoryboardReview.vue` | LLM 改写的分镜表 → 用户可编辑每一段的 prompt |
| `running` | 进度面板 | 轮询 status.json,显示 Phase A(图片生成)进度 |
| `image_review` | `ImageReview.vue` | 网格展示所有参与图片 → 逐张编辑 prompt / 重新生成 |
| `clip_review` | `ClipReview.vue` | 每段 clip 单独 **合成** 按钮 → 最终 **导出视频** |
| `done` | 视频播放器 | 展示 final.mp4 |
| `error` | 错误面板 | 显示错误信息 + **返回** 按钮 |
| `history` | 历史列表 | 历史 run 列表 + 详情 + **用作模板** 回填表单 |
### 4.3 generate_video 完整流程
1. **compose**:填写 `GenerateVideoForm.vue`
- 主题、时长(5-300 秒)、是否配音
- 角色列表:name + description + 参考图上传(≤4MB,PNG/JPEG/WebP)
- 物品/场景参考:name + kind(object/scene/character) + description + 参考图
- 场景列表:duration(3-15) + script(≥20字) + first_frame_prompt + last_frame_prompt
- 可选:上传关键帧图片 / 上传整段视频 clip
- 可选:宽高比(16:9 / 1:1 / 9:16)
- LocalStorage 自动保存草稿
2. **rewrite**:`POST /rewrite` → chunked LLM 改写
- 场景按 token 预算分桶(~2700 tokens/桶)
- 每桶独立 LLM 调用 → 只改写桶内场景
- 用户上传的关键帧/clip 标记 `__pass_through__: true` → LLM 原样照抄
- 返回 storyboard JSON + warnings
3. **review**:`StoryboardReview.vue` 展示 → 用户编辑 prompt → 点 **通过**
4. **run**:`POST /run` → `start_generate_video_run()` → 后台线程
- run_id:`vid_<ts>_<sha256(storyboard)[:10]>`
- 资产存于 `workspace/manager/skill_workshop_runs/<run_id>/`
- status.json 记录状态
5. **image_review**:`GET /run/<id>/images` → 网格展示 → 逐张编辑/重新生成
- `POST /regenerate_image` → `force_intense_mode()` bypass 审批 → 同步重新生成
- `POST /approve_images` → 状态推进到 `awaiting_clip_review`
6. **clip_review**:`GET /run/<id>/clips` → 每段独立 **合成** 按钮
- `POST /clips/<idx>/generate` → 同步生成单段 clip
- `POST /concat_final` → 拼接所有 clip → final.mp4
### 4.4 上传限制
| role | MIME | 最大字节 |
|---|---|---|
| character / first_frame / last_frame | PNG/JPEG/WebP | 4MB |
| clip / edit_asset_video | MP4/MOV/WebM/MKV | 100MB |
| edit_asset_audio | MP3/WAV/AAC/FLAC/OGG | 30MB |
| scene_ref | PNG/JPEG/WebP | 4MB |
角色/首帧/尾帧上传后自动 `strip_white_inplace`(去除边缘白色 → RGBA PNG)。
### 4.5 续传机制
- 前端 draft → `POST /draft` → 持久化到 `workspace/manager/skill_workshop_runs/resume_draft.json`
- app 重启 → `GET /draft` → 恢复 storyboard + run_id
- run_id 确定性:`sha256(canonical storyboard JSON)[:10]` → 相同 storyboard → 相同 run_id → 续传而非重启
---
## 5. 创意工坊 CreativeWorkshop(Recipe)
**组件**:`CreativeWorkshop.vue`
**入口**:Desktop → **创意工坊** 图标(`workshop` app → `WorkshopApp.vue` → `CreativeWorkshop.vue`)
**什么是 Recipe**:在 Familiars 链路的基础上进行模块替换/全量替换形成的自定义新 agent 架构。Recipe 是技能的自动化编排(LLM + 工具图)。
### 5.1 后端 API(`src/bridge/routes/agent_recipes.py`)
| 端点 | 说明 |
|---|---|
| `GET /api/recipes/catalog` | 工具目录(所有可用工具 schema) |
| `GET /api/recipes` | recipe 列表 |
| `POST /api/recipes` | 创建新 recipe |
| `GET /api/recipes/<id>` | 获取完整 recipe(manifest + sidecar files) |
| `PUT /api/recipes/<id>` | 保存 recipe(部分更新 sidecar) |
| `DELETE /api/recipes/<id>` | 删除 recipe |
| `POST /api/recipes/<id>/bind/<agent_id>` | 绑定到 agent |
| `POST /api/recipes/<id>/unbind/<agent_id>` | 从 agent 解绑 |
| `POST /api/recipes/<id>/duplicate` | 复制 recipe |
| `GET /api/recipes/<id>/export` | 下载 .recipe.zip |
| `POST /api/recipes/import` | 上传 .recipe.zip |
| `POST /api/recipes/import-folder` | 从文件夹导入 |
| `POST /api/recipes/<id>/compile` | 编译验证 |
| `POST /api/recipes/<id>/dryrun` | 干跑测试 |
| `POST /api/recipes/<id>/e2e-test` | E2E 端到端测试 |
| `GET /api/recipes/<id>/knowledge/<path>` | 读取知识库文件 |
| `GET /api/recipes/default` | 获取默认 recipe |
| `PUT /api/recipes/default` | 设置默认 recipe |
| `DELETE /api/recipes/default` | 清除默认 |
### 5.2 Recipe 数据结构
```json
{
"manifest": {
"id": "my_recipe",
"name": "我的配方",
"description": "...",
"version": "1.0",
"capabilities": {
"extra_modules": ["requests", "sqlite3"]
},
"state_graph": {
"nodes": [...],
"edges": [...]
},
"output_renderers": [...]
},
"user_code": {"filename.py": "source..."},
"knowledge": {"AGENTS.md": "content..."},
"skill_templates": {"skill_name": "SKILL.md content..."},
"external_kb": {"kb_name": {"filename": "content..."}},
"schemas": {"schema.json": "{...}"},
"assets_b64": {"figure.png": "base64..."}
}5.3 界面布局
顶部条:
- 协议:导入文件夹/zip 的文件路径规范
- 导入 zip / 导入文件夹:快捷导入生成 Recipe
- 导出 zip:打包为可导入的 zip
- 保存:存档当前 Recipe
- 复制:克隆为新 Recipe
- 删除:删除当前 Recipe
- 上传(Relay):一键上传到 relay marketplace
左侧列表:
- 所有 Recipe 按分组列出
- 系统内置(
is_builtin: true)→ 只读,需复制才能编辑 - 每个 Recipe 右侧有状态徽标(绑定/默认/已上传)
主编辑区:
- Recipe 编辑器(
RecipeGraphEditor.vue):state_graph 可视化编辑 - Utils 标签(
UtilsTab.vue):user_code / knowledge / skill_templates / external_kb / schemas / assets - Custom UI 标签(
CustomUITab.vue):.vue renderer 源码 - Recipe Author Chat(
RecipeAuthorChat.vue):vibe-coding 侧边聊天(agent -1) - Capability Approval Panel:capabilities 审批面板
5.4 Recipe 与 Agent 的关系
- Recipe 绑定到 agent → agent 后续对话走 recipe 的 state_graph 配置
- 一个 agent 只能绑定一个 recipe
- 一个 recipe 可绑定多个 agent
scope='recipe'的 Skill 自动共享给同 recipe 下所有 agent
5.5 内置 Recipe(Built-in)
- 位置:
src/recipes/_builtin/<id>/ install_built_ins()在 bridge 启动时同步到workspace/agent_recipes/is_builtin: true→ UI 只读(禁止保存/删除),需 复制 才能编辑- UI 分 系统 / 我的 两个列表
6. 创意工坊 CreativeWorkshop(Flow)
组件:FlowTemplateEditor.vue + FlowTemplateList.vue(在 CreativeWorkshop 内)
后端 API:src/bridge/routes/flow_templates.py
6.1 Flow Template API
| 端点 | 说明 |
|---|---|
GET /api/flow-templates | 列表(摘要行) |
POST /api/flow-templates | 创建 |
GET /api/flow-templates/<id> | 获取完整 body |
PUT /api/flow-templates/<id> | 保存(validate + persist) |
DELETE /api/flow-templates/<id> | 删除(有实例时拒绝) |
POST /api/flow-templates/<id>/validate | 干跑验证 |
POST /api/flow-templates/<id>/duplicate | 克隆 |
GET /api/flow-templates/<id>/export | 下载 .flow.json |
POST /api/flow-templates/import | 上传 .flow.json |
POST /api/flow-templates/preview_bundle | 预检 .flow.zip bundle |
POST /api/flow-templates/import_bundle | 导入 .flow.zip |
GET /api/flow-templates/<id>/export_bundle | 下载 .flow.zip |
6.2 Flow Bundle 结构(V2 track layout, schema_version=3)
my_flow.flow.zip
├── manifest.json 元数据
├── template.json V1 pool 层(节点+连接)
├── layout.json V2 track/module/variable 层
├── contract.md 协作契约(可选)
├── README.md 说明(可选)
├── schemas/ 数据 schema(可选)
├── docs/ 文档(可选)
│ ├── DESIGN.md 设计文档
│ └── DEVELOPMENT.md 开发文档
└── renderers/ 自定义字段渲染器(可选)
└── *.vue6.3 Per-flow Docs
每个 flow 有 docs/ 目录,通过以下端点管理:
GET /api/flow-templates/<id>/docs→ 列出所有文档GET /api/flow-templates/<id>/docs/<name>→ 读取文档内容PUT /api/flow-templates/<id>/docs/<name>→ 写入文档
DESIGN.md 是 flow 的设计文档。DEVELOPMENT 始终解析到全局 FLOW_DEVELOPMENT.md 框架文档(is_global: true,编辑前提示)。
6.4 自定义字段渲染器
renderers/*.vue 是 Vue SFC,编译后挂载到 flow 实例的字段编辑 UI。用于自定义字段类型的可视化编辑。
7. Recipe 编译 / 干跑 / E2E 测试
入口:CreativeWorkshop 编辑器内按钮
7.1 编译(Compile)
POST /api/recipes/<id>/compile
- 验证 state_graph 拓扑完整性
- 检查所有节点引用有效
- 验证 edge condition 表达式通过 AST 白名单
- 检查 tool_whitelist 中的工具存在
- 返回
{ok, errors, warnings}
7.2 干跑(Dryrun)
POST /api/recipes/<id>/dryrun
- 使用 stub asker + mock LLM 跑完整 state_graph
- 验证所有 unit 能执行
- 不消耗真实 LLM token
- 返回
{ok, outcome, trace}
7.3 E2E 端到端测试
POST /api/recipes/<id>/e2e-test
- 创建临时 agent → 绑定 recipe → 发送测试消息 → 验证完整链路
- 使用真实 LLM 调用
- 看 bridge log 的
session.contact.end/e2e_test done pass=判断成败 - 返回
{ok, pass, details}
开发视角
想在工坊里做生态?
- Recipe:修改
workspace/agent_recipes/<id>/→ 导入/导出 → 社区分享 - Flow:
workspace/manager/flows/<id>/→ template.json + layout.json + renderers/ - Broker:见 管线与流手册
