Skip to content

Workshop Manual ​

The usage and development dimensions of the three workshops: Creative Workshop (recipe/flow), Skill Workshop, Skill Forge, Skill Proposals, Broker Workshop. Source: OPERATION.md §19–§20, §37–§38, src/bridge/routes/skill_forge.py, skill_proposals.py, skill_workshop.py, agent_recipes.py, flow_templates.py.


Table of Contents ​

  1. Skill Forge
  2. SKILL.md Format Specification
  3. Skill Change Approvals
  4. Skill Workshop
  5. Creative Workshop (Recipe)
  6. Creative Workshop (Flow)
  7. Recipe Compile / Dry-run / E2E Test

1. Skill Forge ​

Component: SkillForgeModal.vue

Entry: ChatStage multi-select messages (Shift/Ctrl) → top batch action bar → Forge Skill

1.1 Backend API (src/bridge/routes/skill_forge.py) ​

EndpointPhaseDescription
POST /derive_ioPhase 1 fast pathSingle LLM rewrite → parse INPUTS/OUTPUTS/TRIGGER lines → ~30-40s
POST /proposePhase 1 fullrewrite + tool_select + denoise + params + mock + summary → ~12min
POST /reproposePhase 1 re-proposeRegenerate summary after user locks I/O
POST /build_and_previewPhase 2Full chain: denoise → tool_select → params → mock → summary → generate → validate → repair
POST /previewPhase 2 legacyGenerate SKILL.md + validate
POST /reviseReviseAgent mode tool loop (read/grep/edit/validate/finish)
POST /commitCommitPersist SKILL.md + refresh skill_registry.json
GET /revise/inflightQueryList of skill_ids currently being revised
GET /revise/terminal/<skill_id>QueryConsume completed revision results

1.2 3-Step Wizard Flow ​

Step 1 — params (parameter confirmation)

  1. Frontend POST /derive_io → backend single LLM rewrite (workspace/skills/prompts/forger_rewrite.md) → parse intent's INPUTS: / OUTPUTS: / TRIGGER: lines → returns {intent, inputs, outputs, trigger, skill_id_seed}
  2. Shows three editable areas:
    • Input list: Each row {name, type, description}, can add/delete/modify
    • Output list: Same as above
    • Trigger scenarios: Text input
  3. Floating buttons appear after user changes:
    • ✕ Revert: Restore LLM original (baselineInputs/baselineOutputs/baselineTrigger)
    • ✓ Apply: POST /repropose → backend regenerates summary with locked I/O

Step 2 — review

  1. POST /build_and_preview → backend runs full chain → returns {skill_md, errors, skill_id, summary}
  2. Shows full SKILL.md preview (markdown rendered)
  3. Editable:
    • skill_id: snake_case, ^[a-z][a-z0-9_]{0,63}$
    • scope: global / agent / recipe (defaults to recipe when agent is bound to recipe)
    • overwrite: overwrite toggle for same-name conflicts
  4. If errors present, shown in red list:
    • input_missing: Locked input name not found in SKILL.md
    • output_missing: Locked output name not found in SKILL.md
    • script_still_invalid: Embedded script I/O contract mismatch
    • pipeline_validator_crashed: Pipeline validator exception
  5. Can enter user_guidance → POST /revise → agent mode revision

Step 3 — commit

  1. Click Submit → POST /commit → writes to target directory:
    • global → workspace/skills/<skill_id>/SKILL.md
    • agent → workspace/agents/agent_<id>/skills/<skill_id>/SKILL.md
    • recipe → workspace/agent_recipes/<recipe_id>/skills/<skill_id>/SKILL.md
  2. Refreshes skill_registry.json (rebuild_skill_registry)
  3. If registry did not pick it up (empty description causes indexer to skip), falls back to injecting a placeholder entry
  4. Clears dense_recall cache

1.3 Phase 1 vs Phase 2 Data Flow ​

Phase 1 (derive_io):
  User selects messages → POST /derive_io → single LLM rewrite → parse I/O
  User confirms/edits I/O → (optional) POST /repropose → LLM re-summarizes

