Atsushi Kato

Atsushi Kato

Software Engineer

Teams Toolkitを用いたTeams通知Botの開発手順

Teams Toolkitを用いたTeams通知Botの開発手順

自己紹介

23卒の新卒で入社した加藤です。ソフトウェアエンジニアとしてWebアプリやTeamsアプリの開発をしています。

本記事のゴール

Microsoft Team上で動く対話型のアプリであるTeams Botアプリの開発経験がない人でも、Botが動く仕組みを理解し、Teams Toolkitを使ったBotの開発・デプロイを実施できるようになることを目指しています。

想定開発環境

本記事では、MacBook環境においてVSCodeを使用したデモアプリの開発、ローカル環境でのエミュレーターを使用したアプリの起動方法、およびアプリのデプロイ方法を紹介します。開発言語はNode.jsとTypeScriptです。

Teams Toolkitとは

Microsoft Teams ToolkitはMicrosoftが提供しているMicrosoft Teamsアプリ開発用SDKです。Visual Studio Code(以下、VSCode)から使えるものとCLIで使えるものの2種類があり、あらかじめ用意されたシナリオのテンプレートから、アプリの開発・デプロイを簡単に行うことができます。また、ローカル環境でのエミュレーターも用意されており、デバッグも容易に実施できます。 2024年3月現在、VSCodeから使えるTeams Toolkitのテンプレートには以下のものが用意されています。

  • Bot: 基本ボット
  • Bot: AIチャットボット
  • Bot: AIアシスタントボット
  • Bot: チャット通知メッセージ (本記事で使用したテンプレートです)
  • Bot: チャットコマンド
  • Bot: チャットのシーケンシャルワーカー
  • タブ: 基本タブ
  • タブ: FluentUIを使ってリアクションする
  • タブ: ダッシュボード
  • タブ: SPFx(SharePoint Framework)
  • メッセージ拡張機能: カスタム検索結果
  • メッセージ拡張機能: フォームデータと処理データの収集
  • メッセージ拡張機能: リンク未展開
  • Outlookアドイン: タスクウィンドウ
  • Outlookアドイン: 既存のOutlookアドインのインポート

Teams Botアプリの開発に至った背景

Teamsアプリを社内のコミュニケーションツールとして利用しているユーザから、使い慣れているTeams上で使えるアプリが欲しいという要望があり、Teamsアプリの開発を実施することになりました。 アプリの要件としては、ユーザーへの通知やユーザーとのインタラクティブなやり取りができることが挙げられており、後ほど紹介するPower Virtual Agentsではなく、 Bot Framework SDKを使用したTeams Botアプリの開発を行うことになりました。

Teamsアプリの種類について

次に、Teamsのアプリの種類について紹介します。 Teamsには全部で4つのアプリの種類があります。

1. コア アプリ

  • チャット
  • 予定調
  • 通話

などのデフォルトでインストールされているアプリです。

2. Microsoft によって作成されたアプリ

Teamsアプリの発行元がMicrosoftとなっているアプリで、以下の3つです。

  • Admin - Microsoft 365
  • Lists
  • Live Components

3. 独立したアプリ開発者によって作成されたサード パーティ製アプリ

https://www.microsoft.com/ja-jp/store/top-free/apps/mobile
にあるような、公開されているアプリです。

4. 内部使用のためにorganization内に作成されたカスタム アプリ

特定の組織内部でのみ使用可能なアプリで、組織外のユーザーはアプリを見ることもダウンロードすることもできないものになります。

Teams通知Botでできること

  1. Teams通知Botでは、主に2つの機能を実現することができます。
    • ユーザーのアクションに対するリアクション
    • ユーザーがBotアプリをインストールした際に、 Botからユーザーに対し何かしらのメッセージを送る
    • ユーザーがBotアプリをアンインストールした際に、ユーザーのTeamsアカウントに紐づいたメールアドレスにメールを送る
  2. ユーザーがBotに対し個別チャットでメッセージを送った際に、 Botはメッセージを受け取り、任意のメッセージをユーザーに返す
    • ユーザーに対してアクションを行う
    • 任意の条件で特定のユーザーまたはユーザーらに対し個別チャットにてメッセージを送る

