Qiitaにはご存知のとおり質問タブがありますが、そこで気になるものがありました。ホームページに届いた問い合わせをTeamsのチャネルに転送して従業員に共有できる仕組みにしているようです。
なるほど、これだとスレッド単位で回答案を共有しあえますし、ナレッジとして後ほど確認もできるのでよさそうな仕組みです。
生成AIをつかって回答案作れるのでは?
せっかくなので、Teams上に届いた問合せ内容に対する回答案を生成AIを使って作らせて、問題がないか判断したら回答を返信するところまでTeams上で完結できないかな?
と、思いついたのでやってみたのが今回の取り組みです。
Copilot Studioの@メンション起動は使える?
最初におもいついたのは、Copilot Studioで作成したエージェントのTeamsチャネル上からの@メンション呼び出しです。
こちらの記事の記事の後半に出てくるように、チャネルに追加したボットは、@ボット名のようにメンションすると、人に話しかけたように答えてくれます。
ただ、この方法だとスレッド内ですでに投稿されている質問を読み取ってくれるわけではないので、質問内容を改めてボットくんに伝える必要があります。これはスマートではありません。
メンションもとのスレッドIDを取得できれば、内容も取得できるかもですが。このあたりは、Teamsにスレッドが投稿されたことをトリガーにして起動させる自立型エージェントを使えば実現できるんでしょうね。
今回はPower Automateオンリーでやってみます。
コパスタでの作成も興味はありますが、今回はゴリゴリとクラウドフローだけで実現してみます。理由としては、コパスタの自立型エージェントやグラウンディングって結構コスト高いよね、という消極的なものです。個人的には全自動より半自動が好みってのもあります。
おおまなか設計は以下のとおり
以下のステップでクラウドフローを設計できます:
📩 メール受信トリガー
トリガー:「Outlookでメールを受信したとき」
アクション:「Teamsのチャネルにメッセージを投稿」 → メール内容を新規スレッドとして投稿
🤖 AI Builderによる返信案生成の分岐
条件分岐:「返信案を自動生成するか、確認を求めるか」
アクション(確認の場合):「アダプティブカードを投稿して選択を待機」
📚 スレッド内容の取得
アクション:「Teamsメッセージの詳細を取得」 → メッセージID、チャネルID、チームIDを使ってスレッドの本文を取得
アクション:「AI Builderの予測を呼び出す」 → スレッド内容を入力として送信し、返信案を生成
📝 返信案の提示と修正確認
アクション:「アダプティブカードを投稿して確認を求める」 → 「問題ない」「修正する」などの選択肢を提示
条件分岐:「修正する」を選んだ場合
アクション:「編集可能なアダプティブカードを投稿」
📤 メール返信の実行
アクション:「Outlookでメールを送信」 → 修正済みまたは確認済みの返信案を本文として使用
作成前のイメージ
今回のポイントは、届いたメール単位でTeamsの問合せチャネルにスレッドを建てるところです。投稿されたことがトリガーにできるのと、スレッドのIDを使ったレスポンスでアダプティブカードと対話するようなイメージです。
アダプティブカードもCopilotが作ってくれる
上記のような大まかなイメージを伝えると、Copilotはアダプティブカードのテンプレートを提案してきました。まだ使えるかどうかこの段階ではわからないですが、それでもAIすげーなという感想です。
こういうのをバイブコーディングっていうんですか? しらんけど。
チームにチャネルを作りメール内容を投稿する
ひとまず、営業課のチームに専用の「問合せ管理」チャネルを作りました。

メールが届いたらクラウドフローが起動するようにするため、「新しいメールが届いたとき(V3)」をトリガーに設定します。
このトリガー自体の詳細でどのようなメールが届いたときに動作するかを設定できるのですが、個人的にはOutlookの受信トレイをフォルダ分けして、Outlook側で振り分け制御をするほうが好みです。
例えばHPからの最初のメールにだけ反応させるには、件名にRe:が含まれるものは別のフォルダにするとか。そういう条件わけはOutlookのほうが細かく設定できるので、任せてしまうのが個人的にはおすすめです。
届いたメールから、差出人や件名、本文などの情報を一つのテキストとしてまとめてチェックできるようにしておきました。

届いたメールの必要部分だけが抜き出せました。確認ができたので、中身を「チャットまたはチャネルでメッセージを投稿する」アクションに貼り付けます。

