DIVX テックブログ

catch-img

Claude AI、Perplexity AIとペアプロ - REST API統合ツールを対話開発で完成させて作業効率を上げてみた

はじめに

株式会社divxでエンジニアをしているモーです。

DIVXでは、AIは「効率化ツール」ではなく、

設計と判断を前に進めるための相棒として使っています。

本記事は、その一例です。

外部サービスのAPIを使ったシステム運用では、複数のリソース(プロパティ・設定・環境など)を管理する際に、各リソースの設定状態を確認する作業が発生します。特に、本番環境とステージング環境のバージョン管理や、各種機能の有効/無効状態を確認する作業は、管理画面で一つずつ確認すると時間がかかります。そこで 本記事では、外部REST APIを使って、複数リソースの設定を一括で取得・可視化するRubyツールを、AI(Perplexity AI / Claude AI)と対話しながら開発した過程を紹介したいと思います。

背景

課題

弊社では外部サービスのAPIを通じて複数のリソースを運用しており、定期的に以下の情報を確認する必要がありました:

- 環境バージョン情報: Production/Stagingで展開中のバージョン 

- セキュリティ機能: セキュリティ関連機能の使用有無

- 最適化機能: パフォーマンス最適化機能の有無

- その他: リダイレクト設定、オリジンホスト名、ネットワーク設定、エンドポイント情報

これらを手動で確認すると、リソース数×確認項目数の作業が発生し、非効率だと感じることが多々ありました。

既存の方法の問題点

- 管理コンソール: 一つずつのリソースを開いて確認が必要 

- 手作業: ヒューマンエラーのリスク 

- 属人化: 設定確認の手順が属人化しやすい

- 時間コスト: リソースが増えるほど確認時間が増大

目的

本プロジェクトの目的は以下の通りです。

1. 自動化: REST APIを使って、リソース設定を自動取得

2. 可視化: 確認したい項目を一覧表形式で表示 

3. 再現性: スクリプト化して誰でも実行可能に 

4. AI活用: コード生成・デバッグにAIを活用し、開発時間を短縮

取得したい情報(要件定義)

  1. バージョン管理
     ・Production環境のバージョン
     ・Staging環境のバージョン

  2. セキュリティ
     ・セキュリティ機能の有効/無効

  3. 可用性
     ・フェイルオーバー設定の有無

  4. パフォーマンス
     ・最適化機能の使用有無

  5. ルーティング
     ・リダイレクト設定の有無

  6. インフラ
     ・オリジンホスト名
     ・IPバージョン
     ・エンドポイント情報


開発環境・使用技術

開発環境

言語

・Ruby 3.2.3

認証

・API認証(APIキー+シークレット方式)

主要ライブラリ

 ・REST API認証用gem
・net/http(HTTPリクエスト処理)
・json(JSONパース処理)

使用したAIツール

Perplexity AI

 Web検索機能を統合したAIチャットツール。
API仕様の調査および初期コード生成に活用。

Claude AI 

AIチャットサービス。
エラー解決、デバッグ対応、コード修正に活用。


開発の流れ

フェーズ1:Perplexity AIで初期実装

まず、Perplexity AIに要件を伝えて初期コードを生成しました。

【プロンプト(要約)】

 REST API経由で以下の情報を取得するRubyスクリプトを作成してください。
・複数リソースの一覧取得
・各リソースのProduction/Stagingバージョン
・各種機能(セキュリティ、フェイルオーバー等)の使用有無
・設定情報(オリジン、エンドポイント等)

Perplexity AIは、Web検索を並行して行うことで、最新のAPI仕様に基づいたコード構造を迅速に生成できる点が大きな強みです。リサーチと実装の初動を同時に進められる効率の良さがあります。 一方で、実際にコードを実行すると、一部の情報が期待通りに取得できないケースも見受けられました。

【実行結果】

リソース名

ProdVer

StageVer

機能A

機能B

・・・

resource-1

55

53

-

-

N/A

resource-2

6

31

-

-

N/A

バージョン情報は取得できているものの、一部の項目が「-」や「N/A」で、詳細な設定情報が取れておりません。

API仕様の細かい部分や、複雑なJSON構造の扱いに課題があると感じました。
ここからはエラーハンドリングとデバッグに強いClaude AIに切り替えて、詳細な問題解決を進めることにしました。


フェーズ2:Claude AIとのデバッグ対話

課題1:302リダイレクトエラーとの戦い

【最初のエラー】

Claude AIにコードとエラー内容を共有したところ、「デバッグスクリプトを作成しましょう」と提案されました。

【Hostnames API】

URL: https://api.example.com/v1/resources/xxx/versions/xx/hostnames
Response Code: 302
Response Body:
{
"redirectLink": "/v1/resources/xxx/versions/xx/hostnames?groupId=yyy&contractId=zzz"
}

【Claude AIの分析】

302リダイレクトが返されています。
APIがgroupIdおよびcontractIdをURLパラメータとして要求しています。

【修正前コード】

# ruby

hn_url = "/v1/resources/#{resource_id}/versions/#{prod_ver}/hostnames"

【修正後コード】

# ruby

hn_url = "/v1/resources/#{resource_id}/versions/#{prod_ver}/hostnames?groupId=#{group_id}&contractId=#{contract_id}"

【学び】

・REST APIでは、必須パラメータが不足している場合に302リダイレクトで正しいURLを提示することがある。
・Claude AIはエラーレスポンスの内容から不足しているパラメータを即座に特定できる。


課題2:JSON再帰探索の実装

次の課題は、APIから返ってくる複雑にネストされたJSON構造から、特定の設定情報を抽出することでした。

【JSON構造の例】

{

  "rules": {

    "name": "default",

    "behaviors": [

      {"name": "origin", "options": {"hostname": "origin.example.com"}}

    ],

    "children": [

      {

        "name": "Category_A",

        "behaviors": [

          {"name": "caching", ...}

        ],

        "children": [

          {

            "name": "Sub_Category_A",

            "behaviors": [

              {"name": "featureA", "options": {...}}

            ]

          }

        ]

      },

      {

        "name": "Category_B",

        "behaviors": [

          {"name": "featureB", ...}

        ]

      }

    ]

  }

}

この構造から特定のbehavior(機能設定)を探す必要がありますが、どの階層にあるか分かりません。

【最初のコード(失敗)】

# ruby

# トップレベルのbehaviorsしか見ていない

def find_behavior(rules, behavior_name)

  rules['behaviors'].each do |bh|

    return true if bh['name'] == behavior_name

  end

  false

end

これでは子階層(children)の中身を見られません。

【Claude AIとの対話】

私: 「behaviorが見つかりません」

Claude AI: 「JSON構造が再帰的にネストされているようです。再帰関数で全階層を探索しましょう」

【Claude AIが生成した再帰関数】

# ruby

def find_behaviors(node, behavior_name)

  found = []

  # 現在のノードのbehaviorsをチェック

  if node.is_a?(Hash) && node['behaviors'].is_a?(Array)

    node['behaviors'].each do |behavior|

      found << behavior if behavior['name'] == behavior_name

    end

  end

  # 子ルールを再帰的に検索

  if node.is_a?(Hash) && node['children'].is_a?(Array)

    node['children'].each do |child|

      found.concat(find_behaviors(child, behavior_name))  # 再帰呼び出し

    end

  end

  found

end

【動作イメージ】

find_behaviors(root, "featureA")

  ├─ root.behaviors をチェック → なし

  ├─ root.children[0] (Category_A) を探索

  │   ├─ behaviors をチェック → なし

  │   └─ children[0] (Sub_Category_A) を探索

  │       └─ behaviors をチェック → ✅ "featureA" 発見!

  └─ root.children[1] (Category_B) を探索

      └─ behaviors をチェック → "featureB" 発見

【学び】

・複雑にネストされたJSON構造では再帰的探索が必要。
・Claude AIは段階的に再帰関数を構築できる。
・デバッグ過程で「全設定項目をリストアップするスクリプト」も生成できた。


課題3: データ取得フィールドの修正

動作するようになった後、実行結果を見て気づきました。

|resource-1|55|53|-|○|○|○|origin.example.com|IPV4|resource-1.example.com|

                                                             ↑ これは違う

エンドポイント情報が間違っています。

【Claude AIとの対話】

私:「エンドポイントは resource-1.example.com.cdn.netのような形式のはずです」

Claude AI:「リクエスト元のホスト名(source_hostname)を取得していますね。配信先のホスト名(destination_hostname)に修正します」

【修正内容】

# ruby

# 修正前(リクエスト元のホスト名を取得していた)

endpoints = hostnames.map { |hn| hn['source_hostname'] }.join(', ')

# 修正後(配信先のホスト名を取得)

endpoints = hostnames.map { |hn| hn['destination_hostname'] }.join(', ')

【学び】

・AIが生成したコードも100%正確ではない。
・人間側の知識や違和感への気づきが重要。
・Claude AIは指摘内容を即座に反映し、修正案を提示できる。


完成したツール

実行方法

ruby resource_checker.rb

実行結果(サンプル)

|リソース名|ProdVer|StageVer|機能A|Failover|機能B|Redirect|Origin Host|IP Type|Endpoint|

|---|---|---|---|---|---|---|---|---|---|

|resource-1|55|53|-|○|○|○|origin.example.com|IPV4|resource-1.example.com.cdn.net|

|resource-2|6|32|-|○|-|-|origin.example.com|IPV4|resource-2.example.com.cdn.net|

|resource-3|4|24|-|○|○|-|origin.example.com|IPV4|resource-3.example.com.cdn.net|

すべての確認項目が正しく取得できるようになりました。

コアロジック(抜粋)

【再帰的な設定検索】

REST APIのレスポンスは階層構造になっており、目的の設定がどの階層にあるかわかりません。

Claude AIが提案した再帰関数で全階層を探索します。

# ruby

def find_behaviors(node, behavior_name)

  found = []

  # 現在の階層をチェック

  if node.is_a?(Hash) && node['behaviors'].is_a?(Array)

    node['behaviors'].each do |behavior|

      found << behavior if behavior['name'] == behavior_name

    end

  end

  # 子階層を再帰的に探索

  if node.is_a?(Hash) && node['children'].is_a?(Array)

    node['children'].each do |child|

      found.concat(find_behaviors(child, behavior_name))

    end

  end

  found

end

【オリジン情報の抽出】

オリジンサーバのホスト名も同様に再帰探索で取得します。

# ruby

def find_origin(node)

  if node.is_a?(Hash) && node['behaviors'].is_a?(Array)

    node['behaviors'].each do |behavior|

      if behavior['name'] == 'origin' && behavior['options']

        return behavior['options']['hostname']

      end

    end

  end

  if node.is_a?(Hash) && node['children'].is_a?(Array)

    node['children'].each do |child|

      origin = find_origin(child)

      return origin if origin

    end

  end

  nil

end


開発時間の比較

【作業時間一覧】

フェーズ

時間

Perplexity AIで初期実装

約45分

Claude AIでデバッグ(302対応)

10分

JSON再帰探索の実装

15分

その他の修正・検証

10分

合計

約80分

手動でゼロから実装すると3〜4時間はかかる作業が、AIとの対話により約1時間20分で完成しました。


まとめ

本記事では、Perplexity AIとClaude AIを組み合わせることで、複雑なREST API統合ツールを効率的に開発した過程を紹介しました。

開発のポイント

【AIツールの使い分け】

Perplexity AI:API仕様調査および初期コード生成に便利
Claude AI:エラー解決・デバッグに強く、再帰関数などの複雑なロジックの実装に適している

【AIと人間の役割分担】

AI:コード生成、エラー原因の特定、複数の解決策の提示
人間:要件定義、ドメイン知識の判断、AIが生成したコードのレビュー

【対話型開発の効果】

・段階的にデバッグを進められる。
・学びながら開発できる。
・手動実装では3〜4時間かかる作業を約1時間20分に短縮。

最後に

AIとの対話型開発は、単なる時間短縮にとどまらず、技術的な学びを得ながら開発できる点が大きな魅力です。

REST APIを活用した業務自動化や複雑なJSON構造の取り扱い、エラー解決に多くの時間を要している方は、ぜひPerplexity AIとClaude AIを組み合わせた開発手法を試してみてください。


お気軽にご相談ください


ご不明な点はお気軽に
お問い合わせください

サービス資料や
お役立ち資料はこちら

DIVXブログ

テックブログ タグ一覧

人気記事ランキング

関連記事