---
x-i18n:
    generated_at: "2026-07-26T07:46:34Z"
    model: gpt-5.6
    postprocess_version: locale-links-v1
    prompt_version: 32
    provider: openai
    source_hash: 90c6c85a837448f4e5ceccdccf73489db801ad502cbbb2f3eb04d6aff7e902f0
    source_path: plan/swarms.md
    workflow: 16
---

# Swarms — 程式碼模式中的代理分流與協調

狀態：已發布 — 已由 `docs/tools/swarm.md` 取代。本文件保留作為
實作設計紀錄。

## 1. 內容與原因

**Swarm** 是由程式碼模式指令碼以確定性方式協調的多個子代理：
分流 N 個讀取代理、以對抗方式驗證發現、透過具狀態的優先排序器進行整合，
並依決策閘門循環。控制流程（`Promise.all`、
`while`、`if`）_本身就是_協調機制 — 此設計刻意**不採用圖形 DSL、
不新增模式，也不新增頂層工具介面**。

OpenClaw 程式碼模式（QuickJS-WASI、快照／續接、橋接請求）是其
基礎。暫停中的橋接呼叫可歷經 VM 快照與閘道重新啟動，並
從停止之處精確續接 — 這比日誌重播設計更強，而且
不會對指令碼施加確定性限制。

命名：產品／文件名稱為 **Swarm**。程式碼識別碼維持原文：
`agents.*` 客體 API、`tools.swarm` 設定、`swarm` 群組欄位。

## 2. 決策（維護者，2026-07-17）

- 成本：強制執行設定上限；每個 Swarm 的權杖預算為選用。不強制要求預算。
- 核准：子代理以**失敗時關閉／非互動式**方式執行。需要核准的
  動作會遭拒絕；拒絕結果會回報於子代理結果中；由指令碼
  決定後續處理。分流不會向操作員大量傳送提示。
- v1 僅支援由模型撰寫的臨時指令碼。儲存／命名工作流程、命令列介面／排程
  進入點：稍後支援（無介面程式碼模式已可供排程使用）。
- 子代理身分：預設透過 `tools.swarm.defaultAgentId`
  設定使用專用工作代理（依現有子代理目標允許清單驗證）；每次生成可使用
  `agentId` 覆寫。核心不附帶任何內建代理 ID；文件建議使用精簡的
  `worker` 代理設定。
- 不變更 Codex 原始碼。Codex 測試框架使用生成／等待慣用法（§8）。

## 3. 架構概觀

```
程式碼模式指令碼（QuickJS VM、閘道）          Codex V8 指令碼（codex 程序）
  agents.run(...) ── 暫停中的橋接呼叫           tools.sessions_spawn / tools.agents_wait
        │                                                │ 項目／工具／呼叫 RPC（每次 ≤600s）
        ▼                                                ▼
             核心（不限定測試框架，本存放庫）
  sessions_spawn {collect:true, outputSchema, fastMode, groupId}
  agents_wait {ids, timeoutSeconds}
        │
  子代理登錄檔（SQLite）：收集器完成紀錄、Swarm 群組 ID
        │
  子代理 = 一般子代理工作階段（受通道上限限制、核准採失敗時關閉）
        │
  sessions.changed SSE ──► Control UI 圓點／側邊欄／頻道狀態訊息
```

生成／完成／結算語意只有一個標準擁有者（核心工具 + 登錄檔）。
兩種等待傳輸：QuickJS 會無限期暫停橋接呼叫（快照）；
Codex 則在有界 RPC 中輪詢 `agents_wait`。

## 4. 設定閘門（v1）

新增 `tools.swarm`（全域 + 個別代理覆寫，合併模式與
`tools.codeMode` 相同）：

```jsonc
"tools": {
  "swarm": {
    "enabled": false,            // 主閘門，預設關閉
    "maxConcurrent": 8,          // 同時執行的子代理數量（Swarm 通道上限）
    "maxChildrenPerGroup": 50,   // 每個 Swarm 群組的作用中子代理數量
    "maxTotalPerGroup": 200,     // 每個群組生命週期內的生成總數（失控防護）
    "waitTimeoutSecondsMax": 600,
    "defaultAgentId": ""         // 選用；生成省略 agentId 時使用的子代理 ID
  }
}
```

- Zod：聯集 `boolean | strict object`，類似 `CodeModeSchema`
  （`src/config/zod-schema.agent-runtime.ts`）；`swarm: true` → `{enabled: true}`。
- 型別位於 `src/config/types.tools.ts`（個別代理與頂層 `tools` 皆有），
  標籤位於 `schema.labels.ts`，說明位於 `schema.help.runtime.ts`。
- 解析輔助函式 `resolveSwarmConfig(cfg, agentId)` 仿照
  `resolveCodeModeConfig`（`src/agents/code-mode.ts:215`），並限制所有數值範圍。
- 停用時的閘門效果：工具目錄中不會出現 `agents_wait`；
  `sessions_spawn` 上的 `collect`/`outputSchema`/`fastMode`/`groupId` 參數
  會遭拒絕，並顯示明確指出設定鍵的錯誤。其他行為不變。
- `defaultAgentId` 透過 `resolveSubagentAllowedTargetIds`
  （`src/agents/subagent-target-policy.ts`）進行驗證；未知 ID → 生成錯誤，不會回退。

## 5. 核心：收集器模式生成 + `agents_wait`（v1）

### 5.1 `sessions_spawn` 新增項目（全部受 Swarm 啟用狀態控制）

- `collect: boolean` — 為 true 時，子代理執行會登錄至
  `expectsCompletionMessage: false` 並建立**收集器完成紀錄**，
  而不是進行公告／引導傳遞。工具會立即傳回 `{ runId, sessionKey }`。
  不繫結頻道／討論串。
- `outputSchema: object` — JSON Schema。子代理的工具介面會附加一個合成的
  `structured_output` 工具；系統提示詞附加內容會指示它使用最終結果
  呼叫該工具恰好一次。驗證失敗時，子代理會收到一次提醒以重試；若仍失敗，
  完成紀錄會包含 `structured: undefined`、原始文字以及
  `schemaError`。
- `fastMode: true | "auto" | false` — 透過 `resolveSubagentModelAndThinkingPlan`
  （`src/agents/subagent-spawn-plan.ts`），使用現有的 `FastMode` 維度
  （`src/shared/fast-mode.ts`），與模型／思考設定一起傳入子代理工作階段修補。
  省略 = 繼承。
- `groupId: string` — Swarm 群組戳記。預設為
  `swarm:<requesterSessionKey>:<runId-of-requesting-run>`。它會持久保存於
  登錄紀錄與子代理工作階段資料列中，用於上限、列出、批次
  封存及圓點。
- `label: string` 已存在 — 會顯示於圓點和 `subagents list` 中。
- 子代理 ID：`params.agentId` → 否則 `tools.swarm.defaultAgentId` → 否則
  使用請求者代理（現有行為）。

### 5.2 核准採失敗時關閉

收集器子代理使用非互動式核准脈絡執行：任何需要操作員核准的
工具呼叫，都會解析為子代理可見的結構化拒絕結果
（`approval_required`），並預期子代理在結果中回報
受阻情況。實作方式：重用現有的執行／工具核准
原則管線，並對收集器模式的子代理執行強制使用 `deny` 解析器。
收集器子代理不會向操作員介面發出核准事件。

### 5.3 `agents_wait` 工具（新增，受閘門控制）

```
agents_wait({ ids: string[], timeoutSeconds?: number })
→ {
    completed: [{ runId, status: "done"|"failed"|"killed"|"timeout",
                  result: string, structured?: unknown, schemaError?: string,
                  sessionKey, label?, usage?: {inputTokens, outputTokens} }],
    pending: string[]
  }
```

- 只要**至少一個** ID 完成便立即傳回（最先完成／競速
  語意，可支援流水線），或逾時並傳回 `completed: []`。
- `timeoutSeconds` 預設為 30，並限制至 `waitTimeoutSecondsMax`。
- 具冪等性：已完成的 ID 會再次傳回其紀錄（紀錄會
  保留至群組封存）。未知 ID → 個別 ID 錯誤項目，不會擲出錯誤。
- 擁有權：只有生成執行的工作階段（或其父系鏈）可等待
  該執行 — 與程式碼模式中的 `wait` 採用相同擁有權規則
  （`code-mode.ts:1684`）。
- 登錄檔：完成紀錄存放於現有的子代理登錄檔 SQLite
  儲存區（`subagent-registry.store.sqlite.ts`）— 新增欄位，不新增
  儲存區，也不提升結構描述版本（僅新增欄位；請參閱 §9 限制）。

### 5.4 上限強制執行

- `maxConcurrent`：收集器子代理在現有子代理通道上執行，但
  依 Swarm 群組分別計數；超過上限的生成會依先進先出順序排隊（由主機端在
  生成路徑處理 — 立即傳回 runId，釋出名額後開始執行）。
- `maxChildrenPerGroup` / `maxTotalPerGroup`：超過上限後，生成會以具型別的錯誤
  拒絕；錯誤文字會指出設定鍵。
- 深度：收集器子代理維持 `DEFAULT_SUBAGENT_MAX_SPAWN_DEPTH` 語意
  （除非明確設定巢狀，否則子代理均為葉節點）。

## 6. 測試契約（v1，通道 A）

- 單元測試：設定解析／範圍限制；停用時的閘門拒絕；groupId
  預設值；上限強制執行（排隊 + 拒絕）；等待競速語意；等待
  冪等性；擁有權拒絕；結構化輸出驗證 + 提醒重試 +
  schemaError 路徑；fastMode 傳入工作階段修補；defaultAgentId
  驗證。
- 整合測試（vitest、模擬模型執行階段）：生成 3 個收集器子代理、在迴圈中
  等待、斷言最先完成順序與最終清空；閘道重新啟動
  模擬：重新載入登錄檔 → 等待從持久保存的完成紀錄解析。
- 所有測試均與 `*.test.ts` 放置於同一處；不進行即時模型呼叫。

## 7. QuickJS 客體介面（通道 B，核心完成後）

- 客體全域項目安裝於 `CONTROLLER_SOURCE`
  （`src/agents/code-mode.worker.ts:190-374`），保留名稱新增至
  `code-mode-namespaces.ts`：
  - `agents.run(prompt, opts) → Promise<result|structured>` — 語法糖：
    收集器生成 + 在專用橋接方法（`agentWait`）上暫停等待，
    由主機在完成時結算（不輪詢；支援快照）。
  - `agents.session(system, opts) → Promise<handle>`；
    `handle.send(input, opts) → Promise<...>`；`handle.close()`。（v1.1 —
    在 run() 之後發布；使用 `mode:"session"` + 每回合收集器紀錄。）
  - `phase(title)`、`log(message)` — 即發即棄的橋接通知 →
    Swarm 進度事件。
- 橋接方法新增至 `CodeModeBridgeMethod`（`code-mode.ts:91`）：
  `agentSpawn`、`agentWait`、`swarmNote`。`agentSpawn`/`agentWait`
  **依構造即具重播安全性**：冪等性鍵 `(codeModeRunId, bridgeId)`
  儲存於登錄紀錄中；重新啟動會從持久保存的完成紀錄重新結算，
  且絕不重複生成。
- 待處理的 `agentWait` 橋接呼叫會延長執行的快照 TTL（待處理
  代理集合就是訊號；不使用旗標）。
- `API.read("agents.d.ts")` 虛擬檔案記載具型別的介面，以及
  分流／閘門／循環慣用法（`createCodeModeApiVirtualFiles`、
  `code-mode-namespaces.ts:876`）。

## 8. Codex 測試框架投影（後續通道）

- `sessions_spawn`（含新參數）與 `agents_wait` 會流經
  現有的動態工具橋接；在 Codex 程式碼模式指令碼中，它們會自動顯示為
  `tools.*`（已驗證：`codex-rs/code-mode/src/runtime/globals.rs:14-65`、
  `codex-rs/core/src/tools/spec_plan.rs:448-507`）。
- `agents_wait` 會取得較長的動態工具逾時類別（上限 600s；
  `extensions/codex/src/app-server/dynamic-tool-execution.ts:37-39`），並標記為
  逾時／重播安全。
- Codex 父代理的群組鍵：`swarm:<parentSessionKey>:<turnId>`。
- Codex 原生 `spawn_agent` 子代理可共存；其任務鏡像資料列會提供給
  相同的進度介面。

## 9. 持久性與保留

- 不新增儲存區。登錄紀錄會擴充現有的子代理登錄檔
  SQLite 資料表；子代理是一般的 `sessions` 資料列。僅新增欄位
  — **任何需要提升 SQLite 結構描述版本的變更，都必須先取得
  維護者明確核准**（存放庫原則）。
- Swarm 群組 ID 位於登錄紀錄 + 子代理工作階段中繼資料。
- 保留：已完成的收集器紀錄會保留至**群組封存**：
  當父執行完成（或 TTL 到期）時，群組的子代理會
  批次封存（擴充現有的 `DEFAULT_SUBAGENT_ARCHIVE_AFTER_MINUTES`
  清理作業，使其依群組運作）。

## 10. 進度介面（「圓點」）— 後續通道

- 隱含式，由測試框架驅動。衍生自現有的 `sessions.changed` SSE +
  登錄檔；`phase`/`log` 備註新增語意。不由代理驅動呈現。
- Control UI：工作區小工具系列
  （`ui/src/lib/workspace/widgets/`）中的 `swarm` 轉譯器 — 依階段分組的圓點網格、旁白
  行、各圓點的狀態／標籤／模型；側邊欄子代理樹維持不變。
- 頻道：每個群組僅有一則經節流並編輯更新的狀態訊息（遵循
  `docs/concepts/streaming.md`；絕不為每個子代理傳送訊息）。

## 11. 實驗室頁面（控制介面，獨立工作線）

Settings → **Labs**：實驗性功能切換開關，首批項目為 **Code Mode**
與 **Swarm**。每列包含：名稱、單行說明、文件連結、透過
現有的 `config.patch` RPC 連接的切換開關（RFC 7396 合併修補程式——設定
`tools.codeMode.enabled` / `tools.swarm.enabled`），以及適用時顯示的「需要重新啟動」
提示。此頁面可被找到，但文案會明確說明其實驗性狀態。
i18n：所有字串都透過一般的 `en.ts` + 同步流水線處理。

## 12. 執行位置（稍後）

- `placement` 產生時選擇：`"local"`（預設）| `"cloud:<profile>"`，透過
  現有的工作程式環境分派（`sessions.dispatch`）；若共用執行環境中的 SSH 沙箱子項目
  證明不足，稍後再加入集區式執行位置。
- 協調器 VM 一律保留在閘道上；收斂/點狀態/預算
  不受執行位置影響。

## 13. 非目標

- 不使用圖形 DSL——控制流程本身就是圖形（刻意如此，且已記錄於文件）。
- 不變更 Codex 原始碼；不重複使用 Codex Code Mode 內部機制。
- v1 不提供已儲存/具名的工作流程；不提供命令列介面進入點。
- 不逐一向上傳遞每個子項目的操作員核准要求。
- 不在扇出規模下進行 1:1 雲端佈建。
- 不提供穩態執行階段相容性墊片；Swarm 是新的介面，受閘門控管。

## 14. 建置階段 / PR 切分

1. **工作線 A（核心）**：§4 設定 + §5 產生/等待/上限/核准 + §6 測試。
2. **工作線 C（實驗室頁面）**：§11——獨立，可先合併。
3. **工作線 B（QuickJS 介面）**：§7——在 A 的合約合併後進行。
4. 點狀態轉譯器（§10）、Codex 投影（§8）、`agents.session`（§7 v1.1）、
   執行位置（§12）、使用者文件改寫——依此順序在後續 PR 中進行。

每個 PR：CI 通過、`$autoreview` 無問題、預設由閘門關閉、主分支可發布。
