ワンクリックで
api-development
FastGPT API 开发规范。重点强调使用 zod schema 定义入参和出参,在 API 文档中声明路由信息,编写对应的 OpenAPI 文档,以及在 API 路由中使用 schema.parse 进行验证。
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
FastGPT API 开发规范。重点强调使用 zod schema 定义入参和出参,在 API 文档中声明路由信息,编写对应的 OpenAPI 文档,以及在 API 路由中使用 schema.parse 进行验证。
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
手动触发的 FastGPT PR 或本地分支变更梳理技能。仅当用户显式调用 $pr-change-analysis 时使用;用于 reviewer 分析一个 GitHub PR 或当前本地分支相对 upstream/main 的需求变更、影响范围、代码质量与代码风格,不用于自动审查触发。
仅当用户明确手动指定使用 pr-review skill 时触发;不要因为用户传入 PR 链接、要求 review 或要求代码审查而自动触发。
将 FastGPT 文档从中文翻译为面向北美用户的英文。当用户提到翻译文档、i18n、国际化、translate docs、新增/修改了中文文档需要同步英文版时,使用此 skill。也适用于用户要求检查文档翻译缺失、批量翻译、或对比中英文文档差异的场景。
| name | api-development |
| description | FastGPT API 开发规范。重点强调使用 zod schema 定义入参和出参,在 API 文档中声明路由信息,编写对应的 OpenAPI 文档,以及在 API 路由中使用 schema.parse 进行验证。 |
FastGPT 项目 API 路由开发的标准化指南,确保 API 的一致性、类型安全和文档完整性。
文件位置: packages/global/openapi/[module]/[api].ts
文件头部必须声明 API 信息:
import { z } from 'zod';
/* ============================================================================
* API: 获取应用对话日志列表
* Route: POST /api/core/app/logs/list
* Method: POST
* Description: 获取指定应用的对话日志列表,支持分页和多种筛选条件
* Tags: ['App', 'Log', 'Read']
* ============================================================================ */
// 入参 Schema
export const GetAppChatLogsBodySchema = PaginationSchema.extend({
appId: z.string().meta({
example: '68ad85a7463006c963799a05',
description: '应用 ID'
}),
dateStart: z.union([z.string(), z.date()]).meta({
example: '2024-01-01T00:00:00.000Z',
description: '开始时间'
}),
dateEnd: z.union([z.string(), z.date()]).meta({
example: '2024-12-31T23:59:59.999Z',
description: '结束时间'
}),
sources: z.array(z.nativeEnum(ChatSourceEnum)).optional().meta({
example: [ChatSourceEnum.api, ChatSourceEnum.online],
description: '对话来源筛选'
})
});
// 导出入参类型
export type getAppChatLogsBody = z.infer<typeof GetAppChatLogsBodySchema>;
// 出参 Schema
export const GetAppChatLogsResponseSchema = z.object({
total: z.number().meta({ example: 100, description: '总记录数' }),
list: z.array(ChatLogItemSchema)
});
// 导出出参类型
export type getAppChatLogsResponseType = z.infer<typeof GetAppChatLogsResponseSchema>;
API 声明规范:
/**
* 每个 API 文件必须在文件头部声明以下信息:
*
* 1. API 名称 (API): 简短的功能描述
* 2. 路由 (Route): 完整的 API 路径
* 3. 方法 (Method): HTTP 方法 (GET/POST/PUT/DELETE)
* 4. 描述 (Description): API 的详细功能说明
* 5. 标签 (Tags): API 的分类标签数组
*
* 标签示例:
* - 'App': 应用相关 API
* - 'User': 用户相关 API
* - 'Log': 日志相关 API
* - 'Read': 只读操作
* - 'Write': 写入操作
* - 'Delete': 删除操作
*/
OpenAPI Tag 归属规则:
协作者管理 是通用权限能力,应用协作者接口需要同时声明 协作者管理 和应用侧 权限管理;获取应用权限、恢复应用继承权限 是应用自身权限状态接口,只声明应用侧 权限管理。Schema 定义规范:
// ✅ 好的实践: 完整的 meta 信息
export const GetUserSchema = z.object({
userId: z.string().meta({
example: '68ad85a7463006c963799a05',
description: '用户 ID'
}),
email: z.string().email().meta({
example: 'user@example.com',
description: '用户邮箱'
}),
age: z.number().int().positive().meta({
example: 25,
description: '用户年龄'
}),
status: z.enum(['active', 'inactive']).meta({
example: 'active',
description: '用户状态'
})
});
// ❌ 不好的实践: 缺少 meta 信息
export const GetUserSchemaBad = z.object({
userId: z.string(),
email: z.string(),
age: z.number(),
status: z.string()
});
// 嵌套对象应该定义为独立的 Schema
export const AddressSchema = z.object({
street: z.string().meta({ description: '街道地址' }),
city: z.string().meta({ description: '城市' }),
country: z.string().meta({ description: '国家' })
});
export const CreateUserSchema = z.object({
name: z.string().meta({ description: '用户名' }),
address: AddressSchema.meta({ description: '地址信息' })
});
export const GetUserListResponseSchema = z.object({
total: z.number().meta({ example: 100, description: '总数' }),
list: z.array(
z.object({
id: z.string().meta({ description: '用户 ID' }),
name: z.string().meta({ description: '用户名' })
})
).meta({ description: '用户列表' })
});
export const UpdateUserSchema = z.object({
userId: z.string().meta({ description: '用户 ID' }),
// 可选字段使用 .optional()
name: z.string().optional().meta({ description: '用户名' }),
// 或使用 .nullish() 允许 null 和 undefined
email: z.string().email().nullish().meta({ description: '用户邮箱' })
});
import { PaginationSchema } from '@fastgpt/global/openapi/api';
// 继承分页 Schema
export const GetUserListSchema = PaginationSchema.extend({
// 添加额外的筛选字段
keyword: z.string().optional().meta({ description: '搜索关键词' }),
status: z.enum(['active', 'inactive']).optional().meta({ description: '状态筛选' })
});
/* ============================================================================
* API: 获取日志键
* Route: GET /api/core/app/logs/keys
* Method: GET
* Description: 获取应用的日志配置键列表
* Tags: ['App', 'Log', 'Read']
* ============================================================================ */
export const GetLogKeysQuerySchema = z.object({
appId: z.string().meta({ description: '应用 ID' })
});
export const GetLogKeysResponseSchema = z.object({
logKeys: z.array(AppLogKeysSchema).meta({ description: '日志键列表' })
});
/* ============================================================================
* API: 更新日志键
* Route: POST /api/core/app/logs/keys
* Method: POST
* Description: 更新应用的日志配置键
* Tags: ['App', 'Log', 'Write']
* ============================================================================ */
export const UpdateLogKeysBodySchema = z.object({
appId: z.string().meta({ description: '应用 ID' }),
logKeys: z.array(AppLogKeysSchema).meta({ description: '日志键列表' })
});
文件位置: projects/app/src/pages/api/[path]/[route].ts
标准实现模板:
import type { NextApiResponse } from 'next';
import { NextAPI } from '@/service/middleware/entry';
import type { ApiRequestProps } from '@fastgpt/service/type/next';
import {
GetAppChatLogsBodySchema,
GetAppChatLogsResponseSchema,
type getAppChatLogsResponseType
} from '@fastgpt/global/openapi/...';
async function handler(
req: ApiRequestProps,
_res: NextApiResponse
): Promise<getAppChatLogsResponseType> {
// 🔴 步骤 1: 使用 schema.parse() 验证入参
const { appId, dateStart, dateEnd, sources } = GetAppChatLogsBodySchema.parse(req.body);
// 或对于 query 参数
// const { param1, param2 } = YourAPIQuerySchema.parse(req.query);
// 🔴 步骤 2: 业务逻辑处理
const result = await yourBusinessLogic({ appId, dateStart, dateEnd, sources });
// 🔴 步骤 3: 使用 schema.parse() 验证出参
return GetAppChatLogsResponseSchema.parse({
list: result.list,
total: result.total
});
}
export default NextAPI(handler);
完整示例:
import type { NextApiResponse } from 'next';
import type { ApiRequestProps } from '@fastgpt/service/type/next';
import { NextAPI } from '@/service/middleware/entry';
import { authApp } from '@fastgpt/service/support/permission/app/auth';
import {
GetAppChatLogsBodySchema,
GetAppChatLogsResponseSchema,
type getAppChatLogsResponseType
} from '@fastgpt/global/openapi/core/app/log/api';
async function handler(
req: ApiRequestProps,
_res: NextApiResponse
): Promise<getAppChatLogsResponseType> {
// 🔴 1. 验证入参
const { appId, dateStart, dateEnd, sources } = GetAppChatLogsBodySchema.parse(req.body);
// 2. 权限验证 (如果需要)
await authApp({
req,
authToken: true,
appId,
per: AppReadChatLogPerVal
});
// 3. 业务逻辑
const { list, total } = await getChatLogsFromDB({
appId,
dateStart,
dateEnd,
sources
});
// 🔴 4. 验证出参
return GetAppChatLogsResponseSchema.parse({
list,
total
});
}
export default NextAPI(handler);
使用 authApp 或其他权限验证函数:
import { authApp } from '@fastgpt/service/support/permission/app/auth';
import { AppWritePerVal } from '@fastgpt/global/support/permission/app/constant';
async function handler(req: ApiRequestProps, res: NextApiResponse) {
const { appId } = YourAPIBodySchema.parse(req.body);
// 权限验证
await authApp({
req,
authToken: true,
appId,
per: AppWritePerVal // 权限常量
});
// 继续处理...
}
使用统一的错误处理:
import { APIError } from '@fastgpt/service/core/error/controller';
import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
async function handler(req: ApiRequestProps, res: NextApiResponse) {
try {
const { appId } = YourAPIBodySchema.parse(req.body);
if (!appId) {
return Promise.reject(CommonErrEnum.missingParams);
}
// 业务逻辑...
} catch (error) {
// 统一错误处理
return APIError(error)(req, res);
}
}
1. 定义 Schema (packages/global/openapi/core/user/api.ts):
import { z } from 'zod';
/* ============================================================================
* API: 创建用户
* Route: POST /api/core/user/create
* Method: POST
* Description: 创建新用户,返回创建的用户信息
* Tags: ['User', 'Write']
* ============================================================================ */
// 入参
export const CreateUserBodySchema = z.object({
name: z.string().min(2).max(50).meta({
example: 'Alice',
description: '用户名 (2-50 字符)'
}),
email: z.string().email().meta({
example: 'alice@example.com',
description: '用户邮箱'
}),
age: z.number().int().positive().optional().meta({
example: 25,
description: '用户年龄'
}),
avatar: z.string().url().optional().meta({
example: 'https://example.com/avatar.jpg',
description: '头像 URL'
})
});
export type createUserBodyType = z.infer<typeof CreateUserBodySchema>;
// 出参
export const CreateUserResponseSchema = z.object({
userId: z.string().meta({ example: '68ad85a7463006c963799a05', description: '用户 ID' }),
name: z.string().meta({ example: 'Alice', description: '用户名' }),
email: z.string().meta({ example: 'alice@example.com', description: '用户邮箱' }),
createdAt: z.date().meta({ example: '2024-01-01T00:00:00.000Z', description: '创建时间' })
});
export type createUserResponseType = z.infer<typeof CreateUserResponseSchema>;
2. 实现 API (projects/app/src/pages/api/core/user/create.ts):
import type { NextApiResponse } from 'next';
import { NextAPI } from '@/service/middleware/entry';
import type { ApiRequestProps } from '@fastgpt/service/type/next';
import { MongoUser } from '@fastgpt/service/core/user/schema';
import {
CreateUserBodySchema,
CreateUserResponseSchema,
type createUserResponseType
} from '@fastgpt/global/openapi/core/user/api';
async function handler(
req: ApiRequestProps,
_res: NextApiResponse
): Promise<createUserResponseType> {
// 🔴 验证入参
const { name, email, age, avatar } = CreateUserBodySchema.parse(req.body);
// 检查邮箱是否已存在
const existingUser = await MongoUser.findOne({ email });
if (existingUser) {
return Promise.reject('Email already exists');
}
// 创建用户
const user = await MongoUser.create({
name,
email,
age,
avatar,
createdAt: new Date()
});
// 🔴 验证出参
return CreateUserResponseSchema.parse({
userId: user._id.toString(),
name: user.name,
email: user.email,
createdAt: user.createdAt
});
}
export default NextAPI(handler);
Schema 文件 (packages/global/openapi/.../api.ts):
z.infer<typeof Schema> 类型description 和 exampleAPI 路由文件 (projects/app/src/pages/api/.../route.ts):
Schema.parse(req.body) 或 parse(req.query)Schema.parse(responseData)APIError 统一错误处理.optional() 或 .nullish()PaginationSchema错误示例:
// ❌ 错误: 缺少 API 声明
import { z } from 'zod';
export const GetUserSchema = z.object({
id: z.string()
});
正确做法:
// ✅ 正确: 包含完整的 API 声明
import { z } from 'zod';
/* ============================================================================
* API: 获取用户信息
* Route: GET /api/core/user/detail
* Method: GET
* Description: 根据 userId 获取用户详细信息
* Tags: ['User', 'Read']
* ============================================================================ */
export const GetUserSchema = z.object({
id: z.string().meta({
example: '68ad85a7463006c963799a05',
description: '用户 ID'
})
});
错误示例:
// ❌ 错误: 函数返回类型未声明
async function handler(req: ApiRequestProps, res: NextApiResponse) {
const data = YourAPIBodySchema.parse(req.body);
return { success: true, data }; // 类型未声明
}
正确做法:
// ✅ 正确: 声明返回类型
async function handler(
req: ApiRequestProps,
_res: NextApiResponse
): Promise<yourAPIResponseType> {
const data = YourAPIBodySchema.parse(req.body);
return YourAPIResponseSchema.parse({
success: true,
data
});
}
错误示例:
// ❌ 错误: 缺少 meta 信息
export const UserSchema = z.object({
id: z.string(),
name: z.string(),
email: z.string()
});
正确做法:
// ✅ 正确: 完整的 meta 信息
export const UserSchema = z.object({
id: z.string().meta({
example: '68ad85a7463006c963799a05',
description: '用户 ID'
}),
name: z.string().meta({
example: 'Alice',
description: '用户名'
}),
email: z.string().email().meta({
example: 'alice@example.com',
description: '用户邮箱'
})
});
错误示例:
// ❌ 错误: 直接返回数据
async function handler(req: ApiRequestProps, res: NextApiResponse) {
const { appId } = YourAPIBodySchema.parse(req.body);
const result = await getData(appId);
return result; // 未验证出参结构
}
正确做法:
// ✅ 正确: 验证出参
async function handler(req: ApiRequestProps, res: NextApiResponse) {
const { appId } = YourAPIBodySchema.parse(req.body);
const result = await getData(appId);
return YourAPIResponseSchema.parse(result);
}
不好做法:
// ❌ 重复定义相同的结构
export const Schema1 = z.object({
id: z.string(),
name: z.string(),
email: z.string()
});
export const Schema2 = z.object({
id: z.string(),
name: z.string(),
email: z.string()
});
正确做法:
// ✅ 抽取公共 Schema
export const BaseUserSchema = z.object({
id: z.string().meta({ description: 'ID' }),
name: z.string().meta({ description: '名称' }),
email: z.string().email().meta({ description: '邮箱' })
});
export const Schema1 = z.object({
user: BaseUserSchema
});
export const Schema2 = z.object({
users: z.array(BaseUserSchema)
});
/* ============================================================================
* API: [简短功能描述]
* Route: [HTTP 方法] [完整路由路径]
* Method: [GET/POST/PUT/DELETE]
* Description: [详细功能说明]
* Tags: [['模块', '子模块', '操作类型']]
* ============================================================================ */
App, User, Chat, Workflow, DatasetRead, Write, Delete, UpdateAdmin, Public, Internal// 字符串
z.string() // 字符串
.min(2) // 最小长度
.max(50) // 最大长度
.email() // 邮箱格式
.url() // URL 格式
.uuid() // UUID 格式
// 数字
z.number() // 数字
.int() // 整数
.positive() // 正数
.min(0) // 最小值
.max(100) // 最大值
// 布尔
z.boolean() // 布尔值
// 日期
z.date() // 日期对象
.or(z.string()) // 或日期字符串
// 枚举
z.enum(['active', 'inactive']) // 枚举值
z.nativeEnum(MyEnum) // TypeScript 枚举
// 数组
z.array(z.string()) // 字符串数组
.min(1) // 最小长度
.max(10) // 最大长度
// 可选
z.string().optional() // 可选 (undefined)
z.string().nullish() // 可空 (undefined | null)
// 对象
z.object({ // 对象
name: z.string(),
age: z.number()
})
// 继承
PaginationSchema.extend({ // 扩展
keyword: z.string()
})
// 联合类型
z.union([z.string(), z.number()]) // 字符串或数字
z.discriminator('type', { // 判别联合
type1: Type1Schema,
type2: Type2Schema
})
z.string().meta({
example: 'value', // 示例值 (必填)
description: '字段说明' // 字段描述 (必填)
})
// Schema 定义
export const UserSchema = z.object({
id: z.string(),
name: z.string()
});
// 导出类型 (命名规范: camelCase)
export type userType = z.infer<typeof UserSchema>;
// 或使用 PascalCase
export type UserType = z.infer<typeof UserSchema>;
/Volumes/code/fastgpt-pro/FastGPT/packages/global/openapi/core/app/log/api.ts/Volumes/code/fastgpt-pro/FastGPT/projects/app/src/pages/api/core/app/logs/list.tspackages/global/openapi/api.ts.claude/skills/pr-review/fastgpt-style-guide.md.claude/skills/pr-review/code-quality-standards.mdVersion: 1.0 Last Updated: 2026-01-27 Maintainer: FastGPT Development Team