본문으로 건너뛰기
cccskills
무료GitHub에 공개

designing-sdks

Design production-ready SDKs with retry logic, error handling, pagination, and multi-language support. Use when building client libraries for APIs or creating developer-facing SDK interfaces.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

연동 도구StripeAWSOpenAI
설치 방법 보기

포함된 파일(18)

  • SKILL.md12.5 KB
  • examples/go/basic-client.go5.5 KB
  • examples/go/channel-pagination.go1.4 KB
  • examples/go/context-client.go1.2 KB
  • examples/python/async-client.py4.2 KB
  • examples/python/dual-client.py1.8 KB
  • examples/python/sync-client.py3.6 KB
  • examples/typescript/advanced-client.ts7.7 KB
  • examples/typescript/basic-client.ts3.3 KB
  • examples/typescript/resource-based.ts1.6 KB
  • outputs.yaml7.0 KB
  • references/architecture-patterns.md11.8 KB
  • references/authentication.md16.7 KB
  • references/error-handling.md9.2 KB
  • references/pagination.md4.1 KB
  • references/retry-backoff.md11.4 KB
  • references/testing-sdks.md3.0 KB
  • references/versioning.md1.9 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

SDK Design

Design client libraries (SDKs) with excellent developer experience through intuitive APIs, robust error handling, automatic retries, and consistent patterns across programming languages.

When to Use This Skill

Use when building a client library for a REST API, creating internal service SDKs, implementing retry logic with exponential backoff, handling authentication patterns, creating typed error hierarchies, implementing pagination with async iterators, or designing streaming APIs for real-time data.

Core Architecture Patterns

Client → Resources → Methods

Organize SDK code hierarchically:

Client (config: API key, base URL, retries, timeout)
├─ Resources (users, payments, posts)
│   ├─ create(), retrieve(), update(), delete()
│   └─ list() (with pagination)
└─ Top-Level Methods (convenience)

Resource-Based (Stripe style):

const client = new APIClient({ apiKey: 'sk_test_...' })
const user = await client.users.create({ email: 'user@example.com' })

Use for APIs <100 methods. Prioritizes developer experience.

Command-Based (AWS SDK v3):

import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3'
await client.send(new PutObjectCommand({ Bucket: '...' }))

Use for APIs >100 methods. Prioritizes bundle size and tree-shaking.

For detailed architectural guidance, see references/architecture-patterns.md.

Language-Specific Patterns

TypeScript: Async-Only

const user = await client.users.create({ email: 'user@example.com' })

All methods return Promises. Avoid callbacks.

Python: Dual Sync/Async

# Sync
client = APIClient(api_key='sk_test_...')
user = client.users.create(email='user@example.com')

# Async
async_client = AsyncAPIClient(api_key='sk_test_...')
user = await async_client.users.create(email='user@example.com')

Provide both clients. Users choose based on architecture.

Go: Sync with Context

client := apiclient.New("api_key")
user, err := client.Users().Create(ctx, req)

Use context.Context for timeout and cancellation.

Authentication

API Key (Most Common)

const client = new APIClient({ apiKey: process.env.API_KEY })

Store keys in environment variables, never hardcode.

OAuth Token Refresh

const client = new APIClient({
  clientId: 'id',
  clientSecret: 'secret',
  refreshToken: 'token',
  onTokenRefresh: (newToken) => saveToken(newToken)
})

SDK automatically refreshes tokens before expiry.

Bearer Token Per-Request

await client.users.list({
  headers: { Authorization: `Bearer ${userToken}` }
})

Use for multi-tenant applications.

See references/authentication.md for OAuth flows, JWT handling, and credential providers.

Retry and Backoff

Exponential Backoff with Jitter

async function retryWithBackoff<T>(fn: () => Promise<T>, maxRetries: number): Promise<T> {
  let attempt = 0

  while (attempt <= maxRetries) {
    try {
      return await fn()
    } catch (error) {
      attempt++
      if (attempt > maxRetries || !isRetryable(error)) throw error

      const exponential = Math.min(1000 * Math.pow(2, attempt - 1), 10000)
      const jitter = Math.random() * 500
      await sleep(exponential + jitter)
    }
  }
}

function isRetryable(error: any): boolean {
  return (
    error.code === 'ECONNRESET' ||
    error.code === 'ETIMEDOUT' ||
    (error.status >= 500 && error.status < 600) ||
    error.status === 429
  )
}

Retry Decision Matrix:

Error TypeRetry?Rationale
5xx, 429, Network Timeout✅ YesTransient errors
4xx, 401, 403, 404❌ NoClient errors won't fix themselves

Rate Limit Handling

if (error.status === 429) {
  const retryAfter = parseInt(error.headers['retry-after'] || '60')
  await sleep(retryAfter * 1000)
}

Respect Retry-After header on 429 responses.

See references/retry-backoff.md for jitter strategies, circuit breakers, and idempotency keys.

Error Handling

Typed Error Hierarchy

