iT邦幫忙

2025 iThome 鐵人賽

DAY 12
0
生成式 AI

打造基於 MCP 協議與 n8n 工作流的會議處理 Agent系列 第 12

Day 12 系統可靠性升級 - 錯誤處理與狀態回報

  • 分享至 

  • xImage
  •  

昨天我們的 Agent 學會了辨識「會議類型」、「專案名稱」與專案關聯,但一個穩定可靠的系統,不只要能在順利時完美運作,更要在發生意外時能有條理的處理失敗。
今天的目標是為我們的 MCP Agent 建立錯誤處理與狀態回報機制,讓它變得更加「可靠」。

今天的目標與挑戰

  • 在 Notion 新增「錯誤訊息」欄位
  • 在流程開始時就建立記錄並且更新狀態為「處理中」
  • 建立一個獨立的「錯誤處理」工作流,使用 Error Trigger 節點統一捕獲異常
  • 當錯誤發生時,建立錯誤紀錄,並詳細記錄錯誤原因
  • 透過 LINE 發送執行紀錄ID與錯誤紀錄頁面連結的通知,加速問題排查

為什麼需要錯誤處理機制?

如果沒有錯誤處理,流程會直接中斷,我們不僅無法得知任務失敗,也不知道問題出在哪裡,因此一個好的錯誤處理機制能帶來四大好處

  1. 可靠性:系統不會因單點故障而完全崩潰,而是能捕獲異常並執行備用路徑
  2. 可觀測性:當問題發生時,我們能清楚知道是哪個環節、因為什麼原因失敗
  3. 除錯效率:詳細的錯誤通知能讓我們立即定位問題,大幅縮短修復時間
  4. 使用者體驗:系統會明確回報「成功」或「失敗」,而不是讓使用者無限等待或困惑

Step 1:更新 Notion 資料庫結構

需要先為「會議記錄」的資料庫增加欄位,用來追蹤每一次處理的狀態與結果。

1-1 更新與新增欄位

進入「會議記錄」資料庫,新增以下欄位,若已有則不用

  1. 摘要狀態
    • 屬性:狀態 (Status)
    • 選項:待處理錯誤處理中已完成
    • 用途:即時反應每次會議摘要處理的當前階段。
  2. 錯誤訊息
    • 屬性:文字 (Text)
    • 用途:當處理失敗時,用來儲存詳細的錯誤資訊。

Step 2:重構主流程,提前建立 Notion 頁面

因為要在流程的一開始就追蹤狀態,因此我們需要調整 n8n 工作流的順序,概念想法是建立空的記錄,更新完整內容。

2-1 在 Webhook 後新增「建立初始會議記錄」節點

  1. 在「Webhook」節點後方,新增一個 Notion 節點。
  2. Display Name建立初始會議記錄
  3. ActionCreate a Database Page
  4. Database會議記錄
  5. TitleAI會議摘要 {{ new Date().toLocaleDateString('zh-TW') }}
  6. Properties 中,設定以下欄位
    • Key Name or IDSession ID
      • Text{{ $('Webhook').item.json.body.session_id }}
    • Key Name or ID摘要狀態
      • Status摘要生成中

2-2 新增 Edit Fields 節點,保存 Page ID

為了讓後續的節點(包括錯誤流程)知道要更新哪一筆「會議記錄」,我們需要將剛剛建立的 Page ID 保存下來。

  1. 在「建立初始會議記錄」節點後方,新增一個 Edit Fields 節點
  2. Display Name保存 Page ID
  3. ModeManual Mapping
  4. Fields to Set
    • namepageID
    • value{{ $('建立初始會議記錄').first().json.id }}

這樣設定之後,這個 「Edit Fields」 節點就會將 Notion Page ID 成功地加入到工作流的資料中,方便後續所有節點取用。

2-3 修改原有的「寫入會議紀錄」節點

我們在流程開始時建立了初始記錄,現在需要在流程的尾端,將 AI 處理好的完整資料更新回剛剛建立的初始記錄欄位裡。

由於 If 節點會讓資料流產生分岔,我們需要分別處理 TrueFalse 兩條路徑。

處理 True 分支 (成功匹配到專案)

當成功匹配到專案時,已經經過了許多的節點,因此會導致「專案查詢」的輸出結果,會沒有我們之前保存的 pageID

為了解決這個問題,我們需要使用 Merge 節點,將「專案查詢」的結果和我們需要的 pageID 重新合併在一起。

  1. 新增 「Merge」 節點

    • 在「專案查詢」和「寫入會議紀錄」之間,新增一個 Merge 節點。
  2. 設定 「Merge」 節點連線

    • 將「專案查詢」的輸出端,連接到 Merge 節點的 Input 1
    • 這是關鍵步驟,要從前面的「保存 Page ID 與初始資料」節點,另外拉一條輸出線,連接到 Merge 節點的 Input 2
  3. 設定 「Merge」 節點參數
    點開 「Merge」 節點的設定

    • ModeCombine
    • Combine ByPosition
      Merge Settings
  4. 修改「寫入會議紀錄」節點
    將此節點連接到 Merge 節點之後,將 OperationCreate 改為 Update

    • By ID{{ $json.pageID }} (現在可以從 Merge 節點的合併結果中取到值了!)
    • Properties 區域,點擊 Add Property,更新或新增以下所有欄位
      • 會議日期{{ DateTime.now().toISODate() }}
      • 摘要狀態已完成
      • 會議摘要{{ $('AI 摘要與任務提取').first().json.meeting_info.summary }}
      • 行動任務{{ $('AI 摘要與任務提取').first().json.meeting_info.tasks }}
      • 會議類型{{ $('AI 摘要與任務提取').item.json.meeting_info.meeting_type }}
      • Session ID{{ $('AI 摘要與任務提取').item.json.session_id }}
      • GIGI 工作室專案庫: {{ $('專案查詢').first().json.id }}

💡 n8n 偵錯技巧:解決「無法新增屬性」問題

在設定 Update 節點時,可能會遇到編輯器無法載入屬性列表(No execution data available)的問題。這是因為編輯器需要一個「範本 ID」來讀取資料庫結構。

可以使用「先寫死,再改活」的方式來解決

  • 1. 先取得真實 Page ID
    1. 先完整跑一次工作流
    2. 再到工作流上方的 Executions
    3. 找到剛剛錯誤工作流裡面的 「Merge」節點
    4. 複製 pageID
  • 2. 使用真實 Page ID 載入屬性
    1. 回到工作流上方的 Editor 的「寫入會議紀錄」節點
    2. By ID 欄位,暫時貼上剛剛複製的真實 ID
    3. 此時下方的 Properties 區域就可以正常設定了!
  • 3. 設定所有屬性
    Properties 區域,點擊 Add Property,更新或新增以下所有欄位:
    • 會議日期{{ DateTime.now().toISODate() }}
    • 摘要狀態已完成
    • 會議摘要{{ $('AI 摘要與任務提取').first().json.meeting_info.summary }}
    • 行動任務{{ $('AI 摘要與任務提取').first().json.meeting_info.tasks }}
    • 會議類型{{ $('AI 摘要與任務提取').item.json.meeting_info.meeting_type }}
    • Session ID{{ $('AI 摘要與任務提取').item.json.session_id }}
    • GIGI 工作室專案庫: {{ $('專案查詢').first().json.id }}
  • 4. 將 ID 改回動態表達式
    設定完所有屬性後,務必回到 By ID 欄位,將寫死的 ID 重新改回動態表達式 {{ $json.pageID }}

透過這樣的技巧節點就能在執行時動態接收正確的 pageID 了。

處理 False 分支 (未匹配到專案)

如同我剛剛所說的,流程已經經過了許多的節點,因此也會沒有我們之前保存的 pageID,所以我們要

  1. 複製剛剛修改好的「寫入會議紀錄」節點,並且重新命名為「寫入會議紀錄(無關聯)」
  2. 刪除「GIGI 工作室專案庫」這個關聯屬性
  3. 複製剛剛設定好的「Merge」節點
  4. 「Mergee」節點連線
    • 將「If」的 false 輸出端,連接到 Mergee 節點的 Input 1
    • 從前面的「保存 Page ID 與初始資料」節點,另外拉一條輸出線,連接到 Mergee 節點的 Input 2
  5. 將「Mergee」節點的輸出連接到「寫入會議紀錄(無關聯)」的輸入

M2A Agent WorkFlow

完成以上的修改後,工作流就能根據 AI 的判斷結果,準確地更新對應 Notion 頁面的內容與狀態了!


Step 3:建立統一的錯誤處理工作流

現在要建立一個專門處理失敗情境的獨立工作流。

3-1 建立新工作流與 Error Trigger 節點

  1. 在 n8n 主畫面,點擊 Create workflow 建立一個全新的工作流
  2. 新增「Error Trigger」節點,這個節點就是錯誤工作流的入口
  3. 儲存這個工作流,並命名為 M2A Agent Error Handler

3-2 連結主工作流與錯誤工作流

  1. 回到我們主要的 M2A Agent 工作流
  2. 點擊右上角三個點,打開選單後再點擊進入 Settings 打開工作流設定
  3. Error Workflow 的下拉選單中,選擇我們剛剛建立的 M2A Agent Error Handler
  4. 儲存設定

只要 M2A Agent 工作流中任何一個節點(Webhook 除外)執行失敗,n8n 就會自動觸發 M2A Agent Error Handler 工作流,並把錯誤相關的資料傳遞過去。


Step 4:錯誤處理的流程

回到 M2A Agent Error Handler 工作流,來實作錯誤發生時的具體動作。

4-1 Code 節點:格式化錯誤資訊

Error Trigger 傳來的資料結構比較複雜,我們先用一個 Code 節點把它整理成方便使用的格式。

  1. Error Trigger 後新增一個 Code 節點。
  2. Display Name格式化錯誤資訊
  3. JavaScript
const execution = $input.item.json.execution;
const error = $input.item.json.error;

const formattedError = {
  sessionId: `errorID_${execution?.id || 'unknown'}`,
  workflowName: $input.item.json.workflow?.name || execution?.workflow?.name || '未知工作流',
  nodeName: execution?.error?.node?.name || '未知節點',
  errorMessage: execution?.error?.message || '未知錯誤',
  notionUrl: `http://localhost:5678/workflow/Q2Kd8E56GkaFWscI/executions/${execution?.id || 'unknown'}`,
  errorType: execution?.error?.level || 'Unknown',
  timestamp: new Date().toISOString(),
  executionId: execution?.id || 'unknown-execution'
};

return [formattedError];

4-2 Notion 節點:建立錯誤記錄

在 Notion 中建立一筆詳細的錯誤記錄,方便日後追蹤和分析。

  1. 在 「Code」 節點後,新增一個 「Notion」 節點
  2. Display Name:: 建立錯誤訊息
  3. 基本設定
    • CredentialM2A Agent Notion Credential
    • ResourceDatabase Page
    • OperationCreate
    • Database會議記錄
  4. 標題設定
❌ {{ $json.workflowName }} 執行錯誤-ID#{{ $json.executionId }}
  1. 屬性設定:點擊 Add Property
    • 摘要狀態錯誤
    • Session ID{{ $json.sessionId }}
    • 錯誤訊息
    🚨 工作流執行失敗
    
    **失敗節點**: {{ $json.nodeName }}
    **錯誤類型**: {{ $json.errorType }}
    **錯誤訊息**: {{ $json.errorMessage }}
    **執行時間**: {{ $json.timestamp }}
    
    **執行記錄連結**: {{ $json.notionUrl }}
    

4-3 HTTP Request 節點:發送 LINE 通知

複製主流程中的 LINE 通知節點,並貼到此處,確保 JSON 的值設定為

{
  "messages": [
    {
      "type": "text",
      "text": "🚨 M2A Agent 處理失敗通知 🚨\n\n錯誤記錄: {{ $json.name }}\n\n查看詳情: {{ $json.url }}"
    }
  ]
}

Step 5:端到端錯誤流程驗證

現在來實際測試一下結果,需要手動製造一個錯誤。

5-1 模擬錯誤情境

  1. 回到主工作流 M2A Agent
  2. 製造一個想模擬的錯誤情況

5-2 執行測試

  1. 一樣打開 Gradio 前端介面
  2. 上傳音訊檔,輸入指令,點擊「開始處理」
  3. 這次 Gradio 介面「會議摘要」與「行動提取」都會失敗,因為我們的工作流之中有錯誤

5-3 驗證結果

  • LINE 通知: 會收到一則錯誤通知
  • Notion 頁面: 檢查「會議記錄」資料庫,會發現一筆新的記錄,其「摘要狀態」為「錯誤」,且「錯誤訊息」欄位寫滿了詳細的錯誤原因。
  • n8n 後台: 檢查 M2A Agent 工作流的 Executions,會看到一筆失敗的記錄。再檢查 M2A Agent Error HandlerExecutions,會看到一筆成功的記錄。

5-4 復原

測試完成後,請務必記得要復原。


今天的成果總結

完成項目

  • 在 Notion 中建立了狀態追蹤機制 (待處理錯誤處理中已完成
  • 重構了主工作流,實現了「先建立,後更新」的模式
  • 利用 Error Trigger 建立了可重複使用的集中式錯誤處理工作流
  • 實現了失敗時建立新的錯誤欄位並記錄詳細錯誤資訊
  • LINE 錯誤告警,實現了故障發現能力

心得

今天透過建立獨立的錯誤處理工作流,將「成功路徑」與「失敗路徑」分離,實現了軟體工程中一個非常重要的概念,我的主工作流簡潔,只專注於核心業務,而所有的異常處理邏輯則被集中管理,不僅提高了可靠性,也讓未來的維護和擴充變得更加容易。

🎯 明天計劃
從會議對話中自動辨識「參與夥伴」,並與 Notion 使用者資料庫進行匹配,實現會議記錄的智慧標記與歸檔。


上一篇
Day 11 智慧會議辨識類型與專案關聯
下一篇
Day 13 Prompt 架構升級 — 智慧日期解析與模組化設計
系列文
打造基於 MCP 協議與 n8n 工作流的會議處理 Agent17
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言