Agent coordination

เอเจนต์ย่อย

เอเจนต์ย่อยคือการรันเอเจนต์เบื้องหลังที่สร้างจากการรันเอเจนต์ที่มีอยู่ เอเจนต์ย่อยจะทำงานในเซสชันของตนเอง (agent:<agentId>:subagent:<uuid>) และ เมื่อเสร็จแล้วจะประกาศผลลัพธ์กลับไปยังช่องแชตของผู้ร้องขอ การรันเอเจนต์ย่อยแต่ละครั้งจะถูกติดตามเป็น งานเบื้องหลัง

เป้าหมายหลัก:

  • ทำงาน "วิจัย / งานยาว / เครื่องมือช้า" แบบขนานโดยไม่บล็อกการรันหลัก
  • แยกเอเจนต์ย่อยออกจากกันโดยค่าเริ่มต้น (การแยกเซสชัน + การ sandbox แบบเลือกใช้ได้)
  • ทำให้พื้นผิวเครื่องมือใช้งานผิดได้ยาก: เอเจนต์ย่อยจะไม่ได้รับเครื่องมือเซสชันโดยค่าเริ่มต้น
  • รองรับความลึกของการซ้อนที่กำหนดค่าได้สำหรับรูปแบบตัวประสานงาน

คำสั่งสแลช

ใช้ /subagents เพื่อตรวจสอบหรือควบคุมการรันเอเจนต์ย่อยสำหรับเซสชันปัจจุบัน:

text
/subagents list/subagents kill <id|#|all>/subagents log <id|#> [limit] [tools]/subagents info <id|#>/subagents send <id|#> <message>/subagents steer <id|#> <message>/subagents spawn <agentId> <task> [--model <model>] [--thinking <level>]

ใช้ /steer <message> ระดับบนสุดเพื่อบังคับทิศทางการรันที่ใช้งานอยู่ของเซสชันผู้ร้องขอปัจจุบัน ใช้ /subagents steer <id|#> <message> เมื่อเป้าหมายเป็นการรันลูก

/subagents info แสดงเมตาดาต้าการรัน (สถานะ, ประทับเวลา, id เซสชัน, เส้นทางทรานสคริปต์, การล้างข้อมูล) ใช้ sessions_history สำหรับมุมมองการเรียกคืนแบบมีขอบเขต และกรองความปลอดภัยแล้ว; ตรวจสอบเส้นทางทรานสคริปต์บนดิสก์เมื่อคุณ ต้องการทรานสคริปต์เต็มดิบ

การควบคุมการผูกเธรด

คำสั่งเหล่านี้ทำงานบนช่องทางที่รองรับการผูกเธรดแบบคงอยู่ ดู ช่องทางที่รองรับเธรด ด้านล่าง

text
/focus <subagent-label|session-key|session-id|session-label>/unfocus/agents/session idle <duration|off>/session max-age <duration|off>

พฤติกรรมการสร้าง

/subagents spawn เริ่มเอเจนต์ย่อยเบื้องหลังในฐานะคำสั่งผู้ใช้ (ไม่ใช่ รีเลย์ภายใน) และส่งการอัปเดตการเสร็จสิ้นสุดท้ายหนึ่งครั้งกลับไปยัง แชตของผู้ร้องขอเมื่อการรันเสร็จสิ้น

Non-blocking, push-based completion
  • คำสั่งสร้างเป็นแบบไม่บล็อก; คำสั่งจะคืน id การรันทันที
  • เมื่อเสร็จสิ้น เอเจนต์ย่อยจะประกาศข้อความสรุป/ผลลัพธ์กลับไปยังช่องแชตของผู้ร้องขอ
  • เทิร์นของเอเจนต์ที่ต้องใช้ผลลัพธ์จากลูกควรเรียก sessions_yield หลังจากสร้างงานที่จำเป็นแล้ว การทำเช่นนั้นจะจบเทิร์นปัจจุบันและให้เหตุการณ์การเสร็จสิ้นมาถึงเป็นข้อความถัดไปที่โมเดลมองเห็นได้
  • การเสร็จสิ้นเป็นแบบพุช เมื่อสร้างแล้ว อย่าโพล /subagents list, sessions_list หรือ sessions_history ในลูปเพียงเพื่อรอให้เสร็จ; ตรวจสอบสถานะเฉพาะเมื่อจำเป็นสำหรับการดีบักหรือการแทรกแซงเท่านั้น
  • เอาต์พุตของลูกคือรายงาน/หลักฐานให้เอเจนต์ผู้ร้องขอสังเคราะห์ ไม่ใช่ข้อความคำสั่งที่ผู้ใช้เขียน และไม่สามารถแทนที่นโยบายระบบ ผู้พัฒนา หรือผู้ใช้ได้
  • เมื่อเสร็จสิ้น OpenClaw จะพยายามอย่างดีที่สุดเพื่อปิดแท็บ/กระบวนการเบราว์เซอร์ที่ติดตามไว้ซึ่งเปิดโดยเซสชันเอเจนต์ย่อยนั้น ก่อนที่โฟลว์ล้างข้อมูลการประกาศจะดำเนินต่อ
