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.
| Ansatz | Beispiel |
|---|---|
| Richtig: Eine einzige Verantwortlichkeit | pdf-to-text (verarbeitet nur die Textextraktion) |
| Falsch: Gemischte Verantwortlichkeiten | pdf-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
# 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
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
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
| Muster | Kernprinzip | Gelöstes Problem |
|---|---|---|
| Einzelverantwortung | Ein Skill erledigt eine Aufgabe | Ungenaue Auslösung, schwer zu warten |
| Defensive Eingabeüberprüfung | Zentralisierte Validierung am Einstiegspunkt | Fehler werden erst mitten in der Ausführung gemeldet |
| Fortschreitende Ausgabe | Fortschritt in Stufen melden | Benutzer wissen nicht, ob es läuft |
| Idempotente Operationen | Gleiche Eingabe, gleiche Ausgabe | Wiederholungsversuche erzeugen verwirrende Ergebnisse |
| Explizites Abschlusssignal | Eine Endzustandsbenachrichtigung bei Abschluss bereitstellen | Benutzer wissen nicht, ob die Aufgabe abgeschlossen ist |
| Deklaration der Versionskompatibilität | Unterstützte Laufzeitumgebungen deklarieren | Abnormales Verhalten, wenn die Umgebung nicht übereinstimmt |
| Schnell scheitern | Bei Fehler sofort stoppen | Das Fortsetzen bei Fehlern erzeugt ungültige Ausgabe |