Skills Design Patterns and Best Practices
Skill design patterns distilled from extensive practice help you make sound decisions quickly when facing new requirements.
This article summarizes the 7 most commonly used design patterns and their applicable scenarios.
Pattern 1: Single Responsibility Skill
Each Skill does one thing and does it well.
The more focused the functionality, the more precise the description, the higher the trigger accuracy, and the easier the maintenance.
| Approach | Example |
|---|---|
| Correct: Single responsibility | pdf-to-text (only handles text extraction) |
| Incorrect: Mixed responsibilities | pdf-tools (reading, conversion, merging, watermarking... all in one place) |
If you find that a Skill's description needs to be very long to clarify what it "does not do," this usually means it has taken on too many responsibilities and should be split.
Pattern 2: Defensive Input Checking
Perform all input validation centrally at the Skill script entry point, and only enter business logic after validation passes.
Example
# Pattern: Defensive input checking - centralized validation at the entry point, release after passing
import sys
import os
import json
def validate(args) -> list:
"""Centrally validate all inputs and return a list of errors (empty list means all passed)"""
errors = []
if not args.file:
errors.append("Missing argument --file")
elif not os.path.exists(args.file):
errors.append(f"File does not exist: {args.file}")
elif os.path.getsize(args.file) == 0:
errors.append("File content is empty")
if args.limit < 1:
errors.append("--limit must be greater than 0")
return errors
def run(args):
"""Business logic entry point, only called after validation passes"""
# Perform actual processing...
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. Centralized validation
errors = validate(args)
if errors:
result = {"status": "input_error", "errors": errors}
print(json.dumps(result, ensure_ascii=False))
sys.exit(1)
# 2. Execute business logic after validation passes
result = run(args)
print(json.dumps(result, ensure_ascii=False))
Pattern 3: Progressive Output
For Skills that take longer than 5 seconds, progress should be output in stages, rather than leaving the user to face silent waiting.
## 执行流程(渐进式输出示例) ### 步骤一:读取文件 运行读取脚本后,立即告知用户: > 已读取文件:example_data.csv(1,024 行,8 列)正在进行数据清洗... ### 步骤二:数据清洗 清洗完成后,告知用户: > 数据清洗完成:删除重复行 3 条,空值填充 12 处。正在生成报告... ### 步骤三:生成报告 报告生成后,展示下载链接并说明内容: > 报告已生成,包含统计摘要和数据质量评估。
Pattern 4: Idempotent Operations
A Skill's execution results should be idempotent: for the same input, no matter how many times it is executed, the output should be consistent.
Non-idempotent operations (such as appending content on every execution) can cause confusion when users retry.
Example
import os
from datetime import datetime
OUTPUT_DIR = "/mnt/user-data/outputs"
def get_output_path(base_name: str, suffix: str = ".xlsx") -> str:
"""
Generate a deterministic output path
Idempotent approach: overwrite the same-named file on every execution (instead of appending or generating a new file)
Ensure the same input always corresponds to the same output file
"""
# Method A: Fixed filename (same input always overwrites)
return os.path.join(OUTPUT_DIR, f"{base_name}_report{suffix}")
# Method B (timestamp): generate a new file each time (non-idempotent, but preserves history)
# ts = datetime.now().strftime("%Y%m%d_%H%M%S")
# return os.path.join(OUTPUT_DIR, f"{base_name}_{ts}{suffix}")
Pattern 5: Explicit Completion Signal
After a Skill completes execution, it should give a clear "completion signal" so the user knows the task has ended and does not need to keep waiting.
## 任务完成后的输出规范 无论成功还是失败,最后一步必须输出一个明确的状态行: 成功时: > 任务完成:报告已生成,共处理 1,024 行数据,耗时约 3 秒。 失败时: > 任务中断:在"数据清洗"步骤遇到错误(原因:文件编码不是 UTF-8)。 > 建议:将文件另存为 UTF-8 格式后重新上传。
Pattern 6: Version Compatibility Declaration
Declare compatible model versions in the frontmatter of SKILL.md to prevent unexpected behavior in unsupported environments.
---
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 计算机使用环境
---
Pattern 7: Fail Fast
Once an error that prevents continuation is detected, stop immediately and report clearly, rather than continuing execution with the error and producing meaningless output.
Example
import sys
import json
def assert_condition(condition: bool, message: str, hint: str = ""):
"""If conditions are not met, immediately output an error and exit (Fail Fast pattern)"""
if not condition:
result = {
"status": "error",
"message": message,
"hint": hint
}
print(json.dumps(result, ensure_ascii=False))
sys.exit(1)
# Perform all prerequisite checks centrally at the beginning of the script
import os
file_path = sys.argv[1] if len(sys.argv) > 1 else ""
assert_condition(bool(file_path),
"Missing file path argument",
"Usage: python script.py <file path>")
assert_condition(os.path.exists(file_path),
f"File does not exist: {file_path}",
"Please check whether the path is correct, or re-upload the file")
assert_condition(file_path.endswith(".csv"),
"File format not supported, expected .csv",
f"Actual file: {file_path}")
# All checks passed, execute the actual logic
print(json.dumps({"status": "ok", "file": file_path}))
Pattern Quick Reference
| Pattern | Core Principle | Problem Solved |
|---|---|---|
| Single Responsibility | One Skill does one thing | Inaccurate triggering, hard to maintain |
| Defensive Input Checking | Centralized validation at entry point | Errors only reported midway through execution |
| Progressive Output | Report progress in stages | Users don't know if it's running |
| Idempotent Operations | Same input, same output | Retries produce confusing results |
| Explicit Completion Signal | Provide a final state notification when done | Users don't know whether the task is complete |
| Version Compatibility Declaration | Declare supported runtime environments | Abnormal behavior when environment doesn't match |
| Fail Fast | Stop immediately upon error | Continuing with errors produces invalid output |