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 に関連するコンテキストを動的に提供します。
  • VS Code と深く統合: 広範な拡張機能 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 拡張機能の実装コードでツールを参照するために使用される、ツールの一意の名前。名前は {verb}_{noun} の形式で指定します。命名ガイドラインを参照してください。
    displayName UI に表示される、ツールのユーザーフレンドリーな名前。
  3. ツールがエージェントモードで使用できる場合、またはチャットプロンプトで # を使用して参照できる場合は、次のプロパティを追加します。

    ユーザーはチャットビューでツールの有効化または無効化を行うことができます。これは、モデルコンテキストプロトコル (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 はユーザーに最終的な応答を返します。これには、複数のツールからの応答が含まれる場合があります。

ガイドラインと規則

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

    • ツール名: 一意であり、意図を明確に記述する必要があります。ツール名は {verb}_{noun} の形式で構造化します。たとえば、get_weatherget_azure_deployment、または get_terminal_output などです。

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

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

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

  • エラー処理: エラーが発生した場合は、LLM にとって意味のあるメッセージでエラーをスローします。オプションで、異なるパラメーターでの再試行や、別の操作の実行など、LLM が次に何をすべきかに関する指示を提供します。

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