文件導航

用決策模型看住 agent

編碼 agent 是這類模型用得最集中的地方,而且集中在三個位置。 它們有一個共同的結構:把「判斷」從生成模型裡拿出來,交給一個更便宜、 更快的模型去做,程式碼拿到型別化的答案之後自己決定動作。

一、工具呼叫之前:要不要放行

最直接的一處。一個 Claude Code 的 PreToolUse 鉤子做的事是:

問一個 Noul:這條 shell 命令是不是嚴格只讀的? 到 0.95 才自動放行,否則退回常規的許可權提示,而且從不主動拒絕。

三個設計決定值得注意:

  • 0.95 很高。 自動放行的門檻比「判斷它危險」的門檻要高得多 —— 誤放的代價是一臺機器,誤攔的代價是使用者多點一次確認。不對稱的代價要反映在不 對稱的閾值上。
  • 從不 deny。 它只做「自動批准」這一件事,其餘全部交還給原系統。 一個只增加能力的門比一個會奪走能力的門好測 —— 前者最壞情況是沒幫上忙。
  • 危險命令根本不進模型。 本地有一份 hard-no 清單和一個注入過濾器, 在呼叫之前就把它們擋掉。這一條比閾值重要,理由見什麼必須寫在程式碼裡。

實測資料:8 條會改變狀態的命令,0 條被自動放行。

二、agent 想收尾的時候:做完了嗎

另一個高頻位置。一個 Stop 鉤子用決策模型判斷 agent 是否過早收工, 辦法是拿自然語言寫的完成規則去問它。

更剋制的版本是這樣的:

只在「有檔案被改動過、且此後沒有任何通過的檢查」時,才花一次四個問題的呼叫; 任何錯誤都放行(fail-open)。

「只在值得問的時候才問」是這一類的關鍵 —— 這些鉤子在每一輪都會跑, 無條件呼叫會把成本乘以輪數。上面的條件是「有未驗證的改動」, 那正是最容易出現「agent 說自己做完了但其實沒驗證」的時刻。

同類做法還有一個防止過早結束的鉤子,它把「完成規則」寫成自然語言, 讓模型判斷是否滿足,而不是靠模型自己宣告。

三、上下文快滿的時候:哪些還留著

第三處是上下文壓縮 —— 這裡的做法分歧最大,也最有意思。

傳統的壓縮是摘要:把一段對話交給模型,讓它壓成一段文字。代價是 原文沒了,而摘要是不可逆的。

用決策模型的做法不同,它只打分,不改寫:

做法 保留什麼
逐條給工具呼叫與結果打「還需要嗎」的分 判定要留的行逐字保留
低分的段移到 store,原位掛一個 expand() 指標 沒有刪除,只是摺疊
append-only 的凍結字首 prompt cache 不被打斷
在模型看到之前就裁掉冗長的 Bash 輸出 終端噪音不進視窗

共同點是同一句:決策模型在這裡的作用是「保留 / 不保留」的二值判斷, 而不是「改寫」。這恰好是它能做好而生成模型不擅長的事 —— 而「不刪除、只摺疊」這個選擇,把判斷錯誤的代價從「資訊永久丟失」 降成了「多一次展開」。

反面:安全門和效率門要用相反的兜底

這一片生態裡最值得對照的一組資料:同樣是「出錯怎麼辦」, 不同專案選了相反的答案,而兩個都對。

  • 一個許可權判定器:出錯或超時就拒絕。
  • 一個 Stop 鉤子:任何錯誤都放行。

判據不是「哪個更安全」,而是這個門擋的是風險還是效率。 擋風險的(許可權、金鑰、危險命令)錯殺好過漏放;擋效率的(收尾檢查、 格式檢查)漏放好過卡死流程。

一句話

agent 是這類模型最自然的落點,因為它需要大量的廉價判斷, 而且這些判斷的結果馬上要被程式碼消費。但每一處都要先問清楚: 這個門出錯時應該往哪邊倒。