OpenAI API 中的技能
来源: https://developers.openai.com/cookbook/examples/skills_in_api 抓取时间: 2026-07-21 16:19:35
上传、管理可重用技能并将其附加到托管环境。智能体技能让您可以在托管和本地 Shell 环境中上传和重用版本化的文件包。完整参考请参阅 技能文档。
什么是技能?
技能是可重用的文件包(指令 + 脚本 + 资源),打包为文件夹并以必需的 SKILL.md 清单为锚点。OpenAI 将该包复制到执行环境中,以便模型可以根据需要读取指令和运行代码。
在托管 Shell 中,当您将技能附加到 Shell 工具环境 (environment.type="container_auto") 时会发生以下情况:
- 服务将技能上传并解压到运行时中
- 服务读取
SKILL.md前置元数据(名称/描述),然后将每个技能的name、description和path添加到隐藏的系统提示上下文中,让模型知道该技能存在 - 如果模型决定调用某个技能,它会使用
path读取SKILL.md,然后通过 Shell 工具探索文件并执行脚本
技能用于过程:可重复的工作流,其中_方法_很重要(步骤、分支逻辑、格式规则、脚本)。技能适用于以下情况:
- 跨提示/智能体重用
- 版本化并独立交付
- 仅在需要时调用(不嵌入每个系统提示)
何时使用技能
技能特别适合且强大,当…
- 您想要一组可重用、可独立版本化的行为。 示例:"PowerPoint 格式化程序"、"公司特定报告生成器"、"标准数据清理管道"。
- 您的工作流是高度条件性的,或者像复杂流程图一样分支。 示例:如果 X → 执行此操作;否则如果 Y → 执行该操作;加上验证 + 重试。
- 您的工作流需要代码执行和本地工件。 任何受益于脚本、模板、测试夹具或参考资源的内容,这些都应该放在指令旁边。技能被设计为这些资源的 zip 包。
- 您希望保持系统提示精简。 将稳定的过程放在技能中;将全局行为保留在系统提示中。
- 多个智能体或团队共享相同的"组织风格"。 技能是一个很好的"组织标准库"模式。
- 您需要可重复性 技能通过技能版本(见下面的版本控制部分)天然兼容版本固定。
技能不太理想,当…
- 这确实是一个 一次性 任务(对话中的快速内联脚本就可以了)。
- 您主要需要 实时外部数据或副作用。(那是工具/API 调用)。
- 过程每天都在变化(技能在工作流稳定时发挥作用)。
技能 vs. 工具 vs. 系统提示
当边界不清晰时,系统提示和工具模式会变得沉重。使用所有这三者来保持有条理并帮助模型更好地执行。这是一个简单的框架:
系统提示:全局行为和约束 适用于:
- 安全边界、语气、拒绝风格
- 每轮都适用的"始终执行 X"原则
- 小型、稳定的策略
避免:
- 在这里放置长的多步过程(它会使每轮臃肿并变得脆弱)
工具:"在世界中做某事" 当模型必须执行以下操作时使用工具:
- 调用外部服务或数据库
- 创建副作用(环境外的任务,如取消订单或发送电子邮件)
- 获取实时状态
工具应该:
- 范围狭窄
- 具有强类型输入
- 对副作用明确
技能:打包过程(+ 代码 + 资源) 当您希望模型执行以下操作时使用技能:
- 遵循可重复的工作流
- 使用脚本/模板
- 在沙箱中执行代码
- 有时执行,而非总是执行
技能打包:SKILL.md 和文件夹布局
文件夹结构
技能只是一个文件夹包。这是一个示例:
SKILL.md(必需)- 脚本,如
*.py、*.js(可选) - 辅助工具和
requirements.txt - 资源、模板、示例输入
SKILL.md 前置元数据
OpenAI 模型期望名称和描述来自前置元数据(这对于发现和路由很重要)。将名称和描述放在 SKILL.md 前置元数据中。使用每个 API create 调用来上传一个技能包(一个顶层文件夹),其中包含恰好一个 SKILL.md/skill.md。要上传多个技能,请上传多个包。
通过 API 创建技能
在文件夹中组装好技能后,使用 API 调用创建技能。
目录上传或 zip 上传
使用 POST /v1/skills 上传和验证您的技能,从清单前置元数据中提取名称和描述。您可以上传 zip 包或在请求中上传多个文件。
选项 A:上传文件(多部分)
curl -X POST 'https://api.openai.com/v1/skills' \
-H "Authorization: Bearer ***" \
-F 'files[]=@./csv_insights_skill/SKILL.md;filename=csv_insights_skill/SKILL.md;type=text/markdown' \
-F 'files[]=@./csv_insights_skill/calculate.py;filename=csv_insights_skill/calculate.py;type=text/plain'
选项 B:上传 zip
curl -X POST 'https://api.openai.com/v1/skills' \
-H "Authorization: Bearer ***" \
-F 'files=@./csv_insights_skill.zip;type=application/zip'
如果遇到服务器错误,本地 zip 并上传 zip。我们在内部遇到过这种情况,发现这是一个实用的解决方法。
技能对象和版本指针 技能返回标识符和版本指针(例如,默认、最新)。版本指针出现在平台更改和测试中。
将技能挂载到执行中
模型通过 Shell 和容器使用技能。要在 Responses API 中使用技能,请使用 tools[].environment.skills 将它们附加到 Shell 工具。
如何引用技能
指定环境,托管或本地 Shell。托管 vs. 本地
- 托管 Shell:
environment.type="container_auto" - 本地 Shell:
environment.type="local"
技能可以引用为:
skill_reference(通过skill_id,可选带有version或"latest")inline(base64 zip 包)当您不想创建托管技能时
可运行示例:csvinsightsskill 技能
1) 创建技能文件夹。
csv_insights_skill/
├── SKILL.md
├── requirements.txt
├── run.py
└── assets/
└── example.csv
2) 创建您的 SKILL.md
---
name: csv-insights
description: Summarize a CSV, compute basic stats, and produce a markdown report + a plot image.
---
# CSV Insights Skill
## When to use this
Use this skill when the user provides a CSV file and wants:
- a quick summary (row/col counts, missing values)
- basic numeric statistics
- a simple visualization
- results packaged into an output folder (or zip)
## Inputs
- A CSV file path (local) or a file mounted in the container.
## Outputs
- `output/report.md`
- `output/plot.png`
## How to run
python -m pip install -r requirements.txt
python run.py --input assets/example.csv --outdir output
3) 创建您的 run.py
import argparse
from pathlib import Path
import pandas as pd
import matplotlib.pyplot as plt
def write_report(df: pd.DataFrame, outpath: Path) -> None:
lines = []
lines.append(f"# CSV Insights Report\n")
lines.append(f"**Rows:** {len(df)} \n**Columns:** {len(df.columns)}\n")
lines.append("\n## Columns\n")
lines.append("\n".join([f"- `{c}` ({df[c].dtype})" for c in df.columns]))
missing = df.isna().sum()
if missing.any():
lines.append("\n## Missing values\n")
for col, count in missing[missing > 0].items():
lines.append(f"- `{col}`: {int(count)}")
else:
lines.append("\n## Missing values\nNo missing values detected.\n")
numeric = df.select_dtypes(include="number")
if not numeric.empty:
lines.append("\n## Numeric summary (describe)\n")
lines.append(numeric.describe().to_markdown())
outpath.write_text("\n".join(lines), encoding="utf-8")
def make_plot(df: pd.DataFrame, outpath: Path) -> None:
numeric = df.select_dtypes(include="number")
if numeric.empty:
# No numeric columns → skip plotting
return
# Plot the first numeric column as a simple histogram
col = numeric.columns[0]
plt.figure()
df[col].dropna().hist(bins=30)
plt.title(f"Histogram: {col}")
plt.xlabel(col)
plt.ylabel("Count")
plt.tight_layout()
plt.savefig(outpath)
plt.close()
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--input", required=True, help="Path to input CSV")
parser.add_argument("--outdir", required=True, help="Directory for outputs")
args = parser.parse_args()
inpath = Path(args.input)
outdir = Path(args.outdir)
outdir.mkdir(parents=True, exist_ok=True)
df = pd.read_csv(inpath)
write_report(df, outdir / "report.md")
make_plot(df, outdir / "plot.png")
if __name__ == "__main__":
main()
4) Zip 它(推荐)
zip -r csv_insights_skill.zip csv_insights_skill
5) 上传技能
curl -X POST 'https://api.openai.com/v1/skills' \
-H "Authorization: Bearer ***" \
-F 'files=@./csv_insights_skill.zip;type=application/zip'
6) 通过 API 运行技能(托管 Shell 模式)
遵循以下流程:创建技能 → 使用 Shell 工具调用 Responses API,其中 environment.skills 引用该技能
概念上:
from openai import OpenAI
client = OpenAI()
response = client.responses.create(
model="gpt-5.2",
tools=[{
"type": "shell",
"environment": {
"type": "container_auto",
"skills": [
{"type": "skill_reference", "skill_id": "<skill_id>"},
{"type": "skill_reference", "skill_id": "<skill_id>", "version": 2},
],
},
}],
input="Use the skills to analyze the uploaded CSV and write outputs to /mnt/output."
)
print(response.output_text)
7) 通过 API 使用此技能(本地容器模式) 技能也适用于本地 Shell 模式。技能选择和提示行为与托管 Shell 模式相同,但命令执行和文件系统访问仍由您的本地运行时处理。
概念上:
from openai import OpenAI
client = OpenAI()
response = client.responses.create(
model="gpt-5.2",
tools=[
{
"type": "shell",
"environment": {
"type": "local",
"skills": [
{"type": "skill_reference", "skill_id": "<skill_id>"},
{"type": "skill_reference", "skill_id": "<skill_id>", "version": 2},
],
},
}
],
input="Use the configured skills and run locally to summarize today's CSV reports in this repo.",
)
print(response.output_text)
操作最佳实践
1) 保持技能"可发现"
-
在前置元数据中放置 清晰的
name和description。 -
在
SKILL.md中包含:何时使用、如何运行、预期输出、注意事项。 -
添加明确的路由指导:"使用当…" vs. "不使用当…",以及一些关键边缘情况,全部放在
SKILL.md中。 -
在正面示例旁边包含反面示例(技能不应该被触发时)以提高路由准确性。
-
如果路由感觉不一致,在更改代码之前迭代名称、描述和示例。
这在"批量上传"讨论中出现:名称和描述应该来自前置元数据,并且您应该先用少量测试。
2) 优先选择 zip 上传以提高可靠性和可重复性
- Zip 是可移植的,易于版本化,并且在上传行为异常时是有用的解决方法。
3) 在生产环境中版本固定 您希望能够说"运行此过程版本",而不是"运行最新的任何版本"。技能正朝着显式版本(default_version、latest_version)发展,并且版本创建端点正在积极开发中。
- 如何固定:
version: 2 - 如何浮动:
version: "latest" - 省略时会发生什么:默认为
default_version
考虑将模型和技能版本固定在一起,以便在部署中获得可重复的行为。
4) 将技能设计成小型 CLI 一个好的技能脚本:
- 从命令行运行
- 打印确定性的标准输出
- 以使用方式/错误大声失败
- 需要时将输出写入已知文件路径
在技能内添加具体模板和工作示例(输入 → 命令 → 预期输出);在不调用技能的轮次上它们没有成本。当示例是工作流特定的时,优先选择技能中的示例和模板,而不是系统级的少样本提示。
5) 避免在系统提示中复制技能 如果系统提示重复整个过程,人们会:
- 绕过技能
- 将逻辑塞进工具模式
而且您会失去技能的全部意义(可重用性 + 版本控制 + 条件调用)。保持系统提示内容独立。
6) 网络访问 将技能与开放网络访问结合使用是高风险的。如果必须使用网络访问,请使用严格的白名单并将工具输出视为不受信任。对于面向消费者的应用程序,用户期望确认控制,请避免此配置。如果需要网络访问,请将白名单与明确的"允许什么数据离开"指导配对。
7) 使用能够可靠执行多步工作流的模型
当模型在长上下文推理和多步工具执行(文件系统导航、CLI 运行、验证)方面很强时,技能效果最佳。如果您看到部分完成或脆弱的执行,请升级模型或简化工作流,并在 SKILL.md 中添加明确的验证步骤和输出检查。
限制和验证
SKILL.md匹配不区分大小写- 仅允许一个清单文件(
skill.md/SKILL.md) - 前置元数据验证遵循智能体技能规范(名称字段)
- 最大 zip 上传大小:50 MB
- 每个技能版本的最大文件数:500
- 最大未压缩文件大小:25 MB
结论
技能是提示和工具之间缺失的"中间层":提示 定义始终开启的行为,工具 提供原子能力和副作用,技能 打包模型可以 仅在需要时挂载和执行的 可重复过程(指令 + 脚本 + 资源)。
使用技能保持系统提示精简和工作流持久。 从小处着手——用清晰的 SKILL.md 打包一个稳定过程,使其可以作为小型 CLI 运行,然后交付。在生产环境中运行后,固定版本以提高可重复性,通过发布新版本安全迭代,并将您的技能库像内部标准库一样对待:经过审计、可发现并跨智能体共享。
随着用户从单轮助手扩展到长期运行的智能体,技能有助于将"提示意大利面"转变为 可维护、可测试、版本化的工作流——用于构建您可以信任、重用和随时间演变的智能体行为。
要开始使用技能,请查看我们的 文档。