Teams Botの開発方法

チャットにてユーザーとのメッセージのやり取りを行うBotの開発方法は様々ありますが、本記事では定型文でメッセージをやり取りするか、任意のメッセージでやり取りをするかに分けて以下の2種類の開発方法をご紹介します。また、次の章からは任意のメッセージを送信するBotを実際に開発することでBotの仕組みをより深く理解していただけるかと思います。

Power Virtual Agentsを使う方法

Power Virtual Agents は Microsoft Power Platform に含まれるチャットボット開発用のツールで、プログラミングコードを書くことなくBotを構築することができます。

開発コストをかけずに定型文でメッセージを行うBotを作りたい場合は、Power Virtual Agentsを使うと良いでしょう。

Power Virtual Agentsでは、「ユーザーからAというメッセージが来たら、BotはBというメッセージをユーザーに返す」をあらかじめ定めることでユーザー・Bot間でチャットを行うタイプのTeamsBotを開発できます。

Bot Framework SDKを使う方法

ユーザーとBotとの間でインタラクティブなチャットを行えるBotを開発できます。

ユーザーからメッセージを送られる・Botアプリをインストールするなどのアクションにトリガーされてユーザーに対して任意のメッセージを送信したり、フォーム、テキスト、画像、動画、アクションボタン付きのリッチなメッセージの作成と送信を簡単に実装することができます。

Bot Framework

実際にTeams 通知Botを開発してみる

JavaScript を使用した通知ボットのビルド を進めていきます。 この章では、VSCodeのExtension(拡張機能)であるTeams Toolkit を使ってテンプレートからTeams通知アプリの作成を行います。

VSCodeをダウンロードしていない方は、こちらからダウンロードしてください。

  1. VSCodeのExtension(拡張機能)でteamsと打つと、「Teams Toolkit」というアプリが出てくると思うので、ダウンロードしてください。

Teams Toolkit

  1. ダウンロードしたTeams Toolkitをクリックし(①)、 新しいアプリの作成 (② ) をクリックするとテンプレートが選べるので 通知 (③) > チャット通知メッセージ > HTTPトリガー Azure Functions > Javascript/Typescript > プロジェクトを作成するPATH を選択していきます。

プロジェクトを作成する

  1. 前の手順2でテンプレートから通知Botアプリを無事作成できると、新しくプロジェクトが作成されVSCodeが再度開きます。新たに開かれたVSCodeで 拡張機能のTeams Toolkit をクリックし、Microsoft 365 又は Azure アカウントでログインしてください。

Sign inする

Teams Toolkitのテンプレートのフォルダ構成

新たに作成されたプロジェクトのフォルダ構成と、それぞれの役割について説明していきます。

テンプレートからプロジェクトを作成した段階のフォルダ構成は以下の通りです。

├── .vscode
│   ├── extensions.json
│   ├── launch.json
│   ├── tasks.json
│   └── settings.json
├── README.md
├── appPackage
│   ├── color.png
│   ├── manifest.json
│   └── outline.png
├── env
├── host.json
├── infra
│   ├── azure.bicep
│   ├── azure.parameters.json
│   └── botRegistration
│       ├── azurebot.bicep
│       └── readme.md
├── local.settings.json
├── messageHandler
│   └── function.json
├── notifyHttpTrigger
│   └── function.json
├── package.json
├── src
│   ├── adaptiveCards
│   │   └── notification-default.json
│   ├── cardModels.ts
│   ├── httpTrigger.ts
│   ├── internal
│   │   ├── config.ts
│   │   ├── initialize.ts
│   │   ├── messageHandler.ts
│   │   └── responseWrapper.ts
│   └── teamsBot.ts
├── teamsapp.local.yml
├── teamsapp.testtool.yml
├── teamsapp.yml
└── tsconfig.json
  • appPackage
    • Teamsアプリの設定を行うディレクトリ
    • manifest.json を更新することでアプリのアイコン・アプリの説明・タブの追加・外部リンクの設定(プライバシーポリシーページなど)が行えます
  • env
    • dev/local/test 環境の環境変数の設定
  • host.json
  • infra
    • Teamsアプリのインフラを管理するコード
    • Azure Function, Azure Bot Service, Storage Accountの作成などをコードで管理している。
  • messageHandler
    • AzureBotServiceのエンドポイント
  • notifyHttpTrigger
    • AzureFunctionのエンドポイント
  • src
    • アプリのリソース
  • teamsapp.local.yml teamsapp.testtool.yml teamsapp.yml
    • アプリの設定やアプリのライフサイクル(Provision→Deploy→Publish)に関するアクションを定義する
    • 環境を追加する際に、新たに teamsapp.{env}.yml を設定する
    • 既存のアクションをteamsapp.{env}.yml / teamsapp.yml に追加することも可能