Manual-spawn delivery resilience
  • OpenClaw ส่งการเสร็จสิ้นกลับไปยังเซสชันผู้ร้องขอผ่านเทิร์น agent พร้อมคีย์ idempotency ที่เสถียร
  • หากการรันของผู้ร้องขอยังทำงานอยู่ OpenClaw จะพยายามปลุก/บังคับทิศทางการรันนั้นก่อน แทนที่จะเริ่มเส้นทางตอบกลับที่มองเห็นได้เส้นที่สอง
  • หากการส่งมอบการเสร็จสิ้นให้เอเจนต์ผู้ร้องขอล้มเหลวหรือไม่มีเอาต์พุตที่มองเห็นได้ OpenClaw จะถือว่าการส่งมอบล้มเหลวและถอยกลับไปใช้การกำหนดเส้นทาง/ลองใหม่ผ่านคิว โดยจะไม่ส่งผลลัพธ์ดิบของลูกโดยตรงไปยังแชตภายนอก
  • หากไม่สามารถใช้การส่งมอบโดยตรงได้ จะถอยกลับไปใช้การกำหนดเส้นทางผ่านคิว
  • หากการกำหนดเส้นทางผ่านคิวยังไม่พร้อมใช้งาน การประกาศจะถูกลองใหม่ด้วย exponential backoff สั้นๆ ก่อนยอมแพ้ในที่สุด
  • การส่งมอบการเสร็จสิ้นจะคงเส้นทางผู้ร้องขอที่แก้ไขแล้วไว้: เส้นทางการเสร็จสิ้นที่ผูกกับเธรดหรือผูกกับการสนทนาจะชนะเมื่อพร้อมใช้งาน; หากต้นทางการเสร็จสิ้นให้มาเพียงช่องทาง OpenClaw จะเติมเป้าหมาย/บัญชีที่ขาดหายจากเส้นทางที่แก้ไขแล้วของเซสชันผู้ร้องขอ (lastChannel / lastTo / lastAccountId) เพื่อให้การส่งมอบโดยตรงยังทำงานได้
Completion handoff metadata

การส่งต่อการเสร็จสิ้นไปยังเซสชันผู้ร้องขอเป็นบริบทภายในที่สร้างโดยรันไทม์ (ไม่ใช่ข้อความที่ผู้ใช้เขียน) และประกอบด้วย:

  • Result — ข้อความตอบกลับ assistant ที่มองเห็นได้ล่าสุด หรือมิฉะนั้นเป็นข้อความเครื่องมือ/toolResult ล่าสุดที่ทำให้ปลอดภัยแล้ว การรันที่ล้มเหลวแบบสิ้นสุดจะไม่นำข้อความตอบกลับที่จับไว้กลับมาใช้
  • Statuscompleted successfully / failed / timed out / unknown
  • สถิติรันไทม์/โทเค็นแบบย่อ
  • คำสั่งการส่งมอบที่บอกเอเจนต์ผู้ร้องขอให้เขียนใหม่ด้วยเสียงผู้ช่วยปกติ (ไม่ส่งต่อเมตาดาต้าภายในดิบ)
Modes and ACP runtime
  • --model และ --thinking แทนที่ค่าเริ่มต้นสำหรับการรันนั้นโดยเฉพาะ
  • ใช้ info/log เพื่อตรวจสอบรายละเอียดและเอาต์พุตหลังเสร็จสิ้น
  • /subagents spawn เป็นโหมดครั้งเดียว (mode: "run") สำหรับเซสชันแบบคงอยู่ที่ผูกกับเธรด ให้ใช้ sessions_spawn พร้อม thread: true และ mode: "session"
  • สำหรับเซสชันชุดทดสอบ ACP (Claude Code, Gemini CLI, OpenCode หรือ Codex ACP/acpx แบบชัดเจน) ให้ใช้ sessions_spawn พร้อม runtime: "acp" เมื่อเครื่องมือประกาศรันไทม์นั้น ดู โมเดลการส่งมอบ ACP เมื่อดีบักการเสร็จสิ้นหรือลูปเอเจนต์ต่อเอเจนต์ เมื่อเปิดใช้งาน Plugin codex การควบคุมแชต/เธรดของ Codex ควรเลือกใช้ /codex ... แทน ACP เว้นแต่ผู้ใช้จะขอ ACP/acpx อย่างชัดเจน
  • OpenClaw ซ่อน runtime: "acp" จนกว่าจะเปิดใช้งาน ACP, ผู้ร้องขอไม่ได้อยู่ใน sandbox และมีการโหลด Plugin แบ็กเอนด์ เช่น acpx แล้ว runtime: "acp" คาดหวัง id ชุดทดสอบ ACP ภายนอก หรือรายการ agents.list[] ที่มี runtime.type="acp"; ใช้รันไทม์เอเจนต์ย่อยเริ่มต้นสำหรับเอเจนต์การกำหนดค่า OpenClaw ปกติจาก agents_list

โหมดบริบท

เอเจนต์ย่อยแบบเนทีฟจะเริ่มแบบแยกส่วน เว้นแต่ผู้เรียกจะขอ fork ทรานสคริปต์ปัจจุบันอย่างชัดเจน

โหมด เมื่อใดควรใช้ พฤติกรรม
isolated การวิจัยใหม่, การใช้งานอิสระ, งานเครื่องมือช้า หรือสิ่งใดก็ตามที่สามารถบรีฟในข้อความงานได้ สร้างทรานสคริปต์ลูกที่สะอาด นี่เป็นค่าเริ่มต้นและช่วยลดการใช้โทเค็น
fork งานที่ขึ้นอยู่กับการสนทนาปัจจุบัน, ผลลัพธ์เครื่องมือก่อนหน้า หรือคำสั่งที่มีความละเอียดอ่อนซึ่งมีอยู่แล้วในทรานสคริปต์ของผู้ร้องขอ แตกสาขาทรานสคริปต์ของผู้ร้องขอเข้าไปยังเซสชันลูกก่อนที่ลูกจะเริ่ม

ใช้ fork เท่าที่จำเป็น ใช้สำหรับการมอบหมายงานที่ไวต่อบริบท ไม่ใช่ สิ่งทดแทนการเขียนพรอมต์งานให้ชัดเจน

เครื่องมือ: sessions_spawn

เริ่มการรันเอเจนต์ย่อยด้วย deliver: false บนเลน subagent ส่วนกลาง จากนั้นรันขั้นตอนประกาศและโพสต์คำตอบประกาศไปยังช่องแชตของผู้ร้องขอ

