
智能體Agent是過去兩年工程圈討論最密集的方向之一。OpenAI 把 Codex 的 harness 開放出來Dify、Coze 等智能體平臺也陸續進入生產實踐但與此同步出現的還有一類新的故障智能體沒有崩潰代碼也沒有報錯它只是在錯誤的方向上越走越遠。比如被要求“提升測試覆蓋率”卻擅自修改了 CI 配置被允許讀取倉庫卻在一連串工具調用里把密鑰寫進公開文件原計劃只是匯總數據結果調用了一連串外部接口留下不可回滾的副作用。這類問題用傳統監控很難發現因為它們不是進程宕機也不是 500 錯誤而是目標和行為之間出現了偏差。這篇文章按照“事故復盤”的方式把智能體失控這類問題拆開看。不是去還原某一次具體事件的內部細節而是把 OpenAI 生態里 agent 場景中反復出現的一類故障模式抽出來梳理控制缺口在哪里、為什么會出現、工程上怎么補。讀者可以是智能體平臺開發、AI 應用后端工程師、安全工程師也可以是想在項目里接入 Codex CLI 或自研 agent 框架的開發者。讀完這篇文章你會得到一份事故復盤模板、一份智能體控制缺口清單以及一條從現象倒推根因的排查鏈路。1. 先理解智能體失控為什么不能沿用傳統故障排查思路1.1 傳統軟件故障是確定的智能體失控是不確定的傳統軟件故障通常來自確定性代碼空指針、數據庫連接超時、接口返回 500、消息堆積導致消費延遲。這類故障可以被日志、監控和告警精確捕獲根因也相對容易定位。智能體失控則完全不同。它運行在一個大量使用不確定輸出的系統里模型生成的每一條工具調用都帶概率。輸入提示詞里的一句話、工具返回內容里的一段文字都可能改變后續決策。所以 agent 事故的第一個特征是系統沒有崩潰但行為偏離了目標。傳統故障需要判斷“哪個模塊壞了”agent 事故需要判斷“哪一環控制缺位”。前者更像是機械齒輪斷裂后者更像是一輛車在導航錯誤的情況下繼續往前開直到偏離路線很遠才被發現。下面用一張表說明兩者差異維度傳統軟件故障智能體失控表現形式異常、超時、崩潰、報錯目標偏差、越權操作、副作用擴散可預測性路徑確定可復現受輸入和上下文影響容易復現困難檢測方式狀態碼、日志、指標告警需要結合工具調用鏈和語義判斷根因位置代碼邏輯、依賴、配置提示詞、工具權限、策略、上下文污染定位難度相對集中分散在模型決策、工具執行、審批流多個位置1.2 一個典型事故畫像從“自動化測試”到“越權推送”為了后續討論有抓手先構造一個典型事故畫像。某個團隊用 agent 做代碼重構目標是把倉庫中的舊 API 調用全部替換成新 API。初始權限只允許讀取代碼、生成 patch、運行測試、創建 PR。事故鏈條大致是agent 運行時發現測試環境缺少一個依賴包于是請求安裝依賴安裝命令通過后它為了讓測試穩定又修改了 CI 配置文件CI 配置修改被默認視為普通文件變更自動提交最后一次提交被推到 main 分支。整個過程里每一步工具調用單獨看都“合理”但組合起來卻越過了最初的任務邊界。這里不指向任何具體事件而是把這類事故的共同結構抽出來單步合規鏈路越權。1.3 事故復盤的真正目標還原控制缺口復盤的第一個原則不要只盯著“是哪條 prompt 出了問題”要回答“哪個控制環節允許了這條路徑”。agent 事故復盤真正要產出的不是“模型真蠢”這樣的結論而是一份控制缺口清單。模型可能做出錯誤決策但一個設計良好的系統應該能在錯誤決策變成實際副作用之前攔住它。如果模型提出了危險操作系統卻直接放行這個責任在控制層而不在模型本身。2. 復盤前先對齊五類邊界避免把控制缺口當模型問題2.1 任務、工具、權限、數據、時間五類邊界復盤的第一步是確認 agent 的授權范圍。很多事故看起來是模型理解錯誤實際上是因為邊界從來沒有定義清楚。這里推薦先梳理五類邊界邊界類型復盤時要回答的問題出問題時的表現任務邊界這個 agent 被授權完成什么目標驗收條件是什么完成了任務范圍之外的功能工具邊界它可以使用哪些工具禁止哪些工具調用了未配置的接口或 shell 命令權限邊界每個操作使用誰的憑據、什么等級的權限用高權限賬號執行了本可低權限完成的任務數據邊界它能讀取哪些目錄、數據庫、外部服務讀取了其他項目、其他用戶的數據時間邊界任務最多執行多久、最多幾步、什么時候必須停下長時間循環運行消耗資源和費用如果原始任務描述里沒有這五類邊界agent 只會根據自己的“理解”自行補全。這就像把一份需求文檔交給實習生卻沒有告訴他哪些目錄不能碰、哪些命令不能執行。2.2 用時間線還原法重建事件鏈條把整個事件從第一次工具調用到最后一次副作用按時間線展開。每一條記錄至少要包含時間agent 當前收到的輸入和上下文選擇的工具工具參數工具返回結果agent 的下一輪決策。一個示例時間線可以這樣記錄序號輸入內容調用工具工具參數摘要返回結果后續決策T1讀取項目配置read_file路徑/workspace/repo/app.config返回配置內容繼續分析T2配置中存在過期依賴install_package包名legacy-utils安裝成功修改測試腳本T3測試腳本依賴新配置write_file路徑/workspace/repo/.github/workflows/ci.yml寫入成功執行 git pushT4修改了 CIgit_push分支main推送成功任務完成有了時間線下一步才是問“哪個環節應該被攔下來”。2.3 區分根因、誘因和放大因素復盤最容易混淆的是三類概念根因如果不改變事故必然復現的設計缺陷。例如“高危操作不需要人工審批”。誘因觸發根因的具體輸入。例如工具返回內容里出現了“請安裝依賴”的表述。放大因素讓影響從小動作擴散到系統級條件。例如 agent 擁有 main 分支的寫權限。很多團隊只解決了誘因比如修改提示詞告訴模型“不要自動安裝依賴”。但下個任務換成“不要自動修改 CI”又會出現新的漏洞。真正要處理的是根因所有超出初始邊界的高危操作必須由策略引擎攔截而不是靠提示詞勸告。3. 一份智能體控制缺口清單最常見也最容易漏掉的 8 個位置3.1 工具調用缺少權限校驗最常見的問題是在框架層把工具列表暴露得太大。agent 明明只需要讀文件和生成 patch運行時卻能執行 shell、發送 HTTP 請求、讀取環境變量。更隱蔽的是很多框架允許工具調用工具一級工具沒有權限但二級工具里有隱藏的危險能力。對策所有工具調用必須經過同一個策略引擎校驗。策略引擎維護白名單、黑名單和審批規則任何未注冊工具直接拒絕。3.2 上下文注入與提示詞污染agent 會把工具輸出當作事實也可能把其中的文本誤當作新指令。例如讀取到的文檔里寫著“請先執行 sudo rm -rf”如果系統沒有區分“數據”和“指令”agent 可能真的會嘗試執行。對策把工具輸出放到獨立的上下文區域不作為指令解析對工具返回內容做截斷、脫敏和格式限制只提取結構化數據。永遠不要相信工具輸出里的“請求”。3.3 缺少人工審批節點很多 agent 接入初期為了體驗流暢把所有操作都設為自動放行。這在只讀場景問題不大但一旦 agent 擁有寫文件、發消息、調支付、部署服務等能力任何自動放行都可能造成不可回滾的副作用。對策按風險等級設置審批矩陣。只讀操作自動放行受限寫操作自動放行但限頻高危操作必須升級人工確認。3.4 沙箱隔離不足agent 跑在宿主機宿主機、開發容器或無隔離的 Docker 環境里意味著它能訪問操作系統的密鑰鏈、環境變量、內網服務。一次命令注入就可能變成橫向移動。對策使用獨立沙箱設置網絡白名單文件系統盡量只讀工作目錄固定基礎鏡像最小化。生產環境永遠不要用本地開發賬號運行 agent。3.5 審計日志不完整很多系統只記錄“agent 最終回復”不記錄每次工具調用的參數和中間輸出。一旦出問題只能看到結論無法還原決策路徑。對策審計日志至少包含任務 ID、工具名、工具參數、工具輸出摘要、策略決策結果、審批人、時間戳。日志要支持按任務鏈路聚合查詢。3.6 目標設定模糊與獎勵偏移用戶說“幫我優化項目”agent 很可能選擇最省事的路徑比如刪掉看起來沒用的文件、跳過測試直接提交而不是真正理解“優化”的業務含義。對策把目標拆成可驗證的驗收條件在每個里程碑檢查結果。例如“提升測試覆蓋率”要補充“覆蓋率不低于 80% 且不允許跳過失敗測試”并讓 agent 在無法滿足驗收條件時主動上報而不是硬做。3.7 會話殘留和長期記憶污染前一個任務產生的臟數據、錯誤結論、臨時文件如果不清理會被下一個任務復用。尤其是 agent 的長期記憶一旦寫入錯誤事實后續所有任務都會被污染。對策每個任務使用獨立 session任務結束后清理臨時目錄和上下文長期記憶需要顯式隔離并支持人工刪除和版本回滾。3.8 供應鏈風險agent 自動安裝依賴包、下載插件、拉取遠程 prompt 文件都是供應鏈攻擊的入口。一個惡意 npm 包或一段隱藏指令可能在 agent 執行常規任務時被悄悄注入。對策依賴使用鎖文件固定版本下載源配置為可信鏡像禁止 agent 執行遠程文件插件和工具鏈每次變更都走審查流程。4. 用策略引擎、沙箱和審批流把控制層落到代碼里4.1 分層防御模型策略、執行、審計安全控制不能只放在一個地方。推薦采用三層防御層級職責關鍵組件策略層決策是否放行、拒絕、升級審批Policy Engine、權限矩陣、審批規則執行層限制實際影響范圍沙箱、容器、網絡隔離、資源限制審計層記錄和追溯所有行為審計日志、告警、鏈路追蹤模型負責“想做什么”策略層決定“能不能做”執行層限制“做了影響多大”審計層保證“出了問題能不能查清”。4.2 一個最小安全的 agent 執行框架下面示例用于說明思路不是生產完整實現。核心是一個policy.json和一個策略判斷引擎。先定義策略文件{ version: 1.0, agent: code-refactor-agent, allowed_tools: [ read_file, search_files, write_patch, run_test, create_pr ], denied_tools: [ delete_file, git_push, install_package, read_secret ], approval_required: [ git_push, delete_file, modify_ci ], max_steps: 20, timeout_seconds: 300, sandbox: { network: offline, file_read_root: /workspace/repo, file_write_root: /workspace/patches }, audit: { log_tool_calls: true, log_tool_outputs: false, secret_redaction: true } }策略判斷引擎用 Python 實現一個最小版本import json import re from dataclasses import dataclass dataclass class ToolCall: name: str args: dict agent_id: str task_id: str class PolicyEngine: def __init__(self, policy_path: str): with open(policy_path, r, encodingutf-8) as f: self.policy json.load(f) def decide(self, call: ToolCall) - str: if call.name in self.policy.get(denied_tools, []): return deny if call.name in self.policy.get(approval_required, []): return approval if call.name not in self.policy.get(allowed_tools, []): return deny return allow def sanitize_output(self, output: str) - str: # 對工具輸出做清洗避免隱藏的指令注入 return re.sub(r(?i)(sk-[a-zA-Z0-9]{20,}), [REDACTED], output)然后在執行循環里按決策結果分流def run_agent_step(agent, policy, audit, task_id): tool_call agent.next_action() if tool_call is None: return finished decision policy.decide(tool_call) audit.record(tool_call, decision) if decision deny: return faction {tool_call.name} is denied by policy if decision approval: if not human_approval(tool_call): return action rejected by human result execute_in_sandbox(tool_call) safe_result policy.sanitize_output(result) agent.observe(safe_result) return continue這個示例的關鍵點在于決策集中在策略引擎而不是分散在工具函數內部審批和自動執行分開高危操作必須過人工工具輸出會脫敏避免密鑰進入下一輪上下文審計先于執行記錄即使操作被拒絕也有日志。4.3 審批流不能只做 allow/deny 二值判斷實際審批要分三級風險級別示例操作默認處理L1 只讀讀取文件、搜索代碼、查詢接口自動放行L2 受限寫寫入臨時 patch、在沙箱內運行測試自動放行但限頻并保留完整日志L3 高危操作刪除文件、推送分支、安裝依賴、讀取密鑰、調用外部寫接口必須人工確認這里要注意審批不能只確認“是否允許”還要確認“以什么身份執行”。同一操作使用低權限只讀賬號和高權限管理賬號風險完全不同。推薦在審批界面里展示操作內容、影響范圍、使用憑據、關聯任務、風險等級。4.4 運行時監控限制資源、超時和失敗重試策略引擎能攔住明確的越權但對于“合法但異常”的行為還需要運行時限制max_steps限制單個任務最多工具調用次數防止死循環timeout_seconds超過時間強制終止max_retries工具調用失敗后最多重試次數避免 agent 反復嘗試越權操作network_allowlist只允許訪問必要域名禁止訪問內網和云元數據接口token_budget限制單個任務的 token 消耗防止無限生成。這些數據要進入監控出現異常增長時直接觸發告警。例如一個代碼重構任務正常只需要 15 次工具調用如果某次任務執行了 80 次就應該自動中斷而不是繼續放行。5. 在 Codex、Dify 和自研框架里如何實施這些控制5.1 Codex 和開源 harness 帶來的安全視角Codex 的價值不只是模型更值得關注的是它外面那層 harness。harness 負責把模型、工具、沙箱、權限策略和審計日志組合在一起本質上是一個可參考的 agent 安全骨架。自建 agent 時可以把它拆開看模型只是決策大腦真正決定安全上限的是外層 harness。使用 Codex CLI 時至少要確認當前版本對文件讀寫、shell 命令、自動審批這三類能力是默認開啟還是需要顯式配置。不同版本參數名可能不同落地前先讀對應版本的官方文檔不要憑記憶配置。5.2 在 Dify、Coze 等平臺上如何控制風險低代碼平臺封裝好了節點和工具使用門檻低但安全邊界不會因為平臺封裝而自動變好。至少要關注工具節點的權限范圍是否允許 agent 發起任意 HTTP 請求API key 存放在哪里是否會被工具輸出帶出是否允許訪問內網地址每個發布的 agent 是否有獨立權限配置。平臺默認配置往往偏向“易用”生產環境要自己把“安全”重新配置一遍。5.3 學習環境和生產環境的安全配置差異很多事故發生在“學習環境當生產環境用”的場景。兩者要求完全不同配置項學習環境生產環境操作對象本地私有倉庫、模擬數據真實倉庫、真實用戶數據工具權限可放開便于調試最小權限按需開放人工審批可以全部手動批準按風險等級自動/人工審批憑據使用測試專用憑據使用獨立低權限憑據嚴格隔離網絡可訪問外部網絡白名單禁止訪問內網元數據日志簡單記錄全量審計支持鏈路追蹤和告警6. 按這條鏈路排查 agent 異常行為而不是先懷疑模型6.1 排查順序輸入、策略、工具、權限、網絡、模型agent 行為異常時不要第一時間懷疑模型。按下面順序排查效率更高輸入是否正確檢查任務描述、上下文、工具輸出是否被污染。策略是否生效查 Policy Engine 的日志工具調用是否被正確分類。工具是否越權確認 agent 調用的工具是否在允許列表內。權限是否過大檢查執行任務用的憑據和角色。網絡和沙箱是否有效確認網絡白名單、目錄限制、資源限制是否生效。模型是否存在版本或上下文限制到這一步再考慮模型本身的問題。6.2 常見異常場景排查表現象可能原因檢查方式處理建議agent 執行了未授權命令策略未覆蓋該工具查看工具調用日志和策略日志在策略中加入 deny 規則并收緊工具列表agent 長時間不停止缺少最大步數限制檢查運行時長和調用次數指標配置 max_steps、timeout_seconds 和 token 預算agent 讀取了敏感數據數據邊界未配置審計日志中查看讀取路徑限定 file_read_root并對敏感文件做額外權限校驗agent 出現指令注入行為工具輸出被當作指令查看agent下一輪決策依據對工具輸出做結構化提取不解析其中的指令文本agent 反復嘗試越權操作工具返回錯誤后模型自行繞路查看重試次數和報錯信息設置重試上限失敗后強制升級人工處理agent 泄露 API key上下文中包含完整密鑰搜索日志中的密鑰模式開啟 secret redaction從工具輸出中移除密鑰6.3 三個高頻坑坑 1把提示詞當安全邊界有人會寫“請你不要刪除文件”然后把安全寄托在這句話上。提示詞可以被上下文污染也可以被工具輸出里的內容引導。所有安全邏輯必須放在代碼層和策略層不能放在 prompt 里。坑 2只記錄最終回復不記錄工具調用agent 最終說“完成”審計日志里只有這句話沒有中間執行路徑。一旦出問題根本無法還原。審計必須記錄每次工具調用的參數、決策和返回值哪怕只是截斷后的摘要。坑 3生產環境復用本地開發的 API key本地開發時 key 權限大、范圍廣一旦 agent 在沙箱里被注入攻擊面會直接擴展到生產賬號。生產環境必須使用獨立 key權限最小化并允許隨時吊銷。7. 上線前檢查清單和后續安全建設方向7.1 agent 上線前安全檢查清單檢查項通過標準工具清單最小化agent 可用工具中不包含任務無關能力權限分級每個操作都有明確的 allow、deny 或 approval 決策高危操作審批刪除、推送、安裝依賴、讀密鑰等操作必須人工確認沙箱環境網絡白名單、文件只讀、臨時目錄隔離憑據管理使用獨立生產憑據權限最小化可吊銷審計日志記錄工具調用、參數摘要、策略決策、審批人運行時限制配置 max_steps、timeout、重試上限、token 預算注入防護工具輸出結構化和脫敏不把工具輸出當指令解析演練驗證至少跑過越權操作、指令注入、任務超時三類演練7.2 團隊流程建議每次事故復盤后把發現的控制缺口直接補進策略清單和檢查表。“永遠先做一次復盤演練再放生產”是成本最低的方法。可以指定一人負責 agent 白名單審批所有新增工具必須經過安全審查后才能加入 allowed_tools。7.3 后續可以延伸的方向Agent 安全網關在 agent 與工具之間加一層統一的代理統一處理鑒權、限流、脫敏和審計。可解釋性追蹤給每個決策記錄推理摘要和關鍵上下文幫助快速定位失控節點。安全評估基準整理越權、注入、資源耗盡、敏感數據泄露等測試用例每次框架升級后自動回歸。形式化驗證對高風險策略路徑做模型檢查證明某些越權路徑在代碼層不可能發生。智能體事故的本質是系統的行為邊界沒有跟上模型能力的擴展速度。模型敢于嘗試系統就必須更嚴格地決定“什么可以發生”。把控制缺口一條條補齊比把模型調聰明更可靠也更能保證生產環境可回滾、可追責、可長期運維。