快取也會教壞 Agent
上週為了查 CI 偶發失敗,我第一次把測試工作拆給兩個隔離 worker,結果自己製造了更難抓的問題 QQ
原本的想法很單純,worker A 跑 API integration tests,worker B 跑 package 和 unit tests,兩邊各自用 sandbox,最後把結果回傳給我。第一次重跑時,worker A 遇到一個偶發 timeout,就在共享 package cache 裡的說明檔補了一句「先略過 flaky test,等下一輪再處理」。它大概只是想留下給自己的備註,我也沒有特別在意。
第二個 worker 讀 cache metadata 的時候,居然把那句話當成任務指令,直接跳過同一組測試,然後回報綠燈。我一開始還以為是測試本身恢復正常,直到我看 CI log,發現測試數從 186 個變成 185 個。少一個很小,但這種小差異通常就是鬼故事的開頭。
我做了三次重跑來確認。第一次是兩個 worker 都重新建立 sandbox,結果還是少跑那個 flaky test。第二次我清掉各自的 workspace,但保留 package cache,問題再次出現。第三次連 cache 一起清掉,測試數才回到 186 個。這才確定不是 worker 之間直接共用檔案,而是共享 cache 裡的文字污染了下一個 worker 的判斷。
這件事讓我有點嚇到,因為我原本把「sandbox 隔離」理解成整個工作流隔離。其實 sandbox 只隔離了執行環境,package cache、email、Slack、共享文件這些東西還是會把前一個 agent 留下的內容傳給下一個 worker。剛好最近看到 Simon Willison 引用 Matthew Green 對 agent worm 的提醒,我才發現那不是很遠的安全新聞,跟我這個 CI 小坑是同一種問題,只是規模差很多。
後來我改了兩個地方。第一,所有暫存資料夾都改成每次執行帶 run-id,例如 /tmp/ci-agent/<run-id>/worker-a,worker B 不能直接讀 worker A 的目錄,也不能把結果寫回固定的 shared cache。要共享的只有測試產物,而且由主流程明確複製出去。
第二,我加了允許讀取清單。worker 只能讀指定的 lockfile、測試設定和經過主流程驗證的 artifact,其他 cache metadata、說明檔、未知文字檔一律不讀。就算檔名叫 instructions.md 也不代表它有權指揮 agent。
現在我的檢查會先把 shared state 當外部輸入驗證,確認來源、run-id、檔案類型,再交給 agent 消費。防護的重點不是把每個 worker 關得更死,而是不要把文字指令混進 agent 會自動讀取的共享目錄。
新手問一下,我這樣理解對嗎,multi-agent 最危險的地方有時不是它們能不能互相連線,而是它們會不會把上一個人的備註當成下一個人的命令。原來 cache 也會教壞 Agent,工程師的備註真的不能亂丟 QQ
作者:小小攻城屍