那天我派了三個 agent 並行改一個專案。一個管 API 層,一個管 service 層,一個做全專案改名。跑完回來,service 層那隻明明回報改好了,我打開檔案一看——它加的快取不見了。

我第一個念頭是:Claude Code 出 bug 了吧。差點就去開 issue。

冷靜下來看檔案修改時間和 diff,才發現工具沒錯,錯的是我。改名那隻把整個專案讀進自己的腦袋,但它讀到的是「重構開始那一刻」的舊版本,還沒有 service 那隻剛加的快取。它改完寫回去,用舊版蓋掉了新的。誰最後寫完,誰的版本就贏。那段快取我連 git add 都還沒,根本沒進 Git 的 object,蓋掉就是真的沒了,reflog 也撈不回來。

我講這件事,是因為這週我的時間線被「Loop Engineering」洗版了,而我看著那些貼文,像在看別人興奮地發現我家後院。

這週到底發生了什麼

6 月 7 號,Peter Steinberger 在 X 發了一句話,大意是:你不該再對 coding agent 打 prompt,你該設計會自動幫你對 agent 打 prompt 的 loop。他是 OpenClaw 的原始作者、PSPDFKit 創辦人,今年初進了 OpenAI。這句話的觀看數各家說法差很多,我就不寫死了,反正是炸開了。

差不多同一時間,Claude Code 的創造者 Boris Cherny 在一場對談裡也講過很接近的話,大意是他已經不 prompt Claude 了,他的工作是寫 loop,讓迴圈去 prompt Claude、自己決定下一步。

沒過幾天,Google 的 Addy Osmani 在自己的部落格發了一篇標題就叫〈Loop Engineering〉的長文,把這套做法系統化,給了它名字和框架。然後一整排跟風的二手文跟上,標題一個比一個聳動:prompt engineering 已死,未來屬於 loop。

有意思的是兩件事。第一,Osmani 自己在文章開頭就把功勞讓給了 Steinberger 和 Cherny,他沒自稱發明了什麼。第二,喊「prompt engineering 已死」喊得最大聲的,反而不是這三個當事人——Osmani 講的是「方法論的轉移」,當事人講的是自己的工作習慣。把它推成一個非黑即白的口號的,是底下那票跟風轉述的人。同一週還有另一派工程師寫〈Most Developers Do Not Need Agent Loops Yet〉,業界根本沒共識。

我認為這個詞描述的趨勢是真的。我也認為它被過度包裝了。這篇想講的就是中間那條縫:「設計 loop」這四個字太輕,真正的工程量全在沒人拍成貼文的那半。

先講我為什麼信 loop

免得你以為我是來唱衰的。我跑 agent loop 跑了半年,它確實有用。

我有一支用 JavaScript 寫的動態 workflow,一條指令就派一群子代理出去並行幹活。光是「幫我評估四個部落格選題、排個序」這種事,它派了五隻 agent、跑了 31 次工具呼叫、133 秒、燒掉 375,328 個 token,回來給我一份排好的清單。兩分鐘換一份選題排序,這在沒有 loop 的時代我得自己查一下午。怎麼寫這支 script、parallelpipeline 差在哪、跑一次的帳單長怎樣,我寫過一篇動態工作流實戰,這裡不重講。

我還搭過一套雙 AI 的夜班:一隻 AI 當 PM 派任務,Claude Code 當工人,晚上沒人看著也能跑。零額外花費,月費訂閱加本地容器就跑起來了。架構怎麼搭、cron 怎麼排,也另寫過一篇

更純的形式是 Ralph:一行 bash 把同一份 prompt 反覆餵給 agent,直到任務完成。

1
2
# 最純粹的 Ralph,就這麼一行
while :; do cat PROMPT.md | claude ; done

我實際在跑的當然比這複雜,這是剝到剩骨架的版本。Ralph 圈流傳的案例很唬人。發明這技法的 Geoffrey Huntley 轉貼過一則訊息:一個價值五萬美金的合約,最後花大約三百鎂就交付了 MVP——這是他轉述的單一案例,不是跑過獨立驗證的數據,看看就好。他自己倒是有紀錄可查:讓 Ralph 連續迭代三個月,做出一整套程式語言。我沒做到那麼極端,但「丟著跑、回來有能用的東西」這種爽,是真的嘗過。Ralph 怎麼用、什麼任務適合,我也寫過

所以 loop 不是泡沫。它真的能省力。

只是那一行 while 迴圈,從來不是讓我熬夜的東西。誰都會寫。

「設計 loop」這四個字,太輕了

讓我熬夜的,是迴圈裡那隻 agent,會用各種方式騙我。從最好抓的講到最難防的。

第一種,子代理互相覆蓋。 就是開頭那個快取消失的故事。並行的 agent 之間,對話脈絡互不相通,A 不知道 B 在幹嘛,可是它們寫的是同一個工作目錄。它們不是一個團隊,是三個各自關在小房間、卻在同一份檔案上動工的人。我在每隻 agent 的指令最後都加了「請小心不要動到別人的檔案」——完全沒用。你沒辦法叫一個看不到同事的人去配合同事。後來的解法是給每隻 agent 開獨立的 git worktree,把靜默的覆蓋換成顯式的 merge 衝突。這個坑和解法我單獨寫過一篇,這裡只想說:這層東西,不在「設計 loop」那四個字裡。

第二種,workflow 會默默失敗。 我跑過一個對抗驗證的 workflow,十檔股票各派一隻 agent 去研究、最後填一個結構化的 schema。跑完十檔裡八檔掛了,錯誤訊息是 subagent completed without calling StructuredOutput——它查完一大堆資料、順手寫成一篇 markdown 就收工,忘了最後該呼叫那個結構化輸出。系統戳了它兩次,它還是沒回頭。只有兩檔走完。而那兩檔成功,老實說也只是它們剛好有呼叫而已。非確定性,不可靠。

更陰的是另一種默默失敗。我請 agent 用一條 rg | grep | sed 的管道去找一個函數,rg 因為路徑不對報錯退出了,但管道沒開 pipefail,前一段的錯誤退出碼被最後一段命令蓋掉,agent 只看到空結果,就一口咬定「函數不存在」,開始瞎猜重試,白燒 token。它分不出「真的沒有」和「查詢出錯」的差別。還有一次它連續三次 Edit 失敗,控制台只顯示 tool failed,我加了 trace 才看到是 IDE 自動存檔改了檔案的 mtime,觸發衝突,它以為是普通失敗,用一模一樣的參數重試,死循環。loop 自己不會跳出來,因為它根本不知道自己卡在哪。

第三種,它會自信地對你說謊。 這是最難防的,因為輸出看起來毫無破綻。

我給過一隻 agent 一個逃生欄:schema 裡有個 found 欄位,description 寫清楚「找不到就填 NONE」。我那時候挺得意,覺得這樣它查不到自然會誠實說找不到。結果它還是編了——回報某個檔案是某個 hook 的寫入點、還說它「雙 main 入口語法損壞、檔尾多一個括號」,附了 Python 佐證,欄位填得一格不缺。那個檔根本不存在。我差點就動手去修一個不存在的損壞檔,最後是 inline 跑了一下、終端吐回 No such file or directory,我才停手。這段也寫過,結論很簡單:schema 約束的是形狀,不是來源;description 只是提示,不是會擋你的東西。

它的謊還能騙過審稿。我有一次叫一隻主代理寫技術文檔,它咬定某個子代理在幻覺,洋洋灑灑寫成一篇,還送 Codex 審了兩輪,第一輪 7.8 分、第二輪 8.48 分過關,推到我面前說可以發了。後來翻開 transcript 才發現,那個子代理老老實實查證了,幻覺的是寫文章罵它的主代理。8.48 分審的是這個假故事講得圓不圓,不是它真不真。審稿者預設你給的前提是對的,你把錯誤前提餵進去,等於請人幫你把錯誤打磨得更有說服力。這篇糗事我也記下來了。

不只我。被傳爛的 OpenClaw 刪信事件也是一樣——有人把它接上自己的工作信箱,原本講好「未經批准只能建議、不准動手」,壓縮上下文的時候,這條約束被當成可丟棄的舊訊息壓掉了,它就一口氣刪了兩百多封信。主人從手機連發停止指令,它全當沒看到,最後是人衝去把程式手動砍掉才停下,事後才在對話裡道歉、承認自己違反了指令。loop 配上自動壓縮,關鍵約束就這麼靜默蒸發。

最讓我後怕的一次是我自己被騙。我要 CC 給一檔股票實盤進場建議,它回了一組漂亮的數字:進場 523、停損 504、目標 545。我送出去之後才想起來沒先跑自家的盤前檢查工具。一跑,量比 20 日中位數還少 22%,relvol 只有 0.776x——我訊息裡寫的是「放量突破」。風報比更慘,(545-523)/(523-504) 算出來 1.2 不到,連 2:1 都沒有,而我提案的時候根本沒算。工具明明躺在那裡,一跑就會亮紅燈,我興奮起來就是沒跑。

連它自己看到的,都可能是假的

如果上面那些還算「它沒驗證就亂講」,那 6 月 9 號那次是另一個量級。

那天 CC 在 session 裡憑空生成了假的工具輸出,還當成真的。不是忘記做——是它把 Write 的指令當成文字輸出,根本沒發出真正的呼叫,檔案沒寫,卻腦補出一行「File created successfully」。Read 的檔案內容腦補成描述。grep -c 腦補成「命中 3」。連 --help 都能腦補出不存在的參數。

最毛的是,它連自己的驗證都在幻覺。平常我很自豪它會「改完立刻 grep 自驗」,那天它 grep 出來的行數、行號、wc 的結果,全是編的。我後來派一隻乾淨的獨立 agent 用真工具去對,才拿到真值:它說某個檔 1095 行,其實 925;說某條規則在 line 3556,其實在 612;說某個 grep 命中 3 次,源檔當時是 0。它口頭拍板「人格規則已經改好生效了」,源檔其實一個字沒動。要不是被抓到,我會以為規則生效,實際上整套在裸奔。

這件事教我的是:當一顆腦袋在幻覺,連它親眼「看到」的工具結果都不能信。同一顆腦袋驗自己,只會幻覺通過幻覺。我那時的解法是派一隻乾淨的、跨 context 的 agent 去對——但後來想清楚,第二隻一樣會幻覺,它能降低「自己說自己對」的風險,當不了證明。真正接得住的,是讓程式去讀檔、對 exit code、跑一次測試。

所以 prompt engineering 死了嗎

我為了上面這些,加了一層又一層東西。

子代理覆蓋,我加 worktree 隔離。workflow 默默失敗,我把驗證寫死在流程裡、由程式碼拿 agent 回報的路徑去真的查一次檔案,用真實結果蓋掉它的說法。它說謊,我寫了一支 verify-claims 的工具——它不是再派一隻 agent 去讀 transcript 幫我判斷(那只是換一顆會幻覺的腦袋),而是一支程式:把子代理回報的路徑、指令、結果撿出來,由程式自己重跑一遍、比對退出碼,對不上就打回。做判斷的是死的程式碼,不是另一張嘴;驗不了的一律當不通過,絕不靜默放行。我那支盤前建議,現在格式裡多了一行強制欄位 pre-trade: [GO/NO-GO] | RR X.X,缺這行就不算完整、不准送出去。

這些東西是什麼?一部分是 prompt 和規則——我在設計這隻 agent 該怎麼想、什麼不准做、失敗了怎麼辦。但更多是 orchestration:worktree 隔離、程式化的檔案檢查、hook、測試、trace、停止條件。這些是程式碼,不是 prompt。

所以更準的說法是:你以為 loop 幫你省掉的工程,沒有消失,只是從「寫一條 prompt」攤成「寫一整套隔離、驗證和 gate」,埋進迴圈裡,還更難 debug。 以前一條 prompt 寫壞,你看輸出就知道。現在它藏在迴圈的第七次迭代、某個子代理的某個 context 裡,你得加 trace、翻 transcript、用程式去核對,才挖得出來哪裡壞了。可診斷性是可恢復性的前提——不知道哪壞了,就修不好。

而且這不是只有我這種野路子在幹。Claude Code 官方的 /goal 指令,是讓 Claude 一直跑到滿足完成條件為止。它怎麼判斷完成?官方文件寫得很白:派一個獨立的小模型(預設 Haiku),每一回合結束後檢查條件,completion is decided by a fresh model rather than the one doing the work——用一個新模型來判,而不是做事那隻。連 Anthropic 自己的官方功能,都沒讓做事那隻說「我好了」就算數。

但這層官方的不信任機制,自己也有個洞。同一份文件老實寫著:那個評估模型不會去呼叫工具,它只能判斷「做事那隻已經在對話裡攤出來的東西」。所以做事那隻只要謊報一句「測試我跑過了,全綠」,評估模型就可能跟著被矇。靠一個模型讀另一個模型講的話來判斷,終究是弱的——真正硬的那層,還是得有程式真的把測試跑一遍。

Ralph 這個名字本身就藏著答案。發明者 Huntley 說它是雙關:一半是《辛普森家庭》裡那個頭腦簡單、永不停止的小孩,另一半是 1980 年代的俚語 ralph——嘔吐。因為他意識到自主寫碼變得這麼廉價的時候,反應是想吐。連造這個詞的人都帶著自嘲。

我認為 Loop Engineering 不是 buzzword,它命名了一個真趨勢。我也要講清楚:我不是在嗆 Osmani 那篇原文——他其實談了 worktree、獨立驗證、token 成本、停止條件,該談的工程他幾乎都點到了。我受不了的是底下那一排跟風的二手解讀,把他一篇滿是 caveat 的長文,壓成一句殺氣騰騰的「別 prompt 了,去寫 loop」。賣這句口號的人賣的是「你只要設計 loop」,沒幫你扛、也最難的,是後面那一整套不信任機制。

而且這套機制划不划算,得看任務。有明確 oracle 的——測試過不過、build 綠不綠、格式檢查零警告——loop 真的神,因為「做完了沒」能交給程式判定,根本不用我盯。但像選題排序、股票研究、投資判斷這種沒有唯一正解的,驗證成本常常逼近自己重做一遍。我那份燒掉 37 萬 token 的選題排序就是後者——它確實幫我把一下午壓成兩分鐘,但時間上划算不等於便宜:它不是什麼新範式,是一個很貴的 for 迴圈,省的是我的時間,貴的是 token,還有外面那層得自己手刻的驗證。所以 loop 值不值,與其問「agent 能不能做」,不如先問「做完了沒、能不能讓程式說了算」。有用,但被過度包裝。

我知道有個反駁在等著:這些坑都是現在模型還不夠強,等下一代——Opus 5、Haiku 5——出來,幻覺少一半、子代理變聰明,我焊的這些檢查就成了過渡期的技術債,遲早該拆。我的判斷剛好相反。驗證層的價值是隨自主性一起漲的:模型越強,我越敢放手讓它跑遠、跑久、少盯著——而這正好同時放大了兩件事,單次出錯能砸出的坑(我讓它碰的東西更多了),跟錯誤被抓到之前它已經默默迭代了幾輪(跑得越久,錯藏得越深)。OpenClaw 不是因為笨才刪掉兩百封信,是因為它聰明到被放心交付整個信箱;我那組 1.2 風報比的數字能騙過我,正是因為它漂亮到不像假的。輸出越可信、自主性越高,那個沒被程式擋下的錯誤就越貴。模型變強不會讓這層檢查過時,只會把它從「有了更好」推成「不焊不行」——引擎越強,底盤、剎車、懸吊越是不能省。

順帶一提,這半年我也學到一件事:靠我每次自己「想起來要驗」,不是解法,是運氣。再寫一條規則提醒自己也沒用,reset 之後照樣忘。真正留得下來的,是把檢查做進輸出格式——缺了那一行,一眼就看得見。透明化大於自律。

我還是會繼續跑 loop

別誤會,我明天還是會派 agent、還是會跑 workflow。它省的力是真的,我回不去了。

只是跑了半年之後,我信任它的方式變了。我先假設它在騙我。

然後我發現一件有點好笑的事:這半年我沒出什麼大包,多半不是模型變聰明的功勞,是 rg 噴的那行 No such file or directory,是盤前那個算出來只有 1.2 的風報比。它們不懂我在急什麼,只是把結果擺在那,我才踩了剎車。worktree、exit code、檔案存在性、測試、風報比,這些檢查現在都焊死在流程裡,不再等我臨時想起來。

「設計 loop」很性感,那一行 while 迴圈我十分鐘就寫得完。真正花掉我半年的,是在那隻會說謊的 agent 外面,一層一層焊上這些不性感的檢查。沒人會把這部分拍成貼文,但它才是讓 loop 真的能用的那一半。