我試著理解人們如何安全地運行包含 AI 代理的 n8n 工作流程。
特別是,我很想了解諸如發送外部電子郵件、更新客戶記錄、存取 Drive/Notion、發放退款或呼叫第三方 API 等操作。
- 你永遠不會讓 AI 步驟自動執行的操作有哪些?
- 你目前在哪裡使用 Wait 節點、Slack 審批、手動檢查或自訂程式碼?
- 你是否曾經遇過工作流程因為 AI 步驟誤解資料而執行意外操作的情況?
- 在你目前的設定中,稽核「為什麼會發生這個操作」是否很困難?
我目前還在研究初期,相比一般意見,我會更看重真實案例。
實際例子而不是籠統的意見,因為那是你要求的:我這週一直在測試一個代理工作流程,其中發送電子郵件需要通過一項政策檢查,該檢查對收件人網域有允許清單規則。第一次測試運行時,它拒絕了一封本應通過的電子郵件。結果發現兩條重疊的政策規則都在監控同一個動作,其中一條在允許值中輸入了一個單獨的多餘空格。沒有任何東西崩潰,沒有任何錯誤,它只是默默地回退到拒絕——而找出原因需要真正深入審計日誌,該日誌本身還有一個小顯示錯誤,模糊了實際是哪條規則導致了這個問題。
這就是對你上一個問題的誠實回答——審計「為什麼會發生這種情況」並不難是因為這個概念難,而是難因為這些系統會無聲地失敗,你的工具必須足夠可信,以至於你真的相信它告訴你發生了什麼。
關於我從不讓自動運行的:任何涉及金錢、外部電子郵件或他人記錄的不可逆轉的東西。在執行前,這些會先檢查規則——允許、拒絕或保留以供人工審核,而不是一個等待節點坐在上游,寄希望於代理的工具調用恰好尊重它。
我一直將該政策和審計層作為一個獨立的東西來構建,而不是將批准邏輯單獨連接到每個工作流程中——超過 10-15 個工作流程後會很快變得混亂。這是一個 n8n 社區節點,還很早期,粗糙的邊緣是保證的。如果你想看到它的真實運行或自己嘗試破壞它,我很樂意給你展示。
我只能從金錢的角度來談——我是 Sequence (getsequence.io) 的創辦人,我們提供支付基礎設施,許多 AI 代理都在上面運行——但既然退款/支付在你的清單上,以下是我們的使用者真正劃清界限的地方:
**永遠不要自動化:**首次向新交易對手或新增銀行帳戶進行付款。無論金額有多小。對已知交易對手的定期付款通常會在幾週後自動化,一旦人們信任這個流程。
**設定閾值,而非全面核准:**常見的模式是低於 $X 完全自動,$X–$Y 需要 Slack 核准,超過 $Y 需要兩個核准人。全面「核准所有內容」會很快消亡,因為人類會在一週內開始不假思索地核准——這會悄悄地破壞整個目的。
**意外行為:**有的。經典情況是代理誤讀發票金額(小數點或貨幣混淆),並啟動 100 倍預期金額的轉帳。核准步驟會捕捉人類實際閱讀的交易;在工作流程之外強制執行的硬上限會捕捉他們不假思索核准的交易。你兩者都需要。
**審計:**如果你唯一的記錄是 n8n 執行日誌,審計會很痛苦。「為什麼」需要附加到動作本身,而不是附加到你之後必須考古挖掘的工作流程執行。
如果對你的研究有用,我很樂意分享更多具體內容。
我使用過的具體模式:AI Agent 永遠不會獲得直接執行敏感操作(退款、外部電郵、記錄更新)的工具。它只會獲得一個「提議操作」工具,將結構化的負載——操作類型、目標、參數和代理的推理——寫入隊列(Sheets/Postgres)。
單獨的分支會提取該行,發送 Slack 訊息並提供批准/拒絕按鈕,然後在 Wait 節點上等待,由 webhook 恢復——而不是超時。所以不會因為沒有人及時查看就自動執行任何操作。只有在批准後,真正的操作節點(Gmail、HTTP Request 等)才會運行,使用人類看到的確切參數——而不是代理在第二次調用時可能產生的任何內容。這就是防止「批准了 X,執行了 Y」的部分。
對於「為什麼會這樣」——將代理的原始推理文本與批准決定一起記錄在同一行中,這才是後來真正能夠回答的原因。光是工具調用的參數還不夠。
值得標記的一個失敗模式:在 webhook 重試時,代理偶爾會為同一事件兩次調用提議工具,導致重複的批准請求。通過將觸發負載的雜湊作為隊列行上的冪等性密鑰來修復。
@nathan3 的提案行動模式是正確的架構。在稽核方面我想補充一點:將代理的原始推理文本與提案行動一起存儲在同一個隊列行中,而不是只存儲工具調用參數。當後來出現問題時,「代理決定向 X 發送電子郵件,因為它符合規則 Y」的用處比「電子郵件 X 已批准」多 10 倍。
對於冪等性問題 - 對觸發程序有效負載進行雜湊運算可行,但如果你在隊列模式下運行,也可以使用內置的 n8n 執行 ID 作為隊列行上的冪等性密鑰。這樣即使 webhook 被重試,INSERT ... ON CONFLICT DO NOTHING 也會在重複項到達你的批准步驟之前在數據庫級別將其阻止。
不錯的補充,execution ID + ON CONFLICT DO NOTHING 比我之前的做法更簡潔。我之前是手動對觸發器的 payload 進行雜湊處理,並在插入前檢查,但這會帶來額外的讀寫步驟,在檢查和插入之間存在競態條件窗口。將唯一性約束推送到資料庫可以完全消除這個窗口。我要改用這個方法。
提議後執行模式 @nathan3 所描述的一個生產課程要加進去:審核需要 TTL。在請求之後三天點擊 Slack 核准按鈕才執行,但世界已經改變了 - 發票已經支付、對方詳情已更新、價格已波動。審核在請求時是合法的,但到執行時就錯了。
這在你們兩個收斂的隊列列設計中是個便宜的修復:存儲 approved_at + expires_at,讓執行分支檢查兩者。過期的審核意味著重新提議,永遠不執行。TTL 因操作類別而異 — 付款幾分鐘、電郵幾小時是合理的預設值。
好的發現,我沒有考慮到過期的批准。在隊列行上的 approved_at + expires_at,並在兩者上設置執行分支的門控,正是那種廉價修補程式,容易被跳過直到它咬你一口。
我可能會更進一步,即使在 TTL 窗口內:在執行前重新檢查底層狀態(發票仍未支付、價格未變),不僅僅是批准的新鮮度。TTL 能捕捉到明顯的陳舊,但對於付款來說特別是這樣,世界可以在幾分鐘內改變,而不僅僅是幾天 - 批准「新鮮」並不意味著批准時的狀態仍然成立。
與上述答案的不同角度,因為到目前為止,每個人都在限制寫入操作:金錢、電子郵件、記錄。我必須學會限制的操作是不寫任何東西的操作,即AI直接回答客戶的問題。
聊天機器人回覆真實人類也是一種不可逆轉的外部操作。一旦它說了什麼錯誤的話,你就無法回滾。但通常的警覺機制都不會觸發,因為沒有插入任何東西、沒有呼叫外部API、沒有改變任何行。它看起來不像危險的操作類別,所以通常根本不會有任何限制機制。
我用的替代方案不是人工審核步驟,因為你不能把人類放在實時聊天回覆前面而不毀掉產品本身:在檢索和回答之間設置一個信心限制。如果檢索到的證據太薄弱或相似度太低,模型就不能回答。它會說自己沒有那些資訊,然後轉交給人類處理。拒絕是預設設定,而回答是必須被贏得的東西。這和許可清單的形狀相同,只是應用在模型是否可以說話,而不是是否可以行動。
我做錯的兩件事,可能值得傳達一下。
關於你的審計問題:我記錄檢索到的文本塊及其相似度分數,放在每個答案旁邊,而不僅僅是最終文本。沒有這個,「它為什麼會這樣說」是無法回答的,因為答案文本本身無法告訴你模型實際上在看什麼。這是nathan3在關於將代理的推理與決定一起儲存時所說的讀取端版本。
第二點,這個兩天前才抓到我:限制機制本身可能會靜默失敗,而且它是以安全的方向失敗。檢索下游的過濾節點中的一個過期條件正在丟棄每一行,所以限制機制看到零證據並正確地拒絕了。每次執行都顯示為綠色,沒有拋出錯誤。機器人禮貌地告訴人們它不知道那些它明確知道的事情,而且它會一直這樣繼續下去,因為拒絕從來看起來不像是一個失敗。我只是因為提出了一個我已經知道源文檔能回答的問題才發現它。
所以我想添加到上面描述的「建議然後執行」模式中的東西是:無論哪個元件決定「不繼續」,都要監控它觸發的頻率。一個拒絕路徑如果悄悄地從5%的觸發次數變到100%的觸發次數,那就是一個壞掉的系統,看起來卻完全像是一個謹慎的系統。