GitHub Copilot SDK を使用して AI エージェントを実装する

完了

このユニットでは、GitHub Copilot SDK を使用して AI エージェントを構築するためのコア実装パターンについて説明します。 これらのパターンは、任意のエージェント シナリオに適用されます。 このコード例では、C# と .NET を使用します。これは、モジュール演習で使用されるプラットフォームです。

GitHub Copilot SDK クライアントを設定する

最初の手順では、Copilot CLI サーバーへの接続を管理する CopilotClient インスタンスを作成します。 通常、クライアントをシングルトン サービスとしてアプリケーションに登録します。

必要なパッケージをインストールする

GitHub Copilot SDK と Microsoft.Extensions.AI パッケージ (ツール定義に使用) をプロジェクトに追加します。

dotnet add package GitHub.Copilot.SDK
dotnet add package Microsoft.Extensions.AI

クライアントの構成

スタートアップ動作とログ記録を制御するCopilotClientを使用してCopilotClientOptionsを作成します。

var client = new CopilotClient(new CopilotClientOptions
{
    AutoStart = true,
    LogLevel = "info"
});

AutoStart オプションは、最初のセッションの作成時に自動的に Copilot CLI サーバー プロセスを起動するように SDK に指示します。 LogLevel オプションは、SDK 診断出力の詳細度を制御します。

クライアントを作成したら、次の手順を実行します。

await client.StartAsync();

このコードは、CLI サーバーへの接続を確立し、セッション作成用にクライアントを準備します。

エージェント ツールを定義する

ツールを使用すると、エージェントはアプリケーションのバックエンド サービスと対話できます。 GitHub Copilot SDK for .NET では、AIFunctionFactory.Create パッケージのMicrosoft.Extensions.AIを使用してツールを定義します。

ツール サービスを作成する

一般的なパターンは、エージェントが呼び出すことができるすべてのツール メソッドを含む専用のサービス クラスを作成することです。 各メソッドは、エージェントが実行できる 1 つのアクションを表します。

public class SupportAgentTools
{
    public async Task<string> GetOrderDetailsAsync(int orderId)
    {
        // Query the database for order information
        var order = await _dbContext.Orders.FindAsync(orderId);
        return order != null
            ? $"Order {orderId}: {order.ProductName}, Status: {order.Status}"
            : "Order not found.";
    }

    public async Task<string> ProcessReturnAsync(int orderId, string reason)
    {
        // Business logic to process the return
        var order = await _dbContext.Orders.FindAsync(orderId);
        order.Status = "Return Initiated";
        await _dbContext.SaveChangesAsync();
        return $"Return initiated for order {orderId}.";
    }
}

SDK にツールを登録する

サービス メソッドを SDK で使用できるツール定義に変換します。 各ツールには、名前、説明、およびパラメーターの説明が必要です。AI モデルは、それをいつどのように使用するかを理解します。

var toolService = new SupportAgentTools(dbContext);

var tools = new List<AIFunction>
{
    AIFunctionFactory.Create(
        async ([Description("The order ID number")] int orderId) =>
            await toolService.GetOrderDetailsAsync(orderId),
        "get_order_details",
        "Look up the status and details of a specific order."),

    AIFunctionFactory.Create(
        async ([Description("The order ID")] int orderId,
               [Description("The reason for the return")] string reason) =>
            await toolService.ProcessReturnAsync(orderId, reason),
        "process_return",
        "Process a return request for an order.")
};

AIFunctionFactory.Create 呼び出しは、次の 3 つの引数を受け取ります。

  1. 各パラメーターに属性を持つサービス メソッドをラップする[Description]
  2. AI モデルがツールを参照するために使用するツール
  3. ツールを呼び出すタイミングをモデルが理解するのに役立つ説明

パラメーターの [Description] 属性は重要です。各パラメーターが何を表すのかを AI モデルに伝えるので、ツールを呼び出すときにモデルが正確な値を提供するのに役立ちます。

セッションを作成して構成する

セッションは、個々の会話またはタスク コンテキストを表します。 モデル、システム プロンプト、ツール、およびその他の設定とのセッションを構成します。

セッションを構成する

SessionConfigを使用して、セッションの動作を指定します。

var config = new SessionConfig
{
    Model = "gpt-4.1",
    SystemMessage = new SystemMessageConfig
    {
        Mode = SystemMessageMode.Replace,
        Content = @"You are a customer support agent for an e-commerce company.

CAPABILITIES:
- Look up order details
- Process returns

RULES:
- Only assist with order-related inquiries
- Always verify order details before taking action
- Be polite and professional"
    },
    Tools = tools,
    InfiniteSessions = new InfiniteSessionConfig
    {
        Enabled = false
    }
};

主要な構成オプション:

  • モデル: このセッションに使用する AI モデルを指定します。
  • SystemMessage: エージェントのロールと動作を定義します。 Modeは、プロンプトが既定のシステム メッセージ (Replace) を置き換えるか、追加するか (Append) を決定します。
  • ツール: エージェントが使用できるツール定義の一覧。
  • InfiniteSessions: 長い会話のコンテキストの自動圧縮を制御します。 有効にすると、 BackgroundCompactionThresholdBufferExhaustionThreshold を調整して、圧縮が行われるタイミングを制御できます。

セッションを作成する

構成を使用してクライアントからセッションを作成します。

var session = await client.CreateSessionAsync(config);

イベントを使用して応答を処理する

GitHub Copilot SDK は、通信にイベントドリブン モデルを使用します。 メッセージを送信した後、イベントをサブスクライブして応答を受信し、処理が完了したときに検出します。

セッション イベントに登録する

session.On メソッドをパターン マッチングと共に使用して、さまざまなイベントの種類を処理します。