ローカルでTeams通知Botアプリを実行する

次に、ローカル環境でエミュレーターを使用してTeamsアプリを起動する方法について説明します。

必要なライブラリをインストールする

npm install

VSCodeでデバッグする際に起動するブラウザを設定する(デフォルトはEdgeです)

VScodeでデバックする

▶️を推してエミュレーターを起動する

エミュレーターを起動

VSCodeによってブラウザが開かれます。MSアカウントでログインしていない場合、ログインを求められます。

パスワードの入力

ブラウザでTeamsアプリが起動され、Teams通知アプリの追加モーダルが表示されたら、 「追加」 を押します。

アプリの追加

アプリの追加が完了すると、アプリとのチャット画面に遷移します。

ユーザーに通知を送る

起動したアプリには2つのHTTP エンドポイントが提供されています。

POSTエンドポイント: http://localhost:3978/api/messages

  • ユーザーからチャットで送られてきたメッセージを受け取るエンドポイント
  • APIの設定ファイル: {アプリ名}/messageHandler/function.json

POSTエンドポイント: http://localhost:3978/api/notification

  • Botをインストールした全ユーザーに対し、通知メッセージを送れるエンドポイント
  • APIの設定ファイル: {アプリ名}/notifyHttpTrigger/function.json

ユーザーに対し、通知メッセージを送ってみましょう。

ターミナルで下記コマンドを実行し、エンドポイントに向けてリクエストを送ります。

curl -X POST http://localhost:3978/api/notification

すると、Botからメッセージが届きました。

アプリの追加

Botから送られてきたメッセージは通常のテキストメッセージではなくAdaptiveCardというタイプのメッセージです。詳細は https://adaptivecards.io/samples/ を参照してください。

Botにオウム返し機能を作る

次に、ユーザーとBot間のインタラクティブな機能を作るべく、ユーザーからチャットで送られてきたメッセージを受け取るエンドポイントを使用してBotにオウム返しを行う機能を作ろうと思います。 要件は以下の通りです。

  • ユーザーがBotをインストールしたらBotから「インストールありがとうございます。私はオウム返しBotです」とユーザーにメッセージを送る
  • ユーザーからメッセージが送られたら、オウム返しのメッセージを送る src/teamsBot.ts を以下のように書き換えてください。
import { TeamsActivityHandler, TeamsChannelAccount } from "botbuilder";
export class TeamsBot extends TeamsActivityHandler {
  constructor() {
super();
    // ユーザーからメッセージを受け取った際に発火する関数
    this.onMessage(async (context, next) => {
      const incomingMessage = context.activity.text
      await context.sendActivity(`オウム返し: ${incomingMessage}`);
      await next();
    });
    // ユーザーがBotをインストールした際に発火する関数
    this.onTeamsMembersAddedEvent(
      async (membersAdded, teamInfo, context, next) => {
        if (membersAdded.length == 2) {
          const userData: TeamsChannelAccount = membersAdded[0];
          const botData: TeamsChannelAccount = membersAdded[1];
          if (userData.userRole != undefined && botData.userRole == undefined) {
            await context.sendActivity(`インストールありがとうございます。私はオウム返しBotです`);
          }
        }
      }
    );
  }
}

次に、アプリをインストール時の起動確認のためにアプリのアンインストールと再インストールを行なってください。

アンインストール方法

左のナビバーから … マークをクリックし、対象のアプリ( {アプリ名}local ) を右クリックし アンインストール をクリックします。 アンインストール方法

再インストール方法

左のナビバーで アプリ をクリックした後に、 アプリを管理 > アプリをアップロード をクリックします

再インストール方法

ダイアログが表示されたら カスタムアプリをアップロード を選択します。

アップロードを選択

{アプリのPATH}/appPackage/build/appPackage.local.zip ファイルをアップロードします。

ファイルのアップロード

アップロード完了後にアプリの追加ダイアログが表示されると思うので、再度 追加 をクリックします。

すると、「インストールありがとうございます。私はオウム返しBotです」というメッセージが送られ、Botにメッセージを送るとオウム返しのメッセージが送信されます。

オウム返しBot

Teams通知Botのデプロイ方法

Teams Cli のインストール

npm install -g @microsoft/teamsapp-cli
teamsapp -h

初回のデプロイ

初回デプロイ時には、Teams Botを動かすためのAzureFunctionやAzureBotServiceなどのリソースが存在しないので、まずはリソースを作成しましょう。

$ teamsapp provision

check whether azure account is signed in.
subscription is not selected, try to select.
successful to select subscription: hogehoge-subscription
? Select a resource group + New resource group
? New resource group name test-teams-bot-app
? Location for the new resource group Central US
? Azure account: hoge@sample.com
Azure subscription: HogeSubscription
Microsoft 365 account: hoge@sample.com

Cost may incur according to the usage. Do you want to provision resources in dev environment using accounts listed above? yes
Executing provision 
.....
.....

すると、サブスクリプションの選択、リソースグループの選択(もしくは新規作成)、リージョンの選択を訊かれるので回答してください。(アクセス権限があるサブスクリプションが1つのみの場合はサブスクリプションの選択は訊かれません)

今回は環境を何も指定していないので、dev 環境のリソースが作成されているはずです。 下記の4つのファイルが生成/変更されているか確認してください。

  • appPackage/build/manifest.dev.json
  • appPackage/build/appPackage.dev.zip
  • env/.env.dev
  • env/.env.dev.user

次に、dev環境のデプロイを行います。

$ teamsapp deploy --env dev

? Do you want to deploy resources in dev environment? yes
...

2回目以降のデプロイ

2回目以降のデプロイではAzureリソースを作成する必要はないので、下記のデプロイコマンドのみを実行するだけです。

$ teamsapp deploy --env dev

? Do you want to deploy resources in dev environment? yes
...

デプロイされたアプリを動かす

アプリのインストール

左のナビバーで アプリ をクリックした後に、 アプリを管理 > アプリをアップロード をクリックします。

アプリのアップロード

アプリのアップロード2

`{アプリのPATH}/appPackage/build/appPackage.dev.zip ファイルをアップロードします。
{アプリ名}dev という名前のBotからメッセージが来ていれば成功です。

オウム返しのチャット

次にユーザーの通知機能の確認をします。

env/.env.dev の BOT_FUNCTION_ENDPOINT がエンドポイントのホスト部分になります。
{BOT_FUNCTION_ENDPOINT}/api/notification に対して curl でPOSTリクエストを送ります。

以下のようにメッセージが追加で来ていれば成功です。

オウム返しのチャット2

Teams Botの仕組みについて

この章では前の章で実装した通知機能とオウム返しの機能を持つBotの仕組みについて説明していきます。

インストール済みユーザーの管理の仕組み

アプリを起動した後、アプリを 追加すると、.notification.localstore.json というファイルが作成され中に下記のようなフォーマットのJSONオブジェクトが追加されていることが確認できます。

{
   `_{tenantId}_{conversationId}`: {
     "activityId": {activityId},
     "user": {
       "id": {user_id},
        "aadObjectId": {azure_active_directory_id}
      },
      "bot": {
        "id": {bot_id},
        "name": "teams-bot-app"
      },
      "conversation": {
        "conversationType": "personal",
        "tenantId": {tenantId},
        "id": {conversationId}
      },
      "channelId": "msteams",
      "locale": "ja-JP",
      "serviceUrl": "https://smba.trafficmanager.net/jp/"
   },
   ....
}

詳細は割愛しますが、ユーザーがBotをインストールするたびにBotとユーザー間での会話レコードが生成され、conversationId がそれぞれの会話に対して付与されます。この時、会話レコードは_{tenantId}_{conversationId} キーの値として.notification.localstore.json ファイルに書き込まれます。

そしてユーザーがBotアプリをアンインストールすると.notification.localstore.json から対象の_{tenantId}_{conversationId} キーのJSONオブジェクトが削除されます。

AzureにホスティングされたBotはデフォルトでローカル ファイル ストレージにてユーザーの管理を行いますが、Azure Web アプリ(Azure Functionなど)の再起動や再デプロイ時にローカルファイルストレージは初期化されてしまいます。 このため、デプロイする度にインストール済みユーザー情報が消えてしまうので、実際にアプリを運用する際にはAzure Blob StorageやCosmos DBなどの永続的にデータを保管できるストレージでインストール済みユーザーの管理を行うと良いでしょう。

Local環境でのTeams Toolkitによるアプリ起動の仕組み

ローカル環境のアプリ起動では、VSCodeの▶️ボタンをクリックする方法を紹介しました。 では、▶️ボタンをクリックしてから実際にエミュレーターが起動するまでの流れを確認したいと思います。

▶️ボタンをクリックされるとまず最初に、./vscode/launch.json が読み込まれ、選択したDebug in Teams (Chrome)の処理をVSCodeが行います。

./vscode/launch.jsonには下記のような設定が記載されています

{
    "version": "0.2.0",
    "configurations": [
        ....
        {
            "name": "Launch App (Chrome)",
            "type": "chrome",
            "request": "launch",
            "url": "https://teams.microsoft.com/l/app/${{local:TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&${account-hint}",
            "cascadeTerminateToConfigurations": [
                "Attach to Local Service"
            ],
            "presentation": {
                "group": "all",
                "hidden": true
            },
            "internalConsoleOptions": "neverOpen"
        },
        {
            "name": "Attach to Local Service",
            "type": "node",
            "request": "attach",
            "port": 9239,
            "restart": true,
            "presentation": {
                "group": "all",
                "hidden": true
            },
            "internalConsoleOptions": "neverOpen"
        }
    ],
    "compounds": [
        ....
        {
            "name": "Debug in Teams (Chrome)",
            "configurations": [
                "Launch App (Chrome)",
                "Attach to Local Service"
            ],
            "preLaunchTask": "Start Teams App Locally",
            "presentation": {
                "group": "1-local",
                "order": 2
            },
            "stopAll": true
        },
        ....
    ]
}

次に、Debug in Teams (Chrome)preLaunchTaskで定義されている"Start Teams App Locally"を実行するために、./vscode/tasks.jsonが読み込まれます。

// This file is automatically generated by Teams Toolkit.
// The teamsfx tasks defined in this file require Teams Toolkit version >= 5.0.0.
// See https://aka.ms/teamsfx-tasks for details on how to customize each task.
{
    "version": "2.0.0",
    "tasks": [
        .....
        {
            "label": "Start Teams App Locally",
            "dependsOn": [
                "Validate prerequisites",
                "Start local tunnel",
                "Provision",
                "Deploy",
                "Start application"
            ],
            "dependsOrder": "sequence"
        },
    {
       // Create the debug resources.
       // See https://aka.ms/teamsfx-tasks/provision to know the details and how to customize the args.
       "label": "Provision",
       "type": "teamsfx",
        "command": "provision",
        "args": {
           "env": "local"
         }
      },
        .....
    ]
}

次に、./vscode/tasks.json で定義されているタスクから、Teams Toolkit のコマンドが実行されます。 例えば、上記の "Start Teams App Locally" タスクでは実行時に"Validate prerequisites","Start local tunnel","Provision","Deploy","Start application" という5つの依存タスクも実行され、依存タスクである"Deploy" は、teams toolkitのdeployコマンドを実行します。

最後に、teams toolkitのコマンド実行時の流れについて紹介します。 アプリ直下のteamsapp.yml ファイルの中にはライフサイクルが定義されており、それぞれのライフサイクルでは既存のTeams Toolkitアクションのパイプラインを定義することができます。そして、teamsapp {ライフサイクル} を実行することで定義したアクションパイプラインを実行できます。 既存のTeams Toolkitアクションはhttps://github.com/OfficeDev/TeamsFx/wiki/Available-actions-in-Teams-Toolkitを参照してください

下記は、teamsapp.yml に定義しているdeployライフサイクルの例です。

# Triggered when 'teamsfx deploy' is executed
deploy:
  # Run npm command
  - uses: cli/runNpmCommand
    name: install dependencies
    with:
      args: install
  - uses: cli/runNpmCommand
    name: build app
    with:
      args: run build --if-present
  - uses: azureFunctions/zipDeploy
    with:
      artifactFolder: .
      ignoreFile: .funcignore
      resourceId: ${{BOT_AZURE_FUNCTION_APP_RESOURCE_ID}}

Teams通知Botのアーキテクチャ

最後に、Azure上にデプロイされたBotがどのようなアーキテクチャで動いているかについて確認していきたいと思います。 下記は、Teams Toolkitの Bot/チャット通知メッセージ のテンプレートを使用してAzureにデプロイされたBotのインフラアーキテクチャの全体像です。

インフラアーキテクチャの全体像

上記のアーキテクチャの動きの理解を深めるために、ユーザーからメッセージを受け取り、Botがメッセージをレスポンスするシナリオと、 Botからユーザーへメッセージを送信するシナリオについて説明します。

ユーザーから送られてきたメッセージに対し、Botでメッセージを作成し、Botがユーザーにメッセージを送り返すシナリオ

①TeamsでユーザーがBotにメッセージを送る ②AzureBotServiceがデプロイされたアプリ(App Service)にメッセージを送る ③,④アプリ(App Service)がユーザーにメッセージを返す

メッセージのシナリオ1

Botからユーザーへメッセージを送信するシナリオ

①Azure Functionのエンドポイントに対してPOSTリクエストを送る ②,③,④ Azure Functionがメッセージ送信対象ユーザーとメッセージ内容を決め、App Service,AzureBotServiceを通してユーザーにメッセージを送る

メッセージのシナリオ2

まとめ

本記事ではTeams Toolkitを用いたTeams通知Botの開発手順とBotの仕組みについてまとめました。AzureにホスティングされたTeams通知BotはAzure Function・Azure Bot Service上で動いており、Teams Botのデプロイ・ローカル環境でのエミュレーターの実行ではTeams Toolkitを活用することで少ない開発コストでBotの開発から運用までできることが分かりました。

普段の社内コミュニケーションツールはSlackを使っていたためTeamsに関する知識が乏しかったり、Azureサービスに関しても初学者だったのですが、VSCode上のGUIでエミュレータ起動が行えるなどの新し知見を身につけられたり、新規のSDK使用方法の調べ方などが身についたりととても良い経験になったと思います。



エムシーデジタルでは、当社に興味を持ってくださった方が気軽に会社のことを知れるようカジュアル面談を実施しています!
興味のある方はぜひ、以下のキャリアページの「カジュアル面談」からお問い合わせください。

採用情報はこちらから



参考記事

RSS

Tags

Previous

Konatsu Seki

Konatsu Seki

エムシーデジタル全社合宿 in 湯河原

こんにちは! エムシーデジタルの関です。 今回は、3月に開催した1泊2日の湯河原全社合宿の様子をお伝えします。 昨年よりも規模が大きくなり、今回は約70名のほぼ全社員が参加し、研修兼宿泊

  • #Corporate
  • #Culture
  • #Value
  • #合宿

Next

Konatsu Seki

Konatsu Seki

MCD AI Studioってなに?-生成AIを活用した企業の業務変革と新規事業創出支援-

2023年6月1日に設立された「MCD AI Studio」は、生成AIを活用した企業の業務変革及び新規事業創出支援を行う組織です。 では、実際にどういった背景から設立され、具体的にはどん

  • #生成AI
  • #社員インタビュー