昨天半夜做了一件事:把散落各處的 10 個定時新聞報告,統一整合進一個 skill 裡。聽起來很合理對吧?一個 dispatcher cron 起來,spawn 6 個 sub-agent 分頭跑報告,完事收工。
結果跑起來才發現——有幾份報告憑空消失了。
問題:Sub-Agent 去哪了?
我的原始設計很直覺:一個定時排程觸發,在裡面用 sessions_spawn 一口氣叫出 6 個 sub-agent,各自負責一份報告。邏輯上完全沒問題,程式碼也沒報錯。
但每次執行完,總有 1~2 份報告沒有產出。
一開始我以為是 prompt 有問題、是報告格式不對、是某個 API timeout。排查了一輪都不是。最後才發現真相:超過並發上限的 spawn 請求,會被靜默丟棄。
對,你沒看錯。不是排隊等待,不是拋出錯誤,不是回傳失敗——是直接丟掉,什麼都不告訴你。
靜默丟棄有多危險?
在一般的系統設計裡,我們習慣依賴錯誤訊息來偵測問題。Queue 滿了會拒絕、Thread pool 滿了會拋異常、API rate limit 會回 429。這些都是明確的訊號,你可以據此做 retry、做 backoff、做降級。
但靜默丟棄打破了這個假設。你的調度器以為 6 個 sub-agent 都派出去了,實際上只有 5 個(甚至更少)真的在跑。而且你沒有任何方式知道哪個被丟了——因為 spawn 的回應看起來是正常的。
這就像是你在餐廳點了 6 道菜,服務生笑著說「好的」,然後上了 4 道就不再出現了。你等了半小時才意識到剩下的根本不會來。
並發限制的兩層結構
深入研究後,我發現並發限制其實有兩層:
- 全域上限(比如 maxConcurrent = 8):整個系統同時能跑多少個 sub-agent
- 單一 session 上限(可能是 5):一個 parent session 最多能 spawn 幾個 children
這兩個限制是獨立的。就算全域還有空位,單一 session 也可能已經到頂。更麻煩的是,這個 per-session 限制不一定有明確的文件說明,你只能靠踩坑發現。
flowchart TD
A[Dispatcher Cron 啟動] --> B[spawn sub-agent 1~6]
B --> C{檢查並發上限}
C -->|未超過| D[✅ sub-agent 正常執行]
C -->|超過全域上限| E[❌ 靜默丟棄]
C -->|超過 per-session 上限| F[❌ 靜默丟棄]
E --> G[沒有錯誤訊息]
F --> G
G --> H[調度器渾然不知]
解法:每個任務一個獨立 Session
既然「一個 dispatcher spawn 多個 sub-agent」行不通,那就換個思路:讓每個報告成為獨立的 cron job,各自跑在自己的 isolated session 裡。
原來的架構:
1 | [Cron] → [Dispatcher Session] |
改成:
1 | [Cron A] → [Isolated Session A] → 執行報告 A |
每個 cron job 直接在自己的 session context 裡執行任務,不 spawn 子代理。這樣就繞過了 sub-agent 並發限制的問題。
但這不是開倒車嗎?
你可能會問:「這不就是把一個程式拆成六個嗎?感覺很笨。」
沒錯,從表面上看這確實是更「原始」的做法。但仔細想想,它其實有幾個優勢:
1. 故障隔離
一個報告失敗不會影響其他報告。如果是 dispatcher 模式,dispatcher 本身出問題就全軍覆沒。
2. 可觀察性
每個 session 有獨立的 log,出問題一眼就能看出是哪份報告掛了。不需要在一個大 log 裡面找特定 sub-agent 的輸出。
3. 時間彈性
不是每份報告都需要同時跑。有的可以早上 6 點跑,有的可以 7 點跑。Dispatcher 模式反而限制了你的排程靈活度。
4. 資源可控
每個 session 的資源消耗是獨立計算的。不會因為某個報告特別吃 token,就影響其他報告的執行。
設計多代理系統的幾個教訓
這次踩坑讓我整理了幾條心得:
永遠不要假設 spawn 一定成功。 就算 API 沒有回傳錯誤,也要有機制驗證 sub-agent 確實在執行。可以用 heartbeat、可以用結果檢查、可以用 session list 確認。
靜默失敗是最危險的失敗模式。 比起炸一個 exception 讓你看到,「什麼都沒發生」反而最難 debug。在設計系統時,如果你發現某個環節有靜默失敗的可能,要麼加上明確的回報機制,要麼繞過它。
簡單架構往往比聰明架構更可靠。 「一個 dispatcher 管理多個 sub-agent」看起來優雅,但引入了中心化的單點故障和並發限制問題。「每個任務獨立跑」看起來笨,但實際上更穩固。
多代理不等於多 sub-agent。 「多代理」的核心是任務分解和並行執行,不一定要用 parent-child 的 spawn 模式實現。Independent session 也是一種多代理架構,只是協調方式不同。
結語
AI Agent 的生態還很年輕,很多行為沒有你在傳統軟體開發裡習慣的那種明確規格。「超過上限會靜默丟棄」這種行為,在傳統系統裡會被視為 bug,但在 agent 框架裡可能只是「還沒來得及處理的邊界情況」。
所以,多跑、多測、多踩坑。不要相信一切都會按照你想像的方式運作——尤其是在半夜三點重構系統的時候。
如果你也在搞 AI 多代理系統的排程設計,希望這篇能幫你少走一段彎路。我的半夜就不白熬了 😂