ความพร้อมใช้งานขึ้นอยู่กับนโยบายเครื่องมือที่มีผลจริงของผู้เรียก โปรไฟล์ coding และ full เปิดเผย sessions_spawn โดยค่าเริ่มต้น โปรไฟล์ messaging ไม่เปิดเผย; เพิ่ม tools.alsoAllow: ["sessions_spawn", "sessions_yield", "subagents"] หรือใช้ tools.profile: "coding" สำหรับเอเจนต์ที่ควรมอบหมาย งาน นโยบายอนุญาต/ปฏิเสธของช่องทาง/กลุ่ม, provider, sandbox และรายเอเจนต์ ยังสามารถลบเครื่องมือหลังขั้นตอนโปรไฟล์ได้ ใช้ /tools จาก เซสชันเดียวกันเพื่อยืนยันรายการเครื่องมือที่มีผลจริง

ค่าเริ่มต้น:

  • โมเดล: สืบทอดจากผู้เรียก เว้นแต่คุณตั้งค่า agents.defaults.subagents.model (หรือ agents.list[].subagents.model รายเอเจนต์); sessions_spawn.model ที่ระบุอย่างชัดเจนยังคงมีผลเหนือกว่า
  • Thinking: สืบทอดจากผู้เรียก เว้นแต่คุณตั้งค่า agents.defaults.subagents.thinking (หรือ agents.list[].subagents.thinking รายเอเจนต์); sessions_spawn.thinking ที่ระบุอย่างชัดเจนยังคงมีผลเหนือกว่า
  • หมดเวลาการรัน: หากละ sessions_spawn.runTimeoutSeconds ไว้ OpenClaw จะใช้ agents.defaults.subagents.runTimeoutSeconds เมื่อมีการตั้งค่า; มิฉะนั้นจะถอยกลับเป็น 0 (ไม่หมดเวลา)

โหมดพรอมต์การมอบหมายงาน

agents.defaults.subagents.delegationMode ควบคุมเฉพาะแนวทางพรอมต์เท่านั้น; ไม่เปลี่ยนนโยบายเครื่องมือหรือบังคับใช้การมอบหมายงาน

  • suggest (ค่าเริ่มต้น): คงการกระตุ้นในพรอมต์มาตรฐานให้ใช้เอเจนต์ย่อยสำหรับงานที่ใหญ่กว่าหรือช้ากว่า
  • prefer: บอกเอเจนต์หลักให้ตอบสนองต่อเนื่องและมอบหมายสิ่งใดก็ตามที่ซับซ้อนกว่าการตอบกลับโดยตรงผ่าน sessions_spawn

การแทนที่รายเอเจนต์ใช้ agents.list[].subagents.delegationMode

json5
{  agents: {    defaults: {      subagents: {        delegationMode: "prefer",        maxConcurrent: 4,      },    },    list: [      {        id: "coordinator",        subagents: { delegationMode: "prefer" },      },    ],  },}

พารามิเตอร์เครื่องมือ

taskstringrequired

คำอธิบายงานสำหรับเอเจนต์ย่อย

taskNamestring

ตัวระบุเสถียรแบบเลือกได้สำหรับการกำหนดเป้าหมาย subagents ในภายหลัง ต้องตรงกับ [a-z][a-z0-9_]{0,63} และต้องไม่เป็นเป้าหมายที่สงวนไว้ เช่น last หรือ all ควรใช้เมื่อผู้ประสานงานอาจต้องควบคุม หยุด หรือระบุ child เฉพาะหลังจากสร้าง children หลายตัว

labelstring

ป้ายกำกับแบบมนุษย์อ่านได้ที่ระบุได้ตามต้องการ

agentIdstring

สร้างภายใต้ id ของเอเจนต์อื่นเมื่อ subagents.allowAgents อนุญาต

runtime"subagent" | "acp"default: subagent

acp ใช้เฉพาะสำหรับ ACP harness ภายนอก (claude, droid, gemini, opencode หรือ Codex ACP/acpx ที่ร้องขออย่างชัดเจน) และสำหรับรายการ agents.list[] ที่ runtime.type เป็น acp

resumeSessionIdstring

เฉพาะ ACP ดำเนินการต่อจากเซสชัน ACP harness ที่มีอยู่เมื่อ runtime: "acp"; จะถูกละเว้นสำหรับการสร้างเอเจนต์ย่อยแบบเนทีฟ

streamTo"parent"

เฉพาะ ACP สตรีมเอาต์พุตการรัน ACP ไปยังเซสชัน parent เมื่อ runtime: "acp"; ละไว้สำหรับการสร้างเอเจนต์ย่อยแบบเนทีฟ

modelstring

แทนที่โมเดลของเอเจนต์ย่อย ค่าที่ไม่ถูกต้องจะถูกข้าม และเอเจนต์ย่อยจะรันบนโมเดลเริ่มต้นพร้อมคำเตือนในผลลัพธ์ของเครื่องมือ

thinkingstring

แทนที่ระดับ thinking สำหรับการรันเอเจนต์ย่อย

runTimeoutSecondsnumber

ค่าเริ่มต้นเป็น agents.defaults.subagents.runTimeoutSeconds เมื่อมีการตั้งค่า มิฉะนั้นเป็น 0 เมื่อมีการตั้งค่า การรันเอเจนต์ย่อยจะถูกยกเลิกหลังจาก N วินาที

threadbooleandefault: false

เมื่อเป็น true จะร้องขอการผูก thread ของช่องทางสำหรับเซสชันเอเจนต์ย่อยนี้

mode"run" | "session"default: run

หากละ mode และ thread: true ค่าเริ่มต้นจะกลายเป็น session mode: "session" ต้องใช้ thread: true

cleanup"delete" | "keep"default: keep

"delete" จะเก็บถาวรทันทีหลังจากประกาศ (ยังคงเก็บทรานสคริปต์ไว้ผ่านการเปลี่ยนชื่อ)

