VS Codeのエージェントモードを拡張するには、を試してください!

言語モデルツール API

言語モデルツールを使用すると、チャットで大規模言語モデル (LLM) の機能をドメイン固有の機能で拡張できます。ユーザーのチャットプロンプトを処理するために、VS Code のエージェントモードは、会話の一部として専門的なタスクを実行するためにこれらのツールを自動的に呼び出すことができます。VS Code 拡張機能で言語モデルツールを提供することで、エージェントコーディングワークフローを拡張し、エディタとの深い統合を提供できます。

この拡張機能ガイドでは、言語モデルツール API を使用して言語モデルツールを作成する方法と、チャット拡張機能でツール呼び出しを実装する方法を学習します。

MCP サーバーを提供することで、特殊なツールでチャットエクスペリエンスを拡張することもできます。AI 拡張機能の概要で、さまざまなオプションと、どちらのアプローチを使用するかを決定する方法の詳細を参照してください。

LLM におけるツール呼び出しとは何ですか?

言語モデルツールは、言語モデルリクエストの一部として呼び出すことができる関数です。たとえば、データベースから情報を取得したり、計算を実行したり、オンライン API を呼び出したりする関数があるかもしれません。VS Code 拡張機能でツールを提供すると、エージェントモードは会話のコンテキストに基づいてツールを呼び出すことができます。

LLM は実際にツール自体を実行するのではなく、ツールを呼び出すために使用されるパラメータを生成します。ツールが適切なコンテキストで呼び出されるように、ツールの目的、機能、および入力パラメータを明確に記述することが重要です。

次の図は、VS Code のエージェントモードにおけるツール呼び出しフローを示しています。具体的な手順の詳細については、ツール呼び出しフローを参照してください。

Diagram that shows the Copilot tool-calling flow

OpenAI ドキュメントの関数呼び出しの詳細を参照してください。

拡張機能で言語モデルツールを実装する理由は何ですか?

拡張機能で言語モデルツールを実装することには、いくつかの利点があります。

  • ユーザープロンプトへの応答の一部として自動的に呼び出される、専門的でドメイン固有のツールでエージェントモードを拡張します。たとえば、データベースのスキャフォールディングとクエリを有効にして、LLM に関連するコンテキストを動的に提供します。
  • 幅広い拡張機能 API セットを使用することでVS Code と深く統合します。たとえば、デバッグ API を使用して、現在のデバッグコンテキストを取得し、それをツールの機能の一部として使用します。
  • Visual Studio Marketplace を介してツールを配布および展開し、ユーザーに信頼性の高いシームレスなエクスペリエンスを提供します。ユーザーはツールに別のインストールおよび更新プロセスを必要としません。

次のシナリオで、MCP サーバーを使用して言語モデルツールを実装することを検討する場合があります。

  • すでに MCP サーバーの実装があり、VS Code でも使用したい場合。
  • 異なる開発環境やプラットフォームで同じツールを再利用したい場合。
  • ツールがサービスとしてリモートでホストされている場合。
  • VS Code API へのアクセスを必要としない場合。

言語モデルツールを作成する

言語モデルツールの実装は、主に次の2つの部分で構成されます。

  1. 拡張機能のpackage.jsonファイルでツールの構成を定義します。
  2. 言語モデル API リファレンスを使用して、拡張機能コードでツールを実装します。

基本的なサンプルプロジェクトから始めることができます。

1. package.jsonにおける静的構成