チームに投稿されました。こんどはこのスレッドにAIからの回答案を提示させます。

画面左側の詳細のなかにある「AIハブ」を開きます。一番左側の「プロンプト」をつかいます。

いろいろなテンプレートが用意されていますが、今回は「独自のプロンプトを作成する」を利用します。

一番上のタイトル部分にはこのプロンプトのタイトルを入力しておきます。
画面左側にプロンプトを自然言語入力します。左下にある「+コンテンツを追加する」をクリックすると、クラウドフローから与える情報の入力変数を設定することができます。
参照とするナレッジには、今回はMicrosoftの技術情報サイトのURLを記載していますが、例えば自社製品の紹介ページや、ナレッジを蓄積したSharePointサイトなどを指定するとよいのではないでしょうか?

SPOサイトからナレッジを取得できるかまだ試していませんが。
先程の問合せメール本文を例としてサンプルデータ欄に貼り付けてやります。ここまでできたら「テスト」をクリックすると、画面右側に返信メールの案が自動作成されます。感激です。

保存ができたら、先程作成していたクラウドフローに戻り、「プロンプトを実行する」アクションを追加して作成したプロンプトを選択します。

どんな戻り値が出てくるのか確認するために、「作成」に動的結果がわかりやすいように配置して動かしてみます。
結果として、動的な結果の「Text」にAI Builderを使った返信案が返ってくるようです。

ちなみに、「プロンプトの実行」で取得できる情報の中身をCopilotになげて分析させたところ、以下のような情報がわかるようです。

ちなみに、2025年11月からAI Builderクレジットは廃止されて、Copilot Studioの課金体型であるCopilotクレジットに統合されるようです。レートは以下のページで確認できます。
https://learn.microsoft.com/ja-jp/ai-builder/message-management

https://learn.microsoft.com/ja-jp/ai-builder/credit-management
チャネルのスレッドに対して返信させる
さきほどメールトリガーを使ってTeamsチャネルに投稿しましたので、投稿アクションはメッセージIDを持っています。これを使って返信を行います。

ここで、ちょっとプロンプトに修正を加えました。文字がべったりTeamsに投稿されてしまったので、HTMLで出力するようにします。TeamsはHTMLをちゃんと解釈してくれるので表示がきれいになるはずです。
いよいよアダプティブカード
実はここから失敗してます。スレッドに返信するタイプのアダプティブカードである「」は「アダプティブカードを使用してチャネルで返信する」は、「誰かがアダプティブカードに応答した場合」に対応しておらず。
とっても残念なので、初めてMicrosoftのideasに投稿しました。
https://ideas.powerapps.com/d365community/idea/2239ae11-4ba7-f011-aa43-0022484ddfef
ここから先は苦しんでいる姿をご覧ください。
先程返信に投稿した返信案をそのまま返信するか、それとも編集を加えるか。アダプティブカードで確認する動作を組み込みます。ただ、ここで問題が。
「Teamsにアダプティブカードを投稿して応答を待機」アクションは、ユーザーに判断を委ねたあとに回答があるまで待機してくれるのですが、チャネルへの新規投稿しか行えません。
そこで、こちらを参考にさせていただきました。
アイディアとしては、投稿へのアダプティブカードへの返信は「アダプティブカードを使用してチャネルで返信する」アクションを使い、ユーザーからの応答待ちは、別フローを立てて「誰かがアダプティブカードに応答した場合」トリガーで待ち受けるという作戦です。
なんどもAI Builderを動かすとクレジットがもったいないので、フローの上の方でアダプティブカード部分だけテストします。すでにメッセージIDがわかっているので、直打ちすればOKです。
Copilotが作ってくれたJSONを使う
以下のようなJSONを「アダプティブカードを使用してチャネルで返信する」アクションに設定して実行します。このとき、メッセージIDは何度かテスト実行をした際に取得できたIDを使えばよいでしょう。
{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.5",
"body": [
{
"type": "TextBlock",
"text": "AIが生成した返信案について、送信方法を選択してください。",
"wrap": true,
"weight": "Bolder",
"size": "Medium"
},
{
"type": "TextBlock",
"text": "この返信案をどうしますか?",
"wrap": true,
"weight": "Bolder"
},
{
"type": "Input.ChoiceSet",
"id": "sendOption",
"style": "expanded",
"choices": [
{
"title": "このまま送信する",
"value": "sendAsIs"
},
{
"title": "編集する",
"value": "Edite"
},
{
"title": "送信を中止する",
"value": "cancel"
}
]
}
],
"actions": [
{
"type": "Action.Submit",
"title": "決定",
"data": {
"action": "finalDecision"
}
}
]
}
実行してみると、こんな感じでにアダプティブカードが投稿されました。

選択後の結果を補足して条件分け
ここまでできたら、今度はユーザーが選択したあとの処理を別のフローで作っていきます。
「誰かがアダプティブカードに応答した場合」トリガーを使います。

選択するとなぜか名前が変わります。「When someone responds to an adaptive card」
ここからの使い方ですが、下記のサイトが参考になりました。
サイトを参考に、トリガーの「アダプティブカードの入力」には、送信元と同じJSONを貼り付け、カードの種類IDには適当なIDを入力しました。

それで、カードの種類IDと同じものを送信元にも設定すればよいのですが・・・。「アダプティブカードを使用してチャネルで返信する」アクションには、この項目がないのです。
これは、送信元のJSONのactions部分に設定することで解決するようです。
どうやら、「アダプティブカードを使用してチャネルで返信する」からはAction Submitを送ることができないっぽく。変わりにURLを送ってHTTP要求の受信で拾うという手もあるのですが、プレミアムアクションだし・・・。
ここまでなのか?!
あきらめて、「アダプティブカードを投稿して応答を待機する」を使う
使えないものは仕方ありません。アダプティブカード自体に工夫をして、質問、回答案、選択肢を1つのカードでまとめることにしました。
その結果ずいぶんシンプルになりました。
1つめのHTMLからテキスト(プレビュー)は、メールの質問文を指定しています。メール内容がHTMLだった場合にプレーンテキストに変換されます。プロンプトにもこちらを問い合わせの本文として与えます。
2つめのHTMLからテキスト変換は、プロンプト実行で返ってきた生成AIの回答案です。
プロンプトではHTMLで出力するように指定したので、それをあえてテキストに戻します。アダプティブカードの中ではHTMLタグがついたままだと不具合が出たからです。
そして、「アダプティブカードを投稿して応答を待機する」の中身がこちらです。
{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.5",
"body": [
{
"type": "TextBlock",
"text": "**受信日時:** 2025-10-11 11:32",
"wrap": true,
"spacing": "Small"
},
{
"type": "TextBlock",
"text": "**質問者:** yamada.taro@example.com",
"wrap": true,
"spacing": "Small"
},
{
"type": "TextBlock",
"text": "**元の質問:**\n製品Aのライセンス更新方法について教えてください。",
"wrap": true
},
{
"type": "TextBlock",
"text": "**AIによる回答案:**\n製品Aのライセンス更新は、管理ポータルにログイン後「ライセンス管理」から更新手続きを行えます。詳細は以下のURLをご参照ください:https://example.com/license-update",
"wrap": true
},
{
"type": "TextBlock",
"text": "AIが生成した返信案について、送信方法を選択してください。",
"wrap": true,
"weight": "Bolder",
"size": "Medium",
"spacing": "Medium"
},
{
"type": "TextBlock",
"text": "この返信案をどうしますか?",
"wrap": true,
"weight": "Bolder"
},
{
"type": "Input.ChoiceSet",
"id": "sendOption",
"style": "expanded",
"choices": [
{
"title": "このまま送信する",
"value": "sendAsIs"
},
{
"title": "送信を中止する",
"value": "cancel"
}
]
}
],
"actions": [
{
"type": "Action.Submit",
"title": "決定",
"data": {
"action": "finalDecision"
}
}
]
}
上記のサンプル部分を動的なコンテンツに差し替えるとこのようになります。

実行してみると、このような投稿がされました!なかなか良い出来ではないですか?

メール送信部分
ただいま作成中
スレッド返信とトリガーの壁
- 「アダプティブカードを使用してチャネルで返信する」では cardTypeId を設定できない
- Action.Submit がトリガーに渡らない
- 結果として「When someone responds to an adaptive card」トリガーが反応しない
まとめ
今回は、生成AIを使って問い合わせメールの回答案を作成し、Teams上で確認・返信する仕組みをクラウドフローで構築してみました。
課題は残りましたが、Copilotの活用やアダプティブカードの連携など、実践的な知見が得られたので満足です。









