昨天完成了 n8n 工作流程的 JSON 處理與穩定性完善,今天要先將 AI 生成的會議摘要和任務清單整合到 Notion 資料庫中。
先在 Notion 中建立主頁面,並設定部門結構
在主頁面中建立整頁資料庫,並且命名為「GIGI 工作室專案庫」
欄位名稱 | 欄位類型 | 建立步驟 | 設定說明 |
---|---|---|---|
專案名稱 | 標題 (Title) |
預設欄位,重新命名 | 資料庫主欄位 |
狀態 | 狀態 (Status) |
新增屬性 → 狀態 | 選項:「提案中」、「規劃中」、「執行中」、「待驗收」、「已完成」 |
專案負責人 | 人員 (Person) |
新增屬性 → 人員 | 可指派單一負責人 |
主責團隊 | 多選 (Multi-select) |
新增屬性 → 多選 | 選項:「內容創意組」、「營運支援組」、「技術開發組」 |
時程 | 日期 (Date) |
新增屬性 → 日期 | 啟用日期範圍,設定開始與結束日期 |
重要級別 | 選取 (Select) |
新增屬性 → 選取 | 選項:「High」、「Medium」、「Low」 |
專案目標 | 文字 (Text) |
新增屬性 → 文字 | 長文字模式 |
交付成果 | 文字 (Text) |
新增屬性 → 文字 | 長文字模式 |
相關會議 | 關聯 (Relation) |
新增屬性 → 關聯 | 稍後會設定,待會議資料庫建立完成 |
專案資源 | 檔案與媒體 (Files & media) |
新增屬性 → 檔案與媒體 | 可上傳多個檔案 |
在子頁面「技術開發組」中建立整頁資料庫,並且命名為「會議記錄」
欄位名稱 | 欄位類型 | 建立步驟 | 設定說明 |
---|---|---|---|
會議主題 | 標題 (Title) |
預設欄位,重新命名 | 資料庫主欄位 |
會議日期 | 日期 (Date) |
新增屬性 → 日期 | 僅日期,不含時間 |
會議類型 | 多選 (Multi-select) |
新增屬性 → 多選 | 選項:「團隊同步」、「專案討論」、「創意發想」、「決策會議」 |
參與夥伴 | 人員 (Person) |
新增屬性 → 人員 | 可選擇多人 |
討論專案 | 關聯 (Relation) |
新增屬性 → 關聯 | 關聯到「GIGI 工作室專案庫」 |
摘要狀態 | 狀態 (Status) |
新增屬性 → 狀態 | 選項:「待處理」、「摘要生成中」、「已完成」 |
會議摘要 | 文字 (Text) |
新增屬性 → 文字 | 長文字模式,AI 生成內容 |
重要結論 | 文字 (Text) |
新增屬性 → 文字 | 長文字模式 |
行動任務 | 文字 (Text) |
新增屬性 → 文字 | 長文字模式,AI 提取內容 |
任務指派 | 人員 (Person) |
新增屬性 → 人員 | 可指派多人 |
完成期限 | 日期 (Date) |
新增屬性 → 日期 | 僅日期 |
會議附件 | 檔案與媒體 (Files & media) |
新增屬性 → 檔案與媒體 | 可上傳多個檔案 |
錄音檔案連結 | 連結 (URL) |
新增屬性 → 連結 | 雲端錄音檔連結 |
建立時間 | 建立時間 (Created time) |
新增屬性 → 建立時間 | 系統自動產生 |
M2A Agent
剛建立的 M2A Agent
預設無法存取任何頁面,必須手動授權
M2A Agent
,點擊「確認」。剛建立的 Integration 可能不會馬上出現在搜尋列表中,請多嘗試重新整理頁面 (
Ctrl+R
)
在 n8n 裡點擊左上角的加號「+」,再點擊「Credentials」。
搜尋並選擇「Notion API」。
填寫認證資訊:
M2A Agent Notion Credential
點擊「Save」儲存,儲存的同時,n8n 也會自動幫你確認連線
回到 M2A Agent
工作流
Create a database page
。M2A Agent Notion Credential
。AI會議摘要 {{ new Date().toLocaleDateString('zh-TW') }}
{{ new Date().toISOString().split('T')[0] }}
{{ $('AI 摘要與任務提取').item.json.summary }}
修改「Respond to Webhook」節點的 JSON 回應
{
"ai_processing": {
"status": "success",
"summary": {{ JSON.stringify($('AI 摘要與任務提取').item.json.summary) }},
"tasks": {{ JSON.stringify($('AI 摘要與任務提取').item.json.tasks) }}
},
"notion_storage": {
"status": "success",
"message": "會議記錄已成功寫入 Notion",
"notion_page_url": {{ JSON.stringify($json.url) }}
}
}
建立測試檔案 test_notion_integration.py
import os
from src.mcp_agent import MCPAgent
def main():
audio_file_path = "recording/技術開發組會議錄音檔.mp3"
webhook_url = "http://localhost:5678/webhook/m2a-test"
if not os.path.exists(audio_file_path):
print(f"錯誤:找不到指定的錄音檔案:{audio_file_path}")
return
agent = MCPAgent(model_name="medium", webhook_url=webhook_url)
instruction = "請整理這次會議的重點,並列出所有待辦事項以及負責人與截止日期。"
print(f"正在處理的檔案:{audio_file_path}")
print(f"使用的指令:{instruction}")
# 執行音訊處理
result = agent.process_audio(audio_file_path, instruction)
print("最終結果:", result)
if __name__ == "__main__":
main()
python test_notion_integration.py
成功結果
最終結果: {'ai_processing': {'status': 'success', 'summary': '這次會議主要討論了幾個項目:\n\n1. **使用者認證系統**:需要在週五前完成 JWT 的整合,確保 API 安全。\n2. ** 環境配置**:志明負責將 Flask 應用程式 Dark 化,並準備相應的配置檔案(DarkField 和 DarkCompose.yml),要求在週三前完成。\n3. **錯誤處理機制**:小美需研究並解決上次的 Timeout 問題,特別是 M8n 的錯誤處理機制。\n4. **工作流設計**:小美負責設計 M8n 的工作流,並在週四前完成可運作的 Webflow,進行團隊測試。同時,她還需開始規劃晚上的客製化規則以監環境配置**:志明負責將 Flask 應用程式 Dark 化,並準備相應的配置檔案(DarkField 和 DarkCompose.yml),要求在週三前完成。\n3. **錯誤處理機制**:小美需研究並解決上次的 Timeout 問題,特別是 M8n 的錯誤處理機制。\n4. **工作流設計**:小美負責設計 M8n 的工作流,並在週四前完成可運作的 Webflow,進行團隊測試。同時,她還需開始規劃晚上的客製化規則以監控非預期的 API 呼叫。\n5. **系統壓力測試**:志明和小美需準備並提交後端 API 和 M8n 的壓力測試腳本,並在週五下午三點前推上 GitHub。這樣可以在週末進行完整的整合測試。\n\n會 議結束時,確認沒有其他問題,並強調了各項任務的截止時間及責任分配。', 'tasks': '行動項目與待辦事項:\n\n1. **使用者認證系統**\n - 在週五前完成 JWT 的整合,確保 API 安全 。\n \n2. **環境配置**\n - 志明負責將 Flask 應用程式 Dark 化,並準備相應的配置檔案(DarkField 和 DarkCompose.yml)。\n - 要求在週三前完成。\n\n3. **錯誤處理機制**\n - 小美需研究並解決上次的 Timeout 問題,特別是 M8n 的錯誤處理機制。\n\n4. **工作流設計**\n - 小美負責設計 M8n 的工作流,並在週四前完成可運作的 Webflow,進行團隊測試。\n - 同時開始規劃晚上的客製化規則以監控非預期的 API 呼叫。\n\n5. **系統壓力測試**\n - 志明和小美需準備並提交後端 API 和 M8n 的壓力測試腳本,並在週五下午三點前推上 GitHub。\n - 在週末進行完整的整合測試。'}, 'notion_storage': {'status': 'success', 'message': '會議記錄已成功寫入 Notion', 'notion_page_url': 'https://www.notion.so/'}}
我自己測試的時候,我遇到了兩個關鍵的失敗。
"timeout of 120000ms exceeded"
,但是後面的 Notion 節點卻成功的寫入了這個錯誤訊息。catch
區塊回傳錯誤,後面的節點也算是成功接收了這個「錯誤的資訊」。const response = await this.helpers.httpRequest({
method: 'POST',
url: 'http://host.docker.internal:1234/v1/chat/completions',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(taskPayload),
timeout: 300000
});
我自己的測試裡,我有加一個「Notion寫入結果驗證」的 Code 節點。
"Invalid JSON in 'Response Body' field"
的錯誤。同時 VS Code 的測試腳本也報 Expecting value: line 1 column 1 (char 0)
的錯誤。Respond to Webhook
節點終於要回應時,發現連線已經斷掉了,因此報錯。Notion寫入結果驗證
Code 節點。{
"ai_processing": {
"status": "success",
"summary": {{ JSON.stringify($('AI 摘要與任務提取').item.json.summary) }},
"tasks": {{ JSON.stringify($('AI 摘要與任務提取').item.json.tasks) }}
},
"notion_storage": {
"status": "success",
"message": "會議記錄已成功寫入 Notion",
"notion_page_url": {{ JSON.stringify($json.url) }}
}
}
✅ 完成項目
今天 Notion API 的整合讓我學會了如何處理外部服務的認證與權限管理,還有在面對 Timeout 超時與 Invalid JSON 錯誤時,我意識到區分「客戶端等待超時」和「服務端處理超時」的重要性。
透過調整 HTTP Request 的 timeout 參數和最佳化 Respond to Webhook 的資料來源,我也學會了如何在同步模式下,建構一個能處理長時間任務且穩定的工作流程。
🎯 明天計劃
建立通知系統整合,讓團隊成員在會議摘要完成時能即時收到 LINE 的通知。