Token导航 LogoToken导航TokenDH.com
研究检索需要联网github未标认证来源可访问许可证需确认审计通过

api-designAPI 设计

Agent Skill

用于辅助 API 设计、接口文档、请求响应结构和服务集成说明。它适合让 Agent 梳理 endpoint、生成 OpenAPI 草稿、检查字段命名、整理错误码或辅助前后端联调。使用时需要确认真实业务语义、鉴权方式、分页和错误处理规则;涉及生成接口文档时,应避免凭空补字段,最好从现有代码、schema 或接口样例中提取事实。

总安装

329

周安装

14

GitHub Stars

15

下载量

115
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:api-design(API 设计)
来源仓库:https://github.com/wshaddix/dotnet-skills
仓库路径:skills/api-design
安装命令:
npx skills add https://github.com/wshaddix/dotnet-skills --skill api-design
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/wshaddix/dotnet-skills --skill api-design

简介

用于辅助 API 设计、接口文档和请求响应结构梳理。

  • 适合生成 OpenAPI 草稿、检查字段命名或辅助前后端联调。
  • 使用时需确认业务语义、鉴权方式和错误处理规则,避免凭空补字段。
  • 安装命令:npx skills add https://github.com/wshaddix/dotnet-skills --skill api-design。
  • 支持 Codex、Claude、Cursor、Gemini CLI,通过 GitHub 仓库安装。

SKILL.md

Public API Design and Compatibility

When to Use This Skill

Use this skill when:

  • Designing public APIs for NuGet packages or libraries
  • Making changes to existing public APIs
  • Planning wire format changes for distributed systems
  • Implementing versioning strategies
  • Reviewing pull requests for breaking changes

The Three Types of Compatibility

TypeDefinitionScope
API/SourceCode compiles against newer versionPublic method signatures, types
BinaryCompiled code runs against newer versionAssembly layout, method tokens
WireSerialized data readable by other versionsNetwork protocols, persistence formats

Breaking any of these creates upgrade friction for users.


Extend-Only Design

The foundation of stable APIs: never remove or modify, only extend.

Three Pillars

  1. Previous functionality is immutable - Once released, behavior and signatures are locked
  2. New functionality through new constructs - Add overloads, new types, opt-in features
  3. Removal only after deprecation period - Years, not releases

Benefits

  • Old code continues working in new versions
  • New and old pathways coexist
  • Upgrades are non-breaking by default
  • Users upgrade on their schedule

Naming Conventions for API Surface

Type Naming

Type KindSuffix PatternExample
Base classBase suffix only for abstract base typesValidatorBase
InterfaceI prefixIWidgetFactory
ExceptionException suffixWidgetNotFoundException
AttributeAttribute suffixRequiredPermissionAttribute
Event argsEventArgs suffixWidgetCreatedEventArgs
Options/configOptions suffixWidgetServiceOptions
BuilderBuilder suffixWidgetBuilder

Method Naming

PatternConventionExample
SynchronousVerb or verb phraseCalculate(), GetWidget()
AsynchronousAsync suffixCalculateAsync(), GetWidgetAsync()
Boolean queryIs/Has/Can prefixIsValid(), HasPermission()
Try patternTry prefix, out parameterTryGetWidget(int id, out Widget widget)
FactoryCreate prefixCreateWidget(), CreateWidgetAsync()
ConversionTo/From prefixToDto(), FromEntity()

Avoid Abbreviations in Public API

// WRONG -- abbreviations in public surface
public IReadOnlyList<TxnResult> GetRecentTxns(int cnt);

// CORRECT -- spelled out for clarity
public IReadOnlyList<TransactionResult> GetRecentTransactions(int count);

Parameter Ordering

Consistent parameter ordering reduces cognitive load.

Standard Order

  1. Target/subject -- the primary entity being operated on
  2. Required parameters -- essential inputs without defaults
  3. Optional parameters -- inputs with sensible defaults
  4. Cancellation token -- always last (convention enforced by CA1068)
public Task<Widget> GetWidgetAsync(
    int widgetId,                              // 1. Target
    WidgetOptions options,                     // 2. Required
    bool includeHistory = false,               // 3. Optional
    CancellationToken cancellationToken = default); // 4. Always last

Overload Progression

// Simple -- sensible defaults
public Task<Widget> GetWidgetAsync(int widgetId,
    CancellationToken cancellationToken = default)
    => GetWidgetAsync(widgetId, WidgetOptions.Default, cancellationToken);

