api-design-patterns

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

API Design Patterns

API设计模式

When to Use

适用场景

Activate this skill when:
  • Designing new API endpoints or modifying existing endpoint contracts
  • Defining request/response schemas for a feature
  • Standardizing pagination, filtering, or sorting across endpoints
  • Designing a consistent error response format
  • Planning API versioning or deprecation strategy
  • Reviewing API contracts for consistency before implementation
  • Documenting endpoint specifications for frontend/backend coordination
Input: If
plan.md
or
architecture.md
exists, read for context about the feature scope and architectural decisions. Otherwise, work from the user's request directly.
Output: Write API design to
api-design.md
. Tell the user: "API design written to
api-design.md
. Run
/task-decomposition
to create implementation tasks or
/python-backend-expert
to implement."
Do NOT use this skill for:
  • Writing implementation code (use
    python-backend-expert
    )
  • System-level architecture decisions (use
    system-architecture
    )
  • Writing tests for endpoints (use
    pytest-patterns
    )
  • Frontend data fetching implementation (use
    react-frontend-expert
    )
在以下场景激活此技能:
  • 设计新API端点或修改现有端点契约
  • 为功能定义请求/响应schema
  • 统一各端点的分页、过滤或排序机制
  • 设计一致的错误响应格式
  • 规划API版本管理或弃用策略
  • 实现前审查API契约的一致性
  • 编写端点规范以协调前后端开发