class APIError extends Error {
  constructor(
    message: string,
    public status: number,
    public code: string,
    public requestId: string
  ) {
    super(message)
    this.name = 'APIError'
  }
}

class RateLimitError extends APIError {
  constructor(message: string, requestId: string, public retryAfter: number) {
    super(message, 429, 'rate_limit_error', requestId)
  }
}

class AuthenticationError extends APIError {
  constructor(message: string, requestId: string) {
    super(message, 401, 'authentication_error', requestId)
  }
}

Error Handling in Practice

try {
  const user = await client.users.create({ email: 'invalid' })
} catch (error) {
  if (error instanceof RateLimitError) {
    await sleep(error.retryAfter * 1000)
  } else if (error instanceof AuthenticationError) {
    console.error('Invalid API key')
  } else if (error instanceof APIError) {
    console.error(`${error.message} (Request ID: ${error.requestId})`)
  }
}

Include request ID in all errors for debugging.

See references/error-handling.md for user-friendly messages, validation errors, and debugging support.

Pagination

Async Iterators (Recommended)

TypeScript:

for await (const user of client.users.list({ limit: 100 })) {
  console.log(user.id, user.email)
}

Python:

async for user in client.users.list(limit=100):
    print(user.id, user.email)

SDK automatically fetches next page.

Implementation

class UsersResource {
  async *list(options?: { limit?: number }): AsyncGenerator<User> {
    let cursor: string | undefined = undefined

    while (true) {
      const response = await this.client.request('GET', '/users', {
        query: { limit: String(options?.limit || 100), ...(cursor ? { cursor } : {}) }
      })

      for (const user of response.data) yield user

      if (!response.has_more) break
      cursor = response.next_cursor
    }
  }
}

Manual Pagination

let cursor: string | undefined = undefined
while (true) {
  const response = await client.users.list({ limit: 100, cursor })
  for (const user of response.data) console.log(user.id)
  if (!response.has_more) break
  cursor = response.next_cursor
}

Provide both automatic and manual options.

See references/pagination.md for cursor vs. offset pagination and Go channel patterns.

Streaming

Server-Sent Events

async *stream(path: string, body?: any): AsyncGenerator<any> {
  const response = await fetch(url, {
    headers: { 'Accept': 'text/event-stream' },
    body: JSON.stringify(body)
  })

  const reader = response.body!.getReader()
  const decoder = new TextDecoder()

  while (true) {
    const { done, value } = await reader.read()
    if (done) break

    const chunk = decoder.decode(value)
    for (const line of chunk.split('\n')) {
      if (line.startsWith('data: ')) {
        const data = line.slice(6)
        if (data === '[DONE]') return
        yield JSON.parse(data)
      }
    }
  }
}

// Usage
for await (const chunk of client.posts.stream({ prompt: 'Write a story' })) {
  process.stdout.write(chunk.content)
}

Idempotency Keys

Prevent duplicate operations during retries:

import { randomUUID } from 'crypto'

if (['POST', 'PATCH', 'PUT'].includes(method)) {
  headers['Idempotency-Key'] = options?.idempotencyKey || randomUUID()
}

// Usage
await client.charges.create(
  { amount: 1000 },
  { idempotencyKey: 'charge_unique_123' }
)

Server deduplicates requests by key.

Versioning

Semantic Versioning

  • 1.0.0 → 1.1.0: New features (safe)
  • 1.1.0 → 2.0.0: Breaking changes (review)
  • 1.0.0 → 1.0.1: Bug fixes (safe)

Deprecation Warnings

function deprecated(message: string, since: string) {
  return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    const originalMethod = descriptor.value
    descriptor.value = function (...args: any[]) {
      console.warn(`[DEPRECATED] ${propertyKey} since ${since}. ${message}`)
      return originalMethod.apply(this, args)
    }
    return descriptor
  }
}

@deprecated('Use users.list() instead', 'v2.0.0')
async getAll() { return this.list() }

API Version Pinning

const client = new APIClient({
  apiKey: 'sk_test_...',
  apiVersion: '2025-01-01'
})

See references/versioning.md for migration strategies.

Configuration Best Practices

interface ClientConfig {
  apiKey: string
  baseURL?: string
  maxRetries?: number
  timeout?: number
  apiVersion?: string
  onTokenRefresh?: (token: string) => void
}

class APIClient {
  constructor(config: ClientConfig) {
    this.apiKey = config.apiKey
    this.baseURL = config.baseURL || 'https://api.example.com'
    this.maxRetries = config.maxRetries ?? 3
    this.timeout = config.timeout ?? 30000
  }
}

Provide sensible defaults, require only apiKey.

Quick Reference Tables

Authentication Patterns

PatternUse Case
API KeyService-to-service
OAuth RefreshUser-based auth
Bearer Per-RequestMulti-tenant

Retry Strategies

StrategyUse Case
Exponential BackoffDefault retry
Rate Limit429 responses
Max RetriesAvoid infinite loops (3-5)

Pagination Options