Phase 2 (build_and_preview):
  POST /build_and_preview →
    Round 1: denoise (trace denoising)
    Round 2: tool_select + params (parallel)
    Round 3: mock (simulate inputs)
    Round 4: summary
    Round 5: generate (complete SKILL.md)
    → validate (structural validation) + repair (one repair attempt)
    → I/O name presence check
    → per-script I/O validate + repair
    → pipeline gate
  → returns {skill_md, errors}

2. SKILL.md Format Specification ​

2.1 Basic Structure ​

markdown
---
skill_id: my_skill
description: One-line description
version: 1.0
tags:
  category: productivity
trigger_scenarios:
  intent:
    - User says "help me generate a report"
  condition:
    - Agent has access to the reporting system
---

## Skill Inputs
```json
{
  "type": "object",
  "properties": {
    "report_type": {"type": "string", "description": "Report type"},
    "date_range": {"type": "string", "description": "Date range"}
  },
  "required": ["report_type"]
}

Skill Outputs ​

json
{
  "type": "object",
  "properties": {
    "report_content": {"type": "string"},
    "file_path": {"type": "string"}
  }
}

Step 1: Collect Data ​

Input Schema (JSON):

json
{"properties": {"query": {"type": "string"}}, "required": ["query"]}

Instructions: Use the search tool to find relevant information... Output Schema (JSON):

json
{"properties": {"results": {"type": "array"}}}

Step 2: Generate Report ​

...


### 2.2 Validation Rules (`SkillForger.validate()`)

1. **Topology validation**: Metadata → Skill Inputs → Skill Outputs → Steps → correct order
2. **Field name exact match**: Step Input Schema property names must match SKILL-level Inputs or upstream Step Outputs (no fallback)
3. **Tool step I/O 1:1 SET match**: Each tool step's Input Schema must be a subset of the target tool's parameters; Output Schema must be a subset of the tool's return values

### 2.3 Validator Endpoints

POST /api/skills/forge/preview → {skill_md, errors} POST /api/skills/forge/commit → validate first, then pipeline_gate, then write


**pipeline gate** (`_validate_skill_source`): Checks the full data flow contract — every step input must be resolvable from prior step outputs or skill inputs, every step output must be consumed downstream or emitted as a skill output.

### 2.4 Embedded Script Validation

` ```python ` / ` ```bash ` code blocks inside SKILL.md (≥300 bytes) are extracted and validated for I/O contract:
- Script must read inputs from `skill_inputs`
- Script must write results to `skill_outputs`
- Validation failure → one LLM repair attempt
- Still fails after repair → `script_still_invalid` error

### 2.5 Revision Mode (`POST /revise`)

User provides `user_guidance` → `SkillReviseAgent` tool loop:
- `read_skill`: Read current SKILL.md
- `grep_skill`: Search content
- `edit_skill`: Edit SKILL.md
- `validate_skill`: Call validator
- `finish`: Complete revision

Up to `MAX_TURNS` rounds. After revision, placeholder expansion + final gate is executed.

---

## 3. Skill Change Approvals (SkillProposals)

**Component**: `SkillApprovalsView.vue`

**Entry**: Desktop → **Skill Change Approvals** icon (`skill-approvals` app)

**Backend**: `src/bridge/routes/skill_proposals.py`

### 3.1 API Endpoints

| Endpoint | Description |
|---|---|
| `GET /api/skill_proposals` | List all pending proposals (no body, metadata only) |
| `GET /api/skill_proposals/count` | Pending count (for DialogList badge) |
| `GET /api/skill_proposals/<pid>` | Full proposal (with current_body + proposed_body) |
| `POST /api/skill_proposals/<pid>/approve` | Approve → writes to `workspace/skills/` |
| `POST /api/skill_proposals/<pid>/reject` | Reject → archives to `rejected/` |

### 3.2 Approval Queue Storage

- Queue location: `workspace/manager/skill_proposals/pending/`
- Each proposal is one JSON file: `{proposal_id}.json`
- Fields: `proposal_id`, `target_agent_id`, `skill_id`, `target_path`, `created_at`, `trigger`, `current_body`, `proposed_body`, `run_id`, `report_path`

### 3.3 Trigger Condition

When agent's `skill_auto_apply=False` (default) → agent's SKILL.md modifications via `manager_review_tools.apply_agent_updates` enter the approval queue.

### 3.4 Interface Interactions

- List: Each entry shows source agent (`agentName(agentId)`), `skill_id`, `created_at`
- Expanded diff: `current_body` vs `proposed_body` side-by-side comparison
- **Approve**: `approve_proposal(pid)` → writes SKILL.md
- **Reject**: Enter reason → `reject_proposal(pid, reason)` → moves to `rejected/`
- Auto-refresh: 6-second polling (`store.loadPendingSkillProposals()`)

---

## 4. Skill Workshop (SkillWorkshop)

**Component**: `SkillWorkshop.vue` (top-level) + sub-components

**Entry**: Desktop → **Skill Workshop** icon (`skill-workshop` app)

**Targeted at**: Long-flow, manager-only skills requiring step-by-step feedback

### 4.1 Backend API (`src/bridge/routes/skill_workshop.py`)

| Endpoint | Description |
|---|---|
| `GET /api/skill_workshop/skills` | List manager skills with `has_form_component` |
| `POST /api/skill_workshop/upload` | Multipart upload reference images/videos/audio |
| `GET /api/skill_workshop/asset?path=...` | Read files from session/run directories |
| `POST /api/skill_workshop/rewrite` | LLM rewrite storyboard (chunked, bucketed by token budget) |
| `POST /api/skill_workshop/run` | Start runner (background thread) |
| `GET /api/skill_workshop/run/<run_id>/status` | Poll status.json |
| `GET /api/skill_workshop/run/<run_id>/images` | List all involved images (character refs + keyframes) |
| `POST /api/skill_workshop/run/<run_id>/regenerate_image` | Regenerate a single image |
| `POST /api/skill_workshop/run/<run_id>/approve_images` | Approve images → advance to clip_review |
| `GET /api/skill_workshop/run/<run_id>/clips` | List per-clip status |
| `POST /api/skill_workshop/run/<run_id>/clips/<idx>/generate` | Generate a single clip |
| `POST /api/skill_workshop/run/<run_id>/concat_final` | Concatenate all clips → final.mp4 |
| `GET /api/skill_workshop/draft` | Read resume draft |
| `POST /api/skill_workshop/draft` | Save resume draft |
| `GET /api/skill_workshop/history/<skill_id>` | Historical run list |
| `GET /api/skill_workshop/history/<skill_id>/<run_id>` | Single run details |

### 4.2 State Machine (6+ phases)

pick → compose → review → running → image_review → clip_review → done ↘ error ↕ history (entered from pick or done)


| Phase | Component | Description |
|---|---|---|
| `pick` | Main page | Registered manager skill list + **History** button |
| `compose` | `GenerateVideoForm.vue` / `EditVideoForm.vue` | Input form: topic/duration/characters/scenes/reference images |
| `review` | `StoryboardReview.vue` | LLM-rewritten storyboard → user can edit each segment's prompt |
| `running` | Progress panel | Polls status.json, shows Phase A (image generation) progress |
| `image_review` | `ImageReview.vue` | Grid display of all involved images → per-image edit prompt / regenerate |
| `clip_review` | `ClipReview.vue` | Each clip has individual **Compose** button → final **Export Video** |
| `done` | Video player | Displays final.mp4 |
| `error` | Error panel | Shows error message + **Back** button |
| `history` | History list | Historical run list + details + **Use as Template** to backfill form |

### 4.3 generate_video Full Flow

1. **compose**: Fill in `GenerateVideoForm.vue`
   - Topic, duration (5-300 seconds), whether to add voiceover
   - Character list: name + description + reference image upload (≤4MB, PNG/JPEG/WebP)
   - Object/scene references: name + kind(object/scene/character) + description + reference image
   - Scene list: duration(3-15) + script(≥20 chars) + first_frame_prompt + last_frame_prompt
   - Optional: upload keyframe images / upload full video clip
   - Optional: aspect ratio (16:9 / 1:1 / 9:16)
   - LocalStorage auto-saves drafts

2. **rewrite**: `POST /rewrite` → chunked LLM rewrite
   - Scenes bucketed by token budget (~2700 tokens/bucket)
   - Each bucket gets independent LLM call → only rewrites scenes within that bucket
   - User-uploaded keyframes/clips marked `__pass_through__: true` → LLM copies verbatim
   - Returns storyboard JSON + warnings

3. **review**: `StoryboardReview.vue` display → user edits prompts → click **Approve**

4. **run**: `POST /run` → `start_generate_video_run()` → background thread
   - run_id: `vid_<ts>_<sha256(storyboard)[:10]>`
   - Assets stored in `workspace/manager/skill_workshop_runs/<run_id>/`
   - status.json records state

5. **image_review**: `GET /run/<id>/images` → grid display → per-image edit/regenerate
   - `POST /regenerate_image` → `force_intense_mode()` bypasses approval → synchronous regeneration
   - `POST /approve_images` → state advances to `awaiting_clip_review`

6. **clip_review**: `GET /run/<id>/clips` → each clip has independent **Compose** button
   - `POST /clips/<idx>/generate` → synchronous single clip generation
   - `POST /concat_final` → concatenate all clips → final.mp4

### 4.4 Upload Limits

| Role | MIME | Max Size |
|---|---|---|
| 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 |

Character/first-frame/last-frame uploads are automatically `strip_white_inplace` processed (remove edge white → RGBA PNG).

### 4.5 Resume Mechanism

- Frontend draft → `POST /draft` → persisted to `workspace/manager/skill_workshop_runs/resume_draft.json`
- App restart → `GET /draft` → restores storyboard + run_id
- run_id determinism: `sha256(canonical storyboard JSON)[:10]` → same storyboard → same run_id → resume rather than restart

---

## 5. Creative Workshop (Recipe)

**Component**: `CreativeWorkshop.vue`

**Entry**: Desktop → **Creative Workshop** icon (`workshop` app → `WorkshopApp.vue` → `CreativeWorkshop.vue`)

**What is a Recipe**: A custom new agent architecture formed by module substitution / full replacement on top of the Familiars pipeline. Recipes are the automated orchestration of skills (LLM + tool graph).

### 5.1 Backend API (`src/bridge/routes/agent_recipes.py`)

| Endpoint | Description |
|---|---|
| `GET /api/recipes/catalog` | Tool catalog (all available tool schemas) |
| `GET /api/recipes` | Recipe list |
| `POST /api/recipes` | Create new recipe |
| `GET /api/recipes/<id>` | Get full recipe (manifest + sidecar files) |
| `PUT /api/recipes/<id>` | Save recipe (partial update sidecar) |
| `DELETE /api/recipes/<id>` | Delete recipe |
| `POST /api/recipes/<id>/bind/<agent_id>` | Bind to agent |
| `POST /api/recipes/<id>/unbind/<agent_id>` | Unbind from agent |
| `POST /api/recipes/<id>/duplicate` | Copy recipe |
| `GET /api/recipes/<id>/export` | Download .recipe.zip |
| `POST /api/recipes/import` | Upload .recipe.zip |
| `POST /api/recipes/import-folder` | Import from folder |
| `POST /api/recipes/<id>/compile` | Compile validation |
| `POST /api/recipes/<id>/dryrun` | Dry-run test |
| `POST /api/recipes/<id>/e2e-test` | E2E end-to-end test |
| `GET /api/recipes/<id>/knowledge/<path>` | Read knowledge base file |
| `GET /api/recipes/default` | Get default recipe |
| `PUT /api/recipes/default` | Set default recipe |
| `DELETE /api/recipes/default` | Clear default |

### 5.2 Recipe Data Structure

```json
{
  "manifest": {
    "id": "my_recipe",
    "name": "My Recipe",
    "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 Interface Layout ​

Top bar:

  • Protocol: File path conventions for imported folders/zips
  • Import zip / Import folder: Quick-import to generate Recipe
  • Export zip: Package as importable zip
  • Save: Save current Recipe
  • Copy: Clone as new Recipe
  • Delete: Delete current Recipe
  • Upload (Relay): One-click upload to relay marketplace

Left sidebar list:

  • All Recipes listed by group
  • System built-in (is_builtin: true) → read-only, must copy to edit
  • Each Recipe has status badges on the right (bound/default/uploaded)

Main editing area:

  • Recipe Editor (RecipeGraphEditor.vue): Visual state_graph editing
  • Utils tab (UtilsTab.vue): user_code / knowledge / skill_templates / external_kb / schemas / assets
  • Custom UI tab (CustomUITab.vue): .vue renderer source code
  • Recipe Author Chat (RecipeAuthorChat.vue): Vibe-coding side chat (agent -1)
  • Capability Approval Panel: Capabilities approval panel

5.4 Relationship Between Recipe and Agent ​

  • Recipe bound to agent → agent's subsequent dialogues follow the recipe's state_graph configuration
  • One agent can only be bound to one recipe
  • One recipe can be bound to multiple agents
  • Skills with scope='recipe' are automatically shared to all agents under the same recipe

5.5 Built-in Recipes ​

  • Location: src/recipes/_builtin/<id>/
  • install_built_ins() syncs to workspace/agent_recipes/ at bridge startup
  • is_builtin: true → UI is read-only (save/delete forbidden), must copy to edit
  • UI splits into System / My lists

6. Creative Workshop (Flow) ​

Components: FlowTemplateEditor.vue + FlowTemplateList.vue (inside CreativeWorkshop)

Backend API: src/bridge/routes/flow_templates.py

6.1 Flow Template API ​

EndpointDescription
GET /api/flow-templatesList (summary rows)
POST /api/flow-templatesCreate
GET /api/flow-templates/<id>Get full body
PUT /api/flow-templates/<id>Save (validate + persist)
DELETE /api/flow-templates/<id>Delete (refused if instances exist)
POST /api/flow-templates/<id>/validateDry-run validation
POST /api/flow-templates/<id>/duplicateClone
GET /api/flow-templates/<id>/exportDownload .flow.json
POST /api/flow-templates/importUpload .flow.json
POST /api/flow-templates/preview_bundlePre-check .flow.zip bundle
POST /api/flow-templates/import_bundleImport .flow.zip
GET /api/flow-templates/<id>/export_bundleDownload .flow.zip

6.2 Flow Bundle Structure (V2 track layout, schema_version=3) ​

my_flow.flow.zip
├── manifest.json       Metadata
├── template.json       V1 pool layer (nodes + connections)
├── layout.json         V2 track/module/variable layer
├── contract.md         Collaboration contract (optional)
├── README.md           Description (optional)
├── schemas/            Data schemas (optional)
├── docs/               Documentation (optional)
│   ├── DESIGN.md       Design document
│   └── DEVELOPMENT.md  Development document
└── renderers/          Custom field renderers (optional)
    └── *.vue

6.3 Per-flow Docs ​

Each flow has a docs/ directory, managed via the following endpoints:

  • GET /api/flow-templates/<id>/docs → list all documents
  • GET /api/flow-templates/<id>/docs/<name> → read document content
  • PUT /api/flow-templates/<id>/docs/<name> → write document

DESIGN.md is the flow's design document. DEVELOPMENT always resolves to the global FLOW_DEVELOPMENT.md framework document (is_global: true, prompts before editing).

6.4 Custom Field Renderers ​

renderers/*.vue are Vue SFCs, compiled and mounted to the flow instance's field editing UI. Used for visual editing of custom field types.


7. Recipe Compile / Dry-run / E2E Test ​

Entry: Buttons inside CreativeWorkshop editor

7.1 Compile ​

POST /api/recipes/<id>/compile

  • Validates state_graph topology completeness
  • Checks all node references are valid
  • Validates edge condition expressions pass AST whitelist
  • Checks tools in tool_whitelist exist
  • Returns {ok, errors, warnings}

7.2 Dry-run ​

POST /api/recipes/<id>/dryrun

  • Uses stub asker + mock LLM to run full state_graph
  • Validates all units can execute
  • Does not consume real LLM tokens
  • Returns {ok, outcome, trace}

7.3 E2E End-to-end Test ​

POST /api/recipes/<id>/e2e-test

  • Creates temporary agent → binds recipe → sends test message → validates full chain
  • Uses real LLM calls
  • Check bridge log's session.contact.end / e2e_test done pass= to determine pass/fail
  • Returns {ok, pass, details}

Developer Perspective ​

Want to build an ecosystem in the workshop?

  • Recipe: Modify workspace/agent_recipes/<id>/ → import/export → community sharing
  • Flow: workspace/manager/flows/<id>/ → template.json + layout.json + renderers/
  • Broker: See Pipeline & Flow Manual

Familiars · 多 Agent AI 桌面应用