拡張機能で言語モデルツールを定義する最初のステップは、拡張機能のpackage.jsonファイルで定義することです。この構成には、ツール名、説明、入力スキーマ、およびその他のメタデータが含まれます。

  1. 拡張機能のpackage.jsonファイルのcontributes.languageModelToolsセクションにツールのエントリを追加します。

  2. ツールに一意の名前を付けます。

    プロパティ 説明
    name ツールのユニークな名前で、拡張機能の実装コードでツールを参照するために使用されます。名前は{動詞}_{名詞}の形式で指定します。命名ガイドラインを参照してください。
    displayName UI に表示される、ツールにわかりやすい名前です。
  3. ツールがエージェントモードで使用できる場合、またはチャットプロンプトで#で参照できる場合は、次のプロパティを追加します。

    ユーザーは、Model Context Protocol (MCP) ツールの場合と同様に、チャットビューでツールを有効または無効にできます。

    プロパティ 説明
    canBeReferencedInPrompt ツールがエージェントモードで使用できる場合、またはチャットで参照できる場合はtrueに設定します。
    toolReferenceName ユーザーがチャットプロンプトで#を介してツールを参照するための名前です。
    icon UI に表示するツールのアイコンです。
    userDescription UI に表示される、ツールのユーザーフレンドリーな説明です。
  4. modelDescriptionに詳細な説明を追加します。この情報は、LLM がツールをどのコンテキストで使用すべきかを判断するために使用されます。

    • ツールは正確に何をしますか?
    • どのような情報を返しますか?
    • いつ使用すべきで、いつ使用すべきではありませんか?
    • ツールの重要な制限または制約を記述します。
  5. ツールが入力パラメータを取る場合は、ツールの入力パラメータを記述するinputSchemaプロパティを追加します。

    この JSON スキーマは、ツールが入力として受け取るプロパティと、それらが必要かどうかを記述するオブジェクトです。ファイルパスは絶対パスである必要があります。

    各パラメータが何をするか、そしてそれがツールの機能とどのように関連するかを記述します。

  6. ツールが利用可能になるタイミングを制御するwhen句を追加します。

    languageModelToolsコントリビューションポイントでは、when 句を使用して、エージェントモードでツールが利用可能になるタイミング、またはプロンプトで参照できるタイミングを制限できます。たとえば、デバッグコールスタック情報を取得するツールは、ユーザーがデバッグしている場合にのみ利用可能にする必要があります。

    "contributes": {
        "languageModelTools": [
            {
                "name": "chat-tools-sample_tabCount",
                ...
                "when": "debugState == 'running'"
            }
        ]
    }
    
ツール定義の例

次の例は、タブグループ内のアクティブなタブの数をカウントするツールを定義する方法を示しています。

"contributes": {
    "languageModelTools": [
        {
            "name": "chat-tools-sample_tabCount",
            "tags": [
                "editors",
                "chat-tools-sample"
            ],
            "toolReferenceName": "tabCount",
            "displayName": "Tab Count",
            "modelDescription": "The number of active tabs in a tab group in VS Code.",
            "userDescription": "Count the number of active tabs in a tab group.",
            "canBeReferencedInPrompt": true,
            "icon": "$(files)",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "tabGroup": {
                        "type": "number",
                        "description": "The index of the tab group to check. This is optional- if not specified, the active tab group will be checked.",
                        "default": 0
                    }
                }
            }
        }
    ]
}

2. ツール実装

言語モデル API を使用して言語モデルツールを実装します。これは次の手順で構成されます。

  1. 拡張機能のアクティベーション時に、vscode.lm.registerToolでツールを登録します。

    package.jsonnameプロパティで指定したツールの名前を指定します。

    ツールを拡張機能にプライベートにしたい場合は、ツールの登録手順をスキップします。

    export function registerChatTools(context: vscode.ExtensionContext) {
      context.subscriptions.push(
        vscode.lm.registerTool('chat-tools-sample_tabCount', new TabCountTool())
      );
    }
    
  2. vscode.LanguageModelTool<>インターフェースを実装するクラスを作成します。

  3. prepareInvocationメソッドでツール確認メッセージを追加します。

    拡張機能からのツールには常に一般的な確認ダイアログが表示されますが、ツールは確認メッセージをカスタマイズできます。ツールが何をしているのかをユーザーが理解できるように、十分なコンテキストを提供します。メッセージはコードブロックを含むMarkdownStringにすることができます。

    次の例は、タブカウントツールに確認メッセージを提供する方法を示しています。

    async prepareInvocation(
        options: vscode.LanguageModelToolInvocationPrepareOptions<ITabCountParameters>,
        _token: vscode.CancellationToken
    ) {
        const confirmationMessages = {
            title: 'Count the number of open tabs',
            message: new vscode.MarkdownString(
                `Count the number of open tabs?` +
                (options.input.tabGroup !== undefined
                    ? ` in tab group ${options.input.tabGroup}`
                    : '')
            ),
        };
    
        return {
            invocationMessage: 'Counting the number of tabs',
            confirmationMessages,
        };
    }
    

    prepareInvocationundefinedを返した場合、一般的な確認メッセージが表示されます。ユーザーは特定のツールに対して「常に許可」を選択することもできます。

  4. ツール入力パラメータを記述するインターフェースを定義します。

    このインターフェースは、vscode.LanguageModelToolクラスのinvokeメソッドで使用されます。入力パラメータは、package.jsoninputSchemaで定義した JSON スキーマに対して検証されます。

    次の例は、タブカウントツールのインターフェースを示しています。

    export interface ITabCountParameters {
      tabGroup?: number;
    }
    
  5. invokeメソッドを実装します。このメソッドは、チャットプロンプトの処理中に言語モデルツールが呼び出されたときに呼び出されます。

    invokeメソッドは、optionsパラメータでツール入力パラメータを受け取ります。パラメータは、package.jsoninputSchemaで定義された JSON スキーマに対して検証されます。

    エラーが発生した場合、LLM に意味のあるメッセージを伴うエラーをスローします。オプションで、異なるパラメータで再試行したり、異なるアクションを実行したりするなど、LLM が次に何をするべきかについての指示を提供します。

    次の例は、タブカウントツールの実装を示しています。ツールの結果はvscode.LanguageModelToolResult型のインスタンスです。

    async invoke(
        options: vscode.LanguageModelToolInvocationOptions<ITabCountParameters>,
        _token: vscode.CancellationToken
    ) {
        const params = options.input;
        if (typeof params.tabGroup === 'number') {
            const group = vscode.window.tabGroups.all[Math.max(params.tabGroup - 1, 0)];
            const nth =
                params.tabGroup === 1
                    ? '1st'
                    : params.tabGroup === 2
                        ? '2nd'
                        : params.tabGroup === 3
                            ? '3rd'
                            : `${params.tabGroup}th`;
            return new vscode.LanguageModelToolResult([new vscode.LanguageModelTextPart(`There are ${group.tabs.length} tabs open in the ${nth} tab group.`)]);
        } else {
            const group = vscode.window.tabGroups.activeTabGroup;
            return new vscode.LanguageModelToolResult([new vscode.LanguageModelTextPart(`There are ${group.tabs.length} tabs open.`)]);
        }
    }
    

