Skills Design Patterns und Best Practices

Aus umfangreicher Praxis destillierte Skill-Designmuster helfen Ihnen, bei neuen Anforderungen schnell fundierte Entscheidungen zu treffen.

Dieser Artikel fasst die 7 am häufigsten verwendeten Designmuster und ihre Anwendungsszenarien zusammen.


Muster 1: Single Responsibility Skill

Jeder Skill macht eine Sache und macht sie gut.

Je fokussierter die Funktionalität, desto präziser die Beschreibung, desto höher die Trigger-Genauigkeit und desto einfacher die Wartung.

AnsatzBeispiel
Richtig: Eine einzige Verantwortlichkeitpdf-to-text (verarbeitet nur die Textextraktion)
Falsch: Gemischte Verantwortlichkeitenpdf-tools (Lesen, Konvertieren, Zusammenführen, Wasserzeichen setzen... alles an einem Ort)

Wenn Sie feststellen, dass die Beschreibung eines Skills sehr lang sein muss, um klarzustellen, was er „nicht tut“, bedeutet dies normalerweise, dass er zu viele Verantwortlichkeiten übernommen hat und aufgeteilt werden sollte.


Muster 2: Defensive Eingabeprüfung

Führen Sie die gesamte Eingabevalidierung zentral am Einstiegspunkt des Skill-Skripts durch, und gehen Sie erst nach erfolgreicher Validierung in die Geschäftslogik über.

Beispiel

# Dateipfad: scripts/defensive_entry.py
# Muster: Defensive Eingabeprüfung - zentrale Validierung am Einstiegspunkt, Freigabe nach Bestehen

import sys
import os
import json

def validate(args) -> list:
    """Alle Eingaben zentral validieren und eine Liste von Fehlern zurückgeben (leere Liste bedeutet alles bestanden)"""
    errors = []

    if not args.file:
        errors.append("Fehlendes Argument --file")
    elif not os.path.exists(args.Datei):
        errors.append(f"Datei existiert nicht: {args.file}")
    elif os.path.getsize(args.file) == 0:
        errors.append("Dateiinhalt ist leer")

    if args.limit < 1:
        errors.append("--limit muss größer als 0 sein")

    return errors

def run(args):
    """Einstiegspunkt für die Geschäftslogik, wird nur nach erfolgreicher Validierung aufgerufen"""
    # Eigentliche Verarbeitung durchführen...
    return {"status": "success", "file": args.file}

if __name__ == "__main__":
    import argparse
    parser = argparse.ArgumentParser()
    parser.add_argument("--file",  required=False, default="")
    parser.add_argument("--limit", type=int, default=100)
    args = parser.parse_args()

    # 1. Zentralisierte Validierung
    errors = validate(args)
    if errors:
        result = {"status": "input_error", "errors": errors}
        print(json.dumps(result, ensure_ascii=False))
        sys.exit(1)

    # 2. Geschäftslogik nach erfolgreicher Validierung ausführen
    result = run(args)
    print(json.dumps(result, ensure_ascii=False))

Muster 3: Progressive Ausgabe

Bei Skills, die länger als 5 Sekunden dauern, sollte der Fortschritt in Stufen ausgegeben werden, anstatt den Benutzer mit stillem Warten allein zu lassen.

## 执行流程(渐进式输出示例)

### 步骤一:读取文件
运行读取脚本后,立即告知用户:
> 已读取文件:example_data.csv(1,024 行,8 列)正在进行数据清洗...

### 步骤二:数据清洗
清洗完成后,告知用户:
> 数据清洗完成:删除重复行 3 条,空值填充 12 处。正在生成报告...

### 步骤三:生成报告
报告生成后,展示下载链接并说明内容:
> 报告已生成,包含统计摘要和数据质量评估。

Muster 4: Idempotente Operationen

Die Ausführungsergebnisse eines Skills sollten idempotent sein: Bei derselben Eingabe sollte die Ausgabe konsistent sein, egal wie oft sie ausgeführt wird.

Nicht-idempotente Operationen (wie das Anhängen von Inhalten bei jeder Ausführung) können für Verwirrung sorgen, wenn Benutzer einen erneuten Versuch starten.

Beispiel

# Dateipfad: scripts/idempotent_output.py
import os
from datetime import datetime

OUTPUT_DIR = "/mnt/user-data/outputs"