sandbox"inherit" | "require"default: inherit

require จะปฏิเสธการสร้าง เว้นแต่รันไทม์ child เป้าหมายจะอยู่ใน sandbox

context"isolated" | "fork"default: isolated

fork จะแยกทรานสคริปต์ปัจจุบันของผู้ร้องขอไปยังเซสชัน child เฉพาะเอเจนต์ย่อยแบบเนทีฟ การสร้างที่ผูกกับ thread มีค่าเริ่มต้นเป็น fork; การสร้างที่ไม่ใช่ thread มีค่าเริ่มต้นเป็น isolated

ชื่องานและการกำหนดเป้าหมาย

taskName เป็นตัวระบุที่โมเดลเห็นสำหรับการจัดการ orchestration ไม่ใช่คีย์เซสชัน ใช้สำหรับชื่อ child ที่เสถียร เช่น review_subagents, linux_validation หรือ docs_update เมื่อผู้ประสานงานอาจต้องควบคุม หรือหยุด child นั้นในภายหลัง

การแก้เป้าหมายยอมรับการตรงกันแบบชัดเจนกับ taskName และ prefix ที่ไม่กำกวม การจับคู่ถูกจำกัดอยู่ในหน้าต่างเป้าหมาย active/recent เดียวกับที่ใช้ โดยเป้าหมาย /subagents แบบหมายเลข ดังนั้น child ที่เสร็จสิ้นไปนานแล้วจะไม่ทำให้ ตัวระบุที่นำกลับมาใช้ใหม่กำกวม หาก children ที่ active หรือ recent สองตัวใช้ taskName เดียวกัน เป้าหมายจะกำกวม ให้ใช้ดัชนีรายการ คีย์เซสชัน หรือ run id แทน

เป้าหมายที่สงวนไว้ last และ all ไม่ใช่ค่า taskName ที่ถูกต้อง เพราะมีความหมายด้านการควบคุมอยู่แล้ว

เครื่องมือ: sessions_yield

สิ้นสุดเทิร์นโมเดลปัจจุบันและรออีเวนต์รันไทม์ โดยหลักคืออีเวนต์ การเสร็จสิ้นของเอเจนต์ย่อย ให้มาถึงเป็นข้อความถัดไป ใช้หลังจาก สร้างงาน child ที่จำเป็นเมื่อผู้ร้องขอไม่สามารถให้คำตอบสุดท้าย ได้จนกว่า completion เหล่านั้นจะมาถึง

sessions_yield เป็น primitive สำหรับการรอ อย่าแทนที่ด้วยลูป polling ผ่าน subagents, sessions_list, sessions_history, shell sleep หรือการ polling process เพียงเพื่อตรวจจับการเสร็จสิ้นของ child

ใช้ sessions_yield เฉพาะเมื่อรายการเครื่องมือที่มีผลของเซสชันมีเครื่องมือนี้ โปรไฟล์เครื่องมือแบบ minimal หรือ custom บางรายการอาจเปิดเผย sessions_spawn และ subagents โดยไม่เปิดเผย sessions_yield; ในกรณีนั้น อย่าประดิษฐ์ ลูป polling เพียงเพื่อรอการเสร็จสิ้น

เมื่อมี children ที่ active อยู่ OpenClaw จะใส่บล็อกพรอมป์ Active Subagents ขนาดกะทัดรัดที่รันไทม์สร้างขึ้นลงในเทิร์นปกติ เพื่อให้ผู้ร้องขอเห็น เซสชัน child ปัจจุบัน, run ids, สถานะ, ป้ายกำกับ, งาน และ นามแฝง taskName โดยไม่ต้อง polling ฟิลด์งานและป้ายกำกับใน บล็อกนั้นถูก quote เป็นข้อมูล ไม่ใช่คำสั่ง เพราะอาจมีต้นทาง จากอาร์กิวเมนต์การสร้างที่ผู้ใช้/โมเดลให้มา

เครื่องมือ: subagents

แสดงรายการ ควบคุม หรือหยุดการรันเอเจนต์ย่อยที่ถูกสร้างและเป็นของเซสชัน ผู้ร้องขอ ขอบเขตจำกัดอยู่ที่ผู้ร้องขอปัจจุบัน; child จะเห็น/ควบคุมได้เฉพาะ children ที่ตัวเองควบคุมอยู่เท่านั้น

ใช้ subagents สำหรับสถานะตามคำขอ การดีบัก การควบคุม หรือการหยุด ใช้ sessions_yield เพื่อรออีเวนต์การเสร็จสิ้น

เซสชันที่ผูกกับ thread

เมื่อเปิดใช้การผูก thread สำหรับช่องทาง เอเจนต์ย่อยสามารถคงการผูก กับ thread เพื่อให้ข้อความติดตามผลของผู้ใช้ใน thread นั้นยังคง route ไปยัง เซสชันเอเจนต์ย่อยเดียวกัน

ช่องทางที่รองรับ thread

Discord เป็นช่องทางเดียวที่รองรับอยู่ในขณะนี้ รองรับ เซสชันเอเจนต์ย่อยที่ผูกกับ thread แบบถาวร (sessions_spawn พร้อม thread: true), การควบคุม thread แบบ manual (/focus, /unfocus, /agents, /session idle, /session max-age) และคีย์ adapter channels.discord.threadBindings.enabled, channels.discord.threadBindings.idleHours, channels.discord.threadBindings.maxAgeHours และ channels.discord.threadBindings.spawnSessions

ลำดับอย่างย่อ

  • สร้าง

    sessions_spawn พร้อม thread: true (และเลือกใส่ mode: "session" ได้)

  • ผูก

    OpenClaw สร้างหรือผูก thread กับเป้าหมายเซสชันนั้นในช่องทางที่ active

  • Route ข้อความติดตามผล

    การตอบกลับและข้อความติดตามผลใน thread นั้นจะ route ไปยังเซสชันที่ผูกไว้

  • ตรวจสอบ timeout

    ใช้ /session idle เพื่อตรวจสอบ/อัปเดต auto-unfocus เมื่อไม่มีการใช้งาน และ /session max-age เพื่อควบคุมเพดานแบบ hard cap

  • แยกออก

    ใช้ /unfocus เพื่อแยกออกด้วยตนเอง

  • การควบคุมแบบ manual

    คำสั่ง ผลลัพธ์
    /focus <target> ผูก thread ปัจจุบัน (หรือสร้างใหม่) กับเป้าหมายเอเจนต์ย่อย/เซสชัน
    /unfocus ลบการผูกสำหรับ thread ปัจจุบันที่ถูกผูกไว้
    /agents แสดงรายการการรันที่ active และสถานะการผูก (thread:<id> หรือ unbound)
    /session idle ตรวจสอบ/อัปเดต auto-unfocus เมื่อ idle (เฉพาะ thread ที่ผูกและโฟกัสอยู่)
    /session max-age ตรวจสอบ/อัปเดต hard cap (เฉพาะ thread ที่ผูกและโฟกัสอยู่)

    สวิตช์การกำหนดค่า

    • ค่าเริ่มต้นแบบ global: session.threadBindings.enabled, session.threadBindings.idleHours, session.threadBindings.maxAgeHours
    • คีย์ override ของช่องทางและ auto-bind เมื่อสร้าง เป็นแบบเฉพาะ adapter ดู ช่องทางที่รองรับ thread ด้านบน

    ดู เอกสารอ้างอิงการกำหนดค่า และ คำสั่ง slash สำหรับรายละเอียด adapter ปัจจุบัน

    Allowlist

    agents.list[].subagents.allowAgentsstring[]

    รายการ id ของเอเจนต์ที่สามารถกำหนดเป้าหมายผ่าน agentId แบบชัดเจน (["*"] อนุญาตทุกตัว) ค่าเริ่มต้น: เฉพาะเอเจนต์ผู้ร้องขอ หากคุณตั้งค่ารายการและยังต้องการให้ผู้ร้องขอสร้างตัวเองด้วย agentId ให้ใส่ id ของผู้ร้องขอไว้ในรายการ

    agents.defaults.subagents.allowAgentsstring[]

    allowlist ของเอเจนต์เป้าหมายเริ่มต้นที่ใช้เมื่อเอเจนต์ผู้ร้องขอไม่ได้ตั้งค่า subagents.allowAgents ของตัวเอง

    agents.defaults.subagents.requireAgentIdbooleandefault: false

    บล็อกการเรียก sessions_spawn ที่ละ agentId (บังคับให้เลือกโปรไฟล์อย่างชัดเจน) การ override รายเอเจนต์: agents.list[].subagents.requireAgentId

    agents.defaults.subagents.announceTimeoutMsnumberdefault: 120000

    timeout ต่อการเรียกสำหรับความพยายามส่งประกาศ agent ของ Gateway ค่าเป็นจำนวนเต็มบวกในหน่วยมิลลิวินาที และถูก clamp ให้อยู่ในค่าสูงสุดของ timer ที่ปลอดภัยต่อแพลตฟอร์ม การลองใหม่แบบ transient อาจทำให้เวลารอประกาศทั้งหมดนานกว่า timeout ที่กำหนดไว้หนึ่งครั้ง

    หากเซสชันผู้ร้องขออยู่ใน sandbox, sessions_spawn จะปฏิเสธเป้าหมาย ที่จะรันโดยไม่อยู่ใน sandbox

    การค้นพบ

    ใช้ agents_list เพื่อดูว่า id ของเอเจนต์ใดได้รับอนุญาตสำหรับ sessions_spawn อยู่ในขณะนี้ การตอบกลับรวมโมเดลที่มีผลของเอเจนต์แต่ละตัวที่แสดง และ metadata รันไทม์ที่ฝังไว้ เพื่อให้ผู้เรียกแยกความแตกต่างระหว่าง PI, Codex app-server และรันไทม์เนทีฟอื่น ๆ ที่กำหนดค่าไว้ได้

    การเก็บถาวรอัตโนมัติ

    • เซสชันเอเจนต์ย่อยจะถูกเก็บถาวรโดยอัตโนมัติหลังจาก agents.defaults.subagents.archiveAfterMinutes (ค่าเริ่มต้น 60)
    • การเก็บถาวรใช้ sessions.delete และเปลี่ยนชื่อทรานสคริปต์เป็น *.deleted.<timestamp> (โฟลเดอร์เดียวกัน)
    • cleanup: "delete" จะเก็บถาวรทันทีหลังจากประกาศ (ยังคงเก็บทรานสคริปต์ไว้ผ่านการเปลี่ยนชื่อ)
    • การเก็บถาวรอัตโนมัติเป็นแบบ best-effort; timer ที่ค้างอยู่จะหายไปหาก Gateway รีสตาร์ท
    • runTimeoutSeconds ไม่ เก็บถาวรอัตโนมัติ; มันเพียงหยุดการรัน เซสชันยังคงอยู่จนกว่าจะถูกเก็บถาวรอัตโนมัติ
    • การเก็บถาวรอัตโนมัติใช้กับเซสชัน depth-1 และ depth-2 เท่า ๆ กัน
    • การล้างข้อมูลเบราว์เซอร์แยกจากการล้างข้อมูลเก็บถาวร: แท็บ/กระบวนการเบราว์เซอร์ที่ติดตามจะถูกปิดแบบ best-effort เมื่อการรันเสร็จสิ้น แม้ว่าจะเก็บระเบียนทรานสคริปต์/เซสชันไว้ก็ตาม

    เอเจนต์ย่อยแบบซ้อน

    โดยค่าเริ่มต้น เอเจนต์ย่อยไม่สามารถสร้างเอเจนต์ย่อยของตัวเองได้ (maxSpawnDepth: 1) ตั้งค่า maxSpawnDepth: 2 เพื่อเปิดใช้การซ้อนหนึ่งระดับ ซึ่งคือ รูปแบบ orchestrator: main → orchestrator sub-agent → worker sub-sub-agents

    json5
    {  agents: {    defaults: {      subagents: {        maxSpawnDepth: 2, // allow sub-agents to spawn children (default: 1)        maxChildrenPerAgent: 5, // max active children per agent session (default: 5)        maxConcurrent: 8, // global concurrency lane cap (default: 8)        runTimeoutSeconds: 900, // default timeout for sessions_spawn when omitted (0 = no timeout)        announceTimeoutMs: 120000, // per-call gateway announce timeout      },    },  },}

    ระดับความลึก

    ความลึก รูปแบบคีย์เซสชัน บทบาท สร้างได้หรือไม่
    0 agent:<id>:main เอเจนต์หลัก เสมอ
    1 agent:<id>:subagent:<uuid> เอเจนต์ย่อย (orchestrator เมื่ออนุญาต depth 2) เฉพาะเมื่อ maxSpawnDepth >= 2
    2 agent:<id>:subagent:<uuid>:subagent:<uuid> เอเจนต์ย่อยของเอเจนต์ย่อย (leaf worker) ไม่เคย

    สายประกาศ

    ผลลัพธ์ไหลย้อนกลับขึ้นไปตามสาย:

    1. worker depth-2 เสร็จสิ้น → ประกาศไปยัง parent ของมัน (orchestrator depth-1)
    2. orchestrator depth-1 ได้รับประกาศ สังเคราะห์ผลลัพธ์ เสร็จสิ้น → ประกาศไปยัง main
    3. เอเจนต์ main ได้รับประกาศและส่งต่อให้ผู้ใช้

    แต่ละระดับจะเห็นเฉพาะประกาศจาก children โดยตรงของตัวเอง

    นโยบายเครื่องมือตามความลึก

    • บทบาทและขอบเขตการควบคุมจะถูกเขียนลงในเมตาดาต้าเซสชันตอน spawn ซึ่งช่วยป้องกันไม่ให้คีย์เซสชันแบบแบนหรือที่กู้คืนมาได้รับสิทธิ์ orchestrator กลับมาโดยไม่ตั้งใจ
    • ความลึก 1 (orchestrator, เมื่อ maxSpawnDepth >= 2): ได้รับ sessions_spawn, subagents, sessions_list, sessions_history เพื่อให้จัดการลูกของตนได้ เครื่องมือเซสชัน/ระบบอื่น ๆ ยังคงถูกปฏิเสธ
    • ความลึก 1 (leaf, เมื่อ maxSpawnDepth == 1): ไม่มีเครื่องมือเซสชัน (พฤติกรรมเริ่มต้นปัจจุบัน)
    • ความลึก 2 (leaf worker): ไม่มีเครื่องมือเซสชัน — sessions_spawn จะถูกปฏิเสธเสมอที่ความลึก 2 ไม่สามารถ spawn ลูกเพิ่มเติมได้

    ขีดจำกัดการ spawn ต่อเอเจนต์

    แต่ละเซสชันเอเจนต์ (ที่ความลึกใดก็ได้) สามารถมีลูกที่ทำงานอยู่ได้สูงสุด maxChildrenPerAgent (ค่าเริ่มต้น 5) ต่อครั้ง วิธีนี้ป้องกันการกระจายงานแบบ runaway จาก orchestrator ตัวเดียว

    การหยุดแบบ cascade

    การหยุด orchestrator ความลึก 1 จะหยุดลูกความลึก 2 ทั้งหมดของมันโดยอัตโนมัติ:

    • /stop ในแชตหลักจะหยุดเอเจนต์ความลึก 1 ทั้งหมดและ cascade ไปยังลูกความลึก 2 ของพวกมัน
    • /subagents kill <id> หยุดซับเอเจนต์ที่ระบุและ cascade ไปยังลูกของมัน
    • /subagents kill all หยุดซับเอเจนต์ทั้งหมดของผู้ร้องขอและ cascade

    การยืนยันตัวตน

    การยืนยันตัวตนของซับเอเจนต์ถูก resolve ด้วย รหัสเอเจนต์ ไม่ใช่ด้วยประเภทเซสชัน:

    • คีย์เซสชันซับเอเจนต์คือ agent:<agentId>:subagent:<uuid>
    • auth store ถูกโหลดจาก agentDir ของเอเจนต์นั้น
    • โปรไฟล์ auth ของเอเจนต์หลักจะถูกผสานเข้าเป็น fallback; โปรไฟล์เอเจนต์จะ override โปรไฟล์หลักเมื่อมีความขัดแย้ง

    การผสานเป็นแบบเพิ่มเข้าไป ดังนั้นโปรไฟล์หลักจึงพร้อมใช้งานเป็น fallback เสมอ การยืนยันตัวตนที่แยกขาดอย่างสมบูรณ์ต่อเอเจนต์ยังไม่รองรับ

    ประกาศ

    ซับเอเจนต์รายงานกลับผ่านขั้นตอนประกาศ:

    • ขั้นตอนประกาศทำงานภายในเซสชันซับเอเจนต์ (ไม่ใช่เซสชันผู้ร้องขอ)
    • หากซับเอเจนต์ตอบกลับว่า ANNOUNCE_SKIP แบบตรงตัว จะไม่มีการโพสต์สิ่งใด
    • หากข้อความ assistant ล่าสุดเป็นโทเค็นเงียบแบบตรงตัว NO_REPLY / no_reply เอาต์พุตประกาศจะถูกระงับ แม้เคยมีความคืบหน้าที่มองเห็นได้ก่อนหน้า

    การส่งมอบขึ้นอยู่กับความลึกของผู้ร้องขอ:

    • เซสชันผู้ร้องขอระดับบนใช้การเรียก agent แบบ follow-up พร้อมการส่งมอบภายนอก (deliver=true)
    • เซสชันซับเอเจนต์ผู้ร้องขอที่ซ้อนกันจะได้รับการฉีด follow-up ภายใน (deliver=false) เพื่อให้ orchestrator สามารถสังเคราะห์ผลลัพธ์ลูกภายในเซสชันได้
    • หากเซสชันซับเอเจนต์ผู้ร้องขอที่ซ้อนกันหายไป OpenClaw จะ fallback ไปยังผู้ร้องขอของเซสชันนั้นเมื่อพร้อมใช้งาน

    สำหรับเซสชันผู้ร้องขอระดับบน การส่งมอบโดยตรงในโหมดเสร็จสิ้นจะ resolve เส้นทาง conversation/thread ที่ผูกไว้และ hook override ก่อน จากนั้นเติม ฟิลด์ channel-target ที่ขาดจากเส้นทางที่เก็บไว้ของเซสชันผู้ร้องขอ วิธีนี้ทำให้การเสร็จสิ้นไปถึงแชต/หัวข้อที่ถูกต้อง แม้ต้นทางการเสร็จสิ้น จะระบุเพียงช่องทางเท่านั้น

    การรวมผลการเสร็จสิ้นของลูกถูกจำกัดขอบเขตไว้ที่รันของผู้ร้องขอปัจจุบันเมื่อ สร้าง findings การเสร็จสิ้นแบบซ้อน ป้องกันไม่ให้เอาต์พุตลูกจากรันก่อนหน้า ที่ค้างรั่วเข้าสู่ประกาศปัจจุบัน การตอบกลับประกาศจะรักษา routing ของ thread/topic เมื่อมีอยู่บน channel adapters

    บริบทประกาศ

    บริบทประกาศถูกทำให้เป็นมาตรฐานเป็นบล็อกเหตุการณ์ภายในที่เสถียร:

    ฟิลด์ แหล่งที่มา
    แหล่งที่มา subagent หรือ cron
    รหัสเซสชัน คีย์/รหัสเซสชันลูก
    ประเภท ประเภทประกาศ + ป้ายกำกับงาน
    สถานะ ได้มาจากผลลัพธ์รันไทม์ (success, error, timeout หรือ unknown) — ไม่ได้ อนุมานจากข้อความโมเดล
    เนื้อหาผลลัพธ์ ข้อความ assistant ที่มองเห็นได้ล่าสุด มิฉะนั้นเป็นข้อความ tool/toolResult ล่าสุดที่ผ่านการ sanitize
    การติดตามผล คำแนะนำที่อธิบายว่าเมื่อใดควรตอบกลับและเมื่อใดควรเงียบ

    รันที่ล้มเหลวแบบ terminal จะรายงานสถานะล้มเหลวโดยไม่เล่นซ้ำข้อความตอบกลับ ที่จับไว้ เมื่อ timeout หากลูกผ่านได้เพียงการเรียกเครื่องมือ ประกาศสามารถ ยุบประวัตินั้นให้เป็นสรุปความคืบหน้าบางส่วนแบบสั้น แทนที่จะเล่นซ้ำเอาต์พุต เครื่องมือดิบ

    บรรทัดสถิติ

    payload ประกาศมีบรรทัดสถิติที่ท้ายสุด (แม้เมื่อถูก wrap):

    • รันไทม์ (เช่น runtime 5m12s)
    • การใช้โทเค็น (input/output/total)
    • ค่าใช้จ่ายโดยประมาณเมื่อมีการตั้งค่าราคาโมเดล (models.providers.*.models[].cost)
    • sessionKey, sessionId และเส้นทาง transcript เพื่อให้เอเจนต์หลักดึงประวัติผ่าน sessions_history หรือตรวจไฟล์บนดิสก์ได้

    เมตาดาต้าภายในมีไว้สำหรับ orchestration เท่านั้น; การตอบกลับที่ผู้ใช้เห็น ควรถูกเขียนใหม่ด้วยน้ำเสียง assistant ปกติ

    เหตุผลที่ควรเลือก sessions_history

    sessions_history เป็นเส้นทาง orchestration ที่ปลอดภัยกว่า:

    • การเรียกคืนของ assistant ถูกทำให้เป็นมาตรฐานก่อน: ลบ thinking tags; ลบ scaffolding <relevant-memories> / <relevant_memories>; ลบบล็อก payload XML การเรียกเครื่องมือแบบข้อความล้วน (<tool_call>, <function_call>, <tool_calls>, <function_calls>) รวมถึง payload ที่ถูกตัดและปิดไม่สมบูรณ์; ลบ scaffolding การเรียก/ผลลัพธ์เครื่องมือที่ถูกลดระดับและ marker บริบทประวัติ; ลบโทเค็นควบคุมโมเดลที่รั่ว (<|assistant|>, ASCII <|...|> อื่น ๆ, แบบ full-width <|...|>); ลบ XML การเรียกเครื่องมือ MiniMax ที่ malformed
    • ข้อความที่คล้าย credential/token จะถูก redact
    • บล็อกยาวสามารถถูกตัดให้สั้นลงได้
    • ประวัติขนาดใหญ่มากสามารถทิ้งแถวเก่ากว่าหรือแทนที่แถวที่ใหญ่เกินด้วย [sessions_history omitted: message too large]
    • การตรวจ transcript ดิบบนดิสก์เป็น fallback เมื่อคุณต้องการ transcript แบบ byte-for-byte เต็มรูปแบบ

    นโยบายเครื่องมือ

    ซับเอเจนต์ใช้โปรไฟล์และ pipeline นโยบายเครื่องมือเดียวกับพาเรนต์หรือ เอเจนต์เป้าหมายก่อน หลังจากนั้น OpenClaw จะใช้ชั้นข้อจำกัดของซับเอเจนต์

    เมื่อไม่มี tools.profile ที่จำกัด ซับเอเจนต์จะได้รับ เครื่องมือทั้งหมด ยกเว้น เครื่องมือเซสชัน และเครื่องมือระบบ:

    • sessions_list
    • sessions_history
    • sessions_send
    • sessions_spawn

    sessions_history ยังคงเป็นมุมมองการเรียกคืนที่มีขอบเขตและผ่านการ sanitize ที่นี่ด้วย — ไม่ใช่การ dump transcript ดิบ

    เมื่อ maxSpawnDepth >= 2 ซับเอเจนต์ orchestrator ความลึก 1 จะได้รับ sessions_spawn, subagents, sessions_list และ sessions_history เพิ่มเติม เพื่อให้จัดการลูกของตนได้

    Override ผ่าน config

    json5
    {  agents: {    defaults: {      subagents: {        maxConcurrent: 1,      },    },  },  tools: {    subagents: {      tools: {        // deny wins        deny: ["gateway", "cron"],        // if allow is set, it becomes allow-only (deny still wins)        // allow: ["read", "exec", "process"]      },    },  },}

    tools.subagents.tools.allow เป็นตัวกรอง allow-only ขั้นสุดท้าย มันสามารถจำกัด ชุดเครื่องมือที่ resolve แล้วให้แคบลง แต่ไม่สามารถ เพิ่มกลับ เครื่องมือที่ถูกลบ โดย tools.profile ได้ ตัวอย่างเช่น tools.profile: "coding" มี web_search/web_fetch แต่ไม่มีเครื่องมือ browser หากต้องการให้ ซับเอเจนต์โปรไฟล์ coding ใช้ browser automation ได้ ให้เพิ่ม browser ที่ ขั้นโปรไฟล์:

    json5
    {  tools: {    profile: "coding",    alsoAllow: ["browser"],  },}

    ใช้ agents.list[].tools.alsoAllow: ["browser"] ต่อเอเจนต์ เมื่อมีเพียงเอเจนต์เดียว ที่ควรได้รับ browser automation

    Concurrency

    ซับเอเจนต์ใช้ queue lane เฉพาะภายใน process:

    • ชื่อ lane: subagent
    • Concurrency: agents.defaults.subagents.maxConcurrent (ค่าเริ่มต้น 8)

    Liveness และการกู้คืน

    OpenClaw ไม่ถือว่าการไม่มี endedAt เป็นหลักฐานถาวรว่าซับเอเจนต์ ยังมีชีวิตอยู่ รันที่ยังไม่จบซึ่งเก่ากว่า stale-run window จะหยุดถูกนับ เป็น active/pending ใน /subagents list, สรุปสถานะ, descendant completion gating และการตรวจ concurrency ต่อเซสชัน

    หลังจาก Gateway รีสตาร์ท รันที่กู้คืนมาแบบค้างและยังไม่จบจะถูกตัดออก เว้นแต่ เซสชันลูกของมันถูกทำเครื่องหมาย abortedLastRun: true เซสชันลูกที่ถูก ยกเลิกจากการรีสตาร์ทเหล่านั้นยังคงกู้คืนได้ผ่าน flow การกู้คืน orphan ของซับเอเจนต์ ซึ่งจะส่งข้อความ resume สังเคราะห์ก่อนล้าง marker ที่ถูกยกเลิก

    การกู้คืนอัตโนมัติหลังรีสตาร์ทมีขอบเขตต่อเซสชันลูก หากลูกซับเอเจนต์เดียวกัน ถูกยอมรับให้กู้คืน orphan ซ้ำ ๆ ภายใน rapid re-wedge window OpenClaw จะคง tombstone การกู้คืนไว้บนเซสชันนั้นและหยุด auto-resume ในการรีสตาร์ทครั้งต่อ ๆ ไป เรียกใช้ openclaw tasks maintenance --apply เพื่อ reconcile task record หรือ openclaw doctor --fix เพื่อล้างแฟล็กการกู้คืนที่ถูกยกเลิกและค้างบน เซสชันที่ถูก tombstone

    การหยุด

    • การส่ง /stop ในแชตผู้ร้องขอจะ abort เซสชันผู้ร้องขอและหยุดรันซับเอเจนต์ที่ยังทำงานอยู่ซึ่ง spawn จากเซสชันนั้น พร้อม cascade ไปยังลูกที่ซ้อนอยู่
    • /subagents kill <id> หยุดซับเอเจนต์ที่ระบุและ cascade ไปยังลูกของมัน

    ข้อจำกัด

    • การประกาศของซับเอเจนต์เป็นแบบ best-effort หาก gateway รีสตาร์ท งาน "announce back" ที่ pending จะหายไป
    • ซับเอเจนต์ยังคงใช้ทรัพยากร process ของ gateway เดียวกัน; ให้ถือว่า maxConcurrent เป็นวาล์วนิรภัย
    • sessions_spawn เป็นแบบ non-blocking เสมอ: ส่งคืน { status: "accepted", runId, childSessionKey } ทันที
    • บริบทซับเอเจนต์ฉีดเฉพาะ AGENTS.md, TOOLS.md, SOUL.md, IDENTITY.md และ USER.md (ไม่มี MEMORY.md, HEARTBEAT.md หรือ BOOTSTRAP.md)
    • ความลึกการซ้อนสูงสุดคือ 5 (maxSpawnDepth range: 1–5) แนะนำให้ใช้ความลึก 2 สำหรับกรณีใช้งานส่วนใหญ่
    • maxChildrenPerAgent จำกัดจำนวนลูกที่ทำงานอยู่ต่อเซสชัน (ค่าเริ่มต้น 5, range 1–20)

    ที่เกี่ยวข้อง

    Was this useful?