关于 writing-openapi-specs
writing-openapi-specs 是编写和改进 OpenAPI 规范的参考技能,面向 API 设计与文档工作。它汇总命名约定、复杂模式、可复用组件及面向 SDK 生成的编写建议。
主要功能
- 01命名与组织约定
- 02模式和多态结构示例
- 03请求、响应及流式传输指南
- 04可复用组件建议
- 05示例与文档编写规范
- 06SDK 生成注意事项
适用场景
- 01起草新的 OpenAPI 规范
- 02改进操作名称和描述
- 03建模可空或多态数据
- 04为 SDK 生成准备规范
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ speakeasy-api/ sdk-generation-skills --skill writing-openapi-specs安装后在 Claude Code 中输入/writing-openapi-specs确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
reference/components.mdexamples.mdoperations.mdparameters.mdrequest-bodies.mdresponses.mdschemas.mdsecurity.md详细介绍
编写 OpenAPI 规范
OpenAPI 最佳实践和约定参考。本技能为 OpenAPI 规范本身未涵盖的风格、约定和灰色地带提供指导。
何时使用此技能
- 编写新的 OpenAPI 规范
- 改进操作命名和组织方式
- 表达复杂数据类型(枚举、多态、可空)
- 处理文件上传、流式传输或服务器发送事件
- 让规范更适合代码生成
- 了解可复用模式(components 与内联定义)
核心原则
命名约定
操作 ID:使用小写字母和下划线,遵循 resource_action 模式:
# Good
operationId: users_list
operationId: users_get
operationId: users_create
# Avoid
operationId: GetApiV1Users # Auto-generated, not semantic
组件名称:对 schemas、parameters 和其他可复用组件使用 PascalCase:
components:
schemas:
UserProfile: # PascalCase
OrderHistory: # PascalCase
parameters:
PageLimit: # PascalCase
标签:使用小写字母和连字符,创建便于机器处理的标签:
tags:
- name: user-management
description: Operations for managing users
- name: order-processing
description: Operations for processing orders
更多详情,请参阅 reference/operations.md 和 reference/components.md。
文档标准
使用 CommonMark:所有 description 字段均支持 CommonMark 语法,以实现丰富格式:
description: |
Retrieves a user by ID.
## Authorization
Requires `users:read` scope.
## Rate Limits
- 100 requests per minute per API key
- 1000 requests per hour per IP
具体明确:提供可执行的信息,而非泛泛的描述:
# Good
description: Returns a paginated list of active users, ordered by creation date (newest first)
# Avoid
description: Gets users
优先使用 examples 而非 example:复数形式的 examples 字段更有利于生成 SDK:
# Good
examples:
basic_user:
value:
id: 123
name: "John Doe"
admin_user:
value:
id: 456
name: "Jane Admin"
role: admin
# Avoid single example
example:
id: 123
name: "John Doe"
更多详情,请参阅 reference/examples.md。
可复用性
适合创建 components 的内容:
- 多个操作中使用的 schemas
- 通用参数(分页、筛选)
- 通用响应(错误、成功模式)
- 安全方案
适合内联定义的内容:
- 特定操作的请求体
- 独特的响应结构
- 一次性参数
# Reusable schema
components:
schemas:
User:
type: object
properties:
id: {type: integer}
name: {type: string}
# Reference it
paths:
/users/{id}:
get:
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/User'
更多详情,请参阅 reference/components.md。
复杂模式速查
以下模式通常较难处理。下面提供简要示例,并附有详细指南的链接。
枚举
使用字符串枚举,并选择清晰且有语义的值:
type: string
enum:
- pending
- approved
- rejected
- cancelled
避免使用:
- 数字字符串("0"、"1"、"2")
- 通用值("value1"、"value2")
- 含义不明的缩写("pnd"、"appr")
更多内容,请参阅 reference/schemas.md#enums。
多态(oneOf/allOf/anyOf)
oneOf:值恰好匹配一个 schema(类型判别)
PaymentMethod:
oneOf:
- $ref: '#/components/schemas/CreditCard'
- $ref: '#/components/schemas/BankAccount'
- $ref: '#/components/schemas/PayPal'
discriminator:
propertyName: type
mapping:
credit_card: '#/components/schemas/CreditCard'
bank_account: '#/components/schemas/BankAccount'
paypal: '#/components/schemas/PayPal'
allOf:值匹配所有 schemas(组合/继承)
AdminUser:
allOf:
- $ref: '#/components/schemas/User'
- type: object
properties:
permissions:
type: array
items: {type: string}
anyOf:值匹配一个或多个 schemas(灵活的联合)
SearchFilter:
anyOf:
- $ref: '#/components/schemas/TextFilter'
- $ref: '#/components/schemas/DateFilter'
- $ref: '#/components/schemas/NumericFilter'
详细指导,请参阅 reference/schemas.md#polymorphism。
判别器
将判别器与 oneOf 配合使用,以高效识别类型:
Pet:
oneOf:
- $ref: '#/components/schemas/Dog'
- $ref: '#/components/schemas/Cat'
discriminator:
propertyName: petType
mapping:
dog: '#/components/schemas/Dog'
cat: '#/components/schemas/Cat'
Dog:
type: object
required: [petType, bark]
properties:
petType:
type: string
enum: [dog]
bark:
type: string
Cat:
type: object
required: [petType, meow]
properties:
petType:
type: string
enum: [cat]
meow:
type: string
更多内容,请参阅 reference/schemas.md#discriminators。
可空类型
根据 OpenAPI 版本采用不同方式处理 null 值:
OpenAPI 3.1(符合 JSON Schema 2020-12):
type: [string, "null"]
# or
type: string
nullable: true # Still supported for compatibility
OpenAPI 3.0:
type: string
nullable: true
对于可选字段,请使用 required 数组:
type: object
properties:
name: {type: string} # Can be omitted
email: {type: string} # Can be omitted
required: [name] # email is optional
更多内容,请参阅 reference/schemas.md#nullable。
文件上传
使用 multipart/form-data 上传文件:
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
properties:
file:
type: string
format: binary
metadata:
type: object
properties:
description: {type: string}
tags:
type: array
items: {type: string}
required: [file]
在 JSON 中使用 Base64 编码文件:
requestBody:
content:
application/json:
schema:
type: object
properties:
filename: {type: string}
content:
type: string
format: byte # base64-encoded
更多内容,请参阅 reference/request-bodies.md#file-uploads。
服务器发送事件(SSE)
使用 text/event-stream 描述流式响应:
responses:
'200':
description: Stream of events
content:
text/event-stream:
schema:
type: string
description: |
Server-sent events stream. Each event follows the format:
```
event: message
data: {"type": "update", "content": "..."}
```
examples:
notification_stream:
value: |
event: message
data: {"type": "notification", "message": "New order received"}
event: message
data: {"type": "notification", "message": "Order processing complete"}
更多模式,请参阅 reference/responses.md#streaming。
字段参考
各主要 OpenAPI 字段的详细指南:
- 操作:操作 ID、方法、标签、弃用 → reference/operations.md
- 架构:数据类型、多态、枚举、可空 → reference/schemas.md
- 参数:路径、查询、标头、Cookie 参数 → reference/parameters.md
- 请求体:内容类型、文件上传、编码 → reference/request-bodies.md
- 响应:状态码、流式传输、错误模式 → reference/responses.md
- 组件:可复用定义、组织方式 → reference/components.md
- 安全性:身份验证方案、作用域、精细控制 → reference/security.md
- 示例:单个和多个示例、放置位置 → reference/examples.md
SDK 生成注意事项
编写用于生成 SDK 的规范时:
- 始终定义
operationId:这是生成有意义的方法名所必需的 - 提供丰富的示例:有助于生成更好的文档和测试
- 明确说明必需字段:这会影响 SDK 方法签名
- 在 oneOf 中使用判别器:可生成类型安全的联合类型
- 记录错误响应:可生成更好的错误处理代码
适用于 SDK 的操作示例:
paths:
/users:
get:
operationId: users_list
summary: List all users
description: Returns a paginated list of users
parameters:
- name: limit
in: query
schema: {type: integer, default: 20}
- name: offset
in: query
schema: {type: integer, default: 0}
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
required: [data, pagination]
properties:
data:
type: array
items:
$ref: '#/components/schemas/User'
pagination:
$ref: '#/components/schemas/PaginationInfo'
examples:
success:
value:
data: [{id: 1, name: "Alice"}, {id: 2, name: "Bob"}]
pagination: {total: 100, limit: 20, offset: 0}
这会生成:sdk.users.list({limit: 20, offset: 0})
常见陷阱
不要:
- 使用“获取数据”或“返回对象”这类泛泛的描述
- 混用命名约定(选定一种风格并坚持使用)
- 忘记
operationId(会导致自动生成名称) - 需要
examples时使用example(复数形式更好) - 将所有字段都设为必需(谨慎考虑可选字段)
- 将所有内容都内联(使用组件以便复用)
- 对所有内容都使用引用(简单且只用一次的架构应内联)
- 忘记记录错误响应
- 使用没有说明的魔法数字
- 遗漏内容类型(应明确指定)
应该:
- 提供可操作且具体的描述
- 在全文使用一致的命名模式
- 为每个操作定义清晰的
operationId - 使用带命名示例的
examples(复数形式) - 仔细考虑必需字段与可选字段
- 在可复用性与清晰度之间取得平衡
- 记录所有预期响应(成功和错误)
- 说明约束和验证规则
- 明确指定内容类型和格式