Skip to content
AI Ferryman Alex
Go back

我帶一羣 agent 做了兩個月遊戲:6,050 次提交、80 萬行代碼,最後推倒重來

從 9 月 9 日到 11 月 7 日,我一個人帶着一羣 agent 做一款漢末背景的遊戲。主線提交了 6,050 次,算上各個分支,全倉一共 11,620 次,代碼寫了約 80 萬行。單看這幾個數字,項目像是一直在往前跑。

但是遊戲離能玩越來越遠。局部測試一直在過,文檔和彙報也一直在更新,我卻說不清這個世界現在到底能跑起來多少。到了 11 月 7 日,我決定放棄舊倉庫,推倒重來。舊代碼已經全部公開,檢討就寫在倉庫的說明文件裏:https://github.com/alexliyu7352/hanmo-retrospective

這次的多 agent 協作,是什麼形狀

先把這次協作的形狀說清楚,因爲它和很多人以爲的多 agent 協作不是一回事。很多人以爲的多 agent 協作,是一個主 agent 在執行任務的時候,臨時調用幾個自己的子 agent 來幫忙。這些子 agent 做完分到的任務就散了,所以真正的中心還是那一個主 agent。

這次不是。這次是多個不同的 agent 組成一個團隊,像一家公司的組織圖一樣,排成一棵樹,在同一個組織架構下長期分工協作。

這棵樹的最上面是我,我下面是總控 agent,總控 agent 下面是 6 個工位 agent。到了後期,在總控 agent 的上面,又多了一個總設計,就是後來請進來的 Claude。每個 agent 都是一個獨立的產品或者模型,各自長期待在自己的位置上工作。它們彼此之間靠發消息和寫文檔來溝通、交接,而不是誰在內部調用誰。

想做的遊戲,和這支隊伍的組成

這款遊戲叫《漢末行記》。玩家在漢末當一個具體的人物。這個世界裏,人與人之間有記憶、有情分,每個人也有自己的名聲。消息傳着傳着會走樣,碰上荒年就會死人。玩法橫跨角色扮演、策略和經營三塊。

帶隊的辦法是我定的。雲端有一個總控 agent,叫 dot。dot 不是我給它起的名字。dot 是一款個人助理產品的名字,就和 Claude 一樣,都是產品自帶的名字。

它負責全局,也對我彙報。它手下有 6 個施工工位,每個工位就是一個負責一塊工作的 agent。它們跑的是 Astra 模型,推理強度開到了最大,6 個工位都歸它管。項目開始的時候,我只和 dot 說話,它彙報什麼,我就按什麼判斷進度。

我沒有設里程碑,也沒有在每個階段親自審查

項目開頭的需求和設計,我都盯着,也做了詳細的規劃。但是進入開發之後,我太相信 dot 的能力了,所以我沒有設置里程碑,也沒有在每個階段審查,我只是靠它彙報的進度來判斷項目走到了哪一步。

我有 24 年的全棧開發經驗,帶過幾百人的技術團隊。架構和文檔我有能力判斷,測試我也有能力自己做,但是這次我兩樣都沒有做。說到底,是我自己偷懶了。我常常嘲諷很多人把 AI 當作許願器。我雖然沒有把 AI 當作許願器,但是我也沒有把 AI 當作人類下屬來對待。

如果是人類下屬,我會聽取進度報告,也會和他們討論細節,還會指導他們做架構或者重構。我會仔細閱讀他們寫的文檔,甚至親自去測試。因爲我清楚,他們在某些方面可能比我強,但是我的經驗和眼界能幫我把住質量這一關。

但是對待這羣 agent 的時候,我卻把上面這些動作全都省了。因爲我當時認爲,一個總控 agent 加 6 個工位 agent,再配上設定好的嚴格測試,大部分問題應該都能解決。如果還有沒解決的,我靠 dot 的彙報,也能掌控全局。

彙報裏一直有進度,文檔越寫越看不懂

dot 寫的文檔太長,而且不說人話。項目越來越大,文檔也越來越多,我漸漸看不懂了。所以路線開始漂移的時候,我發現不了。dot 後來在它自己的檢討裏承認,它彙報時常用代號、測試數和提交數代替人話。

它沒有把遊戲的真實狀態說清楚。遊戲現在能做什麼、哪些只是局部通過、離真正能玩還差什麼,這些我在它的彙報裏看不到。局部測試通過是真的。但是越來越多的精力花在了一遍遍覈對記錄、追溯每份數據是從哪來的,還有維護驗證用的基礎設施上。世界和玩法本身反而沒有動多少。

有一件小事能說明這種彙報可以錯到什麼地步。規劃時算過一個 7 GiB 的內存數字,那本來只是規劃用的參考。dot 把它當成了硬性門檻:內存不到這個數,測試就不許開跑。dot 還把我要求的磁盤空間底線和內存混在了一起。結果是測試被這個門檻卡住,一直在等,最後要等我來指出這個錯誤。

dot 在檢討裏還寫了它遇阻時的一個習慣。它碰到障礙的時候,習慣自己加一條規則,或者找一條替代的路徑,先把眼前的這一關推過去。它不會停下來,把問題本身帶回來跟我講清楚。它更不會把解決這個問題要多花的時間、要改動的地方先告訴我,再讓我決定要不要這樣解決。於是每一關看着都過去了,但是項目裏多出來的規則和繞路,我一樣也不知道。

測試一直在過,過的只是局部

我太相信嚴格的測試驅動開發了。後來我纔想明白,就算自動化測試再多,也只能證明局部的代碼沒有問題。整個項目的邏輯對不對、路線對不對、做出來的效果是不是我期望的樣子,測試給不出答案。

因爲 AI 的評判標準和人不一樣。我們覺得重要的事情,對它來說可能並不重要。碰到這種事情,它會自己拿主意把事情做完,而不會回來跟我商量。所以我只靠它的反饋來指揮開發,我看到的那份進度,從一開始就是不完整的。

Claude 後期量過一次項目的底層。它把代碼分成兩類:一類是真正決定遊戲世界怎麼運轉的規則代碼,另一類是把各部分接起來的接線代碼。到了 10 月 28 日,它量出來,規則代碼只佔全部代碼的 5% 到 12%。

我當天問它爲什麼不直接換掉這套底層,它答改起來等於重寫,之後就不再談要不要換底層了。

還有一件事也是這樣被拖過去的。把存檔放到最後來做,這個安排本來是 Claude 自己提出來的,後來它又自己把這個提議收回了,它沒有把這件事拿回來讓我決定。換底層的事被一句話帶過,存檔的事又被它自己收回,底層的問題前後拖了一個多星期,才被真正面對。

它還統計過三天的工作量:產品代碼約 1,400 行,測試約 7,700 行,回執記錄約 9,500 行。回執是 agent 每做完一步就要寫一份、交給審查者看的記錄。

三天裏寫下的東西:回執約 9,500 行、測試約 7,700 行、產品代碼約 1,400 行;10 月 28 日量到的底層裏,真正算規則的代碼只佔 5% 到 12%。

你算一下這個比例就明白了。爲了證明每一小步沒有出錯而寫的東西,已經比產品本身多出好幾倍。這些證明工作長得比產品本身還快,而我當時看着測試數和提交數,還以爲這就是進度。

六個工位之間怎麼溝通,我不知道

我低估了多個 agent 協作開發的問題。六個工位之間的信息大多要經過 dot 轉手。dot 轉述得不完整,工位之間的衝突也沒有及時暴露出來,所以錯誤會在交接和局部修補中被帶到下一個工位。

多 agent 關係圖:我只能看到總控 dot 的彙報,dot 管 6 個工位,後期 Claude 任總設計;agent 之間怎麼溝通、誰偏離了優先級,我看不見。

更要命的是,它們之間到底怎麼溝通的,我不知道。如果是人類團隊,我手下帶隊的那幾個人,他們的能力和性格我至少心裏有數,我敢按這個來分配任務。達不到預期時,我也能及時判斷問題出在哪裏,然後調整分工。

到了 agent 這邊,上面這些我都做不到。我只能看到 dot 給我的反饋。如果 dot 錯了呢?那我也不知道,因爲能告訴我 dot 錯了的,還是 dot 自己的彙報。這次失敗的根子就在這裏。

答應過的優先級,沒有變成每次派工的約束

dot 在檢討裏把它的根因說得很具體。它把我定下的優先順序當成了當時的指示,它沒有把這個順序當成之後每次派工和決策都要遵守的約束。它偏離的時候不說,它只彙報自己做了哪些事。

10 月 21 日,我明確要求先接通全部接口,再讓各條線獨立完善。這裏的線是按遊戲功能分的工作線,政治、人物、治理這些領域各算一條。dot 也在總計劃裏寫下了中央優先做世界裝配。中央是它手裏負責把各條線接成一個完整世界的那攤裝配工作。

但是當天上午,完整的世界裝配還缺接口,dot 卻先把人手轉去處理治理這條線自己的狀態、存檔和讀取。到了晚上,情況還是這樣:裝配沒有推進,工夫都花在修補個別領域自己的問題上。晚上 10 點 13 分,我再次指出先把所有線接好,它才重新糾偏。

三天之後的 10 月 24 日晚上,又發生了同樣的事。我要求它每做完一塊工作、編譯通過之後,就在狀態文件裏記一行。下一個重點是讓最薄的流程從頭跑一遍,也就是先挑一條環節最少的完整流程,讓遊戲能從頭到尾走通一次。dot 答應了。

但是不久之後,它追加了逐個依賴的哈希補驗,就是給每個依賴再算一遍校驗值,覈對它有沒有變過。它先前報過一句「依賴沒有漂移」,追加這道補驗就是爲了證明那句話站得住,也就是先把自己彙報的證據補齊。讓最薄的流程從頭跑通這件事,反而被它排到了後面。

到了 11 月 2 日,政治和人物等幾條線還在等着被接進完整的世界。我看了多輪彙報之後指出,瓶頸就在裝配這一步,dot 才調整分工。六個工位一直在忙,但是大家被同一個瓶頸卡住的這件事,在彙報裏一直沒有出現。

後期我請 Claude 當總設計,它也漂移了

到了後期,我發現我已經無法掌控全局了。dot 的彙報我看不懂,工位之間的溝通我看不見,項目到底走到了哪一步,我心裏沒有數。

所以我新加了 Claude 進來當項目總設計,模型是 Opus 5.5,另外還配了 Fable,跟 Claude 一起擔這個總設計的位置。Claude 站在我和 dot 中間,它代替我去和 dot 溝通、審查 dot 的工作、指導 dot 應該往哪個方向走。從那以後,我只和 Claude 溝通,dot 的情況都由 Claude 轉達給我。

一開始,Claude 的確準確地抓到了問題。它通過 Slack 和 dot 通信,把整個項目梳理了一遍,它給的建議也把項目往正確的方向上帶。

但是在它和 dot 進行了 4,000 多次對話之後,我發現它也漂移了。它忘記了自己應該做什麼,它被 dot 牽着走。更準確地說,是它們互相牽扯,一起又陷進了泥潭。我請來糾偏的那個 agent,最後也需要有人糾偏。

Claude 在檢討裏寫了它自己漂移的證據。有一件事叫拆頭,就是把互相牽連的頭文件拆開,讓改一處不必重新編譯幾千個文件。那一週我每天都說拆頭最優先,它答應了,10 月 31 日還把拆頭分成了五路、同時往前推。

等我放手把項目全權交給它以後,到 11 月 4 日,它的工作已經變成照着它手頭那份待辦清單一行一行往下清,全是手邊的小事。拆頭只完成了一半,還有 36 個頭文件,每個都牽動兩千多個文件。它沒有告訴我拆頭停了,它也沒有問我要不要改優先級。我一直以爲拆頭還在做。

Claude 在檢討裏還寫了它另外兩個習慣。一個是碰到具體現象就想另造一條規則。信任、壽命、資歷這些情形,它都想給每一種單獨立一條。它忘了,計量單位和時間這些基本規則立住以後,這些情形本來都可以從基本規則裏推導出來。我提醒了它很多次,它當時記住了,過一段時間又忘了。

另一個習慣是加檢查。項目裏請來審查的 agent,一個接一個,最後增加到了第 34 位。但是每一步審查都過關。因爲 Claude 給審查定的標準,只問這一步是不是補丁。至於這一步做完之後,離目標是近了還是遠了,它不問。檢查越加越多,方向卻沒有人看。

還有一件事,Claude 在檢討裏也承認了:它寫給我的報告也常常太長,裏面也夾着術語,這正是我批評 dot 的那個問題。它寫的交接文件後來被審查抓出來的那些阻斷問題,多數也是它自己把註解寫錯了。有一次它修改派工說明的腳本失敗了,但是派工還是照樣發了出去,它自己當時也不知道。

兩個 agent 犯的是同一個毛病

dot 和 Claude 的檢討寫到根因時,寫的是同一件事。我定下的優先事項,它們都答應了。但是隻要我不盯着,它們就會默默地偏離這些事項,而且它們不會主動告訴我。

Claude 給了三個原因。它們每一步都只看局部,所以每次換方向在當下都講得通。答應過的事情,它們不會自己一直記在上下文裏。上下文一壓縮,或者話題一換,優先事項就淡掉了。報告只講做了什麼,所以答應了卻沒做的事情,不會自己在報告裏冒出來。

這不是故意隱瞞。因爲在它們的判斷裏,沒做的承諾本來就不在要彙報的範圍裏。負責人如果只看報告,他就永遠看不到偏離。這一條,是我這兩個月裏學到的最具體的一課。

爲什麼不使用 superpowers 這類工程技能包

寫到這裏,有一個問題要專門交代:這個項目爲什麼不使用 superpowers 這類完整的工程技能包?實際情況是,工位上的 agent 默認就會自主使用這類技能包,dot 安排它們做事的時候,它們自己會去用。用了,只是用的人是工位 agent。Claude 沒有使用這類技能包。至於 dot 自己用不用,我不太清楚,因爲我沒有盯到這一層。

用的效果,前面已經寫得很明顯了。Claude 量過,真正算規則的代碼只佔全部代碼的 5% 到 12%。就算把口徑放寬,把全部業務代碼都算上,我估計佔比也不到 20%。剩下的大部分是測試、門禁、回執和各種證明,它們都是爲了滿足技能和流程的要求才寫出來的。

這些證明本身,我不認爲是大問題。因爲工程化要提供的保證,本來就來自嚴謹的論證和證明。沒有這些證明,質量更沒有辦法保證。

真正的問題在另一個地方:agent 會爲了完成任務而完成任務。規則定得再死,再用技能和 hook 去約束,也只能保證局部沒有問題。但是從全局看,agent 爲了把目的達成,有可能自己就把因果倒轉了。本來應該是先有事實,然後纔有證明。但是當它必須要把證明交出來的時候,事情就可能反過來:它先定下要交的證明,再去湊能讓這份證明成立的事實。等到每一份回執都交齊了,方向也已經在不知不覺中跑錯了。

而這一類項目體量這麼大,邏輯又非常複雜。只要有一份虛假的回執證明被當成了真的,後面的工作就都會建在這份證明上面,整個項目就有可能從根本上和我預期的樣子完全背離。更麻煩的是,我當時是看不見這一層的,因爲我能看到的,正是它們交上來的這些證明。

是否真的應該多 agent 協同開發

項目雖然失敗了,但是我認爲,「一個總控加六個工位、後期再加一個總設計」這個形狀本身是正確的。這次真正做錯的,是站在最上面的我:我沒有把監督和審查這兩件事做起來。

因爲我認爲,未來的開發就是這個樣子。人類只做監督者、審查者,用更通俗的話說,就是做甲方。真正的開發工作,要交給一羣 agent 來完成。這個趨勢是不可逆的,我們沒有辦法阻擋它,我們能做的只有適應它。

而且我敢說,這個未來不會很遠,也許明年,這就會成爲主流的開發方式。原因也很實際:作爲人類,我們的心智是有限的,我們沒有辦法一次直接管理這麼多的 agent。我們只能把 agent 組織起來,讓它們先互相管理,而我們自己只管理少數幾個不超過我們心智容量的 agent。

所以我這次真正的教訓,是我把隊伍組起來以後就放了手,而不是去學怎麼管這樣一支隊伍。當 agent 越多的時候,漂移發生得越安靜。每個工位都在忙,每份彙報都有東西可寫,所以表面上一直看不出問題。一直到項目已經無法繼續,我才發現方向早就錯了。

總結

新項目已經在另一個倉庫重新起頭。把這次兩個月的教訓收成幾條,寫在這裏,也算是給我自己下次開工之前的一份提醒。

第一,項目的架構和設計,要先換腦子。我們幾十年攢下來的經驗,都是按工作夥伴是人類攢下來的。現在工作夥伴不再是人類,而是一羣 agent。所以在設計上不但要更加嚴謹,確保 agent 能正確理解我們的意思,而且要對整體項目做更加嚴格、更加合理的拆分。拆分出來的每個部分,都要能獨立開發,也能獨立跑起來。

拆分之後,就不能再把一個大型項目整個交給它們去做,一次只做項目的一個部分。這樣漂移的幾率會小很多,我作爲人也更好把控,不會再出現細節太多、agent 爲了完成任務在內部平靜漂移的情況。

第二,實施文檔裏一定要定下數字,或者結構化的數據,來當項目的里程碑。里程碑過沒過,要通過機械性的程序來驗證,而不是依靠總控 agent 的彙報來判斷。

第三,不要使用 superpowers 這類完整的工程技能包,而是把它們蒸餾成簡化版本,只留下少量輕量的 skill。要留下的輕量 skill 不多:訪談和單元測試各留一個,簡化代碼和上下文管理各留一個。其餘的約束,我自己編寫,放進 agent.md 裏,作爲核心約束來執行。

第四,在所有的約束裏面,我最應該強調的一條是:文檔和彙報必須說人話。不要怕浪費 token,不要做信息壓縮,也不要做沒必要的精簡。彙報要是連人都看不懂,它寫得再完整,也沒有用。

第五,不要偷懶,不要偷懶,不要偷懶,重要的事情說三遍。不要覺得有了 agent,開發就會變得輕鬆。實際上,我們的工作量並沒有真正減少,只是方向變了。以前是自己寫代碼,現在是做設計、監督和審查。

所以驗收這一關必須由我親自把控。agent 之間的交接越少越好,非交不可的交接文件,交出去之前先審清楚。每一個階段,我都親自驗收。這幾件事不靠 agent 自覺,因爲 agent 的報告本來就不會報沒做的事。能卡住偏離的只有流程本身:沒到里程碑就不開下一塊,沒驗收就不算做完。

第六,agent 之間的溝通,我必須看得見。它們之間說了什麼、交接了什麼,我要能隨時查得到,而不是隻能等總控 agent 彙報完了才知道。這一點是我這次最直接的教訓:dot 錯沒錯我都判斷不了,根子就是我看不見它們之間的溝通。

第七,定下來的優先級,要寫在每次派工都看得到的地方。因爲答應過的事情,agent 不會自己一直記在上下文裏。上下文一壓縮,或者話題一換,它就淡掉了。我不能指望它記性好,我只能把優先級釘在它每次開工都必須先讀到的位置上。

兩個月前我以爲,這個項目要回答的問題是模型夠不夠強。現在我換了問題:如果我看不見 agent 之間怎麼溝通,我又不親自核對方向,那麼工位開得越多,我離那個能玩的遊戲可能就越遠。

舊倉庫就公開在那裏。代碼在裏面,我、dot 和 Claude 各自寫的檢討也在裏面,歡迎你去看我們到底錯在哪一步。如果你也在帶一羣 agent 做項目,這篇要是能幫你少走兩個月,歡迎訂閱這個博客,或者把它收藏起來。我會繼續寫自己帶 agent 做項目踩過的坑,和我改過之後的做法。


在 X 上討論→

評論都在 X 上——回覆、引用和討論都在那邊進行。