// Detailed -- full control
public Task<Widget> GetWidgetAsync(int widgetId,
    WidgetOptions options,
    CancellationToken cancellationToken = default);

Return Type Selection

When to Return What

ScenarioReturn TypeRationale
Single entity, always existsWidgetThrow if not found
Single entity, may not existWidget?Nullable communicates optionality
Collection, possibly emptyIReadOnlyList<Widget>Immutable, indexable, communicates no mutation
Streaming resultsIAsyncEnumerable<Widget>Avoids buffering entire result set
Operation result with detailResult<Widget> / discriminated unionRich error info without exceptions
Void with asyncTaskNever async void except event handlers
Frequently synchronous completionValueTask<Widget>Avoids Task allocation on cache hits

Prefer IReadOnlyList Over IEnumerable

// WRONG -- caller does not know if result is materialized or lazy
public IEnumerable<Widget> GetWidgets();

// CORRECT -- signals materialized, indexable collection
public IReadOnlyList<Widget> GetWidgets();

// CORRECT -- signals streaming/lazy evaluation explicitly
public IAsyncEnumerable<Widget> GetWidgetsStreamAsync(
    CancellationToken cancellationToken = default);

The Try Pattern

public bool TryGetWidget(int widgetId, [NotNullWhen(true)] out Widget? widget);

public Task<Widget?> TryGetWidgetAsync(int widgetId,
    CancellationToken cancellationToken = default);

Error Reporting Strategies

Exception Hierarchy

public class WidgetServiceException : Exception
{
    public WidgetServiceException(string message) : base(message) { }
    public WidgetServiceException(string message, Exception inner) : base(message, inner) { }
}

public class WidgetNotFoundException : WidgetServiceException
{
    public int WidgetId { get; }
    public WidgetNotFoundException(int widgetId)
        : base($"Widget {widgetId} not found.") => WidgetId = widgetId;
}

public class WidgetValidationException : WidgetServiceException
{
    public IReadOnlyList<string> Errors { get; }
    public WidgetValidationException(IReadOnlyList<string> errors)
        : base("Widget validation failed.") => Errors = errors;
}

When to Use Exceptions vs Return Values

ApproachWhen to Use
Throw exceptionUnexpected failures, programming errors, infrastructure failures
Return null / default"Not found" is a normal, expected outcome
Try pattern (bool + out)Parsing or validation where failure is common and synchronous
Result objectMultiple failure modes that callers need to distinguish

Argument Validation

public Widget CreateWidget(string name, decimal price)
{
    ArgumentException.ThrowIfNullOrWhiteSpace(name);
    ArgumentOutOfRangeException.ThrowIfNegativeOrZero(price);

    return new Widget(name, price);
}

API Change Guidelines

Safe Changes (Any Release)

// ADD new overloads with default parameters
public void Process(Order order, CancellationToken ct = default);

// ADD new optional parameters to existing methods
public void Send(Message msg, Priority priority = Priority.Normal);

// ADD new types, interfaces, enums
public interface IOrderValidator { }
public enum OrderStatus { Pending, Complete, Cancelled }

// ADD new members to existing types
public class Order
{
    public DateTimeOffset? ShippedAt { get; init; }  // NEW
}

Unsafe Changes (Never or Major Version Only)

// REMOVE or RENAME public members
public void ProcessOrder(Order order);  // Was: Process()

// CHANGE parameter types or order
public void Process(int orderId);  // Was: Process(Order order)

// CHANGE return types
public Order? GetOrder(string id);  // Was: public Order GetOrder()

// CHANGE access modifiers
internal class OrderProcessor { }  // Was: public

// ADD required parameters without defaults
public void Process(Order order, ILogger logger);  // Breaks callers!

Deprecation Pattern

// Step 1: Mark as obsolete with version
[Obsolete("Obsolete since v1.5.0. Use ProcessAsync instead.")]
public void Process(Order order) { }

// Step 2: Add new recommended API
public Task ProcessAsync(Order order, CancellationToken ct = default);

// Step 3: Remove in next major version

Extension Points

Interface-Based Extension

// GOOD -- interface-based extension point
public interface IWidgetValidator
{
    ValueTask<bool> ValidateAsync(Widget widget, CancellationToken ct = default);
}

// GOOD -- delegate-based extension for simple hooks
public class WidgetServiceOptions
{
    public Func<Widget, CancellationToken, ValueTask>? OnWidgetCreated { get; set; }
}

Extension Method Guidelines

