claude-skills/

Anthropic公式スキル・プラグインの日本語ディレクトリ

last sync 22h ago
スキルOfficialdevelopment

🔧output-error-http-client

プラグイン
outputai

説明

HTTPクライアントのOutput SDKステップにおける誤用を修正します。 次のような場合に使用: - トレースされていないリクエストが発生している - エラーの詳細が欠落している - axiosに関連するエラーが発生している - HTTPコールが適切にログ記録・リトライされていない

原文を表示

Fix HTTP client misuse in Output SDK steps. Use when seeing untraced requests, missing error details, axios-related errors, or when HTTP calls aren't being properly logged and retried.

ユースケース

  • トレースされていないリクエストを修正する
  • エラーの詳細が欠落しているときに対応する
  • axiosに関連するエラーを解決する
  • HTTPコールのログ記録・リトライを修正する

本文(日本語訳)

HTTP クライアントの誤用を修正する

概要

このスキルは、Output SDK の @outputai/http が提供する httpClient を使わずに、axios・fetch・その他の HTTP クライアントを直接使用している場合の問題を診断・修正するために役立ちます。 Output SDK のクライアントは、トレーシング・自動リトライ・より優れたエラーハンドリングを提供します。

このスキルを使用するタイミング

次のような場合に使用:

  • HTTP リクエストがトレースされていない(ワークフローのトレースに表示されない)
  • 失敗したリクエストのエラー詳細が欠落している
  • axios 関連のエラーやインポートの問題が発生している
  • HTTP 失敗時のリトライが機能していない
  • タイムアウトの動作が一貫していない

根本原因

axios・fetch・その他の HTTP クライアントを直接使用すると、Output SDK の以下の機能がバイパスされます:

  • リクエスト/レスポンスのトレーシング: ワークフローのトレースにコールが記録されない
  • 自動リトライ: 失敗したリクエストが再試行されない
  • エラーの標準化: エラーフォーマットが一貫しない場合がある
  • タイムアウトの制御: タイムアウトがステップのタイムアウトと連携しない場合がある

症状

axios を直接使用している場合

// 誤り: axios を使用
import axios from 'axios';

export const fetchData = step( {
  name: 'fetchData',
  fn: async input => {
    const response = await axios.get( 'https://api.example.com/data' );
    return response.data;
  }
} );

fetch を直接使用している場合

// 誤り: fetch を使用
export const fetchData = step( {
  name: 'fetchData',
  fn: async input => {
    const response = await fetch( 'https://api.example.com/data' );
    return response.json();
  }
} );

解決策

@outputai/httphttpClient を使用してください:

基本的な使い方

import { z, step } from '@outputai/core';
import { httpClient } from '@outputai/http';

export const fetchData = step( {
  name: 'fetchData',
  inputSchema: z.object( {
    endpoint: z.string()
  } ),
  outputSchema: z.object( {
    data: z.unknown()
  } ),
  fn: async input => {
    const client = httpClient( {
      prefixUrl: 'https://api.example.com'
    } );

    const data = await client.get( input.endpoint ).json();
    return { data };
  }
} );

詳細な設定を指定する場合

import { httpClient } from '@outputai/http';

const client = httpClient( {
  prefixUrl: 'https://api.example.com',
  timeout: 30000,  // 30 秒タイムアウト
  retry: {
    limit: 3,      // 最大 3 回リトライ
    methods: [ 'GET', 'POST' ],  // リトライ対象のメソッド
    statusCodes: [ 408, 500, 502, 503, 504 ]  // リトライを発動するステータスコード
  },
  headers: {
    'Authorization': `Bearer ${apiKey}`,
    'Content-Type': 'application/json'
  }
} );

HTTP メソッド

GET リクエスト

const data = await client.get( 'users/123' ).json();

POST リクエスト

const result = await client.post( 'users', {
  json: {
    name: 'John',
    email: 'john@example.com'
  }
} ).json();

PUT リクエスト

const updated = await client.put( 'users/123', {
  json: {
    name: 'John Updated'
  }
} ).json();

DELETE リクエスト

await client.delete( 'users/123' );

クエリパラメータを指定する場合

const data = await client.get( 'search', {
  searchParams: {
    q: 'query',
    limit: 10
  }
} ).json();

移行の完全な例

移行前(誤り — axios を使用)

import axios from 'axios';
import { step } from '@outputai/core';

export const createUser = step( {
  name: 'createUser',
  fn: async input => {
    try {
      const response = await axios.post(
        'https://api.example.com/users',
        { name: input.name, email: input.email },
        {
          headers: { 'Authorization': `Bearer ${process.env.API_KEY}` },
          timeout: 30000
        }
      );
      return response.data;
    } catch ( error ) {
      if ( axios.isAxiosError( error ) ) {
        throw new Error( `API Error: ${error.response?.data?.message}` );
      }
      throw error;
    }
  }
} );

