跳到內容

檔案式 IPC 訊息匯流排

透過 append-only JSONL 實現結構化的跨 Agent 委派,搭配 TaskSpec 工作流。


多數多 Agent 系統要求你安裝和維護訊息代理:Redis、RabbitMQ、Kafka。這就像要求每間小辦公室都有企業郵件伺服器、IT 團隊和 SLA。

DuDuClaw 採用不同的方式:佈告欄

想像走廊上的共用佈告板:

  • Agent A 將任務便利貼釘在板上(附加一行到檔案)
  • 辦公室經理定期巡視,閱讀新便利貼(調度器輪詢檔案)
  • 辦公室經理將便利貼交給 Agent B(啟動子程序)
  • Agent B 將結果釘回佈告板

不需要郵件伺服器。不需要 IT 團隊。不需要 SLA。只要一塊佈告板、一些圖釘,和一位可靠的辦公室經理。


每則訊息是一行 JSON,附加到 bus_queue.jsonl

{"from": "agent-a", "to": "agent-b", "task": "summarize-report", "payload": {...}, "ts": "2026-04-07T10:30:00Z"}
{"from": "agent-b", "to": "agent-a", "task": "summary-result", "payload": {...}, "ts": "2026-04-07T10:30:15Z"}

一行 = 一則訊息。檔案隨時間增長,如同 append-only 日誌。

HeartbeatScheduler 觸發(定期間隔)
|
v
AgentDispatcher 讀取 bus_queue.jsonl
|
v
有我管理的 Agent 的新訊息嗎?
|
+--+--+
| |
有 沒有
| |
| v
| 休眠到下次心跳
|
v
對每則待處理訊息:
|
v
檢查 max_concurrent_runs 信號量
|
+---> 有空位?--> 啟動 Claude CLI 子程序執行任務
|
+---> 全部滿了?--> 留到下次循環處理

JSONL(JSON Lines)具有使其非常適合此用途的特性:

Append-only 天生併發安全。 多個程序可以同時附加到同一個檔案而不會互相破壞資料。每次 append 操作寫入一個完整的行,沒有交錯風險。

檔案天生具有持久性。 如果系統在操作途中崩潰,崩潰前寫入的所有內容都保留下來。不會遺失訊息,不需要恢復協議。

人類可讀。 你可以用 tail -f bus_queue.jsonl 除錯整個訊息歷史。不需要特殊工具、管理控制台或協議解碼器。

零依賴。 不需要安裝、設定、監控、修補或排除任何代理的故障。檔案系統就是代理。

每個 Agent 在心跳設定中有 max_concurrent_runs 設定。這防止大量訊息壓垮系統:

Agent "agnes" 設定:
max_concurrent_runs = 3
目前狀態:
執行中:2 個任務
待處理:5 則訊息
調度器決策:
- 再啟動 1 個任務(達到上限 3)
- 保留剩餘 4 則訊息到下次循環

這是簡單的計數信號量(沒有複雜的佇列管理,沒有優先排程)。當任務完成時,它的空位開放給下一則待處理訊息。


調度器不是持續運行的,它由 HeartbeatScheduler 驅動,為每個 Agent 提供統一的計時機制:

HeartbeatScheduler(每 Agent)
|
+---> 輪詢 bus_queue.jsonl 是否有新任務
|
+---> 檢查 GVU 沉默打破器
| (如果 Agent 最近未演化,
| 觸發主動反思)
|
+---> 觸發任何到期的 cron 任務

間隔可按 Agent 設定。高流量的客服 Agent 可能每 5 秒輪詢一次;背景分析 Agent 可能每 5 分鐘輪詢一次。


每個外部依賴都是潛在的故障點。Redis 需要記憶體管理、監控和備份。Kafka 需要 ZooKeeper(或 KRaft)、主題管理和消費者群組協調。JSONL 檔案只需要…一個檔案系統。

對一個設計為在開發者機器上以單一二進位檔執行的系統而言,這種簡便性是特色,不是妥協。

寫入檔案的訊息能挺過程序重啟、系統重開和崩潰。沒有可能遺失的「傳輸中」狀態。一旦一行被附加,它就是永久的。

訊息代理出問題時,你在除錯不透明的內部狀態。JSONL 檔案出問題時,你用文字編輯器打開它。每次跨 Agent 通訊的完整歷史就在那裡,按時間順序,純文字。

此方案有天然的上限:對數十個 Agent 每天交換數百則訊息,它運作良好。不適合每秒數百萬則訊息。但這正是 DuDuClaw 使用場景的最佳權衡(個人開發者或小團隊執行少量專門 Agent)。


原始 JSONL 訊息對簡單任務夠用,但複雜的多 Agent 工作流需要結構。DelegationEnvelope 提供標準化的交接協定:

DelegationEnvelope:
context: 接收方需要的背景資訊
constraints: 邊界與要求
task_chain: 誰把什麼委派給誰的歷史紀錄
expected_output: 發送方期待收到什麼
delegation_depth: 目前的跳躍次數(上限 5)

信封跟著訊息一起在匯流排上傳遞。每個處理它的 Agent 都會往 task_chain 追加一筆紀錄,形成一條可追蹤的委派路徑:

Agent A → Agent B → Agent C
| | |
v v v
depth=1 depth=2 depth=3

系統強制設定最大委派深度(5 跳)以防止無窮委派迴圈。信封格式向下相容;不理解信封的 Agent 仍可處理原始 payload。


對於橫跨多個步驟、彼此有依賴關係的任務,TaskSpec 系統提供結構化的工作流規劃:

TaskSpec:
steps:
- id: "step-1"
action: "research"
dependencies: []
status: completed
- id: "step-2"
action: "draft"
dependencies: ["step-1"]
status: in_progress
- id: "step-3"
action: "review"
dependencies: ["step-2"]
status: pending

工作流引擎處理:

  • 依賴感知排程:步驟只在其依賴都完成時才執行
  • 自動重試:失敗的步驟最多重試 3 次,帶退避
  • 自動重新規劃:重試用盡後,系統可重新規劃(最多 2 次),調整後續步驟
  • 持久化:TaskSpec 狀態存到 tasks/ 目錄,程序重啟後仍保留
步驟失敗
|
v
重試(最多 3 次)
|
+--+--+
| |
成功 仍然失敗
| |
v v
繼續 重新規劃(最多 2 次)
|
v
生成調整後的步驟
並從那裡重試

  • HeartbeatScheduler:驅動每個 Agent 的輪詢節奏。
  • Agent Registry:調度器知道存在哪些 Agent 及其併發限制。
  • 容器沙盒:當任務需要隔離時,調度器在容器內而非直接在主機上啟動子程序。
  • DelegationEnvelope:為複雜的多 Agent 交接提供結構化背景資訊。
  • TaskSpec:讓多步驟工作流具備依賴感知,支援重試與重新規劃。
  • Multi-Runtime:調度器依每個 Agent 的 runtime 設定,啟動對應的 CLI 後端(Claude/Codex/Gemini)。
  • 審計日誌:所有已調度任務記錄在 JSONL 審計紀錄中。

能用的最簡單方案通常是最好的方案。對 DuDuClaw 規模的跨 Agent 通訊而言,JSONL 檔案提供了訊息代理的一切(持久性、併發安全、可觀測性),卻沒有任何營運開銷。而當任務變複雜時,DelegationEnvelope 與 TaskSpec 又能在不犧牲底層傳輸簡潔性的前提下,補上必要的結構。