
把昨天那條流程複製一份,出口從信改成 Teams 頻道的 adaptive card。指令書只改了一段,plugin 照做了,執行紀錄是綠的。
頻道上那張卡片,標題和日期都在,摘要那一格是空的,下半部整個不見。
原因是我貼進去的摘要裡有一個半形雙引號。那段卡片 JSON 被切成兩半,Teams 收到一段不完整的結構,把畫得出來的部分畫出來,其餘的安靜丟掉。沒有錯誤訊息,沒有紅色驚嘆號,動作那一格也是成功。
信件內文是一串字,卡片是一份必須合法的結構。這是換出口的第一個代價。
昨天那條流程把信寄到一個固定信箱。今天的目標跟昨天完全一樣,還是讓值班的人早上知道昨天出了什麼事。
改的是昨天結尾那個問題暴露出來的東西:值班的人是一個角色,不是一個信箱。
所以今天動的不是能力,是出口指向的對象。改完之後這條流程能做的事一模一樣,它服務的東西卻從一個人變成一個位置。拿掉這次改動會怎樣?換班那天,信準時寄給上一個人,而流程一樣是綠的。
| 寄到收件匣 | 貼到頻道 | |
|---|---|---|
| 看得到的人 | 收件者自己 | 頻道裡所有人,而且留在原地 |
| 沒發生的時候 | 沒有人察覺 | 今天那張卡片沒出現,有人會問 |
| 內容出錯 | 一對一更正 | 更正也要在同一個地方進行 |
| 後續動作 | 回信,脫離原本的上下文 | 就在卡片底下接著討論 |
第二列才是真正的轉折。出口搬到頻道之後,這條流程的可靠度從私事變成公開的事。
這對你不見得是壞消息。一條流程如果沒有人看得見它有沒有跑,壞掉那天不會有任何人告訴你;而一條每天早上該出現在頻道裡的卡片,缺席一次就有人會問。今天換來的監控機制不在系統裡,在那些會抬頭找它的人身上。
代價是同一件事的反面:它壞掉的那一天,全部門都看到了。
Adaptive Card 是 JSON,所以這一天出現一個前面沒有的分工,哪些是資料、哪些是版面。兩者一旦混在同一段字串裡,開頭那個引號事故就會反覆發生。
還有一個官方寫死的限制值得單獨記住:Power Automate 不支援 Adaptive Card 的 templating 功能。 也就是 ${} 那一套資料繫結語法在這裡不會運作。卡片的值只能由流程在執行時把運算式的結果組進 JSON,而組字串這件事,就是需要處理跳脫字元的地方。
於是驗收條件多了一條,而且它沒辦法從執行紀錄上看出來:卡片要在 Teams 裡真的畫出來,不只是動作回報成功。
順帶一提,今天介面與 plugin 的差距是這四天裡最小的。卡片 JSON 在介面裡是貼一大段文字進欄位,用 plugin 也是把同一段文字放進指令書。當一個決定的全部內容都已經寫成結構化的文字,用哪一種方式建它就沒有差別。值得記住的是反面:差別總是出現在還沒被寫下來的那些地方,就像昨天那個內文格式的參數。
最省事的一句是這個:
把昨天那條流程的寄信改成發到 Teams 頻道,用 adaptive card。
改得掉,也會成功。而你的摘要裡遲早會出現一個引號、一個換行,或一個剛好長得像跳脫序列的字串。
下面三段依序跑。第二段會故意把它弄壞。
第一段:出口換成卡片
我要在 Power Automate 建一條流程,請使用 Power Automate plugin 執行。
在你開始建立之前,先把【建立前的回報】做完,我確認之後你才動手。
【環境】
環境名稱:<填入你的環境顯示名稱>
流程名稱:Day18-手動觸發-值班摘要發卡片
建立後保持停用狀態,不要自行啟用。
【觸發程序】
與 Day17-手動觸發-值班摘要寄信 完全相同:
Manually trigger a flow,三個輸入欄位 ReportDate(Text)、
FailedJobCount(Number)、Summary(Text)。
【動作】
只建立一個動作:Microsoft Teams 的
「Post adaptive card in a chat or channel」。
- Post as:Flow bot
- Post in:Channel
- Team/Channel:我會在對話中回答,先問我,不要自行挑選
- Adaptive Card:使用下面這段 JSON
{
"type": "AdaptiveCard",
"$schema": "<http://adaptivecards.io/schemas/adaptive-card.json>",
"version": "1.4",
"body": [
{ "type": "TextBlock", "text": "值班摘要", "weight": "Bolder", "size": "Medium" },
{ "type": "TextBlock", "text": "__REPORT_DATE__", "spacing": "None", "isSubtle": true },
{ "type": "FactSet", "facts": [
{ "title": "未完成作業", "value": "__FAILED_COUNT__" }
]},
{ "type": "TextBlock", "text": "__SUMMARY__", "wrap": true }
]
}
【值的注入方式】
- __REPORT_DATE__、__FAILED_COUNT__、__SUMMARY__ 三個佔位符,
必須由流程在執行時以觸發程序的對應輸入值取代
- 不要改用 Adaptive Card templating 的 ${} 語法,
Power Automate 不支援該功能
- Summary 的值可能包含半形雙引號、反斜線與換行。
請確保注入之後整段仍然是合法 JSON,並說明你用什麼方式處理
【不要做的事】
- 不要加入我沒有列出的動作、條件、變數或迴圈
- 不要修改上面那段卡片 JSON 的結構或欄位
- 不要自行選擇 Team 或 Channel
【建立前的回報】
1. 你打算使用的動作正式名稱,以及它與其他相似動作的差別
2. 需要哪些連線,目前有沒有可用的連線
3. 你打算怎麼處理 Summary 裡的雙引號與換行,寫出實際的運算式
4. 我沒有明講、但你必須自己決定才能建起來的每一項,逐項列出
第 1 項值得看一下它怎麼答。Teams 連接器裡投遞卡片的動作不只一個,有貼到頻道的、貼給個人的、貼完等回應的,而它們的參數與後續行為都不同。這是昨天那個下拉選單的老問題換一個位置出現:你講的那句「發到 Teams」,對應到好幾個不同的動作。
第 3 項是這一天唯一真正的技術內容,把它的答案抄下來,因為那是後面所有「把值組進結構」的通用作法。
第二段:故意把它弄壞
流程已經建好,我要用一組會造成問題的輸入跑一次。
ReportDate:2026-10-02
FailedJobCount:3
Summary:
批次 A "逾時" 未完成
批次 B 連線中斷,已重試 2 次
路徑 D:\jobs\nightly 權限不足
請先不要修改流程。先回答:
1. 這組輸入送進去之後,卡片 JSON 會變成什麼樣子?
把實際會產生的字串寫出來。
2. 這段字串是合法 JSON 嗎?如果不是,第一個出錯的位置在哪裡?
3. 這種情況下,Power Automate 的執行紀錄會顯示成功還是失敗?
Teams 那邊會看到什麼?
三題回答完之後,再實際執行一次,把實際結果跟你的預測對照。
不一致的地方直接說不一致,不要事後修正你的預測。
第 3 題是這一天要停下來的地方。一個「動作成功、結果不對」的狀態,執行紀錄上看不出任何異常,而這一格不是 Teams 的問題,也不是 plugin 的問題,所有把值組進結構的場景都有這個性質。
昨天那封信至少還到了你自己的信箱,你看得到它長得不對。今天這張卡片貼在頻道上,而看到它殘缺的是別人。
第三段:用 plugin 查一次
請對這條流程最近一次的執行做一次 debug,
輸出下列內容,不要直接修改流程:
1. 每一個動作的狀態、輸入與輸出
2. 傳給 Teams 的 Adaptive Card 參數的實際內容,要完整字串
3. 這次執行從 Power Automate 的角度看是成功還是失敗,依據是什麼
第 3 題回答完之後,再告訴我:如果我想知道「卡片有沒有正確渲染」,
在目前這條流程裡有沒有任何一個地方看得到?沒有就說沒有。
最後那一問的答案是沒有。Power Automate 能告訴你的最後一件事,是它把那段字串交給 Teams 了。字串到了對面被怎麼處理,這條流程看不到,也不會有人通知它。
這兩天的流程都要有人按。按的那個人現在是我,而且要在對的時間、帶著對的資料按下去。
真正每天早上知道昨天哪些作業沒跑完的,是那台排程主機,不是我。
一條需要人記得按的流程,它的可靠度上限就是那個人記得的機率。

iThome鐵人賽