移行後(正しい — httpClient を使用)

import { z, step } from '@outputai/core';
import { httpClient } from '@outputai/http';

export const createUser = step( {
  name: 'createUser',
  inputSchema: z.object( {
    name: z.string(),
    email: z.string().email()
  } ),
  outputSchema: z.object( {
    id: z.string(),
    name: z.string(),
    email: z.string()
  } ),
  fn: async input => {
    const client = httpClient( {
      prefixUrl: 'https://api.example.com',
      timeout: 30000,
      retry: { limit: 3 },
      headers: {
        'Authorization': `Bearer ${process.env.API_KEY}`
      }
    } );

    const user = await client.post( 'users', {
      json: {
        name: input.name,
        email: input.email
      }
    } ).json();

    return user;
  }
} );

エラーハンドリング

httpClient は構造化されたエラーハンドリングを提供します:

import { httpClient, HTTPError } from '@outputai/http';

export const fetchData = step( {
  name: 'fetchData',
  fn: async input => {
    const client = httpClient( { prefixUrl: 'https://api.example.com' } );

    try {
      return await client.get( 'data' ).json();
    } catch ( error ) {
      if ( error instanceof HTTPError ) {
        // レスポンスの詳細にアクセス
        const status = error.response.status;
        const body = await error.response.json();
        throw new Error( `API returned ${status}: ${body.message}` );
      }
      throw error;
    }
  }
} );

axios / fetch の使用箇所を探す

コードベースを検索してください:

# axios のインポートを検索
grep -rn "from 'axios'\|from \"axios\"" src/

# fetch の呼び出しを検索
grep -rn "await fetch(" src/

# その他の HTTP ライブラリを検索
grep -rn "got\|node-fetch\|request\|superagent" src/

httpClient のメリット

  1. トレーシング: リクエストがタイミング情報付きでワークフローのトレースに表示される
  2. 自動リトライ: 一時的な障害に対して設定可能なリトライロジックを提供
  3. 一貫したエラー: すべてのリクエストにわたって標準化されたエラーフォーマット
  4. タイムアウトの統合: ステップおよびワークフローのタイムアウトと連携して動作
  5. 型安全性: TypeScript の完全なサポート

設定オプション

オプション 説明 デフォルト
prefixUrl すべてのリクエストのベース URL (必須)
timeout リクエストタイムアウト(ミリ秒) 10000
retry.limit 最大リトライ回数 2
retry.methods リトライ対象の HTTP メソッド ['GET', 'PUT', 'HEAD', 'DELETE', 'OPTIONS', 'TRACE']
retry.statusCodes リトライを発動するステータスコード [408, 413, 429, 500, 502, 503, 504]
headers デフォルトヘッダー {}

確認手順

httpClient への移行後:

  1. ワークフローを実行する: npx output workflow run <name> '<input>'
  2. トレースを確認する: npx output workflow debug <id> --json
  3. トレーシングを検証する: HTTP リクエストがステップのトレースに表示されていることを確認
  4. リトライをテストする: 障害をシミュレートしてリトライの動作を検証

関連する問題

  • ワークフロー関数における I/O については output-error-direct-io を参照
  • 接続の問題については output-services-check を参照
  • 暗号化されたシークレットの管理については output-dev-credentials を参照
原文(English)を表示

Fix HTTP Client Misuse

Overview

This skill helps diagnose and fix issues caused by using axios, fetch, or other HTTP clients directly instead of Output SDK's httpClient from @outputai/http. The Output SDK client provides tracing, automatic retries, and better error handling.

When to Use This Skill

You're seeing:

  • Untraced HTTP requests (not appearing in workflow traces)
  • Missing error details for failed requests
  • axios-related errors or import issues
  • Retries not working for HTTP failures
  • Inconsistent timeout behavior

Root Cause

Using axios, fetch, or other HTTP clients directly bypasses Output SDK's:

  • Request/response tracing: Calls aren't logged in workflow traces
  • Automatic retries: Failed requests aren't retried
  • Error standardization: Error formats may be inconsistent
  • Timeout handling: Timeouts may not integrate with step timeouts

Symptoms

Using axios Directly

// WRONG: Using axios
import axios from 'axios';

export const fetchData = step( {
  name: 'fetchData',
  fn: async input => {
    const response = await axios.get( 'https://api.example.com/data' );
    return response.data;
  }
} );

Using fetch Directly

// WRONG: Using fetch
export const fetchData = step( {
  name: 'fetchData',
  fn: async input => {
    const response = await fetch( 'https://api.example.com/data' );
    return response.json();
  }
} );

Solution

Use httpClient from @outputai/http:

Basic Usage

import { z, step } from '@outputai/core';
import { httpClient } from '@outputai/http';