输入: 若存在
plan.md
architecture.md
,请读取以了解功能范围和架构决策的上下文。否则直接根据用户需求开展工作。
输出: 将API设计写入
api-design.md
。告知用户:"API设计已写入
api-design.md
。运行
/task-decomposition
创建实现任务,或运行
/python-backend-expert
进行开发。"
请勿在以下场景使用此技能:
  • 编写实现代码(请使用
    python-backend-expert
  • 系统级架构决策(请使用
    system-architecture
  • 编写端点测试(请使用
    pytest-patterns
  • 前端数据获取实现(请使用
    react-frontend-expert

Instructions

操作说明

URL Naming Conventions

URL命名规范

Resource Naming Rules

资源命名规则

  1. Plural nouns for collections:
    /users
    ,
    /orders
    ,
    /products
  2. Kebab-case for multi-word resources:
    /order-items
    ,
    /user-profiles
  3. Singular resource by ID:
    /users/{user_id}
    ,
    /orders/{order_id}
  4. Maximum 2 nesting levels:
    /users/{user_id}/orders
    (not
    /users/{user_id}/orders/{order_id}/items/{item_id}
    )
  5. No verbs in URLs: use HTTP methods instead (
    POST /orders
    not
    /orders/create
    )
  6. Query parameters for filtering, sorting, pagination:
    /users?role=admin&sort=-created_at
  1. 集合使用复数名词
    /users
    /orders
    /products
  2. 多词资源使用短横线分隔(Kebab-case)
    /order-items
    /user-profiles
  3. 单个资源通过ID标识
    /users/{user_id}
    /orders/{order_id}
  4. 最多嵌套2层
    /users/{user_id}/orders
    (不推荐
    /users/{user_id}/orders/{order_id}/items/{item_id}
  5. URL中不使用动词:改用HTTP方法(如使用
    POST /orders
    而非
    /orders/create
  6. 过滤、排序、分页使用查询参数
    /users?role=admin&sort=-created_at

URL Structure Template

URL结构模板

/{version}/{resource}                    → Collection (list, create)
/{version}/{resource}/{id}               → Single resource (get, update, delete)
/{version}/{resource}/{id}/{sub-resource} → Nested collection
/{version}/{resource}/actions/{action}   → Non-CRUD operations (rarely needed)
/{version}/{resource}                    → 集合(列表、创建)
/{version}/{resource}/{id}               → 单个资源(获取、更新、删除)
/{version}/{resource}/{id}/{sub-resource} → 嵌套集合
/{version}/{resource}/actions/{action}   → 非CRUD操作(极少需要)

Naming Examples

命名示例

GoodBadReason
GET /v1/users
GET /v1/getUsers
No verbs — HTTP method implies action
POST /v1/users
POST /v1/user/create
POST to collection = create
GET /v1/order-items
GET /v1/orderItems
Kebab-case, not camelCase
GET /v1/users/{id}/orders
GET /v1/users/{id}/orders/{oid}/items
Max 2 nesting levels
POST /v1/orders/{id}/actions/cancel
POST /v1/cancelOrder/{id}
Action sub-resource for non-CRUD
规范写法不规范写法原因
GET /v1/users
GET /v1/getUsers
URL中不使用动词——HTTP方法已隐含操作意图
POST /v1/users
POST /v1/user/create
对集合发起POST请求即表示创建资源
GET /v1/order-items
GET /v1/orderItems
使用短横线分隔(Kebab-case),而非驼峰式(camelCase)
GET /v1/users/{id}/orders
GET /v1/users/{id}/orders/{oid}/items
最多嵌套2层
POST /v1/orders/{id}/actions/cancel
POST /v1/cancelOrder/{id}
非CRUD操作使用动作子资源

HTTP Method Semantics

HTTP方法语义

MethodPurposeRequest BodySuccess StatusIdempotent
GET
Retrieve resource(s)None
200 OK
Yes
POST
Create new resourceRequired
201 Created
No
PUT
Full replaceRequired (full)
200 OK
Yes
PATCH
Partial updateRequired (partial)
200 OK
No*
DELETE
Remove resourceNone
204 No Content
Yes
*PATCH is not inherently idempotent but can be made so with proper implementation.
Response headers for creation:
  • POST
    returning
    201
    SHOULD include a
    Location
    header with the URL of the created resource
Conditional requests:
  • Support
    If-None-Match
    /
    ETag
    for caching on GET endpoints with frequently-accessed resources
方法用途请求体成功状态码幂等性
GET
获取资源(单个/多个)
200 OK
POST
创建新资源必填
201 Created
PUT
完全替换资源必填(完整资源内容)
200 OK
PATCH
部分更新资源必填(部分资源内容)
200 OK
否*
DELETE
删除资源
204 No Content
*PATCH本身不具备幂等性,但可通过合理设计实现幂等。
创建操作的响应头:
  • 返回
    201
    状态码的
    POST
    请求应包含
    Location
    响应头,指向创建后的资源URL
条件请求:
  • 对于频繁访问的资源,GET端点应支持
    If-None-Match
    /
    ETag
    以实现缓存

Schema Naming Conventions (Pydantic v2)

Schema命名规范(Pydantic v2)

Follow a consistent naming pattern for all Pydantic schemas:
PatternPurposeFields
{Resource}Create
POST request bodyWritable fields, no id, no timestamps
{Resource}Update
PUT request bodyAll writable fields required
{Resource}Patch
PATCH request bodyAll fields Optional
{Resource}Response
Single resource responseAll fields including id, timestamps
{Resource}ListResponse
Paginated list responseitems + pagination metadata
{Resource}Filter
Query parametersOptional filter fields
Schema design rules:
  • Never expose internal fields (hashed_password, internal_notes) in Response schemas
  • Always include
    id
    and timestamps (
    created_at
    ,
    updated_at
    ) in Response schemas
  • Use
    model_validate(orm_instance)
    to convert ORM models to response schemas
  • Use
    model_dump(exclude_unset=True)
    for PATCH operations to distinguish "not provided" from "set to null"
  • Reference
    references/pydantic-schema-examples.md
    for concrete examples
为所有Pydantic schema遵循统一的命名模式:
命名模式用途字段特点
{Resource}Create
POST请求体仅包含可写入字段,无id和时间戳
{Resource}Update
PUT请求体所有可写入字段为必填
{Resource}Patch
PATCH请求体所有字段为可选
{Resource}Response
单个资源响应包含所有字段,包括id和时间戳
{Resource}ListResponse
分页列表响应包含资源列表+分页元数据
{Resource}Filter
查询参数可选的过滤字段
Schema设计规则:
  • 响应Schema中绝不能暴露内部字段(如hashed_password、internal_notes)
  • 响应Schema中必须包含
    id
    和时间戳(
    created_at
    updated_at
  • 使用
    model_validate(orm_instance)
    将ORM模型转换为响应Schema
  • PATCH操作使用
    model_dump(exclude_unset=True)
    以区分“未提供”与“设置为null”
  • 参考
    references/pydantic-schema-examples.md
    获取具体示例

Pagination

分页机制

Cursor-Based Pagination (Default)

基于游标分页(默认方式)

Use cursor-based pagination for all list endpoints. It is more performant than offset-based for large datasets and avoids the "shifting window" problem.
Request parameters:
GET /v1/users?cursor=eyJpZCI6MTAwfQ&limit=20
ParameterTypeDefaultDescription
cursor
str | None
None
Opaque cursor from previous response
limit
int
20
Items per page (max 100)
Response format:
json
{
  "items": [...],
  "next_cursor": "eyJpZCI6MTIwfQ",
  "has_more": true
}
Cursor implementation:
  • Encode the last item's sort key (usually
    id
    ) as a base64 string
  • The cursor is opaque to the client — they must not parse or construct it
  • Use
    WHERE id > :last_id ORDER BY id ASC LIMIT :limit + 1
    — fetch one extra to determine
    has_more
所有列表端点默认使用基于游标分页。相较于基于偏移量的分页,它在大数据集下性能更优,且避免了“窗口偏移”问题。
请求参数:
GET /v1/users?cursor=eyJpZCI6MTAwfQ&limit=20
参数类型默认值描述
cursor
str | None
None
来自上一次响应的不透明游标
limit
int
20
每页条目数(最大100)
响应格式:
json
{
  "items": [...],
  "next_cursor": "eyJpZCI6MTIwfQ",
  "has_more": true
}
游标实现方式:
  • 将最后一个条目的排序键(通常为
    id
    )编码为base64字符串
  • 游标对客户端是不透明的——客户端不得解析或自行构造游标
  • 使用
    WHERE id > :last_id ORDER BY id ASC LIMIT :limit + 1
    查询——多获取一条数据以判断
    has_more
    的值

Offset-Based Pagination (When Needed)

基于偏移量分页(按需使用)

Use offset-based only when the client needs to jump to arbitrary pages (e.g., admin tables).
json
{
  "items": [...],
  "total": 150,
  "page": 2,
  "page_size": 20,
  "total_pages": 8
}
仅当客户端需要跳转到任意页面时(如后台管理表格)才使用基于偏移量的分页。
json
{
  "items": [...],
  "total": 150,
  "page": 2,
  "page_size": 20,
  "total_pages": 8
}

Filtering and Sorting

过滤与排序

Filtering

过滤

Use query parameters with field names:
GET /v1/users?role=admin&is_active=true&created_after=2024-01-01
Filtering conventions:
  • Exact match:
    ?field=value
  • Range:
    ?field_min=10&field_max=100
    or
    ?created_after=...&created_before=...
  • Search:
    ?q=search+term
    (for full-text search across multiple fields)
  • Multiple values:
    ?status=active&status=pending
    (OR semantics)
使用与字段名一致的查询参数:
GET /v1/users?role=admin&is_active=true&created_after=2024-01-01
过滤规范:
  • 精确匹配:
    ?field=value
  • 范围查询:
    ?field_min=10&field_max=100
    ?created_after=...&created_before=...
  • 全文搜索:
    ?q=search+term
    (跨多个字段的全文搜索)
  • 多值匹配:
    ?status=active&status=pending
    (OR语义)

Sorting

排序

Use a
sort
query parameter with field name and direction prefix:
GET /v1/users?sort=-created_at        → descending by created_at
GET /v1/users?sort=name               → ascending by name
GET /v1/users?sort=-created_at,name   → multi-field sort
Convention:
-
prefix means descending, no prefix means ascending.
使用
sort
查询参数,字段名前加方向前缀:
GET /v1/users?sort=-created_at        → 按created_at降序排列
GET /v1/users?sort=name               → 按name升序排列
GET /v1/users?sort=-created_at,name   → 多字段排序
规范:
-
前缀表示降序,无前缀表示升序。

Error Response Format

错误响应格式

All API errors follow a consistent format:
json
{
  "detail": "Human-readable error message",
  "code": "MACHINE_READABLE_CODE",
  "field_errors": [
    {
      "field": "email",
      "message": "Invalid email format",
      "code": "INVALID_FORMAT"
    }
  ]
}
所有API错误遵循统一格式:
json
{
  "detail": "人类可读的错误信息",
  "code": "机器可读的错误码",
  "field_errors": [
    {
      "field": "email",
      "message": "邮箱格式无效",
      "code": "INVALID_FORMAT"
    }
  ]
}

Standard Error Codes and Status Mapping

标准错误码与状态码映射

HTTP StatusWhen to UseExample
code
400
Malformed request
BAD_REQUEST
401
Missing or invalid authentication
UNAUTHORIZED
403
Authenticated but not authorized
FORBIDDEN
404
Resource not found
NOT_FOUND
409
Conflict (duplicate, version mismatch)
CONFLICT
422
Validation error (Pydantic)
VALIDATION_ERROR
429
Rate limit exceeded
RATE_LIMITED
500
Unexpected server error
INTERNAL_ERROR
Error schema (Pydantic v2):
python
class FieldError(BaseModel):
    field: str
    message: str
    code: str

class ErrorResponse(BaseModel):
    detail: str
    code: str
    field_errors: list[FieldError] = []
HTTP状态码适用场景示例
code
400
请求格式错误
BAD_REQUEST
401
缺少或无效的身份验证
UNAUTHORIZED
403
已认证但无权限
FORBIDDEN
404
资源不存在
NOT_FOUND
409
冲突(重复、版本不匹配)
CONFLICT
422
验证错误(Pydantic)
VALIDATION_ERROR
429
超出速率限制
RATE_LIMITED
500
意外服务器错误
INTERNAL_ERROR
错误Schema(Pydantic v2):
python
class FieldError(BaseModel):
    field: str
    message: str
    code: str

class ErrorResponse(BaseModel):
    detail: str
    code: str
    field_errors: list[FieldError] = []

API Versioning

API版本管理

Strategy: URL Prefix Versioning

策略:URL前缀版本管理

/v1/users    → Version 1
/v2/users    → Version 2
Versioning rules:
  1. Start with
    /v1/
    for all new APIs
  2. Increment major version only for breaking changes
  3. Non-breaking changes (new optional fields, new endpoints) do NOT require a new version
  4. Support at most 2 active versions simultaneously
Breaking changes that require a new version:
  • Removing a field from a response
  • Changing a field's type
  • Making an optional request field required
  • Changing the URL structure for existing endpoints
  • Changing error response format
Deprecation process:
  1. Add
    Deprecation
    header to the old version:
    Deprecation: true
  2. Add
    Sunset
    header with the retirement date:
    Sunset: Sat, 01 Mar 2026 00:00:00 GMT
  3. Add
    Link
    header pointing to the new version:
    Link: </v2/users>; rel="successor-version"
  4. Log usage of deprecated endpoints for monitoring
  5. Remove the old version after the sunset date
/v1/users    → 版本1
/v2/users    → 版本2
版本管理规则:
  1. 所有新API以
    /v1/
    开头
  2. 仅当发生破坏性变更时才升级主版本号
  3. 非破坏性变更(新增可选字段、新增端点)无需升级版本
  4. 同时最多支持2个活跃版本
需要升级版本的破坏性变更:
  • 从响应中移除字段
  • 改变字段类型
  • 将可选请求字段设为必填
  • 修改现有端点的URL结构
  • 改变错误响应格式
弃用流程:
  1. 为旧版本添加
    Deprecation
    响应头:
    Deprecation: true
  2. 添加
    Sunset
    响应头,注明停用日期:
    Sunset: Sat, 01 Mar 2026 00:00:00 GMT
  3. 添加
    Link
    响应头,指向新版本:
    Link: </v2/users>; rel="successor-version"
  4. 记录旧版本端点的使用情况以监控
  5. 停用日期过后移除旧版本

OpenAPI Documentation

OpenAPI文档

FastAPI generates OpenAPI schemas automatically. Enhance them with:
python
@router.get(
    "/users/{user_id}",
    response_model=UserResponse,
    summary="Get user by ID",
    description="Retrieve a single user's details by their unique identifier.",
    responses={
        404: {"model": ErrorResponse, "description": "User not found"},
    },
    tags=["Users"],
)
async def get_user(user_id: int) -> UserResponse:
    ...
Documentation conventions:
  • Every endpoint has a
    summary
    (short) and optional
    description
    (detailed)
  • Document all non-200 responses with their schema
  • Group endpoints by
    tags
    matching the resource name
  • Use
    response_model
    for automatic response schema documentation
FastAPI会自动生成OpenAPI schema。可通过以下方式增强文档:
python
@router.get(
    "/users/{user_id}",
    response_model=UserResponse,
    summary="根据ID获取用户信息",
    description="通过唯一标识获取单个用户的详细信息。",
    responses={
        404: {"model": ErrorResponse, "description": "用户不存在"},
    },
    tags=["Users"],
)
async def get_user(user_id: int) -> UserResponse:
    ...
文档规范:
  • 每个端点都要有
    summary
    (简短描述)和可选的
    description
    (详细描述)
  • 为所有非200响应状态码文档化对应的schema
  • tags
    对端点分组,标签名与资源名一致
  • 使用
    response_model
    自动生成响应schema文档

Examples

示例

Designing a Products API Contract

设计Products API契约

Objective: Design the contract for a
/v1/products
CRUD endpoint with search and pagination.
Endpoints:
MethodPathDescriptionRequestResponseStatus
GET
/v1/products
List productsQuery: cursor, limit, q, category, sortProductListResponse200
POST
/v1/products
Create productBody: ProductCreateProductResponse201
GET
/v1/products/{id}
Get productProductResponse200
PATCH
/v1/products/{id}
Update productBody: ProductPatchProductResponse200
DELETE
/v1/products/{id}
Delete product204
Schemas:
python
class ProductCreate(BaseModel):
    name: str = Field(min_length=1, max_length=200)
    description: str | None = None
    price_cents: int = Field(gt=0)
    category: str
    sku: str = Field(pattern=r"^[A-Z0-9-]+$")

class ProductPatch(BaseModel):
    name: str | None = None
    description: str | None = None
    price_cents: int | None = Field(default=None, gt=0)
    category: str | None = None

class ProductResponse(BaseModel):
    id: int
    name: str
    description: str | None
    price_cents: int
    category: str
    sku: str
    created_at: datetime
    updated_at: datetime

class ProductListResponse(BaseModel):
    items: list[ProductResponse]
    next_cursor: str | None
    has_more: bool
Search and filtering:
GET /v1/products?q=laptop&category=electronics&sort=-price_cents&limit=20
See
references/endpoint-catalog-template.md
for the full documentation template. See
references/pydantic-schema-examples.md
for additional schema examples.
目标: 设计带搜索和分页功能的
/v1/products
CRUD端点契约。
端点列表:
方法路径描述请求响应状态码
GET
/v1/products
产品列表查询参数:cursor、limit、q、category、sortProductListResponse200
POST
/v1/products
创建产品请求体:ProductCreateProductResponse201
GET
/v1/products/{id}
获取产品详情ProductResponse200
PATCH
/v1/products/{id}
更新产品信息请求体:ProductPatchProductResponse200
DELETE
/v1/products/{id}
删除产品204
Schema定义:
python
class ProductCreate(BaseModel):
    name: str = Field(min_length=1, max_length=200)
    description: str | None = None
    price_cents: int = Field(gt=0)
    category: str
    sku: str = Field(pattern=r"^[A-Z0-9-]+$")

class ProductPatch(BaseModel):
    name: str | None = None
    description: str | None = None
    price_cents: int | None = Field(default=None, gt=0)
    category: str | None = None

class ProductResponse(BaseModel):
    id: int
    name: str
    description: str | None
    price_cents: int
    category: str
    sku: str
    created_at: datetime
    updated_at: datetime

class ProductListResponse(BaseModel):
    items: list[ProductResponse]
    next_cursor: str | None
    has_more: bool
搜索与过滤示例:
GET /v1/products?q=laptop&category=electronics&sort=-price_cents&limit=20
完整文档模板请参考
references/endpoint-catalog-template.md
。 更多Schema示例请参考
references/pydantic-schema-examples.md

Edge Cases

边缘场景

Bulk Operations

批量操作

For operations on multiple resources at once:
POST /v1/users/bulk
Request:
json
{
  "items": [
    {"email": "a@example.com", "name": "Alice"},
    {"email": "b@example.com", "name": "Bob"}
  ]
}
Response (partial success — status 207):
json
{
  "results": [
    {"index": 0, "status": "created", "data": {...}},
    {"index": 1, "status": "error", "error": {"detail": "Email already exists", "code": "CONFLICT"}}
  ],
  "succeeded": 1,
  "failed": 1
}
Use HTTP
207 Multi-Status
when individual items can succeed or fail independently.
针对多个资源的批量操作:
POST /v1/users/bulk
请求体:
json
{
  "items": [
    {"email": "a@example.com", "name": "Alice"},
    {"email": "b@example.com", "name": "Bob"}
  ]
}
响应(部分成功——状态码207):
json
{
  "results": [
    {"index": 0, "status": "created", "data": {...}},
    {"index": 1, "status": "error", "error": {"detail": "邮箱已存在", "code": "CONFLICT"}}
  ],
  "succeeded": 1,
  "failed": 1
}
当单个条目可能独立成功或失败时,使用HTTP
207 Multi-Status
状态码。

File Upload Endpoints

文件上传端点

File uploads use
multipart/form-data
, not JSON:
python
@router.post("/v1/files", response_model=FileResponse, status_code=201)
async def upload_file(
    file: UploadFile,
    description: str = Form(default=""),
) -> FileResponse:
    ...
Validate file size and MIME type before processing. Return
413 Payload Too Large
for oversized files.
文件上传使用
multipart/form-data
,而非JSON:
python
@router.post("/v1/files", response_model=FileResponse, status_code=201)
async def upload_file(
    file: UploadFile,
    description: str = Form(default=""),
) -> FileResponse:
    ...
处理前验证文件大小和MIME类型。对于过大的文件返回
413 Payload Too Large
状态码。

Long-Running Operations

长时运行操作

For operations that cannot complete within a normal request timeout:
  1. Return
    202 Accepted
    with a status URL:
    json
    {"status_url": "/v1/jobs/abc123", "estimated_completion": "2024-01-15T10:30:00Z"}
  2. Client polls the status URL:
    GET /v1/jobs/abc123 → {"status": "processing", "progress": 0.65}
    GET /v1/jobs/abc123 → {"status": "completed", "result_url": "/v1/reports/xyz"}
对于无法在常规请求超时内完成的操作:
  1. 返回
    202 Accepted
    状态码及状态查询URL:
    json
    {"status_url": "/v1/jobs/abc123", "estimated_completion": "2024-01-15T10:30:00Z"}
  2. 客户端轮询状态查询URL:
    GET /v1/jobs/abc123 → {"status": "processing", "progress": 0.65}
    GET /v1/jobs/abc123 → {"status": "completed", "result_url": "/v1/reports/xyz"}

Sub-Resource Design

子资源设计

When a resource logically belongs to a parent but nesting would exceed 2 levels, use a top-level resource with a filter:
undefined
当资源逻辑上属于父资源但嵌套层级会超过2层时,使用顶层资源加过滤参数:
undefined

Instead of: GET /v1/users/{id}/orders/{oid}/items

不推荐:GET /v1/users/{id}/orders/{oid}/items

Use: GET /v1/order-items?order_id=123

推荐: GET /v1/order-items?order_id=123


This keeps URLs flat while maintaining the relationship through filtering.

这样既保持了URL的扁平化,又通过过滤参数维持了资源间的关联关系。

Output File

输出文件

Write the API design to
api-design.md
at the project root:
markdown
undefined
将API设计写入项目根目录下的
api-design.md
markdown
undefined

API Design: [Feature Name]

API设计:[功能名称]

Endpoints

端点列表

MethodURLDescriptionAuth
GET/v1/usersList usersRequired
POST/v1/usersCreate userRequired
方法URL描述身份验证
GET/v1/users用户列表必填
POST/v1/users创建用户必填

Request/Response Schemas

请求/响应Schema

UserCreate

UserCreate

FieldTypeRequiredValidation
emailstringYesValid email
namestringYes1-100 chars
字段类型必填验证规则
emailstring有效的邮箱格式
namestring1-100个字符

UserResponse

UserResponse

FieldTypeDescription
iduuidUser ID
emailstringUser email
字段类型描述
iduuid用户ID
emailstring用户邮箱

Error Codes

错误码

CodeHTTP StatusDescription
USER_NOT_FOUND404User does not exist
EMAIL_EXISTS409Email already registered
错误码HTTP状态码描述
USER_NOT_FOUND404用户不存在
EMAIL_EXISTS409邮箱已注册

Next Steps

下一步

  • Run
    /task-decomposition
    to create implementation tasks
  • Run
    /python-backend-expert
    to implement endpoints
undefined
  • 运行
    /task-decomposition
    创建实现任务
  • 运行
    /python-backend-expert
    开发端点
undefined