def get_output_path(base_name: str, suffix: str = ".xlsx") -> str:
    """
Deterministischen Ausgabepfad generieren

Idempotenter Ansatz: die gleichnamige Datei bei jeder Ausführung überschreiben (anstatt anzuhängen oder eine neue Datei zu generieren)
Sicherstellen, dass dieselbe Eingabe immer derselben Ausgabedatei entspricht
    """

    # Methode A: Fester Dateiname (dieselbe Eingabe überschreibt immer)
    return os.path.join(OUTPUT_DIR, f"{base_name}_report{suffix}")

    # Methode B (Zeitstempel): bei jedem Aufruf eine neue Datei erzeugen (nicht idempotent, aber die Historie bleibt erhalten)
    # ts = datetime.now().strftime("%Y%m%d_%H%M%S")
    # return os.path.join(OUTPUT_DIR, f"{base_name}_{ts}{suffix}")

Muster 5: Explizites Abschlusssignal

Nachdem ein Skill die Ausführung abgeschlossen hat, sollte er ein klares "Abschlusssignal" geben, damit der Benutzer weiß, dass die Aufgabe beendet ist und nicht weiter warten muss.

## 任务完成后的输出规范

无论成功还是失败,最后一步必须输出一个明确的状态行:

成功时:
> 任务完成:报告已生成,共处理 1,024 行数据,耗时约 3 秒。

失败时:
> 任务中断:在"数据清洗"步骤遇到错误(原因:文件编码不是 UTF-8)。
> 建议:将文件另存为 UTF-8 格式后重新上传。

Muster 6: Deklaration der Versionskompatibilität

Deklarieren Sie kompatible Modellversionen im Frontmatter von SKILL.md, um unerwartetes Verhalten in nicht unterstützten Umgebungen zu verhindern.

---
name: data-analyzer
version: 1.2.0
description: 分析 CSV/Excel 数据,生成统计报告。
compatibility:
  claude_models:
    - claude-sonnet-4-20250514   # 经过验证的模型版本
    - claude-opus-4              # 同样支持
  python: ">=3.8"
  platforms:
    - linux    # Claude 计算机使用环境
---

Muster 7: Schnell scheitern

Sobald ein Fehler erkannt wird, der die Fortsetzung verhindert, stoppen Sie sofort und berichten Sie deutlich, anstatt die Ausführung mit dem Fehler fortzusetzen und sinnlose Ausgabe zu erzeugen.

Beispiel

# Dateipfad: scripts/fail_fast.py
import sys
import json

def assert_condition(condition: bool, message: str, hint: str = ""):
    """Wenn Bedingungen nicht erfüllt sind, sofort einen Fehler ausgeben und beenden (Fail-Fast-Muster)"""
    if not condition:
        result = {
            "status":  "error",
            "message": message,
            "hint": hint
        }
        print(json.dumps(result, ensure_ascii=False))
        sys.exit(1)

# Alle erforderlichen Prüfungen zentral am Anfang des Skripts durchführen
import os
file_path = sys.argv[1] if len(sys.argv) > 1 else ""

assert_condition(bool(file_path),
                 "Fehlendes Dateipfad-Argument",
                 "Verwendung: python script.py <Dateipfad>")

assert_condition(os.path.exists(file_path),
                 f"Datei existiert nicht: {file_path}",
                 "Bitte prüfen Sie, ob der Pfad korrekt ist, oder laden Sie die Datei erneut hoch")

assert_condition(file_path.endswith(".csv"),
                 "Dateiformat nicht unterstützt, .csv erwartet",
                 f"Tatsächliche Datei: {file_path}")

# Alle Prüfungen bestanden, führe die eigentliche Logik aus
print(json.dumps({"status": "ok", "file": file_path}))

Muster-Kurzreferenz

MusterKernprinzipGelöstes Problem
EinzelverantwortungEin Skill erledigt eine AufgabeUngenaue Auslösung, schwer zu warten
Defensive EingabeüberprüfungZentralisierte Validierung am EinstiegspunktFehler werden erst mitten in der Ausführung gemeldet
Fortschreitende AusgabeFortschritt in Stufen meldenBenutzer wissen nicht, ob es läuft
Idempotente OperationenGleiche Eingabe, gleiche AusgabeWiederholungsversuche erzeugen verwirrende Ergebnisse
Explizites AbschlusssignalEine Endzustandsbenachrichtigung bei Abschluss bereitstellenBenutzer wissen nicht, ob die Aufgabe abgeschlossen ist
Deklaration der VersionskompatibilitätUnterstützte Laufzeitumgebungen deklarierenAbnormales Verhalten, wenn die Umgebung nicht übereinstimmt
Schnell scheiternBei Fehler sofort stoppenDas Fortsetzen bei Fehlern erzeugt ungültige Ausgabe
Andere Erweiterungen