export const fetchData = step( {
  name: 'fetchData',
  inputSchema: z.object( {
    endpoint: z.string()
  } ),
  outputSchema: z.object( {
    data: z.unknown()
  } ),
  fn: async input => {
    const client = httpClient( {
      prefixUrl: 'https://api.example.com'
    } );

    const data = await client.get( input.endpoint ).json();
    return { data };
  }
} );

With Full Configuration

import { httpClient } from '@outputai/http';

const client = httpClient( {
  prefixUrl: 'https://api.example.com',
  timeout: 30000,  // 30 second timeout
  retry: {
    limit: 3,      // Retry up to 3 times
    methods: [ 'GET', 'POST' ],  // Which methods to retry
    statusCodes: [ 408, 500, 502, 503, 504 ]  // Which status codes trigger retry
  },
  headers: {
    'Authorization': `Bearer ${apiKey}`,
    'Content-Type': 'application/json'
  }
} );

HTTP Methods

GET Request

const data = await client.get( 'users/123' ).json();

POST Request

const result = await client.post( 'users', {
  json: {
    name: 'John',
    email: 'john@example.com'
  }
} ).json();

PUT Request

const updated = await client.put( 'users/123', {
  json: {
    name: 'John Updated'
  }
} ).json();

DELETE Request

await client.delete( 'users/123' );

With Query Parameters

const data = await client.get( 'search', {
  searchParams: {
    q: 'query',
    limit: 10
  }
} ).json();

Complete Migration Example

Before (Wrong - using axios)

import axios from 'axios';
import { step } from '@outputai/core';

export const createUser = step( {
  name: 'createUser',
  fn: async input => {
    try {
      const response = await axios.post(
        'https://api.example.com/users',
        { name: input.name, email: input.email },
        {
          headers: { 'Authorization': `Bearer ${process.env.API_KEY}` },
          timeout: 30000
        }
      );
      return response.data;
    } catch ( error ) {
      if ( axios.isAxiosError( error ) ) {
        throw new Error( `API Error: ${error.response?.data?.message}` );
      }
      throw error;
    }
  }
} );

After (Correct - using httpClient)

import { z, step } from '@outputai/core';
import { httpClient } from '@outputai/http';

export const createUser = step( {
  name: 'createUser',
  inputSchema: z.object( {
    name: z.string(),
    email: z.string().email()
  } ),
  outputSchema: z.object( {
    id: z.string(),
    name: z.string(),
    email: z.string()
  } ),
  fn: async input => {
    const client = httpClient( {
      prefixUrl: 'https://api.example.com',
      timeout: 30000,
      retry: { limit: 3 },
      headers: {
        'Authorization': `Bearer ${process.env.API_KEY}`
      }
    } );

    const user = await client.post( 'users', {
      json: {
        name: input.name,
        email: input.email
      }
    } ).json();

    return user;
  }
} );

Error Handling

The httpClient provides structured error handling:

import { httpClient, HTTPError } from '@outputai/http';

export const fetchData = step( {
  name: 'fetchData',
  fn: async input => {
    const client = httpClient( { prefixUrl: 'https://api.example.com' } );

    try {
      return await client.get( 'data' ).json();
    } catch ( error ) {
      if ( error instanceof HTTPError ) {
        // Access response details
        const status = error.response.status;
        const body = await error.response.json();
        throw new Error( `API returned ${status}: ${body.message}` );
      }
      throw error;
    }
  }
} );

Finding axios/fetch Usage

Search your codebase:

# Find axios imports
grep -rn "from 'axios'\|from \"axios\"" src/

# Find fetch calls
grep -rn "await fetch(" src/

# Find other HTTP libraries
grep -rn "got\|node-fetch\|request\|superagent" src/

Benefits of httpClient

  1. Tracing: Requests appear in workflow traces with timing
  2. Automatic Retries: Configurable retry logic for transient failures
  3. Consistent Errors: Standardized error format across all requests
  4. Timeout Integration: Works with step and workflow timeouts
  5. Type Safety: Full TypeScript support

Configuration Options

Option Description Default
prefixUrl Base URL for all requests (required)
timeout Request timeout in ms 10000
retry.limit Max retry attempts 2
retry.methods HTTP methods to retry ['GET', 'PUT', 'HEAD', 'DELETE', 'OPTIONS', 'TRACE']
retry.statusCodes Status codes to retry [408, 413, 429, 500, 502, 503, 504]
headers Default headers {}

Verification

After migrating to httpClient:

  1. Run the workflow: npx output workflow run <name> '<input>'
  2. Check the trace: npx output workflow debug <id> --json
  3. Verify tracing: HTTP requests should appear in the step trace
  4. Test retries: Simulate failures to verify retry behavior

Related Issues

  • For I/O in workflow functions, see output-error-direct-io
  • For connection issues, see output-services-check
  • For encrypted secrets management, see output-dev-credentials

原文・著作権は Anthropic および各プラグイン作者に帰属します。日本語訳は Claude API による自動翻訳です。