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でできること
- Teams通知Botでは、主に2つの機能を実現することができます。
- ユーザーのアクションに対するリアクション
- ユーザーがBotアプリをインストールした際に、 Botからユーザーに対し何かしらのメッセージを送る
- ユーザーがBotアプリをアンインストールした際に、ユーザーのTeamsアカウントに紐づいたメールアドレスにメールを送る
- ユーザーが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アプリをインストールするなどのアクションにトリガーされてユーザーに対して任意のメッセージを送信したり、フォーム、テキスト、画像、動画、アクションボタン付きのリッチなメッセージの作成と送信を簡単に実装することができます。
実際にTeams 通知Botを開発してみる
JavaScript を使用した通知ボットのビルド を進めていきます。 この章では、VSCodeのExtension(拡張機能)であるTeams Toolkit を使ってテンプレートからTeams通知アプリの作成を行います。
VSCodeをダウンロードしていない方は、こちらからダウンロードしてください。
- VSCodeのExtension(拡張機能)でteamsと打つと、「Teams Toolkit」というアプリが出てくると思うので、ダウンロードしてください。
- ダウンロードしたTeams Toolkitをクリックし(①)、 新しいアプリの作成 (② ) をクリックするとテンプレートが選べるので 通知 (③) > チャット通知メッセージ > HTTPトリガー Azure Functions > Javascript/Typescript > プロジェクトを作成するPATH を選択していきます。
- 前の手順2でテンプレートから通知Botアプリを無事作成できると、新しくプロジェクトが作成されVSCodeが再度開きます。新たに開かれたVSCodeで 拡張機能のTeams Toolkit をクリックし、Microsoft 365 又は Azure アカウントでログインしてください。
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
- デプロイされたAzure上のAzureFunctionのログ設定などが行える
- https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-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によってブラウザが開かれます。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にメッセージを送るとオウム返しのメッセージが送信されます。
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
...
デプロイされたアプリを動かす
アプリのインストール
左のナビバーで アプリ をクリックした後に、 アプリを管理 > アプリをアップロード をクリックします。
`{アプリのPATH}/appPackage/build/appPackage.dev.zip ファイルをアップロードします。
{アプリ名}dev という名前のBotからメッセージが来ていれば成功です。
次にユーザーの通知機能の確認をします。
env/.env.dev の BOT_FUNCTION_ENDPOINT がエンドポイントのホスト部分になります。
{BOT_FUNCTION_ENDPOINT}/api/notification に対して curl でPOSTリクエストを送ります。
以下のようにメッセージが追加で来ていれば成功です。
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)がユーザーにメッセージを返す
Botからユーザーへメッセージを送信するシナリオ
①Azure Functionのエンドポイントに対してPOSTリクエストを送る ②,③,④ Azure Functionがメッセージ送信対象ユーザーとメッセージ内容を決め、App Service,AzureBotServiceを通してユーザーにメッセージを送る
まとめ
本記事ではTeams Toolkitを用いたTeams通知Botの開発手順とBotの仕組みについてまとめました。AzureにホスティングされたTeams通知BotはAzure Function・Azure Bot Service上で動いており、Teams Botのデプロイ・ローカル環境でのエミュレーターの実行ではTeams Toolkitを活用することで少ない開発コストでBotの開発から運用までできることが分かりました。
普段の社内コミュニケーションツールはSlackを使っていたためTeamsに関する知識が乏しかったり、Azureサービスに関しても初学者だったのですが、VSCode上のGUIでエミュレータ起動が行えるなどの新し知見を身につけられたり、新規のSDK使用方法の調べ方などが身についたりととても良い経験になったと思います。
エムシーデジタルでは、当社に興味を持ってくださった方が気軽に会社のことを知れるようカジュアル面談を実施しています!
興味のある方はぜひ、以下のキャリアページの「カジュアル面談」からお問い合わせください。
参考記事
- Teamsアプリの種類について
- Teams Toolkitとは
- Teamsアプリの種類について
- Microsoft Store](https://www.microsoft.com/ja-jp/store/top-free/apps/mobile)
- Bot Framework SDK とは
- Teams通知Botを開発すべき要件とそうでない要件
- Teams Toolkitのテンプレートのフォルダ構成
- 実際にTeams 通知Botを開発してみる
- Teams通知Botのデプロイ方法