現在做一個 Agent 原型確實很容易。給模型幾個工具、一個目標、一個迴圈,一天之內它就會做出一些令人印象深刻的事。
生產環境是另一個問題。Agent 會收到沒有人預想過的輸入,會調用中途失敗的工具,並且偶爾會很有信心地選一條昂貴而錯誤的路。加固,就是讓以上全部變成可承受的工作。
以下是我們在 Agent 接觸真實用戶之前會逐項走完的清單。
邊界
- 每個工具最小權限。 每個工具只拿到剛好夠用的權限範圍。讀取工具不能寫入;寫入工具只碰一張表,而不是整個資料庫。
- 明確標示不可逆操作。 每個工具分三類:可逆、昂貴、不可逆。不可逆操作一律需要審批步驟,無論 Agent 有多確信。
- 在工具邊界做輸入驗證。 Agent 傳來的參數屬於不可信輸入。用 schema 驗證並及早拒絕 —— 不要指望提示能保證參數格式正確。
- 花費與步數上限。 每個任務的 token、工具調用次數與掛鐘時間都要有硬上限,並在程式碼層強制執行。一個陷入迴圈的 Agent,就是一宗帳單事故。
失敗行為
- 每個工具都會失敗。 逾時、部分結果、限流、格式錯誤的回應。Agent 對每一種都要有明確行為 —— 通常是退避重試、然後升級,絕不能當作成功並悄悄繼續。
- 明確的終止條件。 成功與放棄都要是明確狀態。一個沒有辦法說「我做不到」的 Agent,會捏造一個完成。
- 關鍵處要冪等。 如果某一步可能被重試,底層操作必須容許被執行兩次。
- 優雅降級。 當模型不可用時,周邊產品應以縮減模式繼續運作,而不是給用戶一個壞掉的畫面。
指令處理
- 不可信內容是資料,不是指令。 Agent 讀到的任何東西 —— 網頁、文件、工單、電郵 —— 都可能包含針對 Agent 而寫的文字。它絕不能被當成指令執行。這是提示注入的邊界,需要被測試,而不是在系統提示裡寫一句就算。
- 任何對外動作都要確認。 寄送、發佈、付款、刪除。由用戶確認,Agent 只負責提議。
- 追蹤紀錄要有來源。 Agent 執行動作時,日誌應顯示是什麼促成了它,讓意外動作可以追回源頭。
可觀測性
- 逐步追蹤。 每一步的輸入、輸出、工具調用、耗時與成本都要保存且可搜尋。沒有這一層,除錯一次失敗執行就只能靠猜。
- 針對執行軌跡的評估。 不只問「最終答案對不對」,還要問「路徑合不合理」。經過六次昂貴的無用調用才得到正確答案,是一個等著被放大的問題。
- 對已錄軌跡的回歸測試。 每次改提示或換模型之後,重放已知良好的任務。
- 對比率告警,而不只對錯誤告警。 追蹤有多少比例的執行撞到步數上限、升級給人手、或以放棄告終。放棄率上升,通常是上游出現變化的最早訊號。
人的因素
- 先展示計劃,再執行動作。 對多步任務而言,讓用戶先看到預定順序,可以在付出代價之前抓到誤解。
- 讓中斷變得容易。 一個看得見的停止控制,以及中斷後乾淨的狀態。
- 介面上要誠實。 如果系統不確定,就說出來。用戶原諒不確定;但不會原諒第二次自信的錯誤。
簡短版
以上大部分都是普通的工程紀律 —— 權限、錯誤處理、日誌、測試 —— 只是套用在一個剛好是機率性的元件上。能交出可靠 Agent 的團隊,很少是提示寫得最巧妙的那些。他們是把 Agent 當成一個具有特殊失敗模式的分散式系統,並照此做工程的那些。
文章反映撰寫當時的工程實踐,僅供一般參考。