AI 代理程式稽核軌跡:如何記錄聊天機器人的每一個動作

打造一套 AI 代理程式稽核軌跡,清楚呈現你的聊天機器人在每個連接系統中意圖做什麼、嘗試了什麼、改變了什麼,以及重試了幾次。

Cover Image for AI 代理程式稽核軌跡:如何記錄聊天機器人的每一個動作

7 月 9 日,OpenAI 為 GPT-5.6 新增了程式化工具呼叫功能,以及測試版的多代理程式協同作業。這次更新,延續了一股更大的趨勢:從簡短回答,走向能跨工具長時間運作的代理程式。OpenAI 的報告指出,截至 2026 年 5 月,受抽樣調查的 Codex 使用者中有 70.2% 至少要求過一項預估需要真人耗時超過一小時的任務。每個任務涉及的動作越多,意圖、執行與結果之間出現落差的機會就越多。

這些失誤通常只是尋常疏失,而非惡意行為。Google DeepMind 在檢視了一百萬筆程式碼代理程式任務後發現,大多數被標記的事件都源自誤解或過度積極。因此,一份實用的 AI 代理程式稽核軌跡,必須能重建每一個有實質影響的聊天機器人動作——包括那些看似無害、卻造成重複退款、重複工單、重複訂位或重複電子郵件的重試行為。

先從這份最基本的事件紀錄開始。每次狀態變更都儲存為一筆事件,新增事件時只能附加、不能覆寫舊事件,並且把每一筆事件都連結回同一條追蹤軌跡(trace)。

欄位記錄內容重要原因
trace_id對應整個使用者請求的單一 ID重建多步驟的執行過程
action_id對應意圖執行的商業動作的單一 ID將嘗試與重試分組
attempt_id每次工具呼叫的唯一 ID揭露重複執行的情況
idempotency_key傳送給目的地的穩定金鑰防止重複產生副作用
actor使用者、聊天機器人、子代理程式、核准者或服務釐清責任歸屬
tooloperation連接器加上確切的操作顯示執行了哪項能力
input_summaryinput_hash經過遮蔽的摘要,加上標準化輸入內容的雜湊值支援審查,又不必複製機密資訊
decision允許、拒絕、需要核准,或升級處理記錄政策判定結果
result成功、失敗、逾時、未知,或已補償將傳輸狀態與商業結果區分開來
external_reference退款、工單、訂位或訊息 ID將追蹤軌跡連結到記錄系統
occurred_atUTC 格式的伺服器時間戳記為跨服務的事件排序

把意圖、嘗試與結果分開處理

聊天逐字稿通常捕捉的是意圖:「幫我退最近那筆訂單的款。」HTTP 日誌捕捉的是嘗試:POST /refunds。金流處理商捕捉的則是結果:退款 rf_8421 改變了帳戶餘額。這三筆紀錄,沒有一筆能證明另外兩筆確實發生。

把它們視為三項彼此相關、但各自獨立的事實:

  • **意圖(Intent)**記錄使用者的請求、代理程式的理解、選用的工具,以及提議的參數。
  • **嘗試(Attempt)**記錄實際送出的操作、政策判定結果、目的地、逾時設定,以及回應類別。
  • **結果(Effect)**記錄具持久性的外部結果,例如退款 ID 與金額、訂位狀態,或工單狀態轉換。

每當請求逾時,這種區分就變得至關重要。逾時只代表發出請求的一方沒有收到回應,目的地端仍有可能已經完成該動作。如果稽核紀錄把「沒有回應」直接歸類為「失敗」,聊天機器人就可能重試一個其實已經成功的操作。

同樣的界線也能讓權限判斷更精確。聊天機器人工具權限檢查清單協助你決定機器人是否可以呼叫某項能力;而稽核軌跡則提供了該項判定之後實際發生了什麼事的證據。

為每個動作配上四組 ID

光靠一組對話 ID,撐不起一場正式的事故調查。一段支援對話可能觸發好幾個動作,而每個動作又可能經歷好幾次嘗試。

請使用四組生命週期各不相同的識別碼:

對話 ID(Conversation ID)。 將使用者可見的訊息分組,在整個聊天工作階段中保持穩定不變。

追蹤 ID(Trace ID)。 將完成單一請求所需的工作分組。同一段對話中的新請求,應該獲得一條新的追蹤軌跡。

動作 ID(Action ID)。 標識代理程式意圖完成的商業操作,例如「將訂單 10492 退款 $48」。重試時應沿用同一個動作 ID。

嘗試 ID(Attempt ID)。 標識單一次網路呼叫。每次重試都會取得新的嘗試 ID,讓維運人員能看出系統總共嘗試了幾次。

請把追蹤 ID 與動作 ID 一路傳遞到 Webhook、佇列、連接器服務與核准畫面中。如果第三方 API 接受中繼資料,也一併帶上。調查人員應該不論是從一則顧客訊息、一次工作失敗,還是一筆外部交易切入,最終都能追溯到同一條追蹤軌跡。

案例演練:跑了兩次的退款

假設有位顧客這樣寫道:「請退還訂單 10492 上重複收取的 $48。」聊天機器人找到兩筆已請款的付款紀錄,提議退還較新的那一筆,並取得真人核准。金流 API 處理了這筆退款,但回應時間超過了 10 秒的逾時上限。一個背景工作程序在沒有冪等性金鑰的情況下重試了這個請求,因而產生了第二筆退款。

第一次嘗試應該產生像下面這樣的一筆僅供附加(append-only)的事件:

{
  "event_type": "tool.attempt.finished",
  "trace_id": "tr_7f2c",
  "action_id": "act_refund_10492_48usd",
  "attempt_id": "att_01",
  "conversation_id": "conv_5198",
  "actor": {
    "type": "chatbot",
    "id": "billing-support"
  },
  "tool": "payments",
  "operation": "create_refund",
  "decision": "approved",
  "approval_event_id": "apr_6630",
  "input_summary": "Refund $48.00 to payment ending 8812",
  "input_hash": "sha256:4cb3...91e0",
  "idempotency_key": null,
  "result": "timeout_unknown",
  "external_reference": null,
  "occurred_at": "2026-07-15T09:42:18.511Z"
}

timeout_unknown 這個結果,就是關鍵線索。背景工作程序在重試之前,必須先用該動作穩定的識別碼去查詢金流處理商的狀態。如果查到了退款 rf_8421,就附加一筆 effect.confirmed 事件並關閉該動作;如果無法查詢,該動作就該進入人工審查,而不是盲目地再執行一次。

現在假設重複退款已經發生了。一條完整的追蹤軌跡會顯示:同一個動作 ID、兩個嘗試 ID、沒有冪等性金鑰,以及兩個外部退款 ID。補救措施可以另外記錄一筆補償動作。維運人員能藉此回覆顧客,工程師能藉此修正重試邏輯,財務團隊也能根據同一份證據對帳。

這也是為什麼核准紀錄不能只記錄「按下了一次核准」。聊天機器人核准工作流程指南說明了如何在執行前呈現後果與參數。你的稽核軌跡應該用一組標準化雜湊值,把已核准的內容與實際執行的內容綁定在一起。

讓重試變得平淡無奇

在分散式系統中,重試是家常便飯:網路會卡住、佇列會重複派送工作、背景工作程序會重新啟動、供應商也會回傳語意不明的錯誤。安全的設計,必須假設每個動作都可能被嘗試不只一次。

冪等性金鑰應該從穩定不變的商業動作衍生出來,而不是從單次嘗試衍生。以上面的退款為例,這組金鑰可以由租戶 ID、付款 ID、退款金額、原因與動作 ID 組合而成。每次重試都送出同一組金鑰;一旦金額或目的地變了,就等於是一個新動作,需要重新做出判定。

接著,依照結果定義重試規則:

  • 在被接受前就明確失敗: 用同一個動作與冪等性金鑰自動重試。
  • 送出後發生逾時或連線中斷: 先查詢狀態;只有在目的地證實沒有任何結果發生時,才進行重試。
  • 驗證或權限失敗: 停止並明確呈現需要修正的內容。
  • 速率限制或供應商暫時性故障: 遵守供應商的退避(backoff)訊號,並保留相同的動作識別身分。
  • 結果未知且無法查詢: 對有實質影響的動作,一律要求人工審查。

記錄排程器每次重試的原因。「第 2 次嘗試已開始」是薄弱的證據;「在狀態查詢未找到對應退款後,第 2 次嘗試已開始」才是禁得起審查的證據。

把核准內容與實際執行的內容綁定在一起

一筆核准,只對核准當下那個人所看到的動作有效。如果聊天機器人請求核准退款 $48,實際執行時卻退了 $96,那麼「有核准事件存在」這件事本身,只會帶來一種虛假的安全感。

將提議的內容標準化,移除時間戳記等易變欄位,再對結果取雜湊值,並將這組雜湊值與核准紀錄一併儲存。在執行前的最後一刻,再重新計算一次雜湊值——若兩者不一致,就應該讓該次核准失效,並把已變更的提議退回給核准者。

在核准事件中記錄以下細節:

  • 核准者身分與角色;
  • 觸發核准要求的政策或規則;
  • 呈現給人看的、易於理解的後果說明;
  • 標準化內容的雜湊值;
  • 核准的有效期限;
  • 判定結果與(選填的)理由;
  • 追蹤 ID 與動作 ID。

拒絕與過期事件也一併保留。一連串僅供附加的事件,能顯示出代理程式是否遵守了判定結果,還是在被擋下之後,改走了另一條路徑。

遮蔽敏感資訊,但不能破壞證據

原始的工具內容,可能包含存取權杖、付款細節、健康資訊、私人訊息與個人識別資料。把這些內容原封不動複製進一個可搜尋的日誌裡,等於是又建立了一座敏感資料庫。

採用分層式紀錄:在維運事件中放入經過遮蔽的摘要,並儲存標準化輸入內容的雜湊值以偵測變化。如果確實有必要保留完整的內容,就把它加密存放在存取受限的證據儲存區中,搭配較短的保留期限與獨立的存取控管。

以欄位為單位定義遮蔽規則,而不是只靠正規表示式。Bearer token 絕對不應該進入事件管線。電子郵件地址在一般維運檢視畫面中可以遮蔽,但仍可讓一小群支援人員存取。自由輸入的文字欄位需要有大小限制與機密偵測機制,因為使用者確實會把帳密憑證貼進聊天視窗裡。

隱私考量同樣適用於可觀測性(observability)供應商。在匯出追蹤資料之前,先決定哪些欄位可以離開你的環境、資料會儲存在哪個地區,以及刪除請求是否會一併傳播出去。聊天機器人管理員安全指南談的是高權限的設定變更;同樣的職責分離原則,也應該套用在稽核日誌的存取權限與保留規則變更上。

把追蹤資料轉化為維運可以回答的問題

儀表板該回答的是具體問題,而不是拿事件總量來自我慶祝。從能揭露顧客受害情形的查詢開始:

  • 哪些成功的商業結果,是在逾時回應之後才發生的?
  • 哪些動作 ID 產生了不只一個外部參照?
  • 哪些已核准內容的雜湊值,與實際執行內容的雜湊值不一致?
  • 哪些工具的「結果未知」比例最高?
  • 哪些使用者或租戶觸發了最多次重試?
  • 哪些動作是在核准過期之後才完成的?
  • 哪些被拒絕的動作,之後又透過另一個工具嘗試了類似的動作?

每次事故發生時,也一併抽查一批正常的追蹤紀錄。正常案例能讓你在壓力來臨之前,先確認這套結構是否容易理解,也能揭露出遺漏的轉接環節、容易誤導的結果標籤,以及團隊誤以為「另一個服務會記錄」的欄位。

對低風險的動作而言,事後審查或許就已足夠。Google DeepMind 的控管路線圖,同樣把「對可逆行為的事後監控」與「對嚴重動作的即時攔截」區分開來。請依動作的後果嚴重程度,為每項工具指派審查模式:非同步抽樣、異常時警示、執行前需核准,或是同步政策強制執行。

把稽核軌跡當成一項產品功能來測試

即使聊天機器人看起來一切正常,稽核軌跡本身仍然可能失靈。請加入會刻意製造棘手狀態的發布測試:

  1. 在目的地已接受某動作之後,強制製造逾時。
  2. 將同一則佇列訊息重複派送兩次。
  3. 在執行前變更一項已核准的參數。
  4. 在一項多步驟任務進行期間輪替連接器的憑證。
  5. 回傳成功的 HTTP 狀態碼,但商業結果實際上被拒絕。
  6. 讓兩個子代理程式同時處理同一個顧客請求。
  7. 刪除或遮蔽顧客資料,並驗證各項匯出作業中的保留規則是否一致。

每項測試都從三個起點切入:對話本身、內部工作,以及外部交易。三者最終都應該匯回同一條前後一致的追蹤軌跡。就算是沒有參與這套整合開發的人,也應該能說清楚:使用者請求了什麼、代理程式做了什麼判斷、系統嘗試了什麼,以及實際上改變了什麼。

Anthropic 對可信賴代理程式的描述強調,代理程式在跨工具反覆規劃、行動、觀察的過程中,透明度至關重要。務實的標準,是一條能撐過這整個循環的追蹤軌跡,其中也包括子代理程式之間的轉接與真人的介入。

收據本身就是動作的一部分

顯示給顧客看的那句「你的退款已完成」,應該是根據已確認的結果產生,而不是根據聊天機器人的意圖,或是一次成功派發的工具呼叫。同一個顯示給支援團隊看的外部參照,在適當情況下也應該出現在使用者收到的收據上。

隨著聊天機器人的任務橫跨越來越多的工具、模型、背景工作程序與核准流程,AI 代理程式稽核軌跡也逐漸成為動作契約中不可或缺的一環。它既能為顧客提供一張站得住腳的收據,也能讓維運人員從一個出乎意料的結果,一路追溯回催生它的那個確切判斷與嘗試。

在 Agentkit 中,聊天記錄提供了讓人容易閱讀的審查層,自訂 API 動作則負責把聊天機器人連接到你的商業系統;請確保記錄系統的收據,始終與這些對話保持連結。

免費建立你的聊天機器人 →

不需信用卡。

免費開始使用不需信用卡
AI 代理程式稽核軌跡:如何記錄聊天機器人的每一個動作 – Agentkit