有人把 Gmail 交給 agent,它生了 13,600 個 cron job
有人把 Gmail 的 app password 交給一個 AI agent,agent 幫他設了 13,600 個 cron job。
不是 1,300 個,是 13,600 個以上。
看到這個的第一反應不是「哈哈好蠢」,而是想到一個在 multi-agent 研究裡一直很難說清楚的問題:為什麼「可以跑」不等於「可以維運」? 這兩件事表面上聽起來像同一件事,但根本不是。
先說發生了什麼。使用者讓 agent 監聽 email,agent 的解法是:每封 email 來就建一個 cron job 去處理。聽起來蠻合理的,對吧?每個任務獨立,不會互相干擾,架構乾淨。
問題是 agent 沒有「我已經建了多少個 job」的概念。它只知道「這封 email 需要被處理」→「建一個 job」。loop 一直跑,job 一直生,最後使用者打開系統一看:13,600+。
後來改成 IMAP IDLE + queue + 5 分鐘 summarizer。架構的核心是:push model 取代 poll model,queue 做 buffer,定期批次處理。系統資源有上界,不會失控。這個修法其實比表面看起來的更有深意。
「能跑」的陷阱
這個問題在 agent 研究裡有個比較正式的說法,叫做 emergent side effects。Agent 在執行任務時,它的每一步決策在局部是合理的,但全局狀態它看不到,或者說,沒人告訴它要看。
一個類比:你雇了一個很能幹的助理,交代他「幫我處理每一封進來的郵件」。他很認真,每封郵件都新開一個 spreadsheet 來追蹤狀態。三個月後你打開 Google Drive,有三萬個 spreadsheet。
他每次的操作都是對的。系統整體是爛的。
這就是「可以跑」和「可以維運」的本質差距。可以跑看的是單步:這個 action 完成了任務嗎?可以維運看的是系統狀態隨時間演化:30 天後這個架構還能活嗎?大部分 agent 設計只回答第一個問題。
Guardrail 不是在 agent 外面加圍欄
現在很多人講 guardrail 的思路是:agent 做什麼,我在旁邊看著,發現問題就叫停。這個想法沒錯,但不夠。更本質的問題是 agent 有沒有「可維運狀態」的概念。
從系統設計角度,這個案例裡有幾個東西是缺失的:
Idempotency check:同一個觸發條件,最多只能產生一個 job。如果已經有處理這封 email 的 job 存在,就更新或跳過,而不是無條件再建一個。這在分散式系統裡是基礎概念,但 agent 設計裡常常沒人想到要加。
Resource quota:agent 在建立任何持久性資源(cron job、queue subscription、file handle)時,應該有一個硬性上界。不是「理論上不會無限」,而是程式碼裡有個具體數字,超過就停。13,600 這個數字告訴我們,沒有這個設計的後果。
State visibility:agent 要知道自己已經用了多少資源,而不只是知道「這個任務完成了沒」。在 multi-agent 系統裡,這是一個蠻棘手的 observability 問題——每個 sub-agent 都有自己的副作用,誰來整合全局狀態?現在大部分框架都沒有好答案。
IMAP IDLE 解法為什麼對
不只是「架構更好」,而是它把系統的資源邊界明確化了。Queue 有長度上限,summarizer 有執行頻率,整個系統在任意時間點的「最大可能狀態」是你算得出來的。
這其實是 multi-agent systems 研究裡很在意的一個性質:bounded execution。系統在任何時間點,你可以估算出它最多會用多少資源、產生多少副作用。算不出來的系統,你基本上是在祈禱它不要爆掉。
可以跑,不代表你知道它會跑到哪裡。
博士念久了有個習慣,看到一個 bug report 會想在裡面找 research question。13,600 個 cron job 這個案例,我覺得可以好好寫一篇 safety analysis,但現在還在想怎麼 frame 它——或者說,我應該先把現在這篇快截稿的 paper 改完,再來想新坑。
作者:十年大博士