การกำหนดเส้นทางแบบหลายเอเจนต์¶
เป้าหมาย: มีเอเจนต์ที่ แยกจากกัน หลายตัว(เวิร์กสเปซ+agentDir+เซสชันแยก)พร้อมบัญชีช่องทางหลายบัญชี(เช่น WhatsApp สองบัญชี)ภายในGatewayที่กำลังรันหนึ่งตัว ขาเข้าจะถูกกำหนดเส้นทางไปยังเอเจนต์ผ่านการผูก(binding) Inbound is routed to an agent via bindings.
“หนึ่งเอเจนต์”คืออะไร?¶
เอเจนต์คือสมองที่มีขอบเขตครบถ้วนพร้อมของตัวเอง ได้แก่:
- เวิร์กสเปซ(ไฟล์, AGENTS.md/SOUL.md/USER.md, โน้ตภายในเครื่อง, กฎบุคลิก)
- ไดเรกทอรีสถานะ(
agentDir)สำหรับโปรไฟล์การยืนยันตัวตน รีจิสทรีโมเดล และคอนฟิกต่อเอเจนต์ - ที่เก็บเซสชัน(ประวัติแชต+สถานะการกำหนดเส้นทาง)ภายใต้
~/.openclaw/agents/<agentId>/sessions
โปรไฟล์การยืนยันตัวตนเป็นแบบต่อเอเจนต์ เอเจนต์แต่ละตัวจะอ่านจากของตัวเอง: Each agent reads from its own:
~/.openclaw/agents/<agentId>/agent/auth-profiles.json
Main agent credentials are not shared automatically. 1. ห้ามใช้ agentDir ซ้ำ
ระหว่างเอเจนต์ (จะทำให้เกิดการชนกันของการยืนยันตัวตน/เซสชัน) ข้อมูลรับรองของเอเจนต์หลักจะไม่ถูกแชร์โดยอัตโนมัติ ห้ามนำagentDirมาใช้ซ้ำ
ข้ามเอเจนต์(จะทำให้การยืนยันตัวตน/เซสชันชนกัน) หากต้องการแชร์ข้อมูลรับรอง
ให้คัดลอกauth-profiles.jsonไปยังagentDirของเอเจนต์อื่น
Skills เป็นแบบต่อเอเจนต์ผ่านโฟลเดอร์skills/ของแต่ละเวิร์กสเปซ โดยมี Skills ที่ใช้ร่วมกันได้จาก~/.openclaw/skills ดูSkills: per-agent vs shared 2. ดู Skills: per-agent vs shared
Gatewayสามารถโฮสต์เอเจนต์เดียว(ค่าเริ่มต้น)หรือหลายเอเจนต์แบบขนานกันได้
หมายเหตุเวิร์กสเปซ: เวิร์กสเปซของแต่ละเอเจนต์เป็นcwd ค่าเริ่มต้นไม่ใช่sandboxแบบเข้มงวด เส้นทางสัมพัทธ์จะอ้างอิงภายในเวิร์กสเปซ แต่เส้นทางสัมบูรณ์สามารถเข้าถึงตำแหน่งอื่นของโฮสต์ได้ เว้นแต่จะเปิดsandboxing ดูSandboxing 3. พาธแบบสัมพัทธ์จะอ้างอิงภายใน workspace แต่พาธแบบสัมบูรณ์สามารถ เข้าถึงตำแหน่งอื่นบนโฮสต์ได้ เว้นแต่จะเปิดใช้งาน sandboxing 4. ดู Sandboxing
เส้นทาง(แผนที่ย่อ)¶
- คอนฟิก:
~/.openclaw/openclaw.json(หรือOPENCLAW_CONFIG_PATH) - ไดเรกทอรีสถานะ:
~/.openclaw(หรือOPENCLAW_STATE_DIR) - เวิร์กสเปซ:
~/.openclaw/workspace(หรือ~/.openclaw/workspace-<agentId>) - ไดเรกทอรีเอเจนต์:
~/.openclaw/agents/<agentId>/agent(หรือagents.list[].agentDir) - เซสชัน:
~/.openclaw/agents/<agentId>/sessions
โหมดเอเจนต์เดียว(ค่าเริ่มต้น)¶
หากไม่ทำอะไร OpenClawจะรันเอเจนต์เดียว:
agentIdค่าเริ่มต้นเป็น**main**- เซสชันถูกคีย์เป็น
agent:main:<mainKey> - เวิร์กสเปซค่าเริ่มต้นเป็น
~/.openclaw/workspace(หรือ~/.openclaw/workspace-<profile>เมื่อมีการตั้งค่าOPENCLAW_PROFILE) - สถานะค่าเริ่มต้นเป็น
~/.openclaw/agents/main/agent
ตัวช่วยเอเจนต์¶
ใช้วิซาร์ดเอเจนต์เพื่อเพิ่มเอเจนต์ที่แยกจากกันใหม่:
openclaw agents add work
จากนั้นเพิ่มbindings(หรือให้วิซาร์ดทำให้)เพื่อกำหนดเส้นทางข้อความขาเข้า
ตรวจสอบด้วย:
openclaw agents list --bindings
หลายเอเจนต์=หลายคน หลายบุคลิก¶
เมื่อมีหลายเอเจนต์ agentIdแต่ละตัวจะกลายเป็นบุคลิกที่แยกจากกันอย่างสมบูรณ์:
- หมายเลขโทรศัพท์/บัญชีต่างกัน(ต่อช่องทาง
accountId) - บุคลิกต่างกัน(ไฟล์เวิร์กสเปซต่อเอเจนต์เช่น
AGENTS.mdและSOUL.md) - การยืนยันตัวตน+เซสชันแยกกัน(ไม่มีการปะปน เว้นแต่จะเปิดโดยตั้งใจ)
สิ่งนี้ทำให้หลายคนสามารถแชร์เซิร์ฟเวอร์Gatewayเดียวกันได้ โดยคงการแยกสมองAIและข้อมูลอย่างชัดเจน
หมายเลขWhatsAppเดียว หลายคน(DM split)¶
คุณสามารถกำหนดเส้นทางDMของWhatsAppที่ต่างกันไปยังเอเจนต์ต่างกันได้ ขณะใช้บัญชีWhatsAppเดียว จับคู่ตามผู้ส่งแบบE.164(เช่น+15551234567)ด้วยpeer.kind: "dm" การตอบกลับยังคงมาจากหมายเลขWhatsAppเดียวกัน(ไม่มีตัวตนผู้ส่งต่อเอเจนต์) จับคู่ตามผู้ส่งแบบ E.164 (เช่น +15551234567) ด้วย peer.kind: "direct". 6. การตอบกลับยังคงมาจากหมายเลข WhatsApp เดิม (ไม่มีตัวตนผู้ส่งแยกตามเอเจนต์)
รายละเอียดสำคัญ: แชตตรงจะถูกรวมไปยังคีย์เซสชันหลักของเอเจนต์ ดังนั้นการแยกอย่างแท้จริงต้องใช้หนึ่งเอเจนต์ต่อหนึ่งคน
ตัวอย่าง:
{
agents: {
list: [
{ id: "alex", workspace: "~/.openclaw/workspace-alex" },
{ id: "mia", workspace: "~/.openclaw/workspace-mia" },
],
},
bindings: [
{
agentId: "alex",
match: { channel: "whatsapp", peer: { kind: "direct", id: "+15551230001" } },
},
{
agentId: "mia",
match: { channel: "whatsapp", peer: { kind: "direct", id: "+15551230002" } },
},
],
channels: {
whatsapp: {
dmPolicy: "allowlist",
allowFrom: ["+15551230001", "+15551230002"],
},
},
}
หมายเหตุ:
- การควบคุมการเข้าถึงDMเป็นแบบส่วนกลางต่อบัญชีWhatsApp(การจับคู่/allowlist)ไม่ใช่ต่อเอเจนต์
- สำหรับกลุ่มที่ใช้ร่วมกัน ให้ผูกกลุ่มกับเอเจนต์เดียวหรือใช้Broadcast groups
กฎการกำหนดเส้นทาง(ข้อความเลือกเอเจนต์อย่างไร)¶
การผูกเป็นแบบกำหนดแน่นอนและเฉพาะเจาะจงที่สุดชนะ:
- จับคู่
peer(DM/กลุ่ม/รหัสช่องทางแบบตรง) guildId(Discord)teamId(Slack)- จับคู่
accountIdสำหรับช่องทาง - การจับคู่ระดับช่องทาง(
accountId: "*") - ย้อนกลับไปยังเอเจนต์เริ่มต้น(
agents.list[].defaultหรือรายการแรก ค่าเริ่มต้น:main)
หลายบัญชี/หลายหมายเลขโทรศัพท์¶
- ช่องทางที่รองรับ หลายบัญชี (เช่น WhatsApp) ใช้
accountIdเพื่อระบุ การล็อกอินแต่ละครั้ง ช่องทางที่รองรับหลายบัญชี(เช่น WhatsApp)จะใช้accountIdเพื่อระบุการล็อกอินแต่ละครั้งaccountIdแต่ละตัวสามารถกำหนดเส้นทางไปยังเอเจนต์ต่างกันได้ ทำให้เซิร์ฟเวอร์เดียวโฮสต์หลายหมายเลขได้โดยไม่ปะปนเซสชัน
แนวคิด¶
agentId: “สมอง”หนึ่งตัว(เวิร์กสเปซ การยืนยันตัวตนต่อเอเจนต์ ที่เก็บเซสชันต่อเอเจนต์)accountId: อินสแตนซ์บัญชีช่องทางหนึ่งตัว(เช่นบัญชีWhatsApp"personal"เทียบกับ"biz")binding: กำหนดเส้นทางข้อความขาเข้าไปยังagentIdด้วย(channel, accountId, peer)และอาจรวมถึงรหัสกิลด์/ทีม- แชตตรงจะถูกรวมไปยัง
agent:<agentId>:<mainKey>(“หลัก”ต่อเอเจนต์;session.mainKey)
ตัวอย่าง: WhatsAppสองบัญชี→เอเจนต์สองตัว¶
~/.openclaw/openclaw.json(JSON5):
{
agents: {
list: [
{
id: "home",
default: true,
name: "Home",
workspace: "~/.openclaw/workspace-home",
agentDir: "~/.openclaw/agents/home/agent",
},
{
id: "work",
name: "Work",
workspace: "~/.openclaw/workspace-work",
agentDir: "~/.openclaw/agents/work/agent",
},
],
},
// Deterministic routing: first match wins (most-specific first).
bindings: [
{ agentId: "home", match: { channel: "whatsapp", accountId: "personal" } },
{ agentId: "work", match: { channel: "whatsapp", accountId: "biz" } },
// Optional per-peer override (example: send a specific group to work agent).
{
agentId: "work",
match: {
channel: "whatsapp",
accountId: "personal",
peer: { kind: "group", id: "1203630...@g.us" },
},
},
],
// Off by default: agent-to-agent messaging must be explicitly enabled + allowlisted.
tools: {
agentToAgent: {
enabled: false,
allow: ["home", "work"],
},
},
channels: {
whatsapp: {
accounts: {
personal: {
// Optional override. Default: ~/.openclaw/credentials/whatsapp/personal
// authDir: "~/.openclaw/credentials/whatsapp/personal",
},
biz: {
// Optional override. Default: ~/.openclaw/credentials/whatsapp/biz
// authDir: "~/.openclaw/credentials/whatsapp/biz",
},
},
},
},
}
ตัวอย่าง: WhatsAppคุยประจำวัน+Telegramทำงานลึก¶
แยกตามช่องทาง: กำหนดWhatsAppไปยังเอเจนต์เร็วสำหรับทุกวัน และTelegramไปยังเอเจนต์Opus
{
agents: {
list: [
{
id: "chat",
name: "Everyday",
workspace: "~/.openclaw/workspace-chat",
model: "anthropic/claude-sonnet-4-5",
},
{
id: "opus",
name: "Deep Work",
workspace: "~/.openclaw/workspace-opus",
model: "anthropic/claude-opus-4-6",
},
],
},
bindings: [
{ agentId: "chat", match: { channel: "whatsapp" } },
{ agentId: "opus", match: { channel: "telegram" } },
],
}
หมายเหตุ:
- หากมีหลายบัญชีสำหรับช่องทาง ให้เพิ่ม
accountIdลงในการผูก(เช่น{ channel: "whatsapp", accountId: "personal" }) - หากต้องการกำหนดDM/กลุ่มเดียวไปยังOpusขณะที่ที่เหลือยังคงเป็นแชต ให้เพิ่มการผูก
match.peerสำหรับเพียร์นั้น การจับคู่เพียร์จะชนะกฎระดับช่องทางเสมอ
ตัวอย่าง: ช่องทางเดียว เพียร์เดียวไปOpus¶
คงWhatsAppไว้ที่เอเจนต์เร็ว แต่กำหนดDMหนึ่งรายการไปยังOpus:
{
agents: {
list: [
{
id: "chat",
name: "Everyday",
workspace: "~/.openclaw/workspace-chat",
model: "anthropic/claude-sonnet-4-5",
},
{
id: "opus",
name: "Deep Work",
workspace: "~/.openclaw/workspace-opus",
model: "anthropic/claude-opus-4-6",
},
],
},
bindings: [
{
agentId: "opus",
match: { channel: "whatsapp", peer: { kind: "direct", id: "+15551234567" } },
},
{ agentId: "chat", match: { channel: "whatsapp" } },
],
}
การผูกระดับเพียร์ชนะเสมอ ดังนั้นให้วางไว้เหนือกฎระดับช่องทาง
เอเจนต์ครอบครัวผูกกับกลุ่มWhatsApp¶
ผูกเอเจนต์ครอบครัวเฉพาะกับกลุ่มWhatsAppเดียว พร้อมการควบคุมการกล่าวถึงและนโยบายเครื่องมือที่เข้มงวดกว่า:
{
agents: {
list: [
{
id: "family",
name: "Family",
workspace: "~/.openclaw/workspace-family",
identity: { name: "Family Bot" },
groupChat: {
mentionPatterns: ["@family", "@familybot", "@Family Bot"],
},
sandbox: {
mode: "all",
scope: "agent",
},
tools: {
allow: [
"exec",
"read",
"sessions_list",
"sessions_history",
"sessions_send",
"sessions_spawn",
"session_status",
],
deny: ["write", "edit", "apply_patch", "browser", "canvas", "nodes", "cron"],
},
},
],
},
bindings: [
{
agentId: "family",
match: {
channel: "whatsapp",
peer: { kind: "group", id: "120363999999999999@g.us" },
},
},
],
}
หมายเหตุ:
-
- รายการอนุญาต/ปฏิเสธของเครื่องมือเป็น tools ไม่ใช่ skills รายการอนุญาต/ปฏิเสธเครื่องมือเป็นเครื่องมือไม่ใช่Skills หากSkillต้องรันไบนารี ให้แน่ใจว่าอนุญาต
execและมีไบนารีอยู่ในsandbox
- รายการอนุญาต/ปฏิเสธของเครื่องมือเป็น tools ไม่ใช่ skills รายการอนุญาต/ปฏิเสธเครื่องมือเป็นเครื่องมือไม่ใช่Skills หากSkillต้องรันไบนารี ให้แน่ใจว่าอนุญาต
- หากต้องการควบคุมที่เข้มงวดกว่า ให้ตั้งค่า
agents.list[].groupChat.mentionPatternsและคงการเปิดใช้งานallowlistของกลุ่มสำหรับช่องทาง
Sandboxและการกำหนดค่าเครื่องมือต่อเอเจนต์¶
ตั้งแต่v2026.1.6 เป็นต้นไป เอเจนต์แต่ละตัวสามารถมีsandboxและข้อจำกัดเครื่องมือของตัวเองได้:
{
agents: {
list: [
{
id: "personal",
workspace: "~/.openclaw/workspace-personal",
sandbox: {
mode: "off", // No sandbox for personal agent
},
// No tool restrictions - all tools available
},
{
id: "family",
workspace: "~/.openclaw/workspace-family",
sandbox: {
mode: "all", // Always sandboxed
scope: "agent", // One container per agent
docker: {
// Optional one-time setup after container creation
setupCommand: "apt-get update && apt-get install -y git curl",
},
},
tools: {
allow: ["read"], // Only read tool
deny: ["exec", "write", "edit", "apply_patch"], // Deny others
},
},
],
},
}
- หมายเหตุ:
setupCommandอยู่ภายใต้sandbox.dockerและรันเพียงครั้งเดียวเมื่อสร้างคอนเทนเนอร์ หมายเหตุ:setupCommandอยู่ภายใต้sandbox.dockerและรันหนึ่งครั้งเมื่อสร้างคอนเทนเนอร์ การ overridesandbox.docker.*ต่อเอเจนต์จะถูกละเลยเมื่อขอบเขตที่แก้ไขแล้วเป็น"shared"
ประโยชน์:
- การแยกด้านความปลอดภัย: จำกัดเครื่องมือสำหรับเอเจนต์ที่ไม่น่าเชื่อถือ
- การควบคุมทรัพยากร: ทำsandboxเฉพาะเอเจนต์ ขณะคงเอเจนต์อื่นบนโฮสต์
- นโยบายยืดหยุ่น: สิทธิ์ต่างกันต่อเอเจนต์
- หมายเหตุ:
tools.elevatedเป็น แบบโกลบอล และอิงตามผู้ส่ง; ไม่สามารถกำหนดค่าแยกตามเอเจนต์ได้ - หากต้องการขอบเขตแยกตามเอเจนต์ ให้ใช้
agents.list[].toolsเพื่อปฏิเสธexecหมายเหตุ:tools.elevatedเป็นแบบส่วนกลางและอิงผู้ส่ง ไม่สามารถตั้งค่าต่อเอเจนต์ได้ หากต้องการขอบเขตต่อเอเจนต์ ให้ใช้agents.list[].toolsเพื่อปฏิเสธexecสำหรับการกำหนดเป้าหมายกลุ่ม ให้ใช้agents.list[].groupChat.mentionPatternsเพื่อให้@mentionแมปไปยังเอเจนต์ที่ตั้งใจได้อย่างชัดเจน
ดูMulti-Agent Sandbox & Toolsสำหรับตัวอย่างโดยละเอียด