您好,
我有一個以 Teams 對話作為進入點的工作流程。我已經設置了多個條件來篩選請求。目前的流程是:一個請求 = Teams 中的一個回應,然後對話結束。
我新增了一個 n8n AI 代理來利用資料庫中的數據。簡單的「一個請求 = 一個回應」流程運作良好。現在,我希望使用者能夠與代理進行來回對話。例如:
- 使用者:給我客戶「foobar」的地址。
- 代理:我有幾個同名的客戶:
客戶列表。您要哪一個?
- 使用者:第三個。
我的問題是使用者發送的每條訊息都被視為新訊息;因此,工作流程會重新啟動,代理會「忘記」之前的互動。
我嘗試將代理放在迴圈中,但這似乎不是正確的方法 
您有任何建議嗎?
提前感謝。
您的 n8n 設置資訊
- n8n 版本: 2.29.9
- 資料庫(預設值:SQLite):
- n8n EXECUTIONS_PROCESS 設置(預設值:own, main):
- n8n 運行方式(Docker、npm、n8n cloud、桌面應用程式): Docker
- 作業系統: Linux
1 個讚
這個迴圈不是解決方案,值得理解原因:每則 Teams 訊息都作為單獨的執行到達,而 n8n 執行是無狀態的。除非你將其儲存在某處,否則它們之間不會保留任何內容。在單次執行內迴圈只有在整個對話都發生在該單次執行中時才有幫助,但這裡不是這樣,因為使用者的下一則訊息會在幾分鐘後透過新的觸發器到達。
你想要的是以對話為鑰的持久性記憶,而不是迴圈:
將 Memory 節點附加到 AI Agent(使用 Postgres Chat Memory 或 Redis Chat Memory,而不是記憶體內的 Simple Memory,該記憶體會隨著執行而消失,也不會在 Docker 重啟後存活)。
將工作階段鑰設定為 Teams 對話 ID,而不是靜態值。來自同一 Teams 執行緒的每則訊息都會載入相同的歷史記錄,因此「第三個」會根據代理程式上次說的內容進行解析。如果你為所有人使用相同的鑰,使用者將看到彼此的內容,所以這個欄位是需要正確設定的。
在其上保留一個視窗(最後 N 則訊息),以便內容不會永遠增長,你的令牌成本保持可預測。
值得在那時添加的一件事:如果使用者的答案不明確(當代理程式未列出任何內容時的「第三個」),代理程式應該說它不知道,而不是猜測客戶端記錄。來自資料庫查詢的錯誤地址是人們注意到的失敗。
2 個讚
@flipflip 核心要點:UUID,使用「Teams UUID」
如果每次工作流程執行時都產生全新的 UUID,AI 仍會將其視為新的聊天。最簡單的方法是取用 Microsoft Teams 已在其酬載中傳送的唯一 ID,並將其用作您的工作階段 ID。
逐步指南
-
將記憶體節點新增到您的 AI 代理
您需要將記憶體節點連接到 AI 代理節點的左側。
-
在記憶體節點中設定工作階段 ID
按一下以開啟記憶體節點。您會看到名為「工作階段 ID」的欄位(如果沒有看到,請按一下「新增欄位/參數」並選取「工作階段 ID」)。
-
從 Teams 觸發程式對應 ID
在「工作階段 ID」欄位中,對應來自 Microsoft Teams 觸發程式的變數。根據您的需求,您有 2 個選項:
按「聊天室/執行緒」記住(建議):
從 Teams 擷取對話 ID,例如:
{{ $json.conversation.id }} 或 {{ $json.message.conversation.id }}
(優點:如果在群組/頻道中聊天,AI 會記住該特定執行緒的內容)
按「個別使用者」記住:
擷取輸入文字的人員的使用者 ID,例如:
{{ $json.from.id }}
(優點:無論此使用者從哪個聊天室輸入,AI 都會記住與此特定人員的對話歷史記錄)
設定完成後系統如何運作?
要求 1:使用者輸入「給我客戶 foobar 的地址」
Teams 傳送對話 ID = “abc-123” 的訊息
AI 代理接收訊息,並將其記憶體繫結至工作階段 ID “abc-123”
AI 回覆「我有幾個客戶…您要哪一個?」(並儲存此歷史記錄)
要求 2:使用者回覆「第三個」
工作流程從頭開始重新啟動!
但這次,Teams 傳送對話 ID = “abc-123” 的訊息(此對話迴圈的完全相同 ID)。
當記憶體節點看到工作階段 ID “abc-123” 時,它會立即從要求 1 提取聊天歷史記錄,並將其提供給 AI。
AI 立即知道「第三個」是指上一條訊息中的客戶清單!
1 個讚
歡迎 @flipflip!
關鍵是在你的 AI Agent 中附加一個記憶子節點 - 特別是「Window Buffer Memory」節點。在其「Session ID」欄位中,使用 Teams 對話 ID:{{ $json.channelId }} 或任何在你的觸發資料中攜帶 Teams 獨特對話 ID 的欄位。這樣每個 Teams 對話就會獲得自己的記憶窗口,agent 會記住該相同對話內的先前交換。
你的流程變成:Teams 觸發 → AI Agent(包含 Window Buffer Memory 子節點,session ID = Teams 對話 ID)→ 回覆給 Teams。使用者的每條新訊息都會觸發相同的 agent,記憶節點會載入該工作階段的先前輪次,agent 就能掌握上下文。你嘗試的迴圈方法不會在這裡起作用,因為 n8n 不是設計用來暫停執行中途等待使用者輸入的 - 記憶 + 工作階段金鑰才是正確的模式。
各位好,
感謝你們的回覆。你們說得沒錯——使用迴圈絕對不是正確的方法。
我加入了基於 PostgreSQL 的記憶功能,但我沒有使用 Teams 對話 ID,因為它會隨著每條傳送或接收的訊息而改變。相反地,我使用了傳送訊息的使用者資料的 ID。
現在我可以利用 AI 代理的記憶功能,同時區分不同的使用者。
1 個讚
對話 ID 記憶建議是正確的基礎層,但我會在信任它用於生產環境之前添加一個恢復測試。
在你的例子中,「第三個」不僅是記憶問題。它也是一個新鮮度和權威性問題:代理應該只在前一個候選清單仍然與同一 Teams 對話相關聯、清單尚未過期,且使用者仍在回答同一消歧步驟時,才解析「第三個」。
我會在聊天記憶旁邊存儲一個小的恢復記錄:
- Teams 對話 ID / 工作階段金鑰;
- 當前目標,例如消歧客戶端「foobar」;
- 最後候選清單以及時間戳記/來源查詢;
- 允許的後續使用者操作;
- 過時或未知的欄位;
- 明確的非推論,例如,如果候選清單遺失、已過期或來自另一個對話,請勿將「第三個」對應到客戶端;
- 如果恢復失敗時的下一個安全操作,例如,要求使用者重新敘述客戶端。
快速測試:使用只持久化的記憶/恢復輸入冷啟動工作流程,並詢問代理它知道什麼、什麼已過時、什麼必須不推論,以及下一個安全操作是什麼。如果它無法清楚地說出來,工作流程有記憶但沒有可靠的恢復能力。