はじめに
GitHubが2026年3月24日に公開した技術ブログでは、GitHub Copilot SDKを活用してIssueトリアージを自動化するReact Nativeアプリ「IssueCrush」の実装例が紹介されています。本稿では、その設計思想と具体的なコードパターン、運用上の注意点を解説します。
参考記事
- タイトル: Building AI-powered GitHub issue triage with the Copilot SDK
- 著者: Andrea Griffiths
- 発行元: GitHub Blog
- 発行日: 2026年3月24日
- URL: https://github.blog/ai-and-ml/github-copilot/building-ai-powered-github-issue-triage-with-the-copilot-sdk/
要点
- GitHub Copilot SDKを使うと、Copilot Chatと同じAIを自社アプリケーションに組み込むことができる
- React NativeはNode.jsパッケージを直接利用できないため、SDKはサーバーサイドで動作させる設計が必須である
- セッションのライフサイクル管理(start→createSession→sendAndWait→disconnect→stop)を正しく実装しないとメモリリークの原因になる
- プロンプトにはIssueのタイトル・ラベル・著者などの構造化メタデータを渡すと、要約の品質が向上する
- AIサービスが利用できない場合に備えたフォールバック処理を設計段階から組み込むべきである
詳細解説
IssueCrushとは何か
オープンソースプロジェクトや活発なリポジトリを持つチームでは、Issueの増加が日常的な課題です。タイトルを読み、説明を確認し、ラベルを確認して優先度を判断する——これをIssue数十件分繰り返すと、開発者の認知的負荷は相当なものになります。
GitHubのシニア・デベロッパーアドボケートであるAndrea Griffithsは、この課題を解決するためにIssueCrushを開発しました。Issueをスワイプカード形式で表示し、「Get AI Summary」ボタンを押すとCopilotがIssueの要約と推奨アクションを返す仕組みです。左スワイプでクローズ、右スワイプで保持という直感的なUXと組み合わせることで、トリアージの意思決定を素早く行えるように設計されています。
サーバーサイド統合が必須な理由
Copilot SDKの実装で最初に直面する設計上の制約は、React Nativeアプリからの直接利用ができない点です。SDKは内部でCopilot CLIプロセスを起動し、JSON-RPCで通信する仕組みになっており、Node.jsランタイムとCopilot CLIバイナリの両方が必要です。スマートフォンにCLIバイナリをインストールすることは現実的ではないため、統合はサーバーサイドで行うことになります。
このアーキテクチャには、技術的な制約を超えた利点もあります。まず、すべてのクライアントがサーバー上の単一SDKインスタンスを共有するため、モバイルクライアントごとに新しい接続を張る必要がなく、オーバーヘッドが削減されます。また、Copilot認証に使うAPIトークンがクライアント側のReact Nativeバンドルに含まれないため、デコンパイルによる認証情報の漏洩リスクを回避できます。さらに、すべてのプロンプトとレスポンスがサーバーを経由することで、レイテンシの計測や障害の検知が一元的に行えます。
事前準備として必要なものは3点です。サーバーへのCopilot CLIのインストール、GitHub Copilotサブスクリプションまたはユーザー独自のAPIキーを使うBYOK(Bring Your Own Key)設定、そしてCopilot CLIの認証(copilot authコマンドまたは環境変数COPILOT_GITHUB_TOKENの設定)です。
SDKのライフサイクル管理
Copilot SDKはセッションベースのモデルを採用しています。基本的な処理フローは「クライアントの初期化(start())→セッションの作成(createSession())→プロンプトの送信(sendAndWait())→セッションの切断(disconnect())→クライアントの停止(stop())」という順序です。
記事の中で特に強調されているのは、クリーンアップの徹底です。disconnect()を呼び忘れると、リソースのリークが発生します。Griffithsは実際にこのミスで2時間以上のデバッグを要した経験を共有しており、try/finallyブロックでセッション操作を必ず囲むことを推奨しています。クリーンアップ処理に.catch(() => {})を付けるのは、クリーンアップ中に発生したエラーが元のエラーを隠蔽しないようにするためです。
また、SDKのインポートにはrequireではなく動的import()(await import(‘@github/copilot-sdk’))を使う点も注目されています。これにより、SDKに問題が発生してもサーバー自体は起動できるため、デプロイとデバッグが容易になります。
プロンプト設計と応答処理
AIの要約品質を左右するのはプロンプトの構造です。Issue本文をそのまま渡すのではなく、タイトル・Issue番号・リポジトリ名・状態・ラベル・作成日・著者といった構造化されたメタデータを整理して渡すことで、モデルが判断に必要なコンテキストを得やすくなります。
ラベルや著者情報は一見補助的に見えますが、実際には要約の方向性を変える重要な情報です。初めてコントリビュートするユーザーからのIssueと、コアメンテナーからのIssueでは、適切な対応が異なります。AIはこの情報を活用して要約のトーンや推奨アクションを調整します。
応答処理では、sendAndWait()にタイムアウト値(例: 30,000ミリ秒)を指定し、レスポンスオブジェクトのネストされたプロパティには必ずnullチェックを行うことが推奨されています。response.data.contentのように複数段階のプロパティアクセスが必要なため、どこかがundefinedになると実行時エラーになるためです。
グレースフルデグラデーションとキャッシュ
AIサービスは常に利用可能とは限りません。ネットワーク障害、レートリミット、サービスの一時停止といった状況を想定した設計が重要です。IssueCrushでは2種類の障害モードを区別しています。Copilotサブスクリプションに関するエラーはHTTP 403を返し、クライアント側で明確なメッセージを表示します。それ以外のすべてのエラーは、Issueのメタデータ(タイトル・ラベル・本文の最初の一文)から生成したフォールバック要約を返します。これにより、AIが利用できない状況でもトリアージ作業は継続できます。
クライアント側では、生成した要約をIssueオブジェクトにキャッシュする設計が採用されています。一度取得した要約はIssueに紐付けて保持されるため、ユーザーがスワイプで戻ってきた際に即座に表示され、APIの再呼び出しは発生しません。要約のオンデマンド生成(ユーザーがボタンを押した時のみ生成)と合わせることで、無駄なAPI呼び出しとコストを最小化しています。
サーバーは/healthエンドポイントを公開しており、クライアントは起動時にAIの利用可否を確認します。AIが利用できない場合はサマリーボタン自体を非表示にする設計で、動作しないUIを表示しないようにしています。
まとめ
GitHub Copilot SDKは、Copilot ChatのAIを自社アプリに組み込む実用的な選択肢です。サーバーサイド統合・セッション管理の徹底・構造化プロンプト・フォールバック設計の4点が、安定した実装の核心と言えます。IssueCrushのソースコードはGitHub(AndreaGriffiths11/IssueCrush)で公開されており、実際の実装パターンを参照できます。
