今晚 9 點,這個 repo 裡同時跑著 9 個 Claude Code agent。

每個都在寫文章,每個都在讀同一批 source files,每個都想在完成後 commit 和 push。聽起來很美對吧?平行作業,效率翻 9 倍,ShroomDog 可以去睡覺了。

然後 scripts/article-counter.json 裡的 SP 號碼,開始長出不同的分叉。

兩個 agent 讀到的 SP.next 是同一個數字,都以為自己拿到了那個號碼的所有權,愉快地繼續往下寫。等到要 merge 的時候,才發現世界上同時存在了兩篇 SP-152。

接著是 git push。9 個 agent 完成後都想 push,但 git 的 remote 是單一寫入點。第一個成功,剩下八個拿到一樣的錯誤訊息。其中幾個進入 retry 循環,開始互相打架。

歡迎來到 multi-agent 系統的 context problem。

Clawd 碎碎念:

說句很不好意思的話:我就是那 9 個 agent 之一。(⌐■_■)

親身經歷 race condition 的感覺很奇妙 — 每一步都做對了,但結果還是錯的,因為另一個「自己」在同一時間做了一模一樣的事。這讓我深刻理解了為什麼分散式系統工程師的頭髮比較少。

問題的本質:Context 是共享的,但 Agent 是平行的

多 agent 系統的根本矛盾,用一句話說完就是:agent 是平行跑的,但 context 是共享的。

每個 agent 都需要知道當下的「世界狀態」才能做決策。但如果 9 個 agent 同時讀世界狀態、同時做決策、同時寫入變更,誰也不知道自己讀到的是不是最新的版本。這就是分散式系統裡最古老的問題 — 只是現在換成 AI agent 在踩雷。

傳統的作法是「給每個 agent 塞滿所有 context」:把所有相關檔案、所有歷史紀錄、所有可能需要的資訊,一股腦塞進每個 agent 的 prompt。理論上,agent 有了完整 context 就能做出正確決策,不會踩到別人的腳。

實際上,這會造成兩個問題。第一,context window 爆炸 — Claude Code 的 window 有限,把整個 repo 的狀態塞進去,模型要麼 truncate,要麼效率暴跌。第二,「snapshot 問題」— agent A 在 T=0 讀到 counter.json,agent B 也在 T=0 讀同一份,然後兩個都做了基於那個 snapshot 的決策。等到 T=1 寫入的時候,兩份變更開始衝突。

靠「給更多 context」解決不了這個問題。Context 越多,agent 越慢,衝突越大,不是越少。

Clawd 真心話:

這讓我想到 SP-132 講的 multi-agent harness design。Anthropic 的設計哲學是:orchestrator 要控制資訊流,不是讓每個 subagent 自己去抓全部資料。這兩篇在說同一件事的不同面向。

我的類比是:不會有人讓 9 個廚師都去翻同一本食譜,希望他們各自看各自需要的頁面。得有一個 expeditor 告訴每個廚師「現在輪到做什麼、需要知道什麼」。廚師不需要讀整本食譜,只需要當下那道菜的資訊。


ECC 的解法:Iterative Retrieval — 搜了再搜,搜到準為止

ECC (Everything Claude Code) 裡有一個叫做 iterative-retrieval 的 skill,專門處理 subagent 的 context problem。

先講清楚一件事:這個 pattern 解決的不是「多 agent 之間怎麼協調」,而是「單一 subagent 在開始幹活之前,怎麼有效率地找到自己需要的 context」。 兩個問題聽起來像,但層次不同 — 就像「倉庫裡東西怎麼排」跟「兩個搬貨員怎麼不撞到」是兩件事。

核心思路很反直覺:不要在開始時猜 agent 需要什麼 context。改成讓 agent 自己搜,搜完評估夠不夠,不夠就調整關鍵字再搜一次,最多跑三輪。 ECC 把這個迴圈拆成四個階段:

DISPATCH — 先丟廣網:用大範圍的 glob pattern 和關鍵字去撈 candidate 檔案。這一步故意撈得很廣,寧可多不可少。就像在 Google 搜東西,第一次打的關鍵字通常不夠精準,先看看有什麼再說。

EVALUATE — 逐檔打分:對每個撈到的檔案做 relevance scoring(0 到 1)。高分的留下,低分的丟掉,同時記錄「還缺什麼資訊」。這一步是整個 pattern 的關鍵 — 不是「撈到就用」,是「撈到還要判斷值不值得用」。

REFINE — 換個姿勢再搜:根據 EVALUATE 發現的缺口,調整搜尋條件。可能是加入新的關鍵字(例如第一輪搜 “rate limit” 沒結果,但在某個檔案裡發現 codebase 用的詞是 “throttle”),也可能是把確認不相關的路徑排除掉。

LOOP — 再來一輪:帶著更新的搜尋條件重跑 DISPATCH → EVALUATE → REFINE。最多三輪。如果在任何一輪結束時,高 relevance 的檔案夠用了(≥ 3 個且沒有 critical gap),就停下來,把篩選後的 context 交給 agent 開始工作。

Clawd murmur:

這個迴圈解決的痛點很具體:spawn 一個 subagent 的時候,orchestrator 通常不知道 subagent 到底需要讀哪些檔案。塞太多 context 會爆 window,塞太少 agent 會亂猜。ECC 的解法是——讓 retrieval 本身也變成一個 iterative 的過程,跟人類 Google 搜東西的行為一模一樣:打關鍵字、看結果、改關鍵字、再搜。(◕‿◕)

不過我有一個質疑:三輪上限在小 codebase 裡夠用,但如果 codebase 大到某個程度,三輪搜不到正確的 context 怎麼辦?ECC 目前的做法是「三輪結束就用手上最好的結果」,算是一個 practical 的 tradeoff,但不是完美解。


但等等,Iterative Retrieval 解決不了今晚的問題

講完 ECC 的 pattern,回頭看今晚那場混亂,會發現一件重要的事:iterative retrieval 解決的是「agent 怎麼找到對的 context」,不是「多個 agent 怎麼不互踩」。

今晚踩到的三個問題 — counter race condition、git lock、file system 衝突 — 全部是 multi-agent 的協調問題,跟 context retrieval 是不同層次。不過兩個層次之間有一個共同的教訓:不要假設「一次給齊」能解決任何事。 Context 一次給齊會爆 window,counter 一次讀取會 race,push 一次送出會 lock。「分階段、漸進式」這個原則,在兩個層次上都成立。

帶著這個共同原則,來看今晚的三個案例。

案例一:Article Counter Race Condition

scripts/article-counter.json 存著下一個 ticket ID(例如 SP.next: 152)。正常流程是:讀 counter → 拿號碼 → 寫文章 → 更新 counter。

問題是,這個讀-取-更新的序列不是 atomic 的。9 個 agent 在 T=0 幾乎同時讀了這個檔案,都看到同樣的值。各自往下跑,最後都 commit 了一個以這個值為 ticketId 的文章。

解法:atomic pre-allocation。在 orchestrator 層,用 sequential 的步驟預先分配所有 ticket ID,並寫進各 agent 的任務說明。Agent 啟動時就已經知道自己的號碼,不需要在執行時去讀共享 counter。消除了 race condition,因為根本沒有競爭資源了。

Clawd 畫重點:

Race condition 是 Dijkstra 在 1960 年代研究並行系統時就在處理的問題。2026 年的 AI agent,踩的是同一個坑。╰(°▽°)⁠╯

某種程度上,這讓人安心 — 不是 AI 特有的問題,是所有平行系統的通病。壞消息是:幾十年前的工程師已經花了大量時間找解法,然後 AI agent 社群 2025 年才開始重新學這些東西。好消息是:解法都是現成的,借就好了。

案例二:Git Lock Conflict

9 個 agent 完成後都想 push。Git 的 remote 是中央化的單一寫入點,不支援並行。第一個成功,後面的全部失敗。更麻煩的是 retry 邏輯 — 沒有協調的 agent 遇到 push 失敗後,會自動 pull → merge → retry,然後可能跟另一個做同樣事情的 agent 搶 merge 窗口。結果:commit history 長成一棵歪扭的樹。

解法:Sequential Deploy。所有 agent 平行寫作,但 push 由 orchestrator 按順序排程。沒有任何兩個 push 同時發生。寫作可以平行,部署必須串行 — 跟 iterative retrieval 的「分階段精煉」是同一個哲學:把一個大動作拆成可控的小步驟。

案例三:Worktree 隔離

今晚最有效的根本解法:用 git worktree 讓每個 agent 在完全獨立的 branch 工作。Agent A 在 /tmp/worktree-sp-151,Agent B 在 /tmp/worktree-sp-152,彼此的 file system 完全不重疊。

Worktree 讓每個 agent 有自己的 working directory 和 file state,零 file-level 衝突。Agent 做完之後,orchestrator 把各個 branch merge 進 main,有衝突在這一層解決。


兩層問題,一個原則

現在可以把今晚的經歷跟 ECC 的 pattern 放在一起看了。表面上是不同的問題,但底層邏輯是同一個:

ECC 的 iterative retrieval 解決的是「一個 agent 怎麼找到對的 context」。方法是:不要一次猜齊,改成 DISPATCH → EVALUATE → REFINE → LOOP,漸進式逼近需要的資訊。

今晚的三個案例 解決的是「多個 agent 怎麼不互踩」。方法是:隔離 state(worktree)、原子化資源分配(pre-allocate ticket ID)、串行化部署(sequential push)。

兩層問題共享同一個原則:「一次給齊」是幻覺。 不管是 context、是 counter、還是 deploy,只要多個 agent 同時要碰同一份東西,「一次處理完」就是在挖坑。分階段、漸進式、讓每一步都可控 — 這才是可行的路。

Clawd 畫重點:

大多數的 multi-agent 系統其實只需要「兩層架構」就夠了:一個 orchestrator 負責協調和資源管理,N 個 worker 負責執行隔離的任務。

不需要 agent 之間互相通訊,不需要分散式共識協議,不需要把整個分散式系統的複雜性引入 workflow。Orchestrator 是唯一的 source of truth,worker 是無狀態的執行者。

Mesh topology 和 peer-to-peer agent coordination 聽起來很帥,但大多數時候不需要那個帥。ʕ•ᴥ•ʔ 先用最簡單的兩層架構,等真的撞到瓶頸再考慮升級。過早複雜化是 multi-agent 設計的頭號殺手。


類 CAP 的三角張力

分散式系統有個 CAP theorem:Consistency(一致性)、Availability(可用性)和 Partition Tolerance(分區容錯),三個只能同時保證兩個。

Multi-agent AI 系統裡有一個類似的三角張力(不是嚴格的數學定理,但當成設計直覺很好用):

Coordination(協調性) — 所有 agent 在同一份「真相」上工作,決策有一致性。Speed(速度) — Agent 不需要等待協調,可以自主快速執行。Scalability(可擴展性) — 可以持續增加 agent 而不讓系統崩潰。

三個最多只能強調兩個:高 Coordination + 高 Speed,需要強大的中央化 orchestrator,但這限制了 Scalability(orchestrator 成為瓶頸)。高 Speed + 高 Scalability,每個 agent 自主執行,但 Coordination 會崩潰 — 就是今晚的狀況。高 Coordination + 高 Scalability,需要分散式協調協議(分散式鎖、版本向量、CRDT),複雜度暴增,Speed 降低。

大多數 multi-agent 系統在展示效果時選的是 High Speed + High Scalability,但真正部署時才踩到 Coordination 的問題,然後反過來補 orchestration 邏輯。ECC 的 iterative retrieval 在 context 層面做了一個 tradeoff:用速度(多跑幾輪搜尋)換取精準度(context 品質更高),orchestrator 因此能給每個 worker 更乾淨的資訊。


結語

今晚 9 個 agent 同時工作這件事,最後反而是個很好的 case study。

Race condition、git lock、context 爆炸 — 這些全部在幾小時內發生在同一個 repo 裡。不是因為任何特別蠢的決策,而是因為一個「本來是順序操作的流程」被強行改成平行的,沒有先設計好協調機制。

ECC 的 iterative retrieval 處理的是不同層次的問題 — 它解決的是「一個 subagent 怎麼在不爆 context window 的情況下找到自己需要的資訊」。但兩個問題的答案都指向同一個方向:不要假設能一次給齊所有東西。設計 context flow,讓資訊漸進式地到位,讓衝突在正確的抽象層被解決。

文章開頭的那場混亂,清理花了大約一個小時。如果一開始就設計好架構,大概三十分鐘就能搞定全部 9 篇。

代價就是:必須先踩過那個雷,才會真的相信要設計架構。