Skills 输入/输出规范设计
一个优秀的 Skill,不仅能完成任务,还要清晰地定义"接受什么"和"产出什么"。
良好的输入输出规范,是 Skill 可靠运行的基础。
为什么要定义输入输出规范
Skills 面对的是真实的用户请求,输入格式千变万化。
没有明确规范的 Skill,Claude 会自行猜测输入意图,导致行为不稳定。
规范不是限制,而是给 Claude 明确的行动边界,减少歧义,提高输出一致性。
输入规范的四个要素
| 要素 | 说明 | 示例 |
|---|---|---|
| 输入类型 | 文件、文本、URL、参数等 | 用户上传的 PDF 文件 |
| 格式要求 | 文件扩展名、编码、结构 | .csv,UTF-8 编码,第一行为表头 |
| 必填/可选 | 哪些输入是必须的 | 文件路径必填,列名可选 |
| 缺省行为 | 可选参数未提供时如何处理 | 未指定列名时分析所有列 |
在 SKILL.md 中定义输入规范
实例
## 输入规范
### 必填输入
- **数据文件**:用户上传的 `.csv` 或 `.xlsx` 文件
- 编码:UTF-8(CSV)或标准 Excel 格式
- 第一行必须为列标题
- 文件大小不超过 50MB
### 可选输入
- **目标列**:指定分析哪些列,默认分析所有数值列
- **输出格式**:`table`(表格)或 `text`(文字摘要),默认 `table`
- **精度**:保留小数位数,默认 2 位
### 输入缺失时的处理
若文件未上传,告知用户:"请上传需要分析的 CSV 或 Excel 文件。"
若文件格式不支持,告知用户并列出支持的格式列表。
### 必填输入
- **数据文件**:用户上传的 `.csv` 或 `.xlsx` 文件
- 编码:UTF-8(CSV)或标准 Excel 格式
- 第一行必须为列标题
- 文件大小不超过 50MB
### 可选输入
- **目标列**:指定分析哪些列,默认分析所有数值列
- **输出格式**:`table`(表格)或 `text`(文字摘要),默认 `table`
- **精度**:保留小数位数,默认 2 位
### 输入缺失时的处理
若文件未上传,告知用户:"请上传需要分析的 CSV 或 Excel 文件。"
若文件格式不支持,告知用户并列出支持的格式列表。
输出规范的三个维度
维度一:输出内容
明确指定输出什么内容,避免遗漏或过度输出。
实例
## 输出内容
分析完成后,提供以下内容:
1. **统计摘要表格**:各列的行数、均值、最大/最小值、空值数量
2. **数据质量报告**:列出发现的问题(如空值过多、数据类型混乱)
3. **文件路径**:若生成了输出文件,提供下载路径
分析完成后,提供以下内容:
1. **统计摘要表格**:各列的行数、均值、最大/最小值、空值数量
2. **数据质量报告**:列出发现的问题(如空值过多、数据类型混乱)
3. **文件路径**:若生成了输出文件,提供下载路径
维度二:输出格式
指定输出用哪种格式呈现,以及存储到哪里。
| 输出目标 | 格式 | 存储路径 |
|---|---|---|
| 在对话中展示 | Markdown 表格、代码块 | 无需存储 |
| 可下载文件 | .xlsx、.pdf、.html | /mnt/user-data/outputs/ |
| 中间结果 | JSON、CSV | /home/claude/(临时) |
维度三:输出时机
指定什么时候输出,是一次性全部输出,还是分步骤逐步展示。
实例
## 输出时机
1. **读取文件后**:立即告知用户文件的基本信息(行数、列数、大小)
2. **分析进行中**:若分析耗时超过 10 秒,先输出进度提示
3. **分析完成后**:输出完整的统计摘要
4. **文件生成后**:展示文件路径,并调用 present_files 工具
1. **读取文件后**:立即告知用户文件的基本信息(行数、列数、大小)
2. **分析进行中**:若分析耗时超过 10 秒,先输出进度提示
3. **分析完成后**:输出完整的统计摘要
4. **文件生成后**:展示文件路径,并调用 present_files 工具
完整的输入输出规范示例
以下是一个文档摘要 Skill 的完整输入输出规范:
实例
---
name: doc-summarizer
description: >
对用户上传的文档进行摘要提取,支持 PDF、Word(.docx)、纯文本。
当用户需要快速了解文档内容、提取关键信息、生成文档摘要时使用。
---
# 文档摘要器
## 输入规范
### 必填
- 文档文件(.pdf、.docx 或 .txt)
### 可选
- **摘要长度**:`short`(3句)/ `medium`(1段)/ `long`(3段),默认 `medium`
- **语言**:输出语言,默认与原文相同
- **重点方向**:如"重点关注结论部分"、"提取数字数据"
### 异常处理
- 文件超过 10MB:告知用户文件过大,建议分割后上传
- 格式不支持:列出支持的格式并请用户重新上传
- 文档为图片扫描件且无法识别文字:告知无法处理,建议使用 OCR 工具预处理
## 输出规范
### 输出内容(按顺序)
1. 文档基本信息:标题(若有)、页数、字数估计
2. 核心摘要:按用户指定长度输出
3. 关键词:5-8 个主题关键词
### 输出格式
- 全部在对话中展示,使用 Markdown 格式
- 不生成额外文件,除非用户明确要求保存
### 输出示例
---
**文档**:runoob-annual-report.pdf(24页,约 12,000 字)
**摘要**:本报告回顾了 runoob 年度业务表现,用户量同比增长 35%,
技术文档覆盖率提升至 98%。收入结构趋向多元化,广告与会员收入比例持平。
**关键词**:年度报告、用户增长、技术文档、收入结构、多元化
---
name: doc-summarizer
description: >
对用户上传的文档进行摘要提取,支持 PDF、Word(.docx)、纯文本。
当用户需要快速了解文档内容、提取关键信息、生成文档摘要时使用。
---
# 文档摘要器
## 输入规范
### 必填
- 文档文件(.pdf、.docx 或 .txt)
### 可选
- **摘要长度**:`short`(3句)/ `medium`(1段)/ `long`(3段),默认 `medium`
- **语言**:输出语言,默认与原文相同
- **重点方向**:如"重点关注结论部分"、"提取数字数据"
### 异常处理
- 文件超过 10MB:告知用户文件过大,建议分割后上传
- 格式不支持:列出支持的格式并请用户重新上传
- 文档为图片扫描件且无法识别文字:告知无法处理,建议使用 OCR 工具预处理
## 输出规范
### 输出内容(按顺序)
1. 文档基本信息:标题(若有)、页数、字数估计
2. 核心摘要:按用户指定长度输出
3. 关键词:5-8 个主题关键词
### 输出格式
- 全部在对话中展示,使用 Markdown 格式
- 不生成额外文件,除非用户明确要求保存
### 输出示例
---
**文档**:runoob-annual-report.pdf(24页,约 12,000 字)
**摘要**:本报告回顾了 runoob 年度业务表现,用户量同比增长 35%,
技术文档覆盖率提升至 98%。收入结构趋向多元化,广告与会员收入比例持平。
**关键词**:年度报告、用户增长、技术文档、收入结构、多元化
---
脚本层面的输入输出约定
如果 Skill 附带脚本,建议使用 JSON 作为结构化输入输出格式,便于 Claude 解析结果。
实例
# 文件路径:scripts/summarize.py
# 标准化的 JSON 输入输出模式
import json
import sys
def summarize(file_path: str, length: str = "medium") -> dict:
"""
对文档进行摘要
参数:
file_path: 文档路径(必填)
length: 摘要长度,short/medium/long(可选,默认 medium)
返回:
dict,包含 status、data 或 error 字段
"""
try:
# 模拟读取文档
with open(file_path, "r", encoding="utf-8") as f:
content = f.read()
# 模拟生成摘要
summary = content[:200] + "..." # 实际应调用真实摘要逻辑
return {
"status": "success",
"data": {
"word_count": len(content),
"summary": summary,
"length": length
}
}
except FileNotFoundError:
return {"status": "error", "error": f"文件不存在:{file_path}"}
except Exception as e:
return {"status": "error", "error": str(e)}
if __name__ == "__main__":
file_path = sys.argv[1] if len(sys.argv) > 1 else ""
length = sys.argv[2] if len(sys.argv) > 2 else "medium"
result = summarize(file_path, length)
# 统一输出 JSON,便于 Claude 解析
print(json.dumps(result, ensure_ascii=False, indent=2))
# 标准化的 JSON 输入输出模式
import json
import sys
def summarize(file_path: str, length: str = "medium") -> dict:
"""
对文档进行摘要
参数:
file_path: 文档路径(必填)
length: 摘要长度,short/medium/long(可选,默认 medium)
返回:
dict,包含 status、data 或 error 字段
"""
try:
# 模拟读取文档
with open(file_path, "r", encoding="utf-8") as f:
content = f.read()
# 模拟生成摘要
summary = content[:200] + "..." # 实际应调用真实摘要逻辑
return {
"status": "success",
"data": {
"word_count": len(content),
"summary": summary,
"length": length
}
}
except FileNotFoundError:
return {"status": "error", "error": f"文件不存在:{file_path}"}
except Exception as e:
return {"status": "error", "error": str(e)}
if __name__ == "__main__":
file_path = sys.argv[1] if len(sys.argv) > 1 else ""
length = sys.argv[2] if len(sys.argv) > 2 else "medium"
result = summarize(file_path, length)
# 统一输出 JSON,便于 Claude 解析
print(json.dumps(result, ensure_ascii=False, indent=2))
{
"status": "success",
"data": {
"word_count": 12480,
"summary": "runoob 年度报告回顾了平台在过去一年的业务表现...",
"length": "medium"
}
}
使用 JSON 作为脚本输出格式,让 Claude 可以稳定地解析结果,而不需要对自由文本进行猜测性解读。