GuidelineRationale
Place extensions in the same namespace as the typeDiscoverable without extra using statements
Never put extensions in System or System.LinqNamespace pollution
Prefer instance methods over extensions when you own the typeExtensions are a last resort
Keep the this parameter as the most specific usable typeAvoids polluting IntelliSense

Wire Compatibility

For distributed systems, serialized data must be readable across versions.

Requirements

DirectionRequirement
BackwardOld writers → New readers
ForwardNew writers → Old readers

Both are required for zero-downtime rolling upgrades.

Safely Evolving Wire Formats

Phase 1: Add read-side support

public sealed record HeartbeatV2(
    Address From,
    long SequenceNr,
    long CreationTimeMs);  // NEW field

public object Deserialize(byte[] data, string manifest) => manifest switch
{
    "Heartbeat" => DeserializeHeartbeatV1(data),
    "HeartbeatV2" => DeserializeHeartbeatV2(data),
    _ => throw new NotSupportedException()
};

Phase 2: Enable write-side (next minor version)

akka.cluster.use-heartbeat-v2 = on

Defensive Serialization Design

public sealed class WidgetDto
{
    [JsonPropertyName("id")]
    public int Id { get; init; }

    [JsonPropertyName("name")]
    public required string Name { get; init; }

    [JsonPropertyName("category")]
    public string? Category { get; init; }

    [JsonPropertyName("priority")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public int Priority { get; init; }
}

Enum Serialization Strategy

// GOOD -- string serialization is rename-safe
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum WidgetStatus
{
    Draft,
    Active,
    Archived
}

// RISKY -- integer serialization breaks when members are reordered
public enum WidgetPriority
{
    Low = 0,
    Medium = 1,
    High = 2
}

API Approval Testing

Prevent accidental breaking changes with automated API surface testing.

[Fact]
public Task ApprovePublicApi()
{
    var api = typeof(MyLibrary.PublicClass).Assembly.GeneratePublicApi();
    return Verify(api);
}

PR Review Process

  1. PR includes changes to *.verified.txt files
  2. Reviewers see exact API surface changes in diff
  3. Breaking changes are immediately visible
  4. Conscious decision required to approve

Versioning Strategy

Semantic Versioning (Practical)

VersionChanges Allowed
Patch (1.0.x)Bug fixes, security patches
Minor (1.x.0)New features, deprecations, obsolete removal
Major (x.0.0)Breaking changes, old API removal

Key Principles

  1. No surprise breaks - Even major versions should be announced
  2. Extensions anytime - New APIs can ship in any release
  3. Deprecate before remove - [Obsolete] for at least one minor version
  4. Communicate timelines - Users need to plan upgrades

Pull Request Checklist

  • No removed public members (use [Obsolete] instead)
  • No changed signatures (add overloads instead)
  • No new required parameters (use defaults)
  • API approval test updated (.verified.txt changes reviewed)
  • Wire format changes are opt-in (read-side first)
  • Breaking changes documented (release notes, migration guide)

Anti-Patterns

Breaking Changes Disguised as Fixes

// "Bug fix" that breaks users
public async Task<Order> GetOrderAsync(OrderId id)  // Was sync!
{
}

// Correct: Add new method, deprecate old
[Obsolete("Use GetOrderAsync instead")]
public Order GetOrder(OrderId id) => GetOrderAsync(id).Result;

public async Task<Order> GetOrderAsync(OrderId id) { }

Silent Behavior Changes

// Changing defaults breaks users
public void Configure(bool enableCaching = true)  // Was: false!

// Correct: New parameter with new name
public void Configure(
    bool enableCaching = false,
    bool enableNewCaching = true)

Polymorphic Serialization

// AVOID: Type names in wire format
{ "$type": "MyApp.Order, MyApp", "Id": 123 }

// PREFER: Explicit discriminators
{ "type": "order", "id": 123 }

Agent Gotchas

  1. Do not use abbreviations in public API names -- spell out words.
  2. Do not place CancellationToken before optional parameters -- CA1068 enforces last.
  3. Do not return mutable collections from public APIs -- return IReadOnlyList<T>.
  4. Do not change serialized property names without [JsonPropertyName] annotations.
  5. Do not add required parameters to existing public methods -- add overload or use defaults.
  6. Do not use async void in API surface -- return Task or ValueTask.
  7. Do not design exception hierarchies without a base library exception.
  8. Do not put extension methods in the System namespace.

Resources

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

34.47%
按下载量换算40

Claude

33.13%
按下载量换算38

Cursor

18.37%
按下载量换算21

Gemini CLI

8.82%
按下载量换算10

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills