api-integration-patterns

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

API Integration Patterns Skill

API集成模式Skill

Standardized patterns for integrating external APIs and CLI tools in the autonomous-dev plugin ecosystem. Focuses on safety, reliability, and security when calling external services.
在autonomous-dev插件生态系统中集成外部API和CLI工具的标准化模式,重点关注调用外部服务时的安全性、可靠性与稳健性。

When This Skill Activates

本Skill的激活场景

  • Integrating external APIs (GitHub, etc.)
  • Executing subprocess commands safely
  • Implementing retry logic
  • Handling authentication
  • Managing rate limits
  • Keywords: "api", "subprocess", "github", "gh cli", "retry", "authentication"

  • 集成外部API(如GitHub等)
  • 安全执行子进程命令
  • 实现重试逻辑
  • 处理身份验证
  • 管理速率限制
  • 关键词:"api"、"subprocess"、"github"、"gh cli"、"retry"、"authentication"

Core Patterns

核心模式

1. Subprocess Safety (CWE-78 Prevention)

1. 子进程安全(CWE-78防护)

Definition: Execute external commands safely without command injection vulnerabilities.
Critical Rules:
  • ✅ ALWAYS use argument arrays:
    ["gh", "issue", "create"]
  • ❌ NEVER use shell=True with user input
  • ✅ ALWAYS whitelist allowed commands
  • ✅ ALWAYS set timeouts
Pattern:
python
import subprocess
from typing import List

def safe_subprocess(
    command: List[str],
    *,
    allowed_commands: List[str],
    timeout: int = 30
) -> subprocess.CompletedProcess:
    """Execute subprocess with CWE-78 prevention.

    Args:
        command: Command and arguments as list (NOT string!)
        allowed_commands: Whitelist of allowed commands
        timeout: Maximum execution time in seconds

    Returns:
        Completed subprocess result

    Raises:
        SecurityError: If command not in whitelist
        subprocess.TimeoutExpired: If timeout exceeded

    Security:
        - CWE-78 Prevention: Argument arrays (no shell injection)
        - Command Whitelist: Only approved commands
        - Timeout: DoS prevention

    Example:
        >>> result = safe_subprocess(
        ...     ["gh", "issue", "create", "--title", user_title],
        ...     allowed_commands=["gh", "git"]
        ... )
    """
    # Whitelist validation
    if command[0] not in allowed_commands:
        raise SecurityError(f"Command not allowed: {command[0]}")

    # Execute with argument array (NEVER shell=True!)
    return subprocess.run(
        command,
        capture_output=True,
        text=True,
        timeout=timeout,
        check=True,
        shell=False  # CRITICAL
    )
See:
docs/subprocess-safety.md
,
examples/safe-subprocess-example.py

定义:安全执行外部命令,避免命令注入漏洞。
关键规则:
  • ✅ 始终使用参数数组:
    ["gh", "issue", "create"]
  • ❌ 绝不要在包含用户输入的场景下使用shell=True
  • ✅ 始终对允许执行的命令进行白名单限制
  • ✅ 始终设置超时时间
模式代码:
python
import subprocess
from typing import List

def safe_subprocess(
    command: List[str],
    *,
    allowed_commands: List[str],
    timeout: int = 30
) -> subprocess.CompletedProcess:
    """Execute subprocess with CWE-78 prevention.

    Args:
        command: Command and arguments as list (NOT string!)
        allowed_commands: Whitelist of allowed commands
        timeout: Maximum execution time in seconds

    Returns:
        Completed subprocess result

    Raises:
        SecurityError: If command not in whitelist
        subprocess.TimeoutExpired: If timeout exceeded

    Security:
        - CWE-78 Prevention: Argument arrays (no shell injection)
        - Command Whitelist: Only approved commands
        - Timeout: DoS prevention

    Example:
        >>> result = safe_subprocess(
        ...     ["gh", "issue", "create", "--title", user_title],
        ...     allowed_commands=["gh", "git"]
        ... )
    """
    # Whitelist validation
    if command[0] not in allowed_commands:
        raise SecurityError(f"Command not allowed: {command[0]}")

    # Execute with argument array (NEVER shell=True!)
    return subprocess.run(
        command,
        capture_output=True,
        text=True,
        timeout=timeout,
        check=True,
        shell=False  # CRITICAL
    )
参考文档:
docs/subprocess-safety.md
,
examples/safe-subprocess-example.py

2. GitHub CLI (gh) Integration

2. GitHub CLI (gh) 集成

Definition: Standardized patterns for GitHub operations via gh CLI.
Pattern:
python
def create_github_issue(
    title: str,
    body: str,
    *,
    labels: Optional[List[str]] = None,
    timeout: int = 30
) -> str:
    """Create GitHub issue using gh CLI.

    Args:
        title: Issue title
        body: Issue body (markdown)
        labels: Issue labels (default: None)
        timeout: Command timeout in seconds

    Returns:
        Issue URL

    Raises:
        subprocess.CalledProcessError: If gh command fails
        RuntimeError: If gh CLI not installed

    Example:
        >>> url = create_github_issue(
        ...     "Bug: Login fails",
        ...     "Login button doesn't work",
        ...     labels=["bug", "p1"]
        ... )
    """
    # Build gh command (argument array)
    cmd = ["gh", "issue", "create", "--title", title, "--body", body]

    if labels:
        for label in labels:
            cmd.extend(["--label", label])

    # Execute safely
    result = subprocess.run(
        cmd,
        capture_output=True,
        text=True,
        timeout=timeout,
        check=True,
        shell=False
    )

    # Extract URL from output
    return result.stdout.strip()
See:
docs/github-cli-integration.md
,
examples/github-issue-example.py

定义:通过gh CLI执行GitHub操作的标准化模式。
模式代码:
python
def create_github_issue(
    title: str,
    body: str,
    *,
    labels: Optional[List[str]] = None,
    timeout: int = 30
) -> str:
    """Create GitHub issue using gh CLI.

    Args:
        title: Issue title
        body: Issue body (markdown)
        labels: Issue labels (default: None)
        timeout: Command timeout in seconds

    Returns:
        Issue URL

    Raises:
        subprocess.CalledProcessError: If gh command fails
        RuntimeError: If gh CLI not installed

    Example:
        >>> url = create_github_issue(
        ...     "Bug: Login fails",
        ...     "Login button doesn't work",
        ...     labels=["bug", "p1"]
        ... )
    """
    # Build gh command (argument array)
    cmd = ["gh", "issue", "create", "--title", title, "--body", body]

    if labels:
        for label in labels:
            cmd.extend(["--label", label])

    # Execute safely
    result = subprocess.run(
        cmd,
        capture_output=True,
        text=True,
        timeout=timeout,
        check=True,
        shell=False
    )

    # Extract URL from output
    return result.stdout.strip()
参考文档:
docs/github-cli-integration.md
,
examples/github-issue-example.py

3. Retry Logic with Exponential Backoff

3. 带指数退避的重试逻辑

Definition: Automatically retry failed API calls with exponential backoff.
Pattern:
python
import time
from typing import Callable, TypeVar, Any

T = TypeVar('T')

def retry_with_backoff(
    func: Callable[..., T],
    *,
    max_attempts: int = 3,
    base_delay: float = 1.0,
    max_delay: float = 60.0
) -> T:
    """Retry function with exponential backoff.

    Args:
        func: Function to retry
        max_attempts: Maximum retry attempts
        base_delay: Initial delay in seconds
        max_delay: Maximum delay in seconds

    Returns:
        Function result

    Raises:
        Exception: Last exception if all retries fail

    Example:
        >>> result = retry_with_backoff(
        ...     lambda: api_call(),
        ...     max_attempts=5,
        ...     base_delay=2.0
        ... )
    """
    last_exception = None

    for attempt in range(max_attempts):
        try:
            return func()
        except Exception as e:
            last_exception = e

            if attempt < max_attempts - 1:
                # Exponential backoff: 1s, 2s, 4s, 8s, ...
                delay = min(base_delay * (2 ** attempt), max_delay)
                time.sleep(delay)

    raise last_exception
See:
docs/retry-logic.md
,
templates/retry-decorator-template.py

定义:通过指数退避机制自动重试失败的API调用。
模式代码:
python
import time
from typing import Callable, TypeVar, Any

T = TypeVar('T')

def retry_with_backoff(
    func: Callable[..., T],
    *,
    max_attempts: int = 3,
    base_delay: float = 1.0,
    max_delay: float = 60.0
) -> T:
    """Retry function with exponential backoff.

    Args:
        func: Function to retry
        max_attempts: Maximum retry attempts
        base_delay: Initial delay in seconds
        max_delay: Maximum delay in seconds

    Returns:
        Function result

    Raises:
        Exception: Last exception if all retries fail

    Example:
        >>> result = retry_with_backoff(
        ...     lambda: api_call(),
        ...     max_attempts=5,
        ...     base_delay=2.0
        ... )
    """
    last_exception = None

    for attempt in range(max_attempts):
        try:
            return func()
        except Exception as e:
            last_exception = e

            if attempt < max_attempts - 1:
                # Exponential backoff: 1s, 2s, 4s, 8s, ...
                delay = min(base_delay * (2 ** attempt), max_delay)
                time.sleep(delay)

    raise last_exception
参考文档:
docs/retry-logic.md
,
templates/retry-decorator-template.py

4. Authentication Patterns

4. 身份验证模式

Definition: Secure handling of API credentials and tokens.
Principles:
  • Use environment variables for credentials
  • Never hardcode API keys
  • Never log credentials
  • Validate credentials before use
Pattern:
python
import os
from typing import Optional

def get_github_token() -> str:
    """Get GitHub token from environment.

    Returns:
        GitHub personal access token

    Raises:
        RuntimeError: If token not found

    Security:
        - Environment Variables: Never hardcode tokens
        - Validation: Check token format
        - No Logging: Never log credentials
    """
    token = os.getenv("GITHUB_TOKEN")

    if not token:
        raise RuntimeError(
            "GITHUB_TOKEN not found in environment\n"
            "Set with: export GITHUB_TOKEN=your_token\n"
            "Or add to .env file"
        )

    # Validate token format (basic check)
    if not token.startswith("ghp_") and not token.startswith("github_pat_"):
        raise ValueError("Invalid GitHub token format")

    return token
See:
docs/authentication-patterns.md
,
templates/github-api-template.py

定义:安全处理API凭证与令牌。
核心原则:
  • 使用环境变量存储凭证
  • 绝不要硬编码API密钥
  • 绝不要记录凭证信息
  • 使用前验证凭证有效性
模式代码:
python
import os
from typing import Optional

def get_github_token() -> str:
    """Get GitHub token from environment.

    Returns:
        GitHub personal access token

    Raises:
        RuntimeError: If token not found

    Security:
        - Environment Variables: Never hardcode tokens
        - Validation: Check token format
        - No Logging: Never log credentials
    """
    token = os.getenv("GITHUB_TOKEN")

    if not token:
        raise RuntimeError(
            "GITHUB_TOKEN not found in environment\n"
            "Set with: export GITHUB_TOKEN=your_token\n"
            "Or add to .env file"
        )

    # Validate token format (basic check)
    if not token.startswith("ghp_") and not token.startswith("github_pat_"):
        raise ValueError("Invalid GitHub token format")

    return token
参考文档:
docs/authentication-patterns.md
,
templates/github-api-template.py

5. Rate Limiting and Quota Management

5. 速率限制与配额管理

Definition: Handle API rate limits gracefully.
Pattern:
python
import time
from datetime import datetime, timedelta

class RateLimiter:
    """Simple rate limiter for API calls.

    Attributes:
        max_calls: Maximum calls per window
        window_seconds: Time window in seconds
    """

    def __init__(self, max_calls: int, window_seconds: int):
        self.max_calls = max_calls
        self.window_seconds = window_seconds
        self.calls = []

    def wait_if_needed(self) -> None:
        """Wait if rate limit would be exceeded."""
        now = datetime.now()
        cutoff = now - timedelta(seconds=self.window_seconds)

        # Remove old calls outside window
        self.calls = [c for c in self.calls if c > cutoff]

        # Wait if at limit
        if len(self.calls) >= self.max_calls:
            oldest = self.calls[0]
            wait_until = oldest + timedelta(seconds=self.window_seconds)
            wait_seconds = (wait_until - now).total_seconds()

            if wait_seconds > 0:
                time.sleep(wait_seconds)

            # Retry removal after wait
            self.calls = [c for c in self.calls if c > cutoff]

        # Record this call
        self.calls.append(now)
See:
docs/rate-limiting.md
,
examples/github-api-example.py

定义:优雅处理API速率限制。
模式代码:
python
import time
from datetime import datetime, timedelta

class RateLimiter:
    """Simple rate limiter for API calls.

    Attributes:
        max_calls: Maximum calls per window
        window_seconds: Time window in seconds
    """

    def __init__(self, max_calls: int, window_seconds: int):
        self.max_calls = max_calls
        self.window_seconds = window_seconds
        self.calls = []

    def wait_if_needed(self) -> None:
        """Wait if rate limit would be exceeded."""
        now = datetime.now()
        cutoff = now - timedelta(seconds=self.window_seconds)

        # Remove old calls outside window
        self.calls = [c for c in self.calls if c > cutoff]

        # Wait if at limit
        if len(self.calls) >= self.max_calls:
            oldest = self.calls[0]
            wait_until = oldest + timedelta(seconds=self.window_seconds)
            wait_seconds = (wait_until - now).total_seconds()

            if wait_seconds > 0:
                time.sleep(wait_seconds)

            # Retry removal after wait
            self.calls = [c for c in self.calls if c > cutoff]

        # Record this call
        self.calls.append(now)
参考文档:
docs/rate-limiting.md
,
examples/github-api-example.py

Usage Guidelines

使用指南

For Library Authors

针对库开发者

When integrating external APIs:
  1. Use subprocess safely with argument arrays
  2. Whitelist commands to prevent injection
  3. Add retry logic for transient failures
  4. Handle authentication securely via environment
  5. Respect rate limits to avoid quota exhaustion
集成外部API时:
  1. 安全使用subprocess:采用参数数组方式
  2. 命令白名单:防止注入攻击
  3. 添加重试逻辑:处理临时故障
  4. 安全处理身份验证:通过环境变量管理凭证
  5. 遵守速率限制:避免配额耗尽

For Claude

针对Claude

When creating API integrations:
  1. Load this skill when keywords match
  2. Follow safety patterns for subprocess
  3. Implement retries for reliability
  4. Reference templates for common patterns
创建API集成时:
  1. 匹配关键词时加载本Skill
  2. 遵循子进程安全模式
  3. 实现重试逻辑:提升可靠性
  4. 参考模板:复用通用模式

Token Savings

Token使用优化

By centralizing API integration patterns:
  • Before: ~45 tokens per library for subprocess safety docs
  • After: ~10 tokens for skill reference
  • Savings: ~35 tokens per library
  • Total: ~280 tokens across 8 libraries (3-4% reduction)

通过集中管理API集成模式:
  • 优化前:每个库的子进程安全文档约占用45个Token
  • 优化后:仅需约10个Token用于Skill参考
  • 节省量:每个库约节省35个Token
  • 总计:8个库共节省约280个Token(减少3-4%)

Progressive Disclosure

渐进式披露(Progressive Disclosure)

This skill uses Claude Code 2.0+ progressive disclosure architecture:
  • Metadata (frontmatter): Always loaded (~170 tokens)
  • Full content: Loaded only when keywords match
  • Result: Efficient context usage

本Skill采用Claude Code 2.0+的渐进式披露架构:
  • 元数据(前置内容):始终加载(约170个Token)
  • 完整内容:仅当匹配关键词时加载
  • 效果:高效使用上下文

Templates and Examples

模板与示例

Templates

模板

  • templates/subprocess-executor-template.py
    : Safe subprocess execution
  • templates/retry-decorator-template.py
    : Retry logic decorator
  • templates/github-api-template.py
    : GitHub API integration
  • templates/subprocess-executor-template.py
    :安全子进程执行模板
  • templates/retry-decorator-template.py
    :重试逻辑装饰器模板
  • templates/github-api-template.py
    :GitHub API集成模板

Examples

示例

  • examples/github-issue-example.py
    : Issue creation via gh CLI
  • examples/github-pr-example.py
    : PR creation patterns
  • examples/safe-subprocess-example.py
    : Command execution safety
  • examples/github-issue-example.py
    :通过gh CLI创建Issue的示例
  • examples/github-pr-example.py
    :PR创建模式示例
  • examples/safe-subprocess-example.py
    :命令执行安全示例

Documentation

文档

  • docs/subprocess-safety.md
    : CWE-78 prevention
  • docs/github-cli-integration.md
    : gh CLI patterns
  • docs/retry-logic.md
    : Retry strategies
  • docs/authentication-patterns.md
    : Credential handling

  • docs/subprocess-safety.md
    :CWE-78防护指南
  • docs/github-cli-integration.md
    :gh CLI集成模式
  • docs/retry-logic.md
    :重试策略
  • docs/authentication-patterns.md
    :凭证处理指南

Cross-References

交叉引用

This skill integrates with other autonomous-dev skills:
  • library-design-patterns: Security-first design
  • security-patterns: CWE-78 prevention
  • error-handling-patterns: Retry and recovery

本Skill与其他autonomous-dev Skill集成:
  • library-design-patterns:安全优先的设计模式
  • security-patterns:CWE-78防护
  • error-handling-patterns:重试与恢复机制

Maintenance

维护说明

Update when:
  • New API integration patterns emerge
  • Security best practices evolve
  • gh CLI adds new features
Last Updated: 2025-11-16 (Phase 8.8 - Initial creation) Version: 1.0.0
在以下场景时更新本Skill:
  • 出现新的API集成模式
  • 安全最佳实践更新
  • gh CLI新增功能
最后更新: 2025-11-16(Phase 8.8 - 初始创建) 版本: 1.0.0