フュージョン開発アプローチによるボットの開発：スキルの使用

### はじめに

本記事は、ビジネス要件に詳しい市民開発者、高度なプログラミング技術を持つプロ開発者らが協業してソリューションを開発する、フュージョン開発アプローチに関する記事の一つです。

Microsoft は、「[The future of bot building](https://powervirtualagents.microsoft.com/ja-jp/blog/the-future-of-bot-building/)」という記事で、フュージョン開発アプローチをサポートするものとして、下記を紹介しています。

- Power Virtual Agents と Bot Framework Composer の統合
- Power Virtual Agents と Microsoft Azure Bot Service の両方を双方向のスキルとして使用する機能

[前回の記事](https://qiita.com/fsdg-honda/items/b2bdf947c253a621f334
)では、後者の最初のステップとして、Teams Toolkit を使って Microsoft Azure Bot Service に Microsoft Teams のボットをデプロイしました。  
今回は、前回デプロイしたボットをスキルとして利用できるように改修し、Power Virtual Agents から利用してみます。

### スキル

スキルは、ボットが何らかのタスクを実行する機能を、別のボットから利用できる形にしたものです。  
利用する側をスキルコンシューマー、利用される側をスキルまたはスキルボットと呼びます。  
スキルのインターフェイスはスキルマニフェストに定義します。このスキルマニフェストを使ってスキルコンシューマーにスキルを追加すると、スキルコンシューマーのフローの中でスキルを呼び出せるようになります。  
スキルボット側ではどのスキルコンシューマーからのリクエストを受け付けるかを選択することができます。

### エコーボットのスキル実装

前回デプロイしたエコーボットは、受信したメッセージに「Echo: 」を付与して送信する機能がありました。  
この機能を他のボットからも利用できるようにします。下記のような流れでエコーボットを改修します。

- ソースコードの修正（アクティビティハンドラー、サービス登録処理の修正）
- スキルマニフェストの作成
- スキルマニフェストのデプロイ

詳細な説明は下記を参照ください。

https://learn.microsoft.com/ja-jp/azure/bot-service/skill-implement-skill

#### アクティビティハンドラーの修正

スキルコンシューマーとスキルボットのやりとりは、アクティビティと呼ばれるオブジェクト単位で行います。  
ユーザーはスキルコンシューマーを経由してスキルボットの機能を利用することができます。ユーザが入力したメッセージを含むアクティビティをメッセージアクティビティ、エコーボットが返すメッセージをエコーメッセージアクティビティとすると、下記のような流れとなります。

```mermaid
sequenceDiagram
    participant U as ユーザー
    participant C as スキルコンシューマー
    participant S as スキルボット

    U ->> +C: メッセージアクティビティ
    C ->> +S: メッセージアクティビティ
    Note right of S: タスクの実行
    S ->> -C: エコーメッセージアクティビティ
    C ->> -U: エコーメッセージアクティビティ
```

前回デプロイしたエコーボットでは、メッセージアクティビティの処理は`bot/teamsBot.ts`の onMessage()に実装されています。このメソッドを修正します。  
スキル終了時には EndOfConversation アクティビティをスキルコンシューマーに送信する必要があります。  
受信したメッセージの内容によって処理を変えている switch 文に、下記を追加します。

```
        case "end":
        case "stop": {
          await context.sendActivity({
            type: ActivityTypes.EndOfConversation,
            code: EndOfConversationCodes.CompletedSuccessfully,
          });
          break;
        }
```

#### サービス登録処理の修正

Bot Framework へのサービス登録は`bot/index.ts`で行われていますが、ここにスキルコンシューマーの要求を検証するための認証構成を組み込みます。認証構成のために botframework-connector を利用します。

ターミナルから botframework-connector をインストールします。

```

npm install botframework-connector

```

`bot/index.ts`を開き、下記 import を追加します。

```
import {
  allowedCallersClaimsValidator,
  AuthenticationConfiguration,
} from "botframework-connector";
```

ConfigurationBotFrameworkAuthentication を生成している箇所を下記のように変更します。

```
const claimsValidators = allowedCallersClaimsValidator(["*"]);
const authConfig = new AuthenticationConfiguration([], claimsValidators);

const botFrameworkAuthentication = new ConfigurationBotFrameworkAuthentication(
  {},
  credentialsFactory,
  authConfig
);
```

allowedCallersClaimsValidator には、リクエストを受け付けるスキルコンシューマーのボット ID の配列を設定します。  
ここでは、全てのリクエストを受け付けるように"\*"を設定しています。

#### スキルマニフェストの作成

通常のボットのマニフェストとは別にスキルマニフェストを作成します。
スキルマニフェストを定義するスキーマの詳細は、下記を参照ください。

https://learn.microsoft.com/ja-jp/azure/bot-service/skills-write-manifest

ここでは下記のようなマニフェストを作成します。
{ }内は説明を記載するのみで値を伏せていますが、適切な値を設定する必要があります。

```
{
  "$schema": "https://schemas.botframework.com/schemas/skills/v2.2/skill-manifest.json",
  "$id": "{任意のボット ID}",
  "name": "Echo Skill bot",
  "version": "1.0",
  "description": "This is a sample of the echo skill.",
  "publisherName": "{発行者名}",
  "endpoints": [
    {
      "name": "default",
      "protocol": "BotFrameworkV3",
      "description": "Default endpoint for the echo skill",
      "endpointUrl": "https://{ボットのFQDN = state.dev.json の domain}/api/messages",
      "msAppId": "{デプロイしているボットアプリのクライアント ID = state.dev.json の botId }"
    }
  ],
  "activities": {
    "message": {
      "type": "message",
      "description": "Receives user's message"
    }
  }
}
```

#### スキルマニフェストのデプロイ

スキルマニフェストはオンラインで参照できる必要があります。  
ここでは、エコーボットをホストしている App Service からダウンロードできるようにボットの実装を変更します。

##### 静的ファイルの配置

`bot/public/`フォルダ下に前述のスキルマニフェストを記載した下記ファイルを作成します。

```
bot/public/echo-bot-skill-manifest-1.0.json
```

##### ルーティングの追加

`bot/index.ts`の末尾に下記を追加し、`/public/`へのアクセスでは、`public`フォルダのファイルを返すようにします。

```
server.get(
  "/public/*",
  restify.plugins.serveStatic({
    directory: __dirname,
  })
);
```

##### ビルドコマンドの修正

`bot/package.json`の"scripts"に定義されているビルドコマンドに、`./public`から`./lib/`にコピーするコマンドを追加します。

```
    "build": "tsc --build && shx cp -r ./public ./lib/ && shx cp -r ./adaptiveCards ./lib/",
```

##### ローカル環境でのビルド、実行

F5 押下でアプリをデバッグモードで実行します。  
ボットのインストール画面が表示された後、ブラウザで下記 URL にアクセスし、スキルマニフェストの内容が表示されることを確認します。

```
http://localhost:3978/public/echo-bot-skill-manifest-1.0.json
```

##### Azure へのデプロイ

Teams Toolkit の「クラウドへのデプロイ」メニューを実行し、改修したスキルボットをデプロイします。  
 デプロイ完了後、ローカル環境と同様にスキルマニフェストの内容が表示されることを確認します。

```
https://{ボットのFQDN = state.dev.json の domain}/public/echo-bot-skill-manifest-1.0.json
```

##### Azure AD アプリケーション登録のホーム ページ URL を修正

スキルコンシューマーにスキルを追加する際、スキルマニフェストの endpointUrl が Azure AD アプリケーション登録のホーム ページ URL と一致しているかが検証されます。  
Azure ポータルでスキルマニフェストの msAppId に対応するアプリケーションが登録された Azure AD のアカウントにサインインし、「Azure Active Directory」メニューを開きます。  
検索ボックスに msAppId の値を入力すると、該当するアプリケーションが表示されるので、このアプリケーションを選択します。  
「ブランド化とプロパティ」メニューを開き、「ホーム ページ URL」にスキルマニフェストの endpointUrl の値を入力して「保存」を実行します。

### Power Virtual Agents で使用するスキルの追加

Power Virtual Agents でスキルコンシューマーとなる任意のチャットボットを選択し、エコーボットが実装したスキルを追加します。  
チャットボットのメニューから「設定」->「スキル」を開き、「スキルの追加」を選択します。

![スクリーンショット 2023-03-22 213101.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3104149/5aba108b-af63-91c6-e19a-ad9091daa762.png)

「自分のボット ID」が表示されていることを確認します。表示されていない場合は、「Chatbots」からスキルコンシューマーとなるチャットボットを再度選択してみてください。スキルボット側でスキルコンシューマーを制限する場合は、このボット ID をスキルボット側に連携し、スキルボットの実装を、allowedCallersClaimsValidator に渡す配列の要素が許可するボット ID のみとなるように修正します。今回は"

「スキル マニフェストの URL」にスキルマニフェストの endpointUrl の値を入力し、「次へ」ボタンを押すと、スキルマニフェストの検証が行われます。
ここでスキルマニフェストの内容に問題がある場合、エラーメッセージが表示されます。[MS Learn のトラブルシューティング](https://learn.microsoft.com/ja-jp/power-virtual-agents/configuration-add-skills#troubleshooting-errors-during-skill-registration)を参考にエラーを修正してください。

![スクリーンショット 2023-03-22 103619.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3104149/c9c031fa-de1b-a281-0505-550e92174a03.png)

エラーがなければ、スキル名、説明が表示されますので、「保存」ボタンを押すと、インポートが開始されます。

![スクリーンショット 2023-03-22 121129.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3104149/c9d0f499-cd8e-498f-6e32-3d6e9d8a8671.png)

インポートが完了すると下記画面が表示され、スキルが利用可能となります。

![スクリーンショット 2023-03-22 121217.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3104149/d7c81c37-dca5-fd87-964b-2be35221791a.png)

### スキルの要求

スキルを追加すると、任意のトピックからスキルを呼び出せるようになります。  
ここではフォールバックトピックからスキルを呼び出してみます。トピックにノードを追加すると表示されるメニューから、「アクションを呼び出す」を選択し、「Echo Skill bot v1.0」のスキルを選択します。 

![スクリーンショット 2023-03-22 121354.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3104149/3b2b7757-41ae-870a-11c2-e02bd72e9a48.png)

 
編集したトピックを保存した後、「ボットのテスト」画面から任意のメッセージを送ると、エコーボットから「Echo: 」が付与されたメッセージが返ることが確認できます。

![スクリーンショット 2023-03-22 121716.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3104149/2c789ebe-0b87-280b-5ec4-df43d09e2ab1.png)

### まとめ

今回の記事では、前回の記事で作成した、Bot Framework SDK を使ったボットの機能を Power Virtual Agents のボットから呼び出せることを確認しました。
Bot Framework SDK を使ったボットの修正にはプログラミングに関する知識が必要となり、市民開発者には容易でありませんが、プロ開発者がスキルの形式にして提供した場合、簡単に利用できることが確認できたと思います。