Get started
Swarms — การกระจายงานไปยังเอเจนต์และการประสานงานในโหมดโค้ด
Swarms — การกระจายงานไปยังเอเจนต์และการประสานงานในโหมดโค้ด
สถานะ: จัดส่งแล้ว — ถูกแทนที่ด้วย docs/tools/swarm.md เอกสารนี้ยังคงไว้เป็น
บันทึกการออกแบบการนำไปใช้งาน
1. คืออะไรและทำไมจึงต้องมี
swarm คือซับเอเจนต์จำนวนมากที่ได้รับการประสานงานอย่างกำหนดผลลัพธ์แน่นอนจากสคริปต์
โหมดโค้ด: กระจายงานไปยังตัวอ่าน N ตัว ตรวจสอบข้อค้นพบแบบโต้แย้ง สังเคราะห์ผ่าน
ตัวจัดลำดับความสำคัญแบบมีสถานะ และวนซ้ำตามเกตการตัดสินใจ โฟลว์การควบคุม (Promise.all,
while, if) ก็คือ การประสานงาน — โดยตั้งใจให้ ไม่มี DSL แบบกราฟ
ไม่มีโหมดใหม่ และไม่มีพื้นผิวเครื่องมือระดับบนสุดใหม่
โหมดโค้ดของ OpenClaw (QuickJS-WASI, snapshot/resume, คำขอผ่านบริดจ์) เป็น รากฐาน การเรียกบริดจ์ที่พักไว้จะคงอยู่ผ่านสแนปช็อต VM การรีสตาร์ต Gateway และ กลับมาทำงานต่อจากจุดที่หยุดไว้อย่างแม่นยำ — แข็งแกร่งกว่าการออกแบบที่เล่นเจอร์นัลซ้ำ โดย ไม่มีข้อจำกัดด้านการกำหนดผลลัพธ์แน่นอนสำหรับสคริปต์
การตั้งชื่อ: ชื่อในผลิตภัณฑ์/เอกสารคือ Swarm ตัวระบุในโค้ดคงไว้ตามตัวอักษร:
API ฝั่งเกสต์ agents.*, การกำหนดค่า tools.swarm, คอลัมน์กลุ่ม swarm
2. การตัดสินใจ (ผู้ดูแล, 2026-07-17)
- ต้นทุน: บังคับใช้ขีดจำกัดจากการกำหนดค่า; งบประมาณโทเค็นต่อ swarm เป็นทางเลือก ไม่มีงบประมาณบังคับ
- การอนุมัติ: ลูกทำงานแบบ ปิดเมื่อเกิดความล้มเหลว / ไม่โต้ตอบ การดำเนินการที่ต้อง ได้รับอนุมัติจะถูกปฏิเสธ; การปฏิเสธจะถูกรายงานในผลลัพธ์ของลูก; สคริปต์ เป็นผู้ตัดสินใจ ไม่มีพรอมต์รบกวนผู้ปฏิบัติงานจากการกระจายงาน
- v1 รองรับเฉพาะสคริปต์เฉพาะกิจที่โมเดลเขียน เวิร์กโฟลว์ที่บันทึก/ตั้งชื่อไว้ และจุดเข้า CLI/cron: ทำภายหลัง (มีโหมดโค้ดแบบ headless สำหรับ cron อยู่แล้ว)
- อัตลักษณ์ของลูก: ใช้เอเจนต์ผู้ปฏิบัติงานเฉพาะโดยค่าเริ่มต้นผ่านการกำหนดค่า
tools.swarm.defaultAgentId(ตรวจสอบกับรายการอนุญาตเป้าหมายซับเอเจนต์ที่มีอยู่); เขียนทับต่อการสร้าง ด้วยagentIdCore ไม่มีรหัสเอเจนต์แบบรวมมาให้; เอกสารแนะนำการกำหนดค่าเอเจนต์workerแบบกระชับ - ไม่มีการเปลี่ยนแปลงซอร์ส Codex ฮาร์เนส Codex ใช้รูปแบบ spawn/wait (§8)
3. ภาพรวมสถาปัตยกรรม
สคริปต์โหมดโค้ด (QuickJS VM, Gateway) สคริปต์ Codex V8 (กระบวนการ Codex) agents.run(...) ── การเรียกบริดจ์ที่พักไว้ tools.sessions_spawn / tools.agents_wait │ │ RPC ของ item/tool/call (แต่ละครั้ง ≤600s) ▼ ▼ CORE (ไม่ขึ้นกับฮาร์เนส, รีโพนี้) sessions_spawn {collect:true, outputSchema, fastMode, groupId} agents_wait {ids, timeoutSeconds} │ รีจิสทรีซับเอเจนต์ (SQLite): ระเบียนการเสร็จสิ้นของตัวรวบรวม, รหัสกลุ่ม swarm │ ลูก = เซสชันซับเอเจนต์ทั่วไป (จำกัดตามเลน, การอนุมัติแบบปิดเมื่อเกิดความล้มเหลว) │ sessions.changed SSE ──► จุดใน Control UI / แถบด้านข้าง / ข้อความสถานะช่องทางมีเจ้าของหลักหนึ่งเดียวสำหรับความหมายของ spawn/complete/settle (เครื่องมือ Core + รีจิสทรี)
การขนส่งสำหรับ await สองแบบ: QuickJS พักการเรียกบริดจ์ไว้อย่างไม่มีกำหนด (สแนปช็อต);
Codex สำรวจ agents_wait ผ่าน RPC ที่มีขอบเขต
4. เกตการกำหนดค่า (v1)
tools.swarm ใหม่ (ส่วนกลาง + การเขียนทับต่อเอเจนต์ โดยใช้รูปแบบการผสานเดียวกับ
tools.codeMode):
"tools": { "swarm": { "enabled": false, // เกตหลัก, ค่าเริ่มต้นปิด "maxConcurrent": 8, // จำนวนลูกที่ทำงานพร้อมกัน (ขีดจำกัดเลน swarm) "maxChildrenPerGroup": 50, // จำนวนลูกที่ยังทำงานอยู่ต่อกลุ่ม swarm "maxTotalPerGroup": 200, // จำนวนการสร้างตลอดอายุของกลุ่ม (แนวป้องกันการทำงานไม่สิ้นสุด) "waitTimeoutSecondsMax": 600, "defaultAgentId": "" // ไม่บังคับ; รหัสเอเจนต์ลูกเมื่อ spawn ไม่ระบุ agentId }}- 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ในแค็ตตาล็อก; พารามิเตอร์collect/outputSchema/fastMode/groupIdบนsessions_spawnจะถูกปฏิเสธพร้อมข้อผิดพลาดที่ชัดเจนซึ่งระบุคีย์การกำหนดค่า ไม่มีการเปลี่ยนแปลงพฤติกรรมอื่น defaultAgentIdได้รับการตรวจสอบผ่านresolveSubagentAllowedTargetIds(src/agents/subagent-target-policy.ts); รหัสที่ไม่รู้จัก → ข้อผิดพลาดในการสร้าง ไม่ใช่การใช้ค่าทดแทน
5. Core: การสร้างในโหมดตัวรวบรวม + agents_wait (v1)
5.1 ส่วนเพิ่มเติมของ sessions_spawn (ทั้งหมดขึ้นกับการเปิดใช้งาน swarm)
collect: boolean— เมื่อเป็นจริง การทำงานของลูกจะได้รับการลงทะเบียนด้วยexpectsCompletionMessage: falseและ ระเบียนการเสร็จสิ้นของตัวรวบรวม แทนการส่งประกาศ/การชี้นำ เครื่องมือส่งคืน{ runId, sessionKey }ทันที ไม่มีการผูกกับช่องทาง/เธรดoutputSchema: object— JSON Schema ลูกจะได้รับเครื่องมือสังเคราะห์structured_outputที่เพิ่มต่อท้ายพื้นผิวเครื่องมือ; ส่วนเพิ่มเติมของพรอมต์ระบบ สั่งให้เรียกเครื่องมือนี้หนึ่งครั้งเท่านั้นพร้อมผลลัพธ์สุดท้าย เมื่อการตรวจสอบ ล้มเหลว ลูกจะได้รับการกระตุ้นให้ลองใหม่หนึ่งครั้ง; หลังจากนั้นระเบียนการเสร็จสิ้น จะมีstructured: undefinedพร้อมข้อความดิบและschemaErrorfastMode: 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- รหัสเอเจนต์ลูก:
params.agentId→ มิฉะนั้นtools.swarm.defaultAgentId→ มิฉะนั้น เอเจนต์ผู้ร้องขอ (พฤติกรรมที่มีอยู่)
5.2 การอนุมัติแบบปิดเมื่อเกิดความล้มเหลว
ลูกแบบตัวรวบรวมทำงานด้วยบริบทการอนุมัติแบบไม่โต้ตอบ: การเรียกเครื่องมือใด ๆ
ที่ต้องได้รับอนุมัติจากผู้ปฏิบัติงานจะได้รับผลเป็นการปฏิเสธแบบมีโครงสร้าง
(approval_required) ที่ลูกมองเห็น และคาดว่าลูกจะรายงาน
การติดขัดในผลลัพธ์ การนำไปใช้: ใช้ระบบนโยบายการอนุมัติ exec/เครื่องมือ
ที่มีอยู่ซ้ำ โดยบังคับใช้ตัวแก้ค่า 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[] }- ส่งคืนทันทีเมื่อมีรหัส อย่างน้อยหนึ่งรายการ เสร็จสมบูรณ์ (ความหมายแบบ
เสร็จก่อน/แข่งขันกัน ซึ่งทำให้สร้างไปป์ไลน์ได้) หรือเมื่อหมดเวลาพร้อม
completed: [] - ค่าเริ่มต้นของ
timeoutSecondsคือ 30 และถูกจำกัดไว้ที่waitTimeoutSecondsMax - ทำซ้ำได้โดยไม่เปลี่ยนผลลัพธ์: รหัสที่เสร็จสมบูรณ์แล้วจะส่งคืนระเบียนเดิมอีกครั้ง (ระเบียนจะ ถูกเก็บไว้จนกว่าจะเก็บกลุ่มถาวร) รหัสที่ไม่รู้จัก → รายการข้อผิดพลาดต่อรหัส ไม่ใช่การ throw
- ความเป็นเจ้าของ: เฉพาะเซสชันที่สร้างการทำงาน (หรือลำดับพาเรนต์ของเซสชันนั้น) เท่านั้นที่รอ
การทำงานดังกล่าวได้ — กฎความเป็นเจ้าของเดียวกับ
waitในโหมดโค้ด (code-mode.ts:1684) - รีจิสทรี: ระเบียนการเสร็จสิ้นอยู่ในที่เก็บ SQLite ของรีจิสทรีซับเอเจนต์
ที่มีอยู่ (
subagent-registry.store.sqlite.ts) — ฟิลด์ใหม่ ไม่มีที่เก็บใหม่ และไม่มี การเพิ่มเวอร์ชันสคีมา (เฉพาะคอลัมน์เพิ่มเติม; ดูข้อจำกัดใน §9)
5.4 การบังคับใช้ขีดจำกัด
maxConcurrent: ลูกแบบตัวรวบรวมทำงานบนเลนซับเอเจนต์ที่มีอยู่ แต่ นับแยกตามกลุ่ม swarm; การสร้างที่เกินขีดจำกัดจะเข้าคิวแบบ FIFO (ฝั่งโฮสต์ ใน เส้นทางการสร้าง — ส่งคืน runId ทันที และเริ่มทำงานเมื่อมีช่องว่าง)maxChildrenPerGroup/maxTotalPerGroup: การสร้างจะถูกปฏิเสธด้วยข้อผิดพลาดแบบมีชนิด เมื่อเกินค่า; ข้อความข้อผิดพลาดจะระบุคีย์การกำหนดค่า- ความลึก: ลูกแบบตัวรวบรวมคงความหมายของ
DEFAULT_SUBAGENT_MAX_SPAWN_DEPTH(ลูกเป็นโหนดปลายทาง เว้นแต่กำหนดค่าการซ้อนอย่างชัดเจน)
6. สัญญาการทดสอบ (v1, เลน A)
- ยูนิต: การแก้ค่า/จำกัดช่วงการกำหนดค่า; การปฏิเสธโดยเกตเมื่อปิดใช้งาน; การใช้ค่าเริ่มต้น ของ groupId; การบังคับใช้ขีดจำกัด (เข้าคิว + ปฏิเสธ); ความหมายการแข่งขันของการรอ; การทำซ้ำ การรอโดยไม่เปลี่ยนผลลัพธ์; การปฏิเสธความเป็นเจ้าของ; การตรวจสอบเอาต์พุตแบบมีโครงสร้าง + กระตุ้นให้ลองใหม่ + เส้นทาง schemaError; การส่ง fastMode ไปยังแพตช์เซสชัน; การตรวจสอบ defaultAgentId
- การผสานรวม (vitest, รันไทม์โมเดลจำลอง): สร้างลูกแบบตัวรวบรวม 3 ตัว รอ ในลูป ยืนยันลำดับการเสร็จก่อนและการระบายขั้นสุดท้าย; การจำลอง การรีสตาร์ต Gateway: โหลดรีจิสทรีใหม่ → การรอแก้ผลจากการเสร็จสิ้นที่คงอยู่
- การทดสอบทั้งหมดอยู่ร่วมกับ
*.test.ts; ไม่มีการเรียกโมเดลจริง
7. พื้นผิวฝั่งเกสต์ QuickJS (เลน B, หลัง Core)
- โกลบอลฝั่งเกสต์ติดตั้งใน
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> - ซับเอเจนต์
spawn_agentแบบเนทีฟของ Codex อยู่ร่วมกันได้; แถวมิเรอร์งานของซับเอเจนต์เหล่านั้นส่งข้อมูล ไปยังพื้นผิวความคืบหน้าเดียวกัน
9. การคงอยู่และการเก็บรักษา
- ไม่มีที่เก็บใหม่ ระเบียนรีจิสทรีขยายตาราง SQLite ของรีจิสทรีซับเอเจนต์
ที่มีอยู่; ลูกเป็นแถว
sessionsทั่วไป เพิ่มเฉพาะคอลัมน์ — การเปลี่ยนแปลงใด ๆ ที่ต้องเพิ่มเวอร์ชันสคีมา SQLite ต้องได้รับ การอนุมัติอย่างชัดเจนจากผู้ดูแลก่อน (นโยบายรีโพ) - รหัสกลุ่ม swarm อยู่ในระเบียนรีจิสทรี + ข้อมูลเมตาของเซสชันลูก
- การเก็บรักษา: ระเบียนตัวรวบรวมที่เสร็จสมบูรณ์จะคงอยู่จนถึง การเก็บกลุ่มถาวร:
เมื่อการทำงานของพาเรนต์เสร็จสิ้น (หรือ TTL หมดอายุ) ลูกของกลุ่มจะถูกเก็บถาวร
เป็นชุด (ขยายการกวาด
DEFAULT_SUBAGENT_ARCHIVE_AFTER_MINUTESที่มีอยู่ให้ทำงานแยกตามกลุ่ม)
10. พื้นผิวความคืบหน้า ("จุดต่าง ๆ") — เลนภายหลัง
- ทำงานโดยนัยและขับเคลื่อนโดยฮาร์เนส อนุมานจาก SSE
sessions.changedที่มีอยู่ + รีจิสทรี; บันทึกphase/logเพิ่มความหมาย ไม่มีการเรนเดอร์ที่ขับเคลื่อนโดยเอเจนต์ - Control UI: ตัวเรนเดอร์
swarmในตระกูลวิดเจ็ตพื้นที่ทำงาน (ui/src/lib/workspace/widgets/) — ตารางจุดที่จัดกลุ่มตามเฟส บรรทัด ผู้บรรยาย สถานะ/ป้ายกำกับ/โมเดลต่อจุด; ทรีลูกในแถบด้านข้างไม่เปลี่ยนแปลง - ช่องทาง: ข้อความสถานะที่แก้ไขและควบคุมอัตราหนึ่งข้อความต่อกลุ่ม (ปฏิบัติตาม
docs/concepts/streaming.md; ห้ามส่งข้อความแยกต่อลูก)
11. หน้า Labs (Control UI, เลนอิสระ)
Settings → Labs: ตัวสลับฟีเจอร์ทดลอง โดยรายการแรกคือ Code Mode
และ Swarm แต่ละแถวประกอบด้วยชื่อ คำอธิบายหนึ่งบรรทัด ลิงก์เอกสาร และตัวสลับที่เชื่อมต่อ
ผ่าน RPC config.patch ที่มีอยู่ (merge-patch ตาม RFC 7396 — ตั้งค่า
tools.codeMode.enabled / tools.swarm.enabled) พร้อมคำแนะนำว่า "ต้องรีสตาร์ต"
เมื่อเกี่ยวข้อง ผู้ใช้ค้นพบได้ง่าย แต่ข้อความต้องระบุสถานะทดลอง
อย่างชัดเจน i18n: สตริงทั้งหมดผ่าน en.ts + ไปป์ไลน์ซิงค์ตามปกติ
12. ตำแหน่งการทำงาน (ภายหลัง)
placementให้เลือกเมื่อ spawn:"local"(ค่าเริ่มต้น) |"cloud:<profile>"ผ่าน การส่งต่อสภาพแวดล้อม worker ที่มีอยู่ (sessions.dispatch) ส่วนตำแหน่งการทำงานแบบพูล เพิ่มภายหลัง หาก child ของ SSH sandbox ในกล่องที่ใช้ร่วมกันพิสูจน์แล้วว่าไม่เพียงพอ- VM ของ Orchestrator จะอยู่บน Gateway เสมอ ส่วน settle/dots/budget ไม่รับรู้ตำแหน่งการทำงาน
13. สิ่งที่ไม่ใช่เป้าหมาย
- ไม่มี DSL แบบกราฟ — ลำดับการควบคุมคือกราฟ (ตั้งใจออกแบบและมีเอกสารกำกับ)
- ไม่มีการเปลี่ยนแปลงซอร์สของ Codex และไม่ใช้ส่วนภายในของ Codex Code Mode ซ้ำ
- ไม่มีเวิร์กโฟลว์ที่บันทึกไว้/ตั้งชื่อใน v1 และไม่มีจุดเริ่มต้นผ่าน CLI
- ไม่มีการส่งต่อการอนุมัติของผู้ดำเนินการจากแต่ละ child ขึ้นมา
- ไม่มีการจัดเตรียมคลาวด์แบบ 1:1 ในระดับ fan-out
- ไม่มี compat shim สำหรับรันไทม์ในสถานะคงที่ Swarm เป็นพื้นผิวใหม่ที่มีการควบคุมการเปิดใช้
14. ระยะการสร้าง / การแบ่ง PR
- เลน A (core): การกำหนดค่า §4 + spawn/wait/caps/approvals ใน §5 + การทดสอบ §6
- เลน C (หน้า Labs): §11 — เป็นอิสระและรวมได้ก่อน
- เลน B (พื้นผิว QuickJS): §7 — หลังจากรวมสัญญาของ A แล้ว
- ตัวเรนเดอร์ dots (§10), การฉายภาพ Codex (§8),
agents.session(§7 v1.1), ตำแหน่งการทำงาน (§12), การเขียนเอกสารผู้ใช้ใหม่ — เป็น PR ติดตามผลตามลำดับนี้
แต่ละ PR: ไปป์ไลน์ CI ผ่านทั้งหมด, $autoreview สะอาด, ปิดไว้เป็นค่าเริ่มต้น และ main พร้อมเผยแพร่