PatternLanguageUse Case
Async IteratorTypeScript, PythonAutomatic pagination
GeneratorPythonSync pagination
ChannelsGoConcurrent iteration
ManualAllExplicit control

Reference Documentation

Architecture:

  • references/architecture-patterns.md - Resource vs. command organization

Core Patterns:

  • references/authentication.md - OAuth, token refresh, credential providers
  • references/retry-backoff.md - Exponential backoff, jitter, circuit breakers
  • references/error-handling.md - Error hierarchies, debugging support
  • references/pagination.md - Cursor vs. offset, async iterators
  • references/versioning.md - SemVer, deprecation strategies
  • references/testing-sdks.md - Unit testing, mocking, integration tests

Code Examples

TypeScript:

  • examples/typescript/basic-client.ts - Simple async SDK
  • examples/typescript/advanced-client.ts - Retry, errors, streaming
  • examples/typescript/resource-based.ts - Stripe-style organization

Python:

  • examples/python/sync-client.py - Synchronous client
  • examples/python/async-client.py - Async client with asyncio
  • examples/python/dual-client.py - Both sync and async

Go:

  • examples/go/basic-client.go - Simple Go client
  • examples/go/context-client.go - Context patterns
  • examples/go/channel-pagination.go - Channel-based pagination

Best-in-Class SDK Examples

Study these production SDKs:

TypeScript/JavaScript:

  • AWS SDK v3 (@aws-sdk/client-*): Modular, tree-shakeable, middleware
  • Stripe Node (stripe): Resource-based, typed errors, excellent DX
  • OpenAI Node (openai): Streaming, async iterators, modern TypeScript

Python:

  • Boto3 (boto3): Resource vs. client patterns, paginators
  • Stripe Python (stripe): Dual sync/async, context managers

Go:

  • AWS SDK Go v2 (github.com/aws/aws-sdk-go-v2): Context, middleware

Common Pitfalls

Avoid these mistakes:

  1. No Retry Logic - All SDKs need automatic retries for transient errors
  2. Poor Error Messages - Include request ID, status code, error type
  3. No Pagination - Implement automatic pagination with async iterators
  4. Hardcoded Credentials - Use environment variables or config files
  5. Missing Idempotency - Add idempotency keys to prevent duplicate operations
  6. Ignoring Rate Limits - Respect Retry-After header on 429 responses
  7. Breaking Changes - Use SemVer, deprecate before removing

Integration with Other Skills

  • api-design-principles: API design complements SDK design (error codes → error classes)
  • building-clis: CLIs wrap SDKs for command-line access
  • testing-strategies: Test SDKs with mocked HTTP, retry scenarios

Next Steps

Review language-specific examples for implementation details. Study references for deep dives on specific patterns. Examine best-in-class SDKs (Stripe, AWS, OpenAI) for inspiration.

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

Manage Linux systems covering systemd services, process management, filesystems, networking, performance tuning, and troubleshooting. Use when deploying applications, optimizing server performance, diagnosing production issues, or managing users and security on Linux servers.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

ancoleman/ai-design-components5252025년 12월 11일 업데이트

Data pipelines, feature stores, and embedding generation for AI/ML systems. Use when building RAG pipelines, ML feature serving, or data transformations. Covers feature stores (Feast, Tecton), embedding pipelines, chunking strategies, orchestration (Dagster, Prefect, Airflow), dbt transformations, data versioning (LakeFS), and experiment tracking (MLflow, W&B).

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

ancoleman/ai-design-components5252025년 12월 11일 업데이트

Strategic guidance for designing modern data platforms, covering storage paradigms (data lake, warehouse, lakehouse), modeling approaches (dimensional, normalized, data vault, wide tables), data mesh principles, and medallion architecture patterns. Use when architecting data platforms, choosing between centralized vs decentralized patterns, selecting table formats (Iceberg, Delta Lake), or designing data governance frameworks.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

ancoleman/ai-design-components5252025년 12월 11일 업데이트

Design cloud network architectures with VPC patterns, subnet strategies, zero trust principles, and hybrid connectivity. Use when planning VPC topology, implementing multi-cloud networking, or establishing secure network segmentation for cloud workloads.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

ancoleman/ai-design-components5252025년 12월 11일 업데이트

Design comprehensive security architectures using defense-in-depth, zero trust principles, threat modeling (STRIDE, PASTA), and control frameworks (NIST CSF, CIS Controls, ISO 27001). Use when designing security for new systems, auditing existing architectures, or establishing security governance programs.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

ancoleman/ai-design-components5252025년 12월 11일 업데이트

Assembles component outputs from AI Design Components skills into unified, production-ready component systems with validated token integration, proper import chains, and framework-specific scaffolding. Use as the capstone skill after running theming, layout, dashboard, data-viz, or feedback skills to wire components into working React/Next.js, Python, or Rust projects.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

ancoleman/ai-design-components5252025년 12월 11일 업데이트

ancoleman의 스킬 모두 보기

이 스킬의 문제 신고