VS Code 拡張機能サンプルリポジトリで言語モデルツールを実装するための完全なソースコードを表示します。

ツール呼び出しフロー

ユーザーがチャットプロンプトを送信すると、次の手順が発生します。

  1. Copilot は、ユーザーの構成に基づいて利用可能なツールのリストを決定します。

    ツールのリストは、組み込みツール、拡張機能によって登録されたツール、およびMCP サーバーからのツールで構成されます。拡張機能または MCP サーバー(図では緑色で示されています)を介してエージェントモードに貢献できます。

  2. Copilot は、プロンプト、チャットコンテキスト、および考慮すべきツール定義のリストを LLM に提供してリクエストを送信します。

    LLM は応答を生成します。これには、1 つ以上のツール呼び出しリクエストが含まれる場合があります。

  3. 必要に応じて、Copilot は LLM によって提供されたパラメータ値で提案されたツールを呼び出します。

    ツールの応答により、さらに多くのツール呼び出しリクエストが発生する場合があります。

  4. エラーまたはフォローアップツールリクエストがある場合、Copilot はすべてのツールリクエストが解決されるまでツール呼び出しフローを繰り返します。

  5. Copilot は、複数のツールからの応答を含む可能性のある最終応答をユーザーに返します。

ガイドラインと規則

  • 命名: ツールとパラメータに明確でわかりやすい名前を付けます。

    • ツール名: ユニークで、その目的を明確に記述する必要があります。ツール名は{動詞}_{名詞}の形式で構造化します。たとえば、get_weatherget_azure_deployment、またはget_terminal_output

    • パラメータ名: パラメータの目的を記述する必要があります。パラメータ名は{名詞}の形式で構造化します。たとえば、destination_locationticker、またはfile_name

  • 説明: ツールとパラメータに詳細な説明を記述します。

    • ツールが何をするか、いつ使用すべきで、いつ使用すべきではないかを記述します。たとえば、「このツールは、指定された場所の天気を取得します。」
    • 各パラメータが何をするか、そしてそれがツールの機能とどのように関連するかを記述します。たとえば、「destination_locationパラメータは、天気を取得する場所を指定します。有効な場所の名前または座標である必要があります。」
    • ツールの重要な制限または制約を記述します。たとえば、「このツールは、米国内の場所の天気データのみを取得します。他の地域では動作しない場合があります。」
  • ユーザー確認: ツール呼び出しの確認メッセージを提供します。拡張機能からのツールには常に一般的な確認ダイアログが表示されますが、ツールは確認メッセージをカスタマイズできます。ツールが何をしているのかをユーザーが理解できるように、十分なコンテキストを提供します。

  • エラー処理: エラーが発生した場合、LLM に意味のあるメッセージを伴うエラーをスローします。オプションで、異なるパラメータで再試行したり、異なるアクションを実行したりするなど、LLM が次に何をするべきかについての指示を提供します。

ツールを作成するためのその他のベストプラクティスは、OpenAI ドキュメントAnthropic ドキュメントを参照してください。