var responseBuilder = new StringBuilder();
var tcs = new TaskCompletionSource<string>();

session.On(evt =>
{
    switch (evt)
    {
        case AssistantMessageEvent msg:
            responseBuilder.Append(msg.Data.Content);
            break;

        case SessionIdleEvent:
            tcs.SetResult(responseBuilder.ToString());
            break;

        case SessionErrorEvent err:
            tcs.SetException(
                new Exception($"Agent error: {err.Data.Message}"));
            break;
    }
});

各イベントの種類は、特定の目的を果たします。

  • AssistantMessageEvent: エージェントの応答テキストの一部が含まれます。 これらのメッセージ部分を蓄積して、完全な応答を構築します。
  • SessionIdleEvent: すべてのツール呼び出しを含め、エージェントが処理を完了したことを通知します。 このイベントは、応答が完了したことを示します。
  • SessionErrorEvent: 処理中にエラーが発生したことを示します。 Data.Message プロパティには、エラーの説明が含まれています。

メッセージを送信して応答を待機する

SendAsync オブジェクトと共に MessageOptions を使用して、ユーザーのプロンプトをエージェントに送信します。

await session.SendAsync(new MessageOptions
{
    Prompt = "What is the status of order 12345?"
});

// Wait for the response with a timeout
var response = await tcs.Task.WaitAsync(TimeSpan.FromSeconds(30));

ここで示す TaskCompletionSource パターンを使用すると、イベント ドリブン SDK モデルを async/await コードでブリッジできます。 SessionIdleEventが起動すると、累積された応答テキストを使用してタスクが完了します。

エラー処理のベスト プラクティス

堅牢なエラー処理は、運用エージェントにとって重要です。

ツール ハンドラーエラー

try-catch ブロックでツール ハンドラーをラップし、例外をスローするのではなく、意味のあるエラー メッセージを返すようにします。 ツールがエラー メッセージを返すと、AI モデルはそれを解釈し、ユーザーに役立つ応答を提供できます。

AIFunctionFactory.Create(
    async ([Description("The order ID")] int orderId) =>
    {
        try
        {
            return await toolService.GetOrderDetailsAsync(orderId);
        }
        catch (Exception ex)
        {
            return $"Error retrieving order: {ex.Message}";
        }
    },
    "get_order_details",
    "Look up the status and details of a specific order.")

セッション レベルのエラー処理

エージェントの処理中にエラーをキャッチするには、 SessionErrorEvent を使用します。 OnErrorOccurred セッション フックを構成することもできます。ErrorHandling値を返して、エージェントがエラーに応答する方法を制御します。

  • 再試行: 失敗した操作をもう一度試します。
  • スキップ: 失敗した結果なしで処理を続行します。
  • 中止: 処理を停止し、エラーを表示します。

Timeouts

応答を待機するときは、常にタイムアウトを設定します。 前の例では、 WaitAsync(TimeSpan.FromSeconds(30)) を使用して、エージェントで予期しない問題が発生した場合に無期限の待機を防ぎます。

システム プロンプトの設計

システム プロンプトは、最も重要な構成決定の 1 つです。 エージェントが誰であるか、何ができるか、およびエージェントの動作を定義します。 適切に構造化されたシステム プロンプトには、通常、次のものが含まれます。

  • ロールの定義: エージェントが表す内容 (たとえば、"You're a customer support agent for ContosoShop")。
  • 機能: 使用可能なツールと機能。
  • ワークフロー ガイダンス: エージェントがタスクにアプローチする方法 (たとえば、"返品を処理する前に常に注文の詳細を確認する" など)。
  • ルールと制約: エージェントが従う必要がある境界 (たとえば、"注文に関連するトピックについてのみ説明する" や "100 ドルを超える払い戻し要求をエスカレートする" など)。

システム プロンプトにフォーカスを合わせ、具体的な状態に保ちます。 あいまいな命令は予期しない動作につながりますが、過度に制限の厳しい規則によってエージェントが役に立たない可能性があります。

デルタ イベントを使用して応答をストリーム配信する

チャット UI などの対話型アプリケーションでは、完全なメッセージを待つ代わりに、トークンによってエージェントの応答トークンをストリーミングできます。 AssistantMessageDeltaEventを使用して、到着した各部分トークンをキャプチャします。

session.On(evt =>
{
    switch (evt)
    {
        case AssistantMessageDeltaEvent delta:
            // Render each token as it arrives
            Console.Write(delta.Data.DeltaContent);
            break;

        case SessionIdleEvent:
            Console.WriteLine();
            tcs.SetResult("Done");
            break;

        case SessionErrorEvent err:
            tcs.SetException(
                new Exception($"Agent error: {err.Data.Message}"));
            break;
    }
});

DeltaContent プロパティには、増分テキスト フラグメントが含まれています。 ストリーミングは、モデルがメッセージ全体を生成するのを待つのではなく、ユーザーが応答を形成する際に表示されるため、より応答性の高いエクスペリエンスを提供します。

概要

GitHub Copilot SDK は、推論、ツールの使用、コンテキストの維持を可能にする AI エージェントを実装するための強力なフレームワークを提供します。 ツールを使用してエージェントの機能を定義し、明確なシステム プロンプトでセッションを構成し、イベントで応答を処理することで、実際のビジネス価値を提供する高度なエージェントを構築できます。 堅牢なエラー処理と思慮深いプロンプト設計は、運用シナリオでエージェントが確実かつ効果的に動作することを保証するために不可欠です。 次のユニットでは、これらの実装パターンを適用して、GitHub Copilot SDK を使用してサンプルカスタマー サポート エージェントを構築する方法について説明します。