NTT WEST Engineers' Blog 開設にむけて投稿記事レビューのワークフローを爆速で構築した話⑤~Power Automateによるレビューフロー中編~

はじめに

NTT西日本の服部です。本記事はNTT WEST Engineers' Blog 開設にむけて投稿記事レビューのワークフローを爆速で構築した話の第5回の記事となります。
前回までの記事も読んでいただけるとありがたいです。
第5回となる本記事ではPower Automateによるレビューフロー中編としてレビュアーアサイン後のレビューフローについてご紹介します。
本記事は2025年9月時点の情報に基づきます。

第1回でご紹介したワークフローの全体像のうち、以下の図にあたる内容となります。


対象読者

本記事が想定する対象読者は以下の通りです。

  • 自動化に興味がある人
  • 繰り返しの定常的な作業に困っている人
  • Microsoft Forms/Microsoft Lists/Power Automateを使ってみたい人

背景

NTT WEST Engineers' Blog に向けて、ブログ記事のレビュープロセスを効率化したいという要望を受けて執筆者が検討・構築しました。
SaaSの新規サービスを導入する予算はありませんでしたが、幸い全社的にMicrosoft Forms、Microsoft Lists、Power Automateが利用できる環境だったため、これらを用いてブログ記事レビューのワークフローを構築しました。
本記事ではレビュアーアサイン後のレビューフローとして構築したPower Automateのフローについて紹介します。


補足:アダプティブカードについて

今回紹介するフローの中で利用されているアダプティブカードについて事前にご紹介します。
アダプティブカードとは、テキストや画像、ボタンなどを組み合わせたインタラクティブなメッセージカードです。
Microsoft Teamsで利用するアダプティブカードについての詳細は以下の公式ドキュメントを参照ください。
Teams 向けアダプティブ カードの概要 - Power Automate | Microsoft Learn

アダプティブカードを設計する際には以下のデザイナーを利用することができます。
Designer | Adaptive Cards

上記のデザイナーを使ってMicrosoft Teamsに投稿するアダプティブカードをデザインする際には下図赤枠のSelect host appMicrosoft Teamsを選択するようにしてください。

引用元:https://adaptivecards.io/designer

デフォルトで選択されているBot Framework WebChatの場合、画面右上のTarget Version1.6となっておりこちらのバージョンはMicrosoft Teamsに対応していません。
非対応のバージョンで作成されたアダプティブカードをMicrosoft Teamsに投稿すると以下のメッセージが表示されます。


レビュアーアサイン後のレビューフロー

アダプティブカードについてご紹介したところで本題のPower Automateのフローについてご紹介します。 今回レビューの処理用に構築したフローの全体像は以下の通りです。

以下で各ステップの詳細についてご紹介します。

1.アイテムが作成または変更されたとき

このPower Automate のフローが実行される条件(トリガー)になります。
前回の記事でも紹介しましたがMicrosoft Listsにおける一行ごとのデータ(レコード)のことをアイテムといい、本記事においては1アイテム=1件分のレビュー依頼に相当します。
アイテムが新規に作成されたもしくは既存のアイテムの値が変更されたときにこのフローが実行されます。
トリガーの条件として以下を指定しました。

@equals(triggerBody()['OData__x30b9__x30c6__x30fc__x30bf__x30/Value'],'レビュアーアサイン待ち')
@not(equals(triggerBody()['OData__x30ec__x30d3__x30e5__x30a2__x30/Value'],'未設定'))

上記は作成または更新されたアイテムのステータスがレビュアーアサイン待ちかつレビュアーが未設定ではない(=誰かしらレビュアーがアサインされている)ときにこのフローが実行されることを意味しています。
トリガーの条件式の書き方については前回の記事で詳しく解説しているため、そちらを参照ください。

2.項目の更新(レビュー待ち)

実際のレビュー依頼をあげるまえにステータスをレビュー待ちに更新します。
ステータスをレビュー待ちに更新したとしても他のフローのトリガー条件にあてはまることはないため、他のフローは実行されません。

3.アダプティブ カードを投稿して応答を待機する(レビュー依頼)


レビュアーとしてアサインされた担当者にアダプティブカードを送る処理です。
省略されているメッセージ部分には以下のJSONが記載されています。

{
    "type": "AdaptiveCard",
    "body": [
        {
            "type": "TextBlock",
            "size": "Medium",
            "weight": "Bolder",
            "text": "ブログ記事のレビュー依頼"
        },
        {
            "type": "TextBlock",
            "text": "タイトル:@{outputs('項目の更新(レビュー待ち)')?['body/Title']}の記事のレビュアーとして設定されました。  \n以下の下書き記事を見てレビューコメントを入力してください。  \nコメントを入力後レビュー結果に相当するボタンをクリックしてください。",
            "wrap": true
        },
        {
            "type": "ActionSet",
            "actions": [
                {
                    "type": "Action.OpenUrl",
                    "title": "下書きプレビューURL",
                    "url": "@{outputs('項目の更新(レビュー待ち)')?['body/OData__x4e0b__x66f8__x304d__x30d7__x30']}"
                }
            ]
        },
        {
            "type": "Input.Text",
            "placeholder": "Placeholder text",
            "id": "comment",
            "isRequired": true,
            "errorMessage": "レビューコメントは必須項目です。",
            "label": "レビューコメント",
            "isMultiline": true
        },
        {
            "type": "ActionSet",
            "actions": [
                {
                    "type": "Action.Submit",
                    "title": "承認",
                    "id": "approval"
                },
                {
                    "type": "Action.Submit",
                    "title": "差戻",
                    "id": "remand"
                },
                {
                    "type": "Action.Submit",
                    "title": "キャンセル",
                    "id": "cancel"
                },
                {
                    "type": "Action.Submit",
                    "title": "却下",
                    "id": "reject"
                }
            ],
            "horizontalAlignment": "Left"
        },
        {
            "type": "TextBlock",
            "text": "・承認:レビューを完了します。  \n・差戻:投稿者に修正を依頼します。  \n・キャンセル:レビュアーの変更を依頼します。  \n・却下:規定違反などを理由に却下します。",
            "wrap": true
        }
    ],
    "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
    "version": "1.5"
}

上記のアダプティブカードが送信されるとMicrosoft TeamsでWorkflowsという対象から以下のようなメッセージがレビュアーの個人チャット宛に届きます。

下書きプレビューURLのボタンはリンクとなっており、ブログ記事の下書きページを確認することができ、その内容についてレビューした結果をレビューコメントの枠に入力します。
レビューコメントを入力したらレビュー結果に相当するボタンをクリックすることで次の処理に進めることができます。  
また、レビューコメントの属性として"isRequired": true, を指定することで必須の入力項目となり、空欄のままでは次の処理に進められないようにしています。

補足:アダプティブカードのタイムアウト設定について

アダプティブカードは規定では30日でタイムアウトとなりますがこの期間は変更することが可能です。
変更する場合はアダプティブカードのステップの右側にある・・・から設定をクリックします。

設定をクリックすると以下の画面が表示されるため、タイムアウトを設定することが出来ます。

ここでは14日間経過するとタイムアウトするように設定しています。
タイムアウトの期間はISO 8601 形式で期間を指定します。
ISO 8601 形式の詳細については以下を参照ください。
ISO 8601 - Wikipedia
ISO 8601-1:2019(en)

4.スイッチ(レビュー結果)


アダプティブカードに対してレビュアーが操作した結果によって処理が分岐します。
分岐処理の判定には以下の値を使用しています。

outputs('アダプティブ カードを投稿して応答を待機する(レビュー依頼)')?['body/submitActionId']

ここには直前に処理されたアダプティブカードでクリックされたボタンのIDが入ります。
つまりアダプティブカードのメッセージで定義された以下のボタンに割り当てられたIDであるapproval,remand,cancel,rejectのいずれかが入ります。

            "type": "ActionSet",
            "actions": [
                {
                    "type": "Action.Submit",
                    "title": "承認",
                    "id": "approval"
                },
                {
                    "type": "Action.Submit",
                    "title": "差戻",
                    "id": "remand"
                },
                {
                    "type": "Action.Submit",
                    "title": "キャンセル",
                    "id": "cancel"
                },
                {
                    "type": "Action.Submit",
                    "title": "却下",
                    "id": "reject"
                }
            ],

4-1.ケース1(承認)


アダプティブカードで承認がクリックされたときの処理です。
承認された場合には投稿者へのレビュー完了の通知処理とステータスをレビュー完了に変更する処理と事務局への記事公開依頼処理が含まれています。


本来は以下のステップの前にタグの @mention トークンを取得するのステップを追加するべきですが、ここでは割愛しています。

上記の処理によってMicrosoft Teamsで指定されたチャネルにメッセージが投稿されます。

上記の処理によってMicrosoft TeamsでWorkflowsという対象から投稿者の個人チャット宛にメッセージが投稿されます。

4-2.ケース2(差戻)

アダプティブカードで差戻がクリックされたときの処理です。 ここではステータスを差し戻しに更新する処理のみを定義しています。
修正依頼のフローはここでは定義しておらず、別のフローとして定義されています。
修正依頼のフローの詳細については次回ご紹介します。

4-3.ケース3(キャンセル)

アダプティブカードでキャンセルがクリックされたときの処理です。
レビュアーが業務都合などの理由から担当者を変更して欲しい場合に使うことを想定しています。
ここではステータスをレビュアーアサイン待ちに、レビュアーを未設定に更新する処理を実行します。
この処理によって前回ご紹介したレビュアーアサイン依頼のフローのトリガー条件を満たすことになり、レビュアーのアサインからやり直すことができます。

4-4.ケース4(却下)


アダプティブカードで却下がクリックされたときの処理です。
記事の内容が規定に反する等の理由から投稿できないと判断されたときに使うことを想定しています。
ここではステータスを却下/消滅に更新する処理と投稿者へのレビュー結果通知の処理を定義しています。

上記の処理によってMicrosoft TeamsでWorkflowsという対象から投稿者の個人チャット宛にメッセージが投稿されます。

5.項目の更新(レビュータイムアウトに伴うレビュアーリセット)

本記事でアダプティブカードのタイムアウトについて解説しましたが、アダプティブカードがタイムアウトするとフローの処理としては失敗となりそこで処理が終了してしまいます。
そこで万が一タイムアウトが発生した場合の処理の定義が以下の内容になります。
ここではケース3(キャンセル)と同じでステータスをレビュアーアサイン待ちに、レビュアーを未設定に更新することでレビュアーのアサイン依頼のフローを呼び出せるようにしています。

タイムアウト用の処理を定義したい場合は分岐したいステップの直後(今回はアダプティブカードのステップの直後)で⊕ボタンをクリックして並列分岐の追加をクリックします。

分岐先で追加したステップ(今回は項目の更新)の右側の・・・から実行条件の構成をクリックします。

実行条件の構成をクリックすると以下の画面が表示され、直前のステップ(ここではアダプティブカードのステップ)の処理結果がどうなったときにこのステップを実行するかを選択することができます。ここではタイムアウトした場合に実行すると定義しています。
成功しました以外が選択された状態で完了をクリックすると該当のステップに繋がる矢印が赤の破線に変更されます。


注意事項

今回ご紹介したPower Automateのフローは意図的にフローの実行結果から別のフローを呼び出すという設計にしていますが、設定内容を誤ると無限ループが発生する可能性があります。
本記事の内容を流用される場合には無限ループが発生しないように十分に注意して設計/構築してください。
無限ループへの対処法については以下の日本マイクロソフトのブログ記事も参照ください。
Power Automate のフローで無限トリガーループが起きる際の対処法 | Japan Dynamics CRM & Power Platform Support Blog


まとめ

今回は本シリーズの最も重要なレビューフローについてご紹介しました。
多くの処理が含まれるため非常に長い記事となりましたがここまで読んでいただきありがとうございます。
次回は本シリーズの最終回で修正依頼と投稿完了通知のフローのご紹介となります。
もしよろしければ最後までお付き合いください。


執筆者

服部 真智(NTT西日本 ビジネス営業本部所属)
普段はAWS案件の提案、設計、構築等の支援を行っています。
自業務の効率化のためにPython,Power Automate,生成AI等を使って日々試行錯誤しています。
2025 Japan AWS Top Engineers (Services)


商標

Microsoft (Microsoft Entra 、 Microsoft Teams 、 Power Automate 、 Microsoft Lists 、 Microsoft Forms)及び関連する名称並びにそれぞれのロゴは、米国 Microsoft Corporation の米国およびその他の国における商標または登録商標です。

© NTT WEST, Inc.