💻

既存の API を Copilot for Microsoft 365 プラグインにする

2024/06/02に公開

はじめに

2024/04/15 に API ベースの Teams メッセージ拡張機能を作成することができるようになりました。

https://devblogs.microsoft.com/microsoft365dev/expand-your-apps-capabilities-and-reach-on-microsoft-teams-using-api-based-message-extensions?WT.mc_id=M365-MVP-5002941

これまでは Teams メッセージ拡張機能は Microsoft Bot Framework でしか作ることができませんでした。この機能により既存の API を追加の開発なしで Teams アプリにすることができます。また Teams メッセージ拡張機能は Copilot for Microsoft 365 プラグインになりますので、既存の API を Copilot for Microsoft 365 から利用できることになるということです。これは非常に強力なアップデートだと思います。

実際に既存の API を使って Copilot for Microsoft 365 から呼び出せるようになるところを見てみたいと思います。

https://learn.microsoft.com/ja-jp/microsoftteams/platform/messaging-extensions/build-api-based-message-extension?WT.mc_id=M365-MVP-5002941

実装方法

サンプルとしてこちらの API を使用することにします。

https://github.com/karamem0/zenn-search

Teams アプリを作成するためには以下の 3 つのファイルが必要です。これらは開発者ポータルで作成することができます。

  • アプリ マニフェスト ファイル
  • 透明なアイコン ファイル (PNG 形式)
  • フル カラーのアイコン ファイル (PNG 形式)

API ベースの Teams メッセージ拡張機能の場合は追加で以下のファイルが必要です。

  • API の OpenAPI 仕様 (JSON 形式または YAML 形式)
  • 応答レンダリング テンプレート

追加ファイルの準備

OpenAPI 仕様は ASP.NET Core Web API であれば Swashbuckle.AspNetCore を、Azure Functions であれば Microsoft.Azure.WebJobs.Extensions.OpenApi を利用できます。Microsoft Docs では 2.0 および 3.0.x がサポートされているとありますが、2.0 ではうまく読めなかったので、3.0.x になるようにします。

public static IServiceCollection AddOpenAPI(this IServiceCollection services)
{
    _ = services.AddSingleton<IOpenApiConfigurationOptions>(provider => new OpenApiConfigurationOptions()
    {
        Info = new OpenApiInfo()
        {
            Version = "1.0.0",
            Title = "Zenn Search API"
        },
        Servers = DefaultOpenApiConfigurationOptions.GetHostNames(),
        OpenApiVersion = OpenApiVersionType.V3,
        IncludeRequestingHostName = true,
        ForceHttps = false,
        ForceHttp = false,
    });
    return services;
}

コードが修正できない場合は頑張って OpenAPI 仕様を作ることになります。

応答レンダリング テンプレートは 2 種類のアダプティブ カードを含む JSON 形式ファイルです。アダプティブ カードはデザイナーで作成したものを貼り付けます。

開発者ポータルでの設定

Microsoft Teams の 開発者ポータル にログインします。

Apps - New app をクリックしします。アプリ名を入力して Add をクリックします。

Basic information でアプリの情報を入力します。これは Copiot for Microsoft 365 からの呼び出しに使用されますので説明は詳細に記述してください。入力したら Save をクリックします。

App FeatureMessage extensions をクリックします。Message extension typeAPI を選択します。OpenAPI 仕様をアップロードします。Save クリックします。

成功したことを示すダイアログが表示されるので Got it をクリックします。

Add をクリックします。API を選択して Next をクリックします。

応答レンダリング テンプレートをアップロードします、なのですが、現時点ではエラーが発生してします。

いったん応答レンダリング テンプレートのバージョンを devPreview にするとアップロードできるようになります。

  {
-   "version": "1.0",
+   "version": "devPreview",

コマンドの情報を入力します。ここも詳細に記述してください。Add をクリックします。

Save をクリックします。

これでアプリの設定は完了なのですが、プレビューをしてみるとエラーが発生します。

エラーの詳細を見るとバージョンが正しくないと言われています。先ほど書き換えたからですね。

version | Value "devPreview" does not match constant "1.0".

開発者ポータルでは直接ファイルを変更することができません。仕方がないのでアプリ パッケージをダウンロードし、再び 1.0 に修正した上で、アップロードしなおします。

  {
-   "version": "devPreview",
+   "version": "1.0",
    ...

改めてプレビューをするとアプリが追加できるようになります。

認証の設定

API が匿名アクセス可能な場合はこれで設定完了です。API が認証を要求する場合は追加の設定が必要となります。API ベースの Teams メッセージ拡張機能は シークレット および Microsoft Entra ID による認証に対応しています。なお シークレット は Bearer トークンのみをサポートしています。今回は Azure Functions の API キーでのアクセスをさせる想定なのですが、このままではできないということになります。これに対応するために、Azure API Management を作成し、ポリシーで Bearer トークンを X-Functions-Key ヘッダーに変換します。

<policies>
    <inbound>
        <base />
        <set-backend-service id="apim-generated-policy" backend-id="{{backend-id}}" />
        <set-header name="X-Functions-Key" exists-action="override">
            <value>@(Regex.Match(context.Request.Headers.GetValueOrDefault("Authorization",""), "^Bearer (?<key>.+)$").Groups["key"]?.Value)</value>
        </set-header>
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

シークレットはアプリ マニフェスト ファイルに記述するのではなく、開発者ポータルに設定しアプリ マニフェスト ファイルから参照する形になります。開発者ポータルで Tools - API key registration - Create an API Key をクリックします。

Add secret をクリックします。シークレット (今回は Azure Functions の関数キー) を入力して Save をクリックします。

API の情報を入力して Save をクリックします。Target Teams app については開発中は Any Teams app で構いませんが、通常は Exsiting Teams app に設定することをおすすめします。

作成された API キーの Registration ID をコピーします。

Registration ID をアプリ マニフェスト ファイルに設定します。これも開発者ポータルから設定できないので、アプリ パッケージをダウンロードして修正し、アップロードします。

{
  ...
  "composeExtensions": [
    {
      "composeExtensionType": "apiBased",
      "authorization": {
        "authType": "apiSecretServiceAuth",
        "apiSecretServiceAuthConfiguration": {
          "apiSecretRegistrationId": "{{registration-id}}"
        }
      },
      ...
    }
  ]
  ...
}

実行結果

まずはメッセージ拡張機能単体で動作することを確認します。チャットで拡張機能を表示して検索すると検索結果が表示されることを確認できます。

次に Copilot での動作を確認します。Copilot チャットで拡張機能をオンにします。

Copilot に聞いてみます。ちゃんと検索結果をもとに回答できることが確認できます。

おわりに

追加のプログラミングなしで既存の API を Copilot for Microsoft 365 に統合できることがわかりました。いくつか難しい設定があるのと、開発者ポータルの不具合もあるようなので、まだまだこれからといったところですが、ぜひ試していただければと思います。

Discussion