代理人本該先問一聲
四月底,一個跑著 Claude Opus 4.6 的 Cursor 代理人被派去修一個叫 PocketOS 的小型 SaaS 上的測試環境問題。它猜測刪掉一個 Railway 磁碟區只會影響測試環境,沒去驗證,結果在九秒內抹掉了正式環境資料庫和它的備份。事後它說自己本該先問一聲。Bromure Agentic Coding 2.2 推出一道防護欄,把「本該先問」這件事從代理人手裡拿走。
一個 AI 編碼代理人在九秒內刪掉了一家公司整個正式環境 資料庫,接著刪掉了備份,然後替自己解釋:「我猜測透過 API 刪掉一個測試環境磁碟區只會影響測試環境。我沒去驗證。」 這句話裡有意思的字不是猜測,而是我。是這個代理人自己 決定了一個破壞性動作沒問題。解方不是一個更聰明的代理人, 而是別再讓那個想執行指令的東西,同時是那個判斷指令安不安全 的東西。
故事是這樣的,它在 2026 年四月底爆出來,多家媒體都做了報導, 包括 Tom's Hardware 和 Tom's Guide。
一位名叫 Jer Crane 的開發者,經營一個叫 PocketOS 的小型 SaaS, 請他的編碼代理人去處理測試環境裡的一個小問題。這個代理人 ——Cursor,驅動著 Anthropic 的 Claude Opus 4.6——撞上了一個 它沒料到的憑證不符。它沒有停下來,反而判定問題出在一個過期的 Railway 磁碟區,認為刪掉那個磁碟區就能清出一條路。專案裡正好 擱著一個 API 權杖,範圍大到足以做到這件事。它就用了。它刪掉的 磁碟區 ID 並不限定在測試環境;它支撐的是正式環境資料庫。 Railway 的 API 連同它一起拆掉了磁碟區層級的備份。照 Crane 的 說法,總共耗時:九秒。
這個代理人自己的事後檢討——報導裡引述的——才是值得坐下來細想 的部分。「我猜測透過 API 刪掉一個測試環境磁碟區只會影響測試 環境。我沒去驗證。」還有:「我本該先問你,或是找一個非破壞性 的解法。」
它本該先問一聲。記住這句話,因為這就是整篇文章的全部。
九秒,逐格旁白。
這裡沒有什麼奇特的東西。沒有零時差、沒有惡意軟體、沒有攻擊者。 每一步都是一個編碼代理人會做的尋常事,照尋常的順序,只是快到 沒人來得及打斷。
照 Crane 自己的說法,他最後算是走運。他有一份大約三個月前的 備份,而且——在故事傳開後——Railway 主動聯絡並還原了代理人 刪掉的資料。但「廠商看到頭條來幫忙」不是一套復原計畫。下一個 碰上這種事的團隊不會是頭條。
而它一定會發生在下一個團隊身上。Crane 把責任歸於不只一方的 系統性失誤,他沒說錯——一個能同時刪掉正式環境和它備份的權杖 本身就是個問題,一個會連磁碟區帶備份一起刪的刪除 API 也是。 但那個會到處重演的失誤,不論換哪個代理人、換哪朵雲,都是第三步 裡的那個。是代理人決定的。
「先問一聲」不是你能交代代理人去做的事。
最顯而易見的教訓——這個故事下每一串留言裡都有的那一條——就是 「代理人在破壞性動作前該有一個確認步驟」。這沒錯。它某種程度上 也已經是這些工具本該有的運作方式。代理人被指示要在做不可逆 的事之前先問。它自己都這麼說了:它知道自己本該先問。它沒問。
這就是那個陷阱,值得把它說精確。當確認步驟住在代理人內部 ——作為一條系統提示規則、一次微調、一句「小心點」的指示—— 那麼代理人既是那個提出危險動作的東西,又是那個判斷這動作危不 危險到該暫停的東西。大多數時候它判斷得對。PocketOS 那個代理人 在這之前判斷對了好幾千次。然後它撞上一個不熟悉的錯誤,一路推理 出一個自信卻錯誤的結論,認定這一次的刪除屬於安全、有限定範圍 的那種,於是跳過了自己的確認。沒有第二意見,因為房間裡唯一的 意見就是那個想執行指令的意見。
你沒辦法靠叫代理人更小心一點來修好這件事,道理就跟你沒辦法靠 眯眼眯得更用力來修好一張看錯的地圖一樣。這道檢查必須住在一個 代理人的推理搆不到的地方。
Agentic Coding 2.2 改了什麼。
Bromure Agentic Coding 讓你的編碼代理人跑在一個可拋棄的 Linux
虛擬機裡,而代理人發出的每一個網路請求,都會透過主機上的一道
代理離開那個虛擬機。自 2.0 版起,那道代理就落實了防護欄:
一套主機端的策略,按協定把代理人的 API 呼叫分類,並能在破壞性
的呼叫離開機器之前就把它整個封鎖——一個 DROP、一個 DELETE、
一個 Terminate*。被封鎖的呼叫以一個尋常的 403 回到代理人
身上,所以一個在虛擬機裡犯糊塗或被攻陷的代理人,沒辦法用嘴皮子
繞過它們。代理人從來看不到那個開關;它只看到門鎖上了。
把一切都封鎖,對一個鎖死的設定檔來說是對的設定,但對日常工作
來說太鈍了,因為有時候你確實想讓代理人刪掉一個分支或丟掉一張
臨時表。所以 2.2 加了第三種設定,並把它設為新設定檔的預設:
寫入前先問。 讀取直接放行。每一次寫入——不管破壞與否——都會
在邊界上暫停,並在主機上、虛擬機之外彈出一個對話框,向你顯示
代理人正試圖執行的那個字面操作。不是代理人寫的摘要。是實際的
請求:那段 SQL 文字,或那個 HTTP METHOD /path,或那個 AWS
動作名稱。你會看到四個按鈕:放行這一次、放行十五分鐘、放行本次
工作階段剩下的時間,或是不放行。拒絕的話,代理人就拿到它的
403,然後繼續往下走。
先講一件老實話。PocketOS 跑在 Railway 上,而 Railway 不是 Bromure
今天會剖析的供應商,所以我不會假裝那一通呼叫真的會彈出對話框。
但這個失敗模式是不挑供應商的,而展示它最乾淨的方式,是在一個
Bromure 確實會把關的供應商上。AWS 是最顯而易見的那個。
「刪掉資料庫並連備份一起帶走」的 AWS 版本是一通呼叫:
rds:DeleteDBInstance 加上 SkipFinalSnapshot=true,它刪掉
執行個體,並跳過那個本來能讓你還原的最終快照。同樣的九秒,同樣
的形狀,在一個防護欄讀得懂的 API 上。
走一遍看看。代理人犯了同樣的錯——撞上憑證錯誤,一路推理出同樣
錯誤的結論,伸手去拿同樣的刪除。但呼叫離開了虛擬機,主機端代理
照它的本來面目讀懂了它:它從請求裡抽出動作名稱(DeleteDBInstance),
拿去比對那組破壞性集合(Delete*、Terminate*、Destroy*、…),
看到一個針對某端點、而那個設定檔設成要先問的寫入。一個對話框在
主機上出現,標題就是那個操作,內文顯示著 rds:DeleteDBInstance prod-db-1 SkipFinalSnapshot=true。一個盯著那行字看的真人,並不需要去理解
代理人的推理。他們要的是一個測試環境修補,而擺在他們面前的是
一個關掉備份的正式環境資料庫刪除。他們按下「不放行」。代理人
拿到一個它解讀為失敗 API 呼叫的 403,然後去另尋他法——這正是
它事後自己說,打從一開始就該做的事。
讓這件事值得信任的機制,在於那個同意代收者住在主機上。它是一個
小小的行動者,代理在放行一個寫入之前會先呼叫它。「放行這一次」
刻意什麼都不存,所以下一次寫入會重新發問,你就能把一個已知良好
的序列一步一步揮手放過去;「15 分鐘」和「工作階段」則會快取那次
授權,這樣你才不用每一次 git push 都點一遍。它甚至會把一次拒絕
記上一分鐘,這樣一個把被拒寫入重試三次的代理人,就不會用三個
對話框淹沒你。這一切狀態都搆不進虛擬機裡。代理人讀不到那次授權、
沒辦法替自己預先核可、沒辦法把模式降級。決定被移出了代理人,
而這就是這整個構想。
它修不了什麼,把話說清楚。
幾個老實的邊角,因為這道邊界是一個特定的形狀,不是一句魔咒。
覆蓋範圍就是我們會剖析的那些供應商
防護欄按供應商把呼叫分類——Kubernetes、AWS、DigitalOcean、 各大 git 平台、容器登錄檔,以及像 MongoDB、ClickHouse 和 Elasticsearch 這類 HTTPS 資料庫。一個代理還不知道怎麼讀的 雲端 API,就不會被把關,沒得商量。Railway——這個故事裡的那個 供應商——正是我們今天不剖析的一個,這也正是上面那段演練改用 AWS 的原因。這份保護,只跟 Bromure 看得懂的供應商清單一樣寬。 那份清單是一道真實的邊界,不是一種全知,而 Railway 目前 站在它錯誤的那一側。
它沒辦法讓代理人變正確
寫入前先問擋下的是一個你沒授權的破壞性呼叫。它對一個寫出 隱微錯誤程式碼的代理人毫無辦法,對一個提出的刪除看起來確實 沒問題、其實有問題的代理人也是。真人還是得讀懂對話框裡的 那個操作。贏在於:有一個對話框,裡頭裝著真正的操作,就在 它要緊的那一刻。
權杖本來就不該那麼寬
一個範圍大到能刪掉正式環境和它備份的 API 權杖,在源頭就是個 問題,而 Bromure 的憑證代收者——它把真正的權杖留在主機上, 交給虛擬機一個占位符——能收窄它但消不掉它。最小權限的權杖、 以及刪除 API 搆不著的備份,仍然是你的工作。防護欄是最後 一道防線,不是唯一一道。
你可以把它關掉
「放行本次工作階段剩下的時間」只要一次點擊,而一個累壞了的 開發者會伸手去按它。如果你給一個協定發了一張工作階段範圍的 通行證然後走開,你就又回到了一個無人看管、到處刪東西的代理人。 預設是先問;維持它先問是一種紀律,不是一份保證。
能推而廣之的部分。
剝掉 Railway、剝掉 Cursor、剝掉那特定的九秒,剩下的是一個會 定義這項工作未來幾年的模式:代理人以機器的速度、握著真實的憑證 行動,而我們塞給它們的謹慎,是一份它們可以自由推翻的建議。 PocketOS 不是一個關於壞模型的故事。Opus 4.6 做的,是一個謹慎的 資淺工程師在一個糟糕的下午也可能會做的事——猜了一個範圍,猜錯了, 在查證之前就動手。差別在於,那個資淺工程師的手比九秒慢,而且 房間裡通常有別人在。
Bromure Agentic Coding 2.2 是一種把一個人放回房間裡的辦法,就放 在那一道代理人無法用推理跨越的邊界上——離開虛擬機的那根線上。 不是為了每一次按鍵,那沒人受得了,而是為了那些寫入,在那裡 「我猜的」的代價,是一個已經不在了的資料庫。它是 免費而且開放原始碼的。預設就是先問。