記事公開日
【Copilot Studio】カードのボタンにデータを埋め込み、変数の持ち越しをやめる
この記事のポイント
Copilot Studio で、ボタンが押されたら続きの処理をしたいときは、必要な値をボタンの中に入れておくと、押されたときにその値を取り出して使えます。
押されるまで変数で値を持っておく必要がなく、押したカードはその場で書き換えてボタンを消せます。
- ボタンの中に、画面に出ない値を入れておける:
カードのボタンには、画面には表示されない値を持たせられます。ボタンが押されると、その値がエージェントに送られてきます。 - 押されたことを受け取るトピックで、値を取り出す:
「呼び出された時」トリガーのトピックで、ボタンから送られてきた値を取り出して使います。 - 押したカードを書き換えて、ボタンを消せる:
押されたカードを、結果を表示するカードに置き換えられます。Teams で試したところ、古いカードを後から押しても、押したカードに入れた値で処理が続きました。
こんにちは!DXソリューション営業本部の大和矢です。
Copilot Studio で、アダプティブ カード(以下、カード)に「担当者に確認しますか?」のようなボタンを出し、押されたら続きの処理をしたい場面はありませんか?
このとき、押されるまで「何の質問だったか」を変数で持っておくのは面倒です。
別の質問が割り込んだり、古いカードを後から押されたりしたときの取り違えにも、備えなければなりません。
この記事では、ボタンそのものに値を埋め込んで押されたときに取り出す方法と、押したカードを置き換えてボタンを消す方法を紹介します。
まず完成した動きを画面で見てから、仕組みと作り方を順に紹介します。
対象は Teams に公開したエージェントで、仕様・挙動は2026年10月時点のものです。
完成イメージ:押したカードがその場で置き換わり、古いカードでも正しく動く
この記事で作るのは、次のような動きです。
Teams で「カードAを送って」と入力すると、エージェントが確認のカードを返します。
「確認する」(赤枠)を押すと、カードがその場で「受け付けました。」に置き換わり、ボタンが消えます。
置き換わったカードには、押したカードの質問文が「ご質問」として出ています。
カードが何枚あっても、押したカードの値で処理が続きます。
たとえば、「カードAを送って」のあとに「カードBを送って」を送り、違う質問のカードを2枚出した状態で、古い方(カードA)の「確認する」を押します。
古い方のカードは、カードAの質問文「来月の有給残日数を教えてください」のまま置き換わりました。
あとから送ったカードBの質問文には、引きずられていません。
この動きを、トピックだけで作ります。
まずは、なぜこの作り方を選んだのかを説明します。
押されたら続きの処理をするとき、値をどこに持っておくか
ボタンが押されてから処理を続けるには、押されるまで、質問文などの値をどこかに持っておく必要があります。
筆者がまず考えたのは、次の2つの作り方です。
ただし、どちらにも弱いところがあります。
「アダプティブ カードで質問する」ノードで返事を待つ
1つ目は、「アダプティブ カードで質問する」ノードでカードを出し、押されるまでトピックを止めて待つ作り方です。
待っている間は同じトピックの中にいるので、値はトピック変数のまま使えます。
気になるのは、ボタンを押す前に、利用者が別の質問を入力したときです。
どうなるかは、ノードのプロパティにある、別のトピックへの切り替えを許可するかどうかの設定で変わります(Ask with Adaptive Cards)。
- 許可する(既定):
別の質問に答えるトピックに切り替わり、そのトピックが終わると、同じカードがもう一度送られます。 - 許可しない:
別の質問は、カードへの正しい返事ではないとみなされ、カードが送り直されます(既定では最大2回)。
どちらの場合も、利用者から見ると「さっきのカードがまた出てきた」という動きになり、戸惑いやすくなります。
待たずに終え、押されたら別のトピックで受ける
2つ目は、カードを出したらトピックを終え、ボタンが押されたら別のトピックで受ける作り方です。
トピックが終わるとトピック変数は消えるので、値はグローバル変数に入れて持ち越します。
グローバル変数は、1つの名前に1つの値しか持てません。
押される前に別の質問が来てカードがもう1枚出ると、変数は新しい質問の値で上書きされます。
その状態で古いカードのボタンを押すと、新しい質問の値で処理が進んでしまう恐れがあります。
会話をリセットすると変数は消えるので、リセット後に古いカードを押されたときの手当ても必要です。
さらに、カードのボタンは、押したあとも押せる状態で残ります。
公式ドキュメントにも、次のように書かれています(Ask with Adaptive Cards)。
By design, Adaptive Cards allow selecting their submit buttons multiple times.
(アダプティブ カードは、設計上、送信ボタンを何度でも選択できます。)
二度押しや、古いカードを押されたときに備える処理も、別に作らなければなりません。
カードに値を持たせれば、持ち越しが要らない
そこで、ほかに良い方法がないか調べたところ、カードのボタンそのものに値を入れておけることが分かりました。
こちらの方法なら、値を変数で持ち越す必要がありません。
今回は、こちらの方法を検証しました。
先の2つの作り方と比べると、次のようになります。
| 作り方 | 値の置き場所 | 気になる点 |
|---|---|---|
| 返事を待つ | トピック変数 | 別の質問をはさむと、設定に応じてカードが再び送られる |
| 別のトピックで受ける | グローバル変数 | 値は1つだけで、上書きやリセットで消える。二度押しへの備えも要る |
| カードに値を埋め込む | カードのボタン | カードごとに値を持つ。押したカードは置き換えてボタンを消せる |
では、ボタンに値を持たせる仕組みは、公式にどう定められているのでしょうか。次の節で確認します。
カードのボタンには、値を隠して持たせられる
カードのボタンを Action.Execute で作ると、ボタンに値を隠して持たせ、押されたときにその値を受け取れます。
Action.Execute は、押されるとエージェントに通知を送るボタンの種類です。
Action.Execute の data プロパティ(ボタンに持たせる値を書く項目)について、Adaptive Cards の公式ドキュメントは次のように説明しています(Universal Action Model)。
Initial data that input fields will be combined with. These are essentially 'hidden' properties.
(入力欄の値と組み合わされる初期データです。実質的には「隠し」プロパティです。)
ボタンが押されると、Teams はエージェントに Invoke(画面には表示されない、ボタンが押されたことを知らせる通知)を送ります。
この Invoke には、押されたボタンの定義の写しが入っています(Universal Action Model)。
A copy of the action as defined in the Adaptive Card. Like with Action.Submit, the data property of the action includes the values of the various inputs in the card, if there are any
(アダプティブ カードで定義されたアクションの写しです。Action.Submit(従来の送信ボタン)と同様に、アクションの data プロパティには、カードに入力欄があればその値も含まれます。)
つまり、カードを送るときにボタンの data に入れた値は、押されたときにエージェントに戻ってきます。
Copilot Studio では、この Invoke をトピックで受け、Invoke 応答(Teams に返す返事)を返せます(Send an event or activity)。
Invoke and Invoke response are used for Microsoft Teams. You create a topic with an invoke trigger to intercept an incoming Invoke from Teams, and use an Invoke response activity node to send an appropriate response back to Teams.
(Invoke と Invoke 応答は Microsoft Teams で使います。Teams から届く Invoke を受け取るには、Invoke のトリガーを持つトピックを作り、Invoke 応答のアクティビティノードで、適切な応答を Teams に返します。)
Invoke 応答にカードを入れて返すと、押されたカードが、返したカードに置き換わります(Sequential Workflows)。
ここまでをまとめると、作るものはトピック2つです。
- カードを送るトピック:ボタンの data に、押されたときに使う値を入れる
- Invoke を受けるトピック:data から値を取り出し、Invoke 応答でカードを置き換える
次の節から、筆者が検証用のエージェントで動かした YAML(トピックの中身を文字で書き表した形式)から要点を抜き出し、一部を簡略化して、順に作り方を紹介します。
手順1:ボタンに値を埋め込んでカードを送る
カードを送るトピックでは、ボタンの data に、押されたときに使いたい値を入れておきます。
検証では、「カードAを送って」「カードBを送って」と入力すると、それぞれ別のダミーの質問文を Topic.Question に入れて、カードを送るトピックを作りました。
質問文を2種類にしたのは、あとで「違う質問のカードが2枚あるとき」を確かめるためです。
カードを送るノードの YAML は、次のとおりです(カードの本文は「ご質問」の行だけ残しています)。
押さえておきたいのは、次の2点です。
- cardContent(カードの中身を書く項目)を「=」で始めると、カードを Power Fx の数式として書けます。
YAML で「=」から書き始めるのは、Power Fx の式であることを示す決まりです(Power Fx YAML formula grammar)。
数式で書くと、トピックの変数(ここでは Topic.Question)をカードに入れられます(Ask with Adaptive Cards)。 - verb は、Action.Execute に用意されている、どのボタンが押されたかを見分けるための項目です。
値(ここでは cardDemo_yes と cardDemo_no)は、自由に決められます(Action.Execute)。
data には、押されたときに使う値を入れます。
このノードで、完成イメージの最初のカードが届きます。
カードに見えている「ご質問」は、本文に表示しているだけです。
値が埋め込まれているのは、画面には見えないボタンの data のほうです。
「確認する」を押すと、次の手順2で作るトピックが動きます。
手順2:「呼び出された時」トリガーで、押されたボタンの値を取り出す
ボタンが押されたときに届く Invoke は、「呼び出された時」トリガーのトピックで受けます。
このトリガーは、公式ドキュメントでは「It's invoked」(呼び出されたとき)と記載されています(Set topic triggers)。
Fires when an invoke activity is received. Most commonly received from the Teams channel—for example, when the user interacts with a message or search extension in Teams.
(Invoke アクティビティを受け取ったときに発動します。最もよく届くのは Teams チャネルからで、たとえば利用者が Teams のメッセージ拡張や検索拡張を操作したときです。)
引用のとおり、Invoke はカードのボタン以外の操作でも届きます。
そのため、トリガーの条件で verb を見て、手順1のカードのボタンが押されたときだけ動くようにします。
トピックの前半の YAML は次のとおりです。
押されたボタンの値は、届いた Invoke の中身が入るシステム変数 System.Activity.Value の、action.data の下にあります。
手順1で data に q という名前で入れた質問文は、System.Activity.Value.action.data.q で取り出せます。
取り出した値は、Text()(値を文字列に変える関数)で文字列にしてから使っています。
同じトピックを画面で開くと、次のようになります。
トリガーは「呼び出された時」で、そのあとに値を取り出すノードが2つ並びます。
ここで取り出した値は、カードを送ったときのトピック変数とは関係がありません。
カードを送ったトピックはすでに終わっていて、その変数は残っていないからです。
手がかりは、押されたボタンが持っていた data だけです。
では、取り出した値を使って、押されたカードをどう書き換えるのでしょうか。次の節で紹介します。
手順3:Invoke 応答で、押したカードを置き換える
値を取り出したら、Invoke 応答で新しいカードを返し、押されたカードを置き換えます。
置き換えたカードにボタンを付けなければ、同じカードを二度押されることはありません。
Invoke 応答の中身の形は、Adaptive Cards の公式ドキュメントで決められています(Universal Action Model)。
statusCode に 200(成功の意味)、type に application/vnd.microsoft.card.adaptive(返す中身がアダプティブ カードであることを示す値)を入れ、value に新しいカードを入れます。
この組み合わせについて、公式ドキュメントの表では次のように説明されています。
The request was successfully processed, and the response includes an Adaptive Card that the client should display in place of the current one.
(要求は正常に処理されました。応答には、クライアント(ここでは Teams)が現在のカードの代わりに表示すべきアダプティブ カードが含まれています。)
押されたボタンが「確認する」のときの YAML は、次のとおりです(置き換えるカードの本文は一部を省いています)。
「確認しない」のときは、本文を「確認は行いませんでした。」に変えた同じ形のノードを、もう1つの条件の下に置いています。
value が2重になっているのは、外側の status と body が、Teams に返す HTTP 応答(Teams からの呼び出しに対する返事)のステータスコード(処理の結果を表す番号で、200 は成功)と本文にあたるためです。
Universal Action Model にも、ボットの HTTP 応答について次のように書かれています(Universal Action Model)。
[...] the HTTP response's status code returned by the Bot must be equal to 200 and the body of the HTTP response must be formatted as follows
([…] ボットが返す HTTP 応答のステータスコードは 200 で、HTTP 応答の本文は次の形にしなければなりません。)
Copilot Studio のドキュメントには、Invoke 応答のノードにこの形を書いた例は見つかりませんでした。
今回は、Bot Framework(Microsoft のボットを作るための仕組み)で Invoke に返す応答の形(InvokeResponse Class)に合わせて書き、Teams でカードが置き換わることを確認しました。
同じ部分を画面で開くと、条件ごとに置き換えのノードが並び、「種類」が「応答の呼び出し」になっています。
Teams で「確認する」を押すと、完成イメージのとおり、カードがその場で「受け付けました。」に置き換わり、送信者名の横に「更新済み」と表示されます。
「確認しない」を押した場合は、「確認は行いませんでした。」に置き換わります。
どちらのカードにも、埋め込んだ質問文が「ご質問」として出ています。
この「ご質問」は、手順2で data から取り出した値です。
検証用のエージェントでは置き換えだけにしていますが、実際には、このあとに取り出した値を使う処理(フローの呼び出しなど)を続けます。
ほかの場面でも、押したカードの値で処理が続くかを確かめる
完成イメージでは、違う質問のカードが2枚ある場面を紹介しました。
ほかにも、変数で持ち越す作り方では崩れやすい場面を2つ試し、どちらも押したカードの値で処理が続きました。
場面ごとに、押す前(赤枠が押したボタン)と押したあとの画面を並べます。
カードを出したあと、別の発話をはさんでから押す
「カードAを送って」でカードを出したあと、ボタンを押さずに「こんにちは」と入力しました。
エージェントがあいさつを返したあとで、上に残っている古いカードの「確認する」を押します。
押したあとの画面です。
「こんにちは」より前のカードが「受け付けました。」に置き換わり、「ご質問」にはカードAの質問文が出ています。
同じ質問のカードが2枚あるとき、古い方を押す
「カードAを送って」を2回続けて送り、同じ質問のカードを2枚出しました。
この状態で、古い方の「確認する」を押します。
押したあとの画面です。
置き換わったのは古い方の1枚だけで、新しい方はボタンが付いたカードのまま残っています。
実装するときの注意点
作るときに気を付けたい点を、2つ挙げます。
Action.Execute に対応したチャネルで確かめる
Action.Execute は、すべてのチャネルで使えるわけではありません。
公式ドキュメントでは、Web サイトへの埋め込みに使う Web Chat が Action.Execute に対応していないこと、Teams ではカードのバージョンが 1.5 までであることが書かれています(Ask with Adaptive Cards)。
The Bot Framework Web Chat component (that is, the default website integration pattern) supports version 1.6 but doesn't support Action.Execute [...] Teams is also limited to version 1.5
(Bot Framework の Web Chat コンポーネント、つまり既定の Web サイト埋め込みは、バージョン 1.6 に対応していますが、Action.Execute には対応していません。[…] Teams もバージョン 1.5 までに限られます。)
筆者は、エージェントを Teams に公開して動きを確かめました。
Teams 以外のチャネルで使う場合は、Action.Execute に対応しているかを事前にご確認ください。
埋め込んだ値は、利用者の手元に届く
data は画面に表示されないだけで、カードの一部として Teams に届きます。
利用者に見せてはいけない値は、data に入れないでください。
また、data もメッセージの一部なので、Teams のメッセージの上限(約 100 KB)に含まれます(Send and receive messages)。
長い本文を埋め込む場合は、カード全体の大きさにご注意ください。
よくある質問
Q. ボタンに埋め込んだ値は、どうやって取り出しますか?
「呼び出された時」トリガーのトピックで、System.Activity.Value.action.data の下から取り出します。
data に q という名前で入れた値なら、System.Activity.Value.action.data.q です。
筆者は Text() で文字列にしてから使い、Teams で動くことを確認しました。
Q. 押したあとのカードのボタンを消すには、どうすればよいですか?
Invoke 応答で、statusCode に 200、type に application/vnd.microsoft.card.adaptive、value に新しいカードを入れて返します。
公式ドキュメントでは、現在のカードの代わりに表示するカードとして説明されています(Universal Action Model)。
新しいカードにボタンを付けなければ、置き換えたあとは押せなくなります。
Q. 古いカードを後から押されても、正しく動きますか?
Teams での検証では、別の発話をはさんでから押した場合、同じ質問のカードが2枚ある場合、違う質問のカードが2枚ある場合のいずれも、押したカードの値で処理が続きました。
値をカードごとにボタンに持たせているため、あとから送ったカードの値に引きずられません。
Q. Action.Execute のカードは、どのチャネルで使えますか?
公式ドキュメントでは、Web サイトへの埋め込みに使う Web Chat は Action.Execute に対応しておらず、Teams はカードのバージョン 1.5 までと書かれています(Ask with Adaptive Cards)。
筆者は Teams に公開して動きを確かめました。
Teams 以外のチャネルで使う場合は、事前に対応をご確認ください。
Q. ボタンに埋め込んだ値は、利用者から見えますか?
data は画面には表示されませんが、カードの一部として Teams に届きます。
利用者に見せてはいけない値は、data に入れないでください。
まとめ:値はカードに持たせ、押したカードは置き換える
この記事では、カードのボタンに値を埋め込み、押されたときに取り出して処理を続ける方法を紹介しました。
学びは3つです。
- ボタンの中に入れた値は、押されたときに戻ってくる:
カードのボタンには、画面に表示されない値を持たせられます。
押されるとその値がエージェントに届くので、押されるまで変数で値を持っておく必要はありません。 - 押されたことは「呼び出された時」トリガーで受け取る:
ボタンに付けた名前をトリガーの条件で確かめれば、目的のボタンが押されたときだけトピックが動きます。
届いた値は、このトピックの中で取り出して使います。 - 押したカードは、結果を表示するカードに置き換えられる:
ボタンのないカードに置き換えれば、二度押しや、古いカードの押下に備える処理が要らなくなります。
変数の持ち越しや二度押しへの備えに手間をかけていた方は、まず確認ボタン1つから、カードに値を持たせる形に置き換えてみてはいかがでしょうか。
押したらボタンが消えて結果が残るので、利用者にとっても迷わないエージェントになるはずです。
QUICK E-Solutionsでは、Copilot Studio / Power Platform 環境のセキュリティ・ガバナンス設計から、エージェント開発のPoC・本番構築、運用・継続改善まで一貫して支援しています。
以下のリンクからご提供しているサービスの詳細をご確認いただけます。
※このブログで参照されている、Copilot Studio、Teams、Power Fxは、米国Microsoft Corporationの米国およびその他の国における商標または登録商標です。

