Multi-Skill Collaboration Workflow

This project integrates the first three hands-on projects into a complete "data report generation" workflow.

Goal: Master multi-Skill orchestration and how to design an orchestration Skill that coordinates the overall workflow.


Workflow Goal

The user uploads a business data file, and the system automatically completes the following end-to-end tasks, ultimately delivering a complete business report.

User uploads file .csv / .xlsx Data cleaning data-cleaner Summary generation doc-summarizer Report output Excel + Summary Deliver to user present_files

Design Principles for Orchestration Skill

The orchestration Skill does not perform specific business processing; it is only responsible for scheduling the outputs of other Skills, passing intermediate results, and reporting progress to the user at key points.

What the orchestration Skill doesWhat the orchestration Skill does not do
Call sub-Skill scripts in orderRe-implement functionality already existing in sub-Skills
Pass file paths between stepsDirectly manipulate data content
Report overall progress to the userFocus on internal details of a single step
Handle remediation logic after step failuresCatch exceptions inside sub-Skills

Orchestration Script

Example

# File path: scripts/orchestrator.py
# Orchestration entry script for multi-Skill collaboration

import subprocess
import sys
import json
import os
import shutil

SKILLS_BASE  = "/mnt/skills/public"
WORK_DIR     = "/home/claude/report_work"
OUTPUT_DIR   = "/mnt/user-data/outputs"

def run(script_path: str, *args) -> dict:
    """Run the specified script and return the JSON result"""
    cmd    = [sys.executable, script_path] + list(args)
    result = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
    try:
        return json.loads(result.stdout)
    except json.JSONDecodeError:
        return {
            "status":  "error",
            "message": result.stderr or result.stdout or "Script has no output"
        }

def orchestrate(input_file: str) -> dict:
    """Execute the complete report generation workflow"""
    os.makedirs(WORK_DIR, exist_ok=True)

    # ── Phase 1: Data cleaning ─────────────────────────────────
    print("【1/3】Cleaning data...", flush=True)
    clean_result = run(
        f"{SKILLS_BASE}/data-cleaner/scripts/clean_data.py",
        input_file,
        os.path.join(WORK_DIR, "cleaned.csv")
    )
    if clean_result.get("status") != "success":
        return {"status": "error", "stage": "Data cleaning",
                "message": clean_result.get("message")}

    print(f" Cleaned: removed {clean_result.get('dup_removed', 0)} duplicate rows,"
          f"filled {clean_result.get('nulls_filled', 0)} missing values", flush=True)

    # ── Phase 2: Statistical analysis ─────────────────────────────────
    print("【2/3】Generating statistical report...", flush=True)
    stats_result = run(
        f"{SKILLS_BASE}/data-cleaner/scripts/calc_stats.py",
        clean_result["output"],
        os.path.join(WORK_DIR, "stats.json")
    )
    if stats_result.get("status") != "success":
        return {"status": "error", "stage": "Statistical analysis",
                "message": stats_result.get("message")}

    # ── Phase 3: Generate Excel report ──────────────────────────
    print("【3/3】Generating Excel report...", flush=True)
    output_name  = os.path.splitext(os.path.basename(input_file))[0] + "_report.xlsx"
    output_path  = os.path.join(OUTPUT_DIR, output_name)

    report_result = run(
        f"{SKILLS_BASE}/data-cleaner/scripts/gen_report.py",
        clean_result["output"],
        stats_result.get("output", ""),
        output_path
    )
    if report_result.get("status") != "success":
        return {"status": "error", "stage": "Report generation",
                "message": report_result.get("message")}

    # Clean up working directory
    shutil.rmtree(WORK_DIR, ignore_errors=True)

    return {
        "status":     "success",
        "output":     output_path,
        "clean_stats": {
            "dup_removed":  clean_result.get("dup_removed", 0),
            "nulls_filled": clean_result.get("nulls_filled", 0)
        }
    }

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print(json.dumps({"status": "error", "message": "Usage: python orchestrator.py <file path>"}))
        sys.exit(1)

    result = orchestrate(sys.argv[1])
    print(json.dumps(result, ensure_ascii=False, indent=2))
【1/3】正在清洗数据...
  已清洗:删除重复行 5 条,填充空值 18 处
【2/3】正在生成统计报告...
【3/3】正在生成 Excel 报告...
{
  "status": "success",
  "output": "/mnt/user-data/outputs/example_sales_report.xlsx",
  "clean_stats": {"dup_removed": 5, "nulls_filled": 18}
}

SKILL.md for the Orchestration Skill

---
name: report-pipeline
version: 1.0.0
description: >
  完整的数据报告生成流水线:自动对上传的 CSV/Excel 文件执行数据清洗、
  统计分析并生成 Excel 报告。当用户需要一键生成数据报告、
  从原始数据直接输出分析报告时触发。
---

# 数据报告流水线

## 前置条件

需要以下 Skills 已安装:
- data-cleaner v1.0+
- 本 Skill 的脚本位于 /mnt/skills/public/report-pipeline/

## 执行

获取用户上传的文件路径后,直接运行编排脚本:

```bash
python scripts/orchestrator.py <文件路径>
```

脚本会实时输出每阶段的进度,完成后输出最终文件路径。
解析 JSON 输出后调用 present_files 展示报告文件。

## 失败处理

若任意阶段失败,输出包含 stage 和 message 的错误信息,
告知用户是哪个阶段失败以及可能的原因,不要继续执行后续阶段。
Other extensions