Mainstream messaging
Discord
OpenClaw เชื่อมต่อกับ Discord ในฐานะบอตผ่าน Discord gateway อย่างเป็นทางการ รองรับ DM และช่องกิลด์
DM ของ Discord ใช้โหมดจับคู่เป็นค่าเริ่มต้น
ลักษณะการทำงานของคำสั่งแบบเนทีฟและแค็ตตาล็อกคำสั่ง
ขั้นตอนการวินิจฉัยและแก้ไขปัญหาข้ามช่อง
การตั้งค่าด่วน
สร้างแอปพลิเคชัน Discord ที่มีบอต เพิ่มบอตลงในเซิร์ฟเวอร์ แล้วจับคู่กับ OpenClaw หากทำได้ ให้ใช้เซิร์ฟเวอร์ส่วนตัว และหากจำเป็น ให้สร้างเซิร์ฟเวอร์ก่อน (Create My Own > For me and my friends)
สร้างแอปพลิเคชัน Discord และบอต
ใน Discord Developer Portal ให้คลิก New Application แล้วตั้งชื่อ (เช่น "OpenClaw")
เปิด Bot ในแถบด้านข้าง แล้วตั้งค่า Username เป็นชื่อเอเจนต์
เปิดใช้งาน Intent ที่มีสิทธิ์พิเศษ
ขณะที่ยังอยู่ในหน้า Bot ให้เปิดใช้งานรายการต่อไปนี้ภายใต้ Privileged Gateway Intents:
- Message Content Intent (จำเป็น)
- Server Members Intent (แนะนำ และจำเป็นสำหรับรายการอนุญาตตามบทบาท การจับคู่ชื่อกับ ID และกลุ่มสิทธิ์เข้าถึงผู้ชมของช่อง)
- Presence Intent (ไม่บังคับ ใช้เฉพาะสำหรับการอัปเดตสถานะการแสดงตน)
คัดลอกโทเค็นบอต
ในหน้า Bot ให้คลิก Reset Token แล้วคัดลอกโทเค็น
สร้าง URL คำเชิญและเพิ่มบอตลงในเซิร์ฟเวอร์
เปิด OAuth2 ในแถบด้านข้าง ใน OAuth2 URL Generator ให้เปิดใช้งานขอบเขตต่อไปนี้:
botapplications.commands
ในส่วน Bot Permissions ที่ปรากฏขึ้น ให้เปิดใช้งานอย่างน้อย:
General Permissions
- View Channels
Text Permissions
- Send Messages
- Read Message History
- Embed Links
- Attach Files
- Add Reactions (ไม่บังคับ)
นี่คือค่าพื้นฐานสำหรับช่องข้อความทั่วไป หากบอตจะโพสต์ในเธรด รวมถึงเวิร์กโฟลว์ของช่องฟอรัมหรือสื่อที่สร้างหรือดำเนินเธรดต่อ ให้เปิดใช้งาน Send Messages in Threads ด้วย
คัดลอก URL ที่สร้างขึ้น เปิดในเบราว์เซอร์ เลือกเซิร์ฟเวอร์ แล้วคลิก Continue ตอนนี้บอตควรปรากฏในเซิร์ฟเวอร์แล้ว
เปิดใช้งานโหมดนักพัฒนาและรวบรวม ID
ในแอป Discord ให้เปิดใช้งาน Developer Mode เพื่อให้คัดลอก ID ได้:
- User Settings (ไอคอนรูปเฟือง) → Developer → เปิด Developer Mode (บนอุปกรณ์เคลื่อนที่: App Settings → Advanced)
- คลิกขวาที่ ไอคอนเซิร์ฟเวอร์ → Copy Server ID
- คลิกขวาที่ อวาตาร์ของตนเอง → Copy User ID
เก็บ Server ID และ User ID ไว้พร้อมกับโทเค็นบอต เนื่องจากขั้นตอนถัดไปต้องใช้ทั้งสามรายการ
อนุญาต DM จากสมาชิกเซิร์ฟเวอร์
เพื่อให้การจับคู่ทำงานได้ Discord ต้องอนุญาตให้บอตส่ง DM ถึงคุณ คลิกขวาที่ ไอคอนเซิร์ฟเวอร์ → Privacy Settings → เปิด Direct Messages
เปิดการตั้งค่านี้ไว้หากใช้ DM ของ Discord กับ OpenClaw หากใช้เฉพาะช่องกิลด์ สามารถปิดได้หลังจากจับคู่แล้ว
ตั้งค่าโทเค็นบอตอย่างปลอดภัย (ห้ามส่งในแชต)
โทเค็นบอตเป็นข้อมูลลับ ให้ตั้งค่าบนเครื่องที่เรียกใช้ OpenClaw ก่อนส่งข้อความถึงเอเจนต์:
export DISCORD_BOT_TOKEN="YOUR_BOT_TOKEN"cat > discord.patch.json5 <<'JSON5'{channels: {discord: { enabled: true, token: { source: "env", provider: "default", id: "DISCORD_BOT_TOKEN" },},},}JSON5openclaw config patch --file ./discord.patch.json5 --dry-runopenclaw config patch --file ./discord.patch.json5openclaw gatewayหาก OpenClaw ทำงานเป็นบริการเบื้องหลังอยู่แล้ว ให้รีสตาร์ตผ่านแอป OpenClaw บน Mac หรือหยุดแล้วเริ่มกระบวนการ openclaw gateway run ใหม่
สำหรับการติดตั้งเป็นบริการที่มีการจัดการ ให้เรียกใช้ openclaw gateway install จากเชลล์ที่ตั้งค่า DISCORD_BOT_TOKEN ไว้ หรือจัดเก็บตัวแปรไว้ใน ~/.openclaw/.env เพื่อให้บริการสามารถแก้ค่า env SecretRef ได้หลังรีสตาร์ต
หากโฮสต์ถูกบล็อกหรือจำกัดอัตราโดยการค้นหาแอปพลิเคชันของ Discord ขณะเริ่มต้น ให้ตั้งค่า ID แอปพลิเคชัน/ไคลเอนต์จาก Developer Portal เพื่อให้ขั้นตอนเริ่มต้นข้ามการเรียก REST ดังกล่าวได้ โดยใช้ channels.discord.applicationId สำหรับบัญชีเริ่มต้น หรือ channels.discord.accounts.<accountId>.applicationId สำหรับบอตแต่ละตัว
กำหนดค่า OpenClaw และจับคู่
ขอให้เอเจนต์ดำเนินการ
แชตกับเอเจนต์ OpenClaw ผ่านช่องที่มีอยู่ (เช่น Telegram) แล้วแจ้งให้ดำเนินการ หาก Discord เป็นช่องแรก ให้ใช้แท็บ CLI / การกำหนดค่าแทน
"ฉันตั้งค่าโทเค็นบอต Discord ในการกำหนดค่าแล้ว โปรดตั้งค่า Discord ให้เสร็จสมบูรณ์โดยใช้ User ID
<user_id>และ Server ID<server_id>"
CLI / การกำหนดค่า
การกำหนดค่าแบบใช้ไฟล์:
{channels: {discord: {enabled: true,token: {source: "env",provider: "default",id: "DISCORD_BOT_TOKEN",},},},}env สำรองสำหรับบัญชีเริ่มต้น:
DISCORD_BOT_TOKEN=...สำหรับการตั้งค่าด้วยสคริปต์หรือจากระยะไกล ให้เขียนบล็อก JSON5 เดียวกันโดยใช้ openclaw config patch --file ./discord.patch.json5 --dry-run แล้วเรียกใช้อีกครั้งโดยไม่มี --dry-run สตริง token แบบข้อความธรรมดาก็ใช้งานได้เช่นกัน และรองรับค่า SecretRef สำหรับ channels.discord.token ผ่านผู้ให้บริการ env/file/exec ดูการจัดการข้อมูลลับ
สำหรับบอต Discord หลายตัว ให้เก็บโทเค็นบอตและ ID แอปพลิเคชันของแต่ละบอตไว้ภายใต้บัญชีของบอตนั้น บัญชีจะสืบทอด channels.discord.applicationId ระดับบนสุด ดังนั้นให้ตั้งค่าที่ระดับดังกล่าวเฉพาะเมื่อทุกบัญชีใช้ ID แอปพลิเคชันเดียวกัน
{channels: {discord: {enabled: true,accounts: {personal: { token: { source: "env", provider: "default", id: "DISCORD_PERSONAL_TOKEN" }, applicationId: "111111111111111111",},work: { token: { source: "env", provider: "default", id: "DISCORD_WORK_TOKEN" }, applicationId: "222222222222222222",},},},},}อนุมัติการจับคู่ผ่าน DM ครั้งแรก
เมื่อ gateway ทำงานแล้ว ให้ส่ง DM ถึงบอตใน Discord บอตจะตอบกลับด้วยรหัสจับคู่
ขอให้เอเจนต์ดำเนินการ
ส่งรหัสจับคู่ให้เอเจนต์ผ่านช่องที่มีอยู่:
"อนุมัติรหัสจับคู่ Discord นี้:
<CODE>"
CLI
openclaw pairing list discordopenclaw pairing approve discord <CODE>รหัสจับคู่จะหมดอายุหลังจาก 1 ชั่วโมง หลังอนุมัติแล้ว ให้แชตกับเอเจนต์ผ่าน DM ของ Discord
แนะนำ: ตั้งค่าพื้นที่ทำงานของกิลด์
เมื่อ DM ทำงานแล้ว สามารถเปลี่ยนเซิร์ฟเวอร์เป็นพื้นที่ทำงานเต็มรูปแบบ ซึ่งแต่ละช่องจะมีเซสชันเอเจนต์และบริบทของตนเอง แนะนำสำหรับเซิร์ฟเวอร์ส่วนตัวที่มีเพียงคุณและบอต
เพิ่มเซิร์ฟเวอร์ลงในรายการอนุญาตของกิลด์
การดำเนินการนี้ช่วยให้เอเจนต์ตอบกลับได้ในทุกช่องบนเซิร์ฟเวอร์ ไม่ใช่เฉพาะ DM
ขอให้เอเจนต์ดำเนินการ
"เพิ่ม Discord Server ID
<server_id>ของฉันลงในรายการอนุญาตของกิลด์"
การกำหนดค่า
{channels: {discord: {groupPolicy: "allowlist",guilds: {YOUR_SERVER_ID: { requireMention: true, users: ["YOUR_USER_ID"],},},},},}อนุญาตให้ตอบกลับโดยไม่ต้อง @mention
ตามค่าเริ่มต้น เอเจนต์จะตอบกลับในช่องกิลด์เฉพาะเมื่อถูก @mention เท่านั้น สำหรับเซิร์ฟเวอร์ส่วนตัว โดยทั่วไปควรตั้งค่าให้ตอบกลับทุกข้อความ
ในช่องกิลด์ การตอบกลับปกติจะโพสต์โดยอัตโนมัติตามค่าเริ่มต้น สำหรับห้องที่เปิดใช้งานตลอดเวลาและใช้ร่วมกัน ให้เลือกใช้ messages.groupChat.visibleReplies: "message_tool" เพื่อให้เอเจนต์เฝ้าดูโดยไม่ส่งข้อความ และโพสต์เฉพาะเมื่อตัดสินว่าการตอบกลับในช่องมีประโยชน์ วิธีนี้ทำงานได้ดีที่สุดกับโมเดลรุ่นล่าสุดที่ใช้เครื่องมือได้อย่างน่าเชื่อถือ เช่น GPT-5.6 Sol เหตุการณ์ห้องแบบแวดล้อมจะไม่มีการส่งข้อความ เว้นแต่เครื่องมือจะส่ง ดูการกำหนดค่าโหมดเฝ้าดูฉบับเต็มที่เหตุการณ์ห้องแบบแวดล้อม
หาก Discord แสดงสถานะกำลังพิมพ์และบันทึกแสดงการใช้โทเค็น แต่ไม่มีข้อความถูกโพสต์ ให้ตรวจสอบว่าเทิร์นนั้นได้รับการกำหนดค่าเป็นเหตุการณ์ห้องแบบแวดล้อม หรือเลือกให้การตอบกลับที่มองเห็นได้ส่งผ่านเครื่องมือส่งข้อความหรือไม่
ขอให้เอเจนต์ดำเนินการ
"อนุญาตให้เอเจนต์ของฉันตอบกลับบนเซิร์ฟเวอร์นี้ได้โดยไม่ต้องถูก @mention"
การกำหนดค่า
ตั้งค่า requireMention: false ในการกำหนดค่ากิลด์:
{channels: {discord: {guilds: {YOUR_SERVER_ID: { requireMention: false,},},},},}หากต้องการบังคับให้การตอบกลับในกลุ่ม/ช่องที่มองเห็นได้ส่งผ่านเครื่องมือส่งข้อความ ให้ตั้งค่า messages.groupChat.visibleReplies: "message_tool"
วางแผนการใช้หน่วยความจำในช่องกิลด์
หน่วยความจำระยะยาว (MEMORY.md) จะโหลดโดยอัตโนมัติเฉพาะในเซสชัน DM เท่านั้น ช่องกิลด์จะไม่โหลดไฟล์นี้
ขอให้เอเจนต์ดำเนินการ
"เมื่อฉันถามคำถามในช่อง Discord ให้ใช้ memory_search หรือ memory_get หากต้องใช้บริบทระยะยาวจาก MEMORY.md"
ด้วยตนเอง
สำหรับบริบทที่ใช้ร่วมกันในทุกช่อง ให้วางคำสั่งที่คงที่ไว้ใน AGENTS.md หรือ USER.md (แทรกลงในทุกเซสชัน) เก็บบันทึกระยะยาวไว้ใน MEMORY.md และเข้าถึงเมื่อต้องการด้วยเครื่องมือหน่วยความจำ
ตอนนี้ให้สร้างช่องและเริ่มแชต เอเจนต์จะเห็นชื่อช่อง และแต่ละช่องเป็นเซสชันที่แยกจากกัน โดยตั้งค่า #coding, #home, #research หรือรายการอื่นที่เหมาะกับเวิร์กโฟลว์
โมเดลรันไทม์
- Gateway เป็นผู้ควบคุมการเชื่อมต่อ Discord
- การกำหนดเส้นทางการตอบกลับเป็นแบบกำหนดแน่นอน: ข้อความขาเข้าจาก Discord จะตอบกลับไปยัง Discord
- เมทาดาทาของกิลด์/ช่อง Discord จะถูกเพิ่มลงในพรอมต์ของโมเดลในฐานะบริบทที่ไม่น่าเชื่อถือ ไม่ใช่คำนำหน้าการตอบกลับที่ผู้ใช้มองเห็น หากโมเดลคัดลอกกรอบข้อมูลดังกล่าวกลับมา OpenClaw จะลบเมทาดาทาที่คัดลอกออกจากการตอบกลับขาออกและจากบริบทการเล่นซ้ำในอนาคต
- ตามค่าเริ่มต้น (
session.dmScope=main) แชตโดยตรงจะใช้เซสชันหลักของเอเจนต์ร่วมกัน (agent:main:main) - ช่องกิลด์ใช้คีย์เซสชันที่แยกจากกัน (
agent:<agentId>:discord:channel:<channelId>) - DM แบบกลุ่มจะถูกละเว้นตามค่าเริ่มต้น (
channels.discord.dm.groupEnabled=false) - คำสั่งแบบสแลชเนทีฟทำงานในเซสชันคำสั่งที่แยกจากกัน (
agent:<agentId>:discord:slash:<userId>) ขณะเดียวกันยังส่งต่อCommandTargetSessionKeyไปยังเซสชันการสนทนาที่กำหนดเส้นทางไว้ - การส่งประกาศ Cron/Heartbeat แบบข้อความล้วนไปยัง Discord จะยุบเหลือเฉพาะคำตอบสุดท้ายที่ผู้ช่วยมองเห็นและส่งเพียงครั้งเดียว เพย์โหลดสื่อและคอมโพเนนต์แบบมีโครงสร้างจะยังคงเป็นหลายข้อความเมื่อเอเจนต์สร้างเพย์โหลดที่ส่งได้หลายรายการ
ช่องฟอรัม
ช่องฟอรัมและช่องสื่อของ Discord ยอมรับเฉพาะโพสต์ในเธรดเท่านั้น OpenClaw รองรับการสร้างโพสต์ดังกล่าว 2 วิธี:
- ส่งข้อความไปยังช่องหลักของฟอรัม (
channel:<forumId>) เพื่อสร้างเธรดโดยอัตโนมัติ ชื่อเธรดจะเป็นบรรทัดแรกที่ไม่ว่างของข้อความ (ตัดให้ไม่เกินขีดจำกัดชื่อเธรด 100 อักขระของ Discord) - ใช้
openclaw message thread createเพื่อสร้างเธรดโดยตรง อย่าส่ง--message-idสำหรับช่องฟอรัม
ส่งไปยังช่องหลักของฟอรัมเพื่อสร้างเธรด:
openclaw message send --channel discord --target channel:<forumId> \ --message "ชื่อหัวข้อ\nเนื้อหาของโพสต์"สร้างเธดฟอรัมอย่างชัดเจน:
openclaw message thread create --channel discord --target channel:<forumId> \ --thread-name "ชื่อหัวข้อ" --message "เนื้อหาของโพสต์"ช่องหลักของฟอรัมไม่ยอมรับคอมโพเนนต์ของ Discord หากต้องการใช้คอมโพเนนต์ ให้ส่งไปยังเธรดโดยตรง (channel:<threadId>)
คอมโพเนนต์แบบโต้ตอบ
OpenClaw รองรับคอนเทนเนอร์คอมโพเนนต์ v2 ของ Discord สำหรับข้อความของเอเจนต์ ใช้เครื่องมือข้อความพร้อมเพย์โหลด components ผลลัพธ์จากการโต้ตอบจะถูกส่งกลับไปยังเอเจนต์ในรูปแบบข้อความขาเข้าปกติ และเป็นไปตามการตั้งค่า replyToMode ของ Discord ที่มีอยู่
บล็อกที่รองรับ:
text,section,separator,actions,media-gallery,file- แถวการดำเนินการรองรับปุ่มได้สูงสุด 5 ปุ่ม หรือเมนูเลือก 1 เมนู
- ประเภทการเลือก:
string,user,role,mentionable,channel
โดยค่าเริ่มต้น คอมโพเนนต์ใช้ได้เพียงครั้งเดียว ตั้งค่า components.reusable=true เพื่ออนุญาตให้ใช้ปุ่ม รายการเลือก และฟอร์มได้หลายครั้งจนกว่าจะหมดอายุ
หากต้องการจำกัดผู้ที่คลิกปุ่มได้ ให้ตั้งค่า allowedUsers บนปุ่มนั้น (ID ผู้ใช้ Discord, แท็ก หรือ *) ผู้ใช้ที่ไม่ตรงเงื่อนไขจะได้รับข้อความปฏิเสธที่มองเห็นได้เฉพาะตน
โดยค่าเริ่มต้น คอลแบ็กของคอมโพเนนต์จะหมดอายุหลังจาก 30 นาที ตั้งค่า channels.discord.agentComponents.ttlMs เพื่อเปลี่ยนอายุของรีจิสทรีคอลแบ็กสำหรับบัญชีเริ่มต้น หรือ channels.discord.accounts.<accountId>.agentComponents.ttlMs สำหรับแต่ละบัญชี ค่านี้มีหน่วยเป็นมิลลิวินาที ต้องเป็นจำนวนเต็มบวก และจำกัดสูงสุดที่ 86400000 (24 ชั่วโมง) TTL ที่ยาวขึ้นเหมาะกับขั้นตอนการรีวิว/อนุมัติที่ต้องให้ปุ่มยังคงใช้งานได้ แต่จะขยายช่วงเวลาที่ข้อความ Discord เก่ายังสามารถทริกเกอร์การดำเนินการได้ ควรใช้ TTL ที่สั้นที่สุดซึ่งเพียงพอต่อการใช้งาน และคงค่าเริ่มต้นไว้หากคอลแบ็กที่ค้างเก่าอาจสร้างความสับสน
คำสั่งสแลช /model และ /models จะเปิดตัวเลือกโมเดลแบบโต้ตอบ ซึ่งมีรายการแบบเลื่อนลงสำหรับผู้ให้บริการ โมเดล และรันไทม์ที่เข้ากันได้ พร้อมขั้นตอน Submit ส่วน /models add เลิกใช้แล้ว และจะส่งข้อความแจ้งการเลิกใช้แทนการลงทะเบียนโมเดลจากแชต การตอบกลับของตัวเลือกจะมองเห็นได้เฉพาะตนและใช้งานได้เฉพาะผู้ใช้ที่เรียกใช้เท่านั้น เมนูเลือกของ Discord จำกัดไว้ที่ 25 ตัวเลือก ดังนั้นให้เพิ่มรายการ provider/* ใน agents.defaults.modelPolicy.allow เมื่อต้องการให้ตัวเลือกแสดงเฉพาะโมเดลที่ค้นพบแบบไดนามิกสำหรับผู้ให้บริการที่เลือก เช่น openai หรือ vllm
ไฟล์แนบ:
- บล็อก
fileต้องชี้ไปยังการอ้างอิงไฟล์แนบ (attachment://<filename>) - ระบุไฟล์แนบผ่าน
media/path/filePath(ไฟล์เดียว) และใช้media-galleryสำหรับหลายไฟล์ - ใช้
filenameเพื่อเขียนทับชื่อที่อัปโหลดเมื่อชื่อนั้นควรตรงกับการอ้างอิงไฟล์แนบ
ฟอร์มโมดัล:
- เพิ่ม
components.modalพร้อมฟิลด์ได้สูงสุด 5 ฟิลด์ - ประเภทฟิลด์:
text,checkbox,radio,select,role-select,user-select - OpenClaw จะเพิ่มปุ่มทริกเกอร์โดยอัตโนมัติ
ตัวอย่าง:
{ channel: "discord", action: "send", to: "channel:123456789012345678", message: "ข้อความสำรองที่ไม่บังคับ", components: { reusable: true, text: "เลือกเส้นทาง", blocks: [ { type: "actions", buttons: [ { label: "อนุมัติ", style: "success", allowedUsers: ["123456789012345678"], }, { label: "ปฏิเสธ", style: "danger" }, ], }, { type: "actions", select: { type: "string", placeholder: "เลือกตัวเลือก", options: [ { label: "ตัวเลือก A", value: "a" }, { label: "ตัวเลือก B", value: "b" }, ], }, }, ], modal: { title: "รายละเอียด", triggerLabel: "เปิดฟอร์ม", fields: [ { type: "text", label: "ผู้ร้องขอ" }, { type: "select", label: "ลำดับความสำคัญ", options: [ { label: "ต่ำ", value: "low" }, { label: "สูง", value: "high" }, ], }, ], }, },}การควบคุมการเข้าถึงและการกำหนดเส้นทาง
นโยบาย DM
channels.discord.dmPolicy ควบคุมการเข้าถึง DM ส่วน channels.discord.allowFrom คือรายการอนุญาต DM มาตรฐาน
pairing(ค่าเริ่มต้น)allowlist(ต้องมีผู้ส่งallowFromอย่างน้อยหนึ่งราย)open(กำหนดให้channels.discord.allowFromต้องมี"*")disabled
หากนโยบาย DM ไม่ได้เปิดไว้ ผู้ใช้ที่ไม่รู้จักจะถูกบล็อก (หรือได้รับข้อความให้จับคู่ในโหมด pairing)
ลำดับความสำคัญสำหรับหลายบัญชี:
channels.discord.accounts.default.allowFromใช้กับบัญชีdefaultเท่านั้น- สำหรับบัญชีหนึ่งบัญชี
allowFromมีลำดับความสำคัญเหนือdm.allowFromแบบเดิม - บัญชีที่มีชื่อจะรับช่วง
channels.discord.allowFromเมื่อไม่ได้ตั้งค่าทั้งallowFromของบัญชีนั้นเองและdm.allowFromแบบเดิม - บัญชีที่มีชื่อจะไม่รับช่วง
channels.discord.accounts.default.allowFrom
ระบบยังคงอ่าน channels.discord.dm.policy และ channels.discord.dm.allowFrom แบบเดิมเพื่อความเข้ากันได้ openclaw doctor --fix จะย้ายค่าเหล่านี้ไปยัง dmPolicy และ allowFrom เมื่อสามารถทำได้โดยไม่เปลี่ยนแปลงการเข้าถึง
รูปแบบเป้าหมาย DM สำหรับการส่ง:
user:<id>- การกล่าวถึง
<@id>
โดยปกติ ID ตัวเลขล้วนจะถูกตีความเป็น ID ช่องเมื่อมีค่าเริ่มต้นของช่องทำงานอยู่ แต่ ID ที่ระบุอยู่ใน allowFrom ของ DM ที่มีผลสำหรับบัญชีจะถูกตีความเป็นเป้าหมาย DM ของผู้ใช้เพื่อความเข้ากันได้
กลุ่มการเข้าถึง
DM ของ Discord และการให้สิทธิ์คำสั่งข้อความสามารถใช้รายการ accessGroup:<name> แบบไดนามิกใน channels.discord.allowFrom
ชื่อกลุ่มการเข้าถึงใช้ร่วมกันในทุกช่องข้อความ ใช้ type: "message.senders" สำหรับกลุ่มแบบคงที่ซึ่งระบุสมาชิกด้วยไวยากรณ์ allowFrom ปกติของแต่ละช่อง หรือใช้ type: "discord.channelAudience" เมื่อต้องการให้กลุ่มผู้ชม ViewChannel ปัจจุบันของช่อง Discord กำหนดสมาชิกแบบไดนามิก พฤติกรรมกลุ่มการเข้าถึงที่ใช้ร่วมกัน: กลุ่มการเข้าถึง
{accessGroups: {operators: { type: "message.senders", members: { "*": ["global-owner-id"], discord: ["discord:123456789012345678"], telegram: ["987654321"], },},},channels: {discord: { dmPolicy: "allowlist", allowFrom: ["accessGroup:operators"],},},}ช่องข้อความ Discord ไม่มีรายชื่อสมาชิกแยกต่างหาก type: "discord.channelAudience" จำลองการเป็นสมาชิกดังนี้: ผู้ส่ง DM เป็นสมาชิกของกิลด์ที่กำหนดค่าไว้ และในขณะนั้นมีสิทธิ์ ViewChannel ที่มีผลในช่องที่กำหนดค่าไว้ หลังจากใช้การเขียนทับจากบทบาทและช่องแล้ว
ตัวอย่าง: อนุญาตให้ทุกคนที่มองเห็น #maintainers ส่ง DM ถึงบอตได้ ขณะที่ยังปิด DM สำหรับบุคคลอื่นทั้งหมด
{accessGroups: {maintainers: { type: "discord.channelAudience", guildId: "1456350064065904867", channelId: "1456744319972282449", membership: "canViewChannel",},},channels: {discord: { dmPolicy: "allowlist", allowFrom: ["accessGroup:maintainers"],},},}สามารถผสมรายการแบบไดนามิกและแบบคงที่ได้:
{accessGroups: {maintainers: { type: "discord.channelAudience", guildId: "1456350064065904867", channelId: "1456744319972282449",},},channels: {discord: { dmPolicy: "allowlist", allowFrom: ["accessGroup:maintainers", "discord:123456789012345678"],},},}การค้นหาจะปฏิเสธการเข้าถึงเมื่อเกิดข้อผิดพลาด หาก Discord ส่งคืน Missing Access การค้นหาสมาชิกล้มเหลว หรือช่องเป็นของกิลด์อื่น ผู้ส่ง DM จะถือว่าไม่ได้รับอนุญาต
เปิดใช้ Server Members Intent ใน Discord Developer Portal เมื่อใช้กลุ่มการเข้าถึงตามผู้ชมของช่อง DM ไม่มีสถานะสมาชิกกิลด์รวมอยู่ด้วย ดังนั้น OpenClaw จะค้นหาสมาชิกผ่าน Discord REST ขณะตรวจสอบสิทธิ์
นโยบายกิลด์
การจัดการกิลด์ควบคุมโดย channels.discord.groupPolicy:
openallowlistdisabled
ค่าพื้นฐานที่ปลอดภัยเมื่อมี channels.discord คือ allowlist
พฤติกรรมของ allowlist:
- กิลด์ต้องตรงกับ
channels.discord.guilds(แนะนำให้ใช้idและยอมรับ slug) - รายการอนุญาตผู้ส่งที่ไม่บังคับ:
users(แนะนำ ID ที่คงที่) และroles(เฉพาะ ID บทบาท) หากกำหนดค่าอย่างใดอย่างหนึ่ง ผู้ส่งจะได้รับอนุญาตเมื่อตรงกับusersหรือroles - การจับคู่ชื่อ/แท็กโดยตรงถูกปิดไว้โดยค่าเริ่มต้น เปิดใช้
channels.discord.dangerouslyAllowNameMatching: trueเฉพาะเป็นโหมดความเข้ากันได้ในกรณีฉุกเฉินเท่านั้น - รองรับชื่อ/แท็กสำหรับ
usersแต่ ID ปลอดภัยกว่าopenclaw security auditจะแจ้งเตือนเมื่อมีการใช้รายการชื่อ/แท็ก - หากกิลด์กำหนดค่า
channelsไว้ ช่องที่ไม่อยู่ในรายการจะถูกปฏิเสธ - หากกิลด์ไม่มีบล็อก
channelsช่องทั้งหมดในกิลด์ที่อยู่ในรายการอนุญาตนั้นจะได้รับอนุญาต
ตัวอย่าง:
{channels: {discord: { groupPolicy: "allowlist", guilds: { "123456789012345678": { requireMention: true, ignoreOtherMentions: true, users: ["987654321098765432"], roles: ["123456789012345678"], channels: { general: { enabled: true }, help: { enabled: true, requireMention: true }, }, }, },},},}คีย์ allow ต่อช่องแบบเดิมจะถูกย้ายไปยัง enabled โดย openclaw doctor --fix
หากตั้งค่าเฉพาะ DISCORD_BOT_TOKEN และไม่ได้สร้างบล็อก channels.discord ค่าสำรองขณะรันไทม์คือ groupPolicy="allowlist" (พร้อมคำเตือนในบันทึก) แม้ว่า channels.defaults.groupPolicy จะเป็น open
การกล่าวถึงและ DM แบบกลุ่ม
โดยค่าเริ่มต้น ข้อความในกิลด์ต้องมีการกล่าวถึงจึงจะผ่าน
การตรวจจับการกล่าวถึงประกอบด้วย:
- การกล่าวถึงบอตอย่างชัดเจน
- รูปแบบการกล่าวถึงที่กำหนดค่าไว้ (
agents.list[].groupChat.mentionPatternsและใช้messages.groupChat.mentionPatternsเป็นค่าสำรอง) - พฤติกรรมตอบกลับบอตโดยนัยในกรณีที่รองรับ
เมื่อเขียนข้อความขาออกของ Discord ให้ใช้ไวยากรณ์การกล่าวถึงมาตรฐาน: <@USER_ID> สำหรับผู้ใช้, <#CHANNEL_ID> สำหรับช่อง และ <@&ROLE_ID> สำหรับบทบาท อย่าใช้รูปแบบการกล่าวถึงชื่อเล่น <@!USER_ID> แบบเดิม
requireMention กำหนดค่าต่อกิลด์/ช่อง (channels.discord.guilds...)
ignoreOtherMentions สามารถเลือกทิ้งข้อความที่กล่าวถึงผู้ใช้/บทบาทอื่นแต่ไม่ได้กล่าวถึงบอต (ไม่รวม @everyone/@here)
DM แบบกลุ่ม:
- ค่าเริ่มต้น: ละเว้น (
dm.groupEnabled=false) - รายการอนุญาตที่ไม่บังคับผ่าน
dm.groupChannels(ID ช่องหรือ slug)
การกำหนดเส้นทางเอเจนต์ตามบทบาท
ใช้ bindings[].match.roles เพื่อกำหนดเส้นทางสมาชิกกิลด์ Discord ไปยังเอเจนต์ต่างกันตาม ID บทบาท การผูกตามบทบาทยอมรับเฉพาะ ID บทบาท และจะประเมินหลังการผูกกับเพียร์หรือเพียร์หลัก แต่ก่อนการผูกเฉพาะกิลด์ หากการผูกกำหนดฟิลด์จับคู่อื่นด้วย (เช่น peer + guildId + roles) ฟิลด์ที่กำหนดค่าไว้ทั้งหมดต้องตรงกัน
{ bindings: [ { agentId: "opus", match: { channel: "discord", guildId: "123456789012345678", roles: ["111111111111111111"], }, }, { agentId: "sonnet", match: { channel: "discord", guildId: "123456789012345678", }, }, ],}คำสั่งแบบเนทีฟและการตรวจสอบสิทธิ์คำสั่ง
commands.nativeมีค่าเริ่มต้นเป็น"auto"และเปิดใช้งานสำหรับ Discord- การกำหนดค่าเฉพาะช่อง:
channels.discord.commands.native commands.native=falseจะข้ามการลงทะเบียนและล้างคำสั่งแบบ slash ของ Discord ระหว่างการเริ่มต้น คำสั่งที่ลงทะเบียนไว้ก่อนหน้านี้อาจยังคงปรากฏใน Discord จนกว่าจะนำคำสั่งเหล่านั้นออกจากแอป Discord- การตรวจสอบสิทธิ์คำสั่งแบบเนทีฟใช้รายการอนุญาต/นโยบายของ Discord ชุดเดียวกับการจัดการข้อความปกติ
- คำสั่งอาจยังคงปรากฏใน UI ของ Discord สำหรับผู้ใช้ที่ไม่ได้รับอนุญาต แต่เมื่อเรียกใช้ OpenClaw จะบังคับใช้การตรวจสอบสิทธิ์และตอบกลับว่า "ไม่ได้รับอนุญาต"
- การตั้งค่าเริ่มต้นของคำสั่งแบบ slash:
ephemeral: true(channels.discord.slashCommand.ephemeral)
ดูรายการคำสั่งและลักษณะการทำงานได้ที่ คำสั่งแบบ slash
รายละเอียดฟีเจอร์
แท็กตอบกลับและการตอบกลับแบบเนทีฟ
Discord รองรับแท็กตอบกลับในเอาต์พุตของเอเจนต์:
[[reply_to_current]][[reply_to:<id>]]
ควบคุมโดย channels.discord.replyToMode:
off(ค่าเริ่มต้น): ไม่มีการจัดเธรดการตอบกลับโดยนัย แต่ยังคงใช้แท็ก[[reply_to_*]]ที่ระบุไว้อย่างชัดเจนfirst: แนบการอ้างอิงการตอบกลับแบบเนทีฟโดยนัยกับข้อความ Discord ขาออกข้อความแรกของรอบall: แนบการอ้างอิงดังกล่าวกับทุกข้อความขาออกbatched: แนบเฉพาะเมื่อเหตุการณ์ขาเข้าเป็นชุดข้อความหลายข้อความที่ผ่านการหน่วงรวม เหมาะสำหรับกรณีที่ต้องการใช้การตอบกลับแบบเนทีฟเป็นหลักกับแชตที่มีข้อความจำนวนมากต่อเนื่องและตีความได้ไม่ชัดเจน ไม่ใช่ทุกๆ รอบที่มีเพียงข้อความเดียว
รหัสข้อความจะแสดงในบริบท/ประวัติเพื่อให้เอเจนต์สามารถระบุข้อความเป้าหมายได้อย่างเจาะจง
ตัวอย่างลิงก์
โดยค่าเริ่มต้น Discord จะสร้างการฝังลิงก์แบบสมบูรณ์สำหรับ URL ส่วน OpenClaw จะระงับการฝังที่สร้างขึ้นดังกล่าวในข้อความ Discord ขาออกตามค่าเริ่มต้น ดังนั้น URL ที่เอเจนต์ส่งจะยังคงเป็นลิงก์ธรรมดา เว้นแต่จะเลือกเปิดใช้:
{channels: {discord: { suppressEmbeds: false,},},}ตั้งค่า channels.discord.accounts.<id>.suppressEmbeds เพื่อกำหนดค่าทับสำหรับหนึ่งบัญชี การส่งผ่านเครื่องมือข้อความของเอเจนต์ยังสามารถส่ง suppressEmbeds: false สำหรับข้อความเดียวได้อีกด้วย เพย์โหลด Discord embeds ที่ระบุอย่างชัดเจนจะไม่ถูกระงับโดยการตั้งค่าตัวอย่างลิงก์เริ่มต้น
ตัวอย่างสตรีมสด
OpenClaw สามารถสตรีมฉบับร่างการตอบกลับได้โดยส่งข้อความชั่วคราวและแก้ไขข้อความเมื่อข้อความใหม่เข้ามา channels.discord.streaming.mode รับค่า off | partial | block | progress (ค่าเริ่มต้นเมื่อไม่ได้ตั้งค่าคีย์ streaming/คีย์เดิม streamMode) streamMode เป็นนามแฝงเดิม ให้เรียกใช้ openclaw doctor --fix เพื่อเขียนการกำหนดค่าที่บันทึกไว้ใหม่ให้อยู่ในรูปแบบซ้อนมาตรฐาน streaming
{channels: {discord: { streaming: { mode: "progress", progress: { maxLines: 8, maxLineChars: 120, toolProgress: false, commentary: false, }, },},},}offปิดใช้งานการแก้ไขตัวอย่างใน Discordpartialแก้ไขข้อความตัวอย่างเดียวเมื่อโทเค็นเข้ามาblockส่งส่วนข้อความขนาดฉบับร่าง โดยปรับขนาดและจุดแบ่งได้ด้วยstreaming.preview.chunk(minChars,maxChars,breakPreference) ซึ่งถูกจำกัดไว้ที่textChunkLimitเมื่อเปิดใช้งานการสตรีมแบบบล็อกอย่างชัดเจน OpenClaw จะข้ามสตรีมตัวอย่างเพื่อหลีกเลี่ยงการสตรีมซ้ำprogressเก็บฉบับร่างสถานะที่แก้ไขได้หนึ่งรายการไว้จนกว่าจะส่งผลลัพธ์สุดท้าย โดยค่าเริ่มต้นจะแสดงหนึ่งบรรทัดจากคำนำหรือคำบรรยายล่าสุดของเอเจนต์ โดยไม่มีป้ายกำกับที่สร้างขึ้น ช่องว่าง หรือแถวเครื่องมือ- ผลลัพธ์สุดท้ายที่เป็นสื่อ ข้อผิดพลาด และการตอบกลับที่ระบุอย่างชัดเจนจะยกเลิกการแก้ไขตัวอย่างที่รอดำเนินการ
streaming.preview.toolProgressมีค่าเริ่มต้นเป็นtrueในโหมดpartial/blockโหมดความคืบหน้าของ Discord มีค่าเริ่มต้นไม่แสดงแถวเครื่องมือ ให้ตั้งค่าstreaming.progress.toolProgress: trueเพื่อเลือกเปิดใช้- ตั้งค่า
streaming.progress.toolProgress: trueเพื่อเพิ่มแถวเครื่องมือ/ความคืบหน้าแบบกระชับ เช่น🛠️ Bash: run testsหรือ🔎 Web Search: for "query"เพื่อความเข้ากันได้ การกำหนดค่าprogress.labelหรือprogress.labelsที่มีอยู่จะยังคงใช้ค่าเริ่มต้นของแถวเครื่องมือก่อนหน้า ตั้งค่าtoolProgress: falseเพื่อใช้ป้ายกำกับแบบกำหนดเองโดยไม่มีแถว streaming.progress.commentary(ค่าเริ่มต้นfalse) เลือกเปิดใช้คำอธิบายดิบของผู้ช่วยในฉบับร่างความคืบหน้าชั่วคราว บรรทัดสถานะคำนำ/คำบรรยายเริ่มต้นไม่ขึ้นกับตัวเลือกนี้ คำอธิบายจะถูกล้างก่อนแสดงผล ยังคงเป็นข้อมูลชั่วคราว และไม่เปลี่ยนแปลงการส่งคำตอบสุดท้ายstreaming.progress.maxLineCharsควบคุมงบประมาณตัวอย่างความคืบหน้าต่อบรรทัด ร้อยแก้วจะถูกย่อที่ขอบเขตคำ ส่วนรายละเอียดคำสั่งและพาธจะเก็บส่วนท้ายที่เป็นประโยชน์ไว้streaming.preview.commandText/streaming.progress.commandTextควบคุมรายละเอียดคำสั่ง/การดำเนินการในบรรทัดความคืบหน้าแบบกระชับ:raw(ค่าเริ่มต้น) หรือstatus(เฉพาะป้ายกำกับเครื่องมือ)
ซ่อนข้อความคำสั่ง/การดำเนินการดิบโดยยังคงแสดงบรรทัดความคืบหน้าแบบกระชับ:
{ "channels": { "discord": { "streaming": { "mode": "progress", "progress": { "toolProgress": true, "commandText": "status" } } } }}การสตรีมตัวอย่างรองรับเฉพาะข้อความ การตอบกลับที่มีสื่อจะกลับไปใช้การส่งตามปกติ
ประวัติ บริบท และลักษณะการทำงานของเธรด
บริบทประวัติของกิลด์:
channels.discord.historyLimitค่าเริ่มต้น20- ค่าทดแทน:
messages.groupChat.historyLimit 0ปิดใช้งาน
การควบคุมประวัติ DM:
channels.discord.dmHistoryLimitchannels.discord.dms["<user_id>"].historyLimit
ลักษณะการทำงานของเธรด:
- เธรด Discord จะกำหนดเส้นทางเป็นเซสชันช่องและรับช่วงการกำหนดค่าจากช่องแม่ เว้นแต่จะมีการกำหนดค่าทับ
- เซสชันเธรดจะรับช่วงการเลือก
/modelระดับเซสชันของช่องแม่เป็นค่าทดแทนเฉพาะโมเดล การเลือก/modelภายในเธรดมีลำดับความสำคัญสูงกว่า และจะไม่คัดลอกประวัติบันทึกการสนทนาของช่องแม่ เว้นแต่จะเปิดใช้งานการรับช่วงบันทึกการสนทนา channels.discord.thread.inheritParent(ค่าเริ่มต้นfalse) เลือกให้เธรดใหม่ที่สร้างอัตโนมัติเริ่มต้นจากบันทึกการสนทนาของช่องแม่ การกำหนดค่าทับต่อบัญชี:channels.discord.accounts.<id>.thread.inheritParent- รีแอ็กชันจากเครื่องมือข้อความสามารถแก้ไขเป้าหมาย DM
user:<id>ได้ guilds.<guild>.channels.<channel>.requireMention: falseจะถูกเก็บรักษาไว้ระหว่างการใช้ค่าทดแทนเพื่อเปิดใช้งานขั้นตอนการตอบกลับ
หัวข้อช่องจะถูกแทรกเป็นบริบทที่ ไม่น่าเชื่อถือ รายการอนุญาตจะควบคุมว่าใครสามารถทริกเกอร์เอเจนต์ได้ แต่ไม่ใช่ขอบเขตการปกปิดบริบทเสริมทั้งหมด
เซสชันที่ผูกกับเธรดสำหรับเอเจนต์ย่อย
Discord สามารถผูกเธรดเข้ากับเป้าหมายเซสชัน เพื่อให้ข้อความติดตามผลในเธรดนั้นยังคงกำหนดเส้นทางไปยังเซสชันเดิม (รวมถึงเซสชันของเอเจนต์ย่อย)
คำสั่ง:
/focus <target>ผูกเธรดปัจจุบัน/เธรดใหม่เข้ากับเป้าหมายเอเจนต์ย่อย/เซสชัน/unfocusนำการผูกเธรดปัจจุบันออก/agentsแสดงการทำงานที่กำลังใช้งานและสถานะการผูก/session idle <duration|off>ตรวจสอบ/อัปเดตการยกเลิกโฟกัสอัตโนมัติเมื่อไม่มีการใช้งานสำหรับการผูกที่โฟกัสอยู่/session max-age <duration|off>ตรวจสอบ/อัปเดตอายุสูงสุดแบบตายตัวสำหรับการผูกที่โฟกัสอยู่
การกำหนดค่า:
{session: {threadBindings: { enabled: true, idleHours: 24, maxAgeHours: 0,},},channels: {discord: { threadBindings: { enabled: true, idleHours: 24, maxAgeHours: 0, spawnSessions: true, defaultSpawnContext: "fork", },},},}หมายเหตุ:
session.threadBindings.*ตั้งค่าเริ่มต้นส่วนกลาง ส่วนchannels.discord.threadBindings.*กำหนดค่าทับลักษณะการทำงานของ DiscordspawnSessionsควบคุมการสร้าง/ผูกเธรดอัตโนมัติสำหรับsessions_spawn({ thread: true })และการสร้างเธรด ACP ค่าเริ่มต้น:truedefaultSpawnContextควบคุมบริบทเอเจนต์ย่อยแบบเนทีฟสำหรับการสร้างที่ผูกกับเธรด ค่าเริ่มต้น:"fork"- คีย์
spawnSubagentSessions/spawnAcpSessionsที่เลิกใช้แล้วจะถูกย้ายข้อมูลโดยopenclaw doctor --fix - หากปิดใช้งานการผูกเธรดสำหรับบัญชี
/focusและการดำเนินการผูกเธรดที่เกี่ยวข้องจะไม่พร้อมใช้งาน
ความคืบหน้าของเอเจนต์ย่อยบนข้อความต้นทาง
ตั้งค่า channels.discord.subagentProgress: true เพื่อแสดงกิจกรรมของลูกที่ทำงานอยู่เบื้องหลังบนข้อความ Discord ที่เริ่มการทำงานของแม่
{channels: {discord: { subagentProgress: true,},},}ขณะที่การทำงานของลูกยังใช้งานอยู่ OpenClaw จะคงสถานะกำลังพิมพ์ของ Discord ไว้นานสูงสุดหนึ่งชั่วโมง และแทนที่รีแอ็กชันแสดงจำนวนหนึ่งรายการ (1️⃣ ถึง 🔟) เมื่อจำนวนการทำงานพร้อมกันเปลี่ยนแปลง โดย 🔟 ยังใช้แทนจำนวน 10 ขึ้นไปด้วย รีแอ็กชันแสดงจำนวนจะถูกนำออกหลังจากลูกตัวสุดท้ายสิ้นสุดลง ลูกที่ล้มเหลว หมดเวลา หรือถูกยุติจะทิ้งรีแอ็กชัน 🔴 ไว้
ฟีเจอร์นี้ต้องเลือกเปิดใช้และใช้ค่าเวลาและอีโมจิเริ่มต้นภายในแบบคงที่ บอตต้องมีสิทธิ์ Add Reactions เพื่อแสดงผลตอบกลับด้วยรีแอ็กชัน channels.discord.accounts.<id>.subagentProgress ระดับบัญชีจะกำหนดค่าทับค่าระดับบนสุด
การผูกช่อง ACP แบบถาวร
สำหรับพื้นที่ทำงาน ACP แบบ "เปิดตลอดเวลา" ที่เสถียร ให้กำหนดค่าการผูก ACP แบบระบุชนิดระดับบนสุดซึ่งกำหนดเป้าหมายไปยังการสนทนาใน Discord
พาธการกำหนดค่า: bindings[] พร้อม type: "acp" และ match.channel: "discord"
{agents: {list: [ { id: "codex", runtime: { type: "acp", acp: { agent: "codex", backend: "acpx", mode: "persistent", cwd: "/workspace/openclaw", }, }, },],},bindings: [{ type: "acp", agentId: "codex", match: { channel: "discord", accountId: "default", peer: { kind: "channel", id: "222222222222222222" }, }, acp: { label: "codex-main" },},],channels: {discord: { guilds: { "111111111111111111": { channels: { "222222222222222222": { requireMention: false, }, }, }, },},},}หมายเหตุ:
/acp spawn codex --bind hereผูกช่องหรือเธรดปัจจุบันไว้กับที่ และเก็บข้อความในอนาคตไว้ในเซสชัน ACP เดิม ข้อความในเธรดจะรับช่วงการผูกจากช่องแม่- ในช่องหรือเธรดที่ผูกไว้
/newและ/resetจะรีเซ็ตเซสชัน ACP เดิมไว้กับที่ การผูกเธรดชั่วคราวสามารถกำหนดค่าทับการแก้ไขเป้าหมายได้ขณะที่ยังใช้งานอยู่ spawnSessionsควบคุมการสร้าง/ผูกเธรดลูกผ่าน--thread auto|here
ดูรายละเอียดลักษณะการทำงานของการผูกได้ที่ เอเจนต์ ACP
การแจ้งเตือนรีแอ็กชัน
โหมดการแจ้งเตือนรีแอ็กชันต่อกิลด์ (guilds.<id>.reactionNotifications):
offown(ค่าเริ่มต้น)allallowlist(ใช้guilds.<id>.users)
เหตุการณ์รีแอ็กชันจะถูกแปลงเป็นเหตุการณ์ระบบและแนบกับเซสชัน Discord ที่ได้รับการกำหนดเส้นทาง
เหตุการณ์สถานะออนไลน์
เลือกให้กิลด์ปลุกเอเจนต์ตามเส้นทางเมื่อสมาชิกที่เป็นมนุษย์เปลี่ยนสถานะจากออฟไลน์เป็นออนไลน์:
{ channels: { discord: { intents: { presence: true }, guilds: { "111111111111111111": { presenceEvents: { channelId: "222222222222222222", users: ["333333333333333333"], // ไม่บังคับ; จำกัดผู้ชมช่องให้แคบลงอีก reconnectSuppressSeconds: 300, // ไม่บังคับ; ช่วงเงียบของเซสชันใหม่ (0 ปิดใช้งาน) burstLimit: 8, // ไม่บังคับ; จำนวนเหตุการณ์สูงสุดต่อช่วงเหตุการณ์ต่อเนื่อง burstWindowSeconds: 60, // ไม่บังคับ; หน้าต่างเลื่อนสำหรับตรวจจับเหตุการณ์ต่อเนื่อง }, }, }, }, },}presenceEvents ต้องเปิดใช้งาน Heartbeat สำหรับเอเจนต์ที่รับการกำหนดเส้นทาง และเปิดสิทธิ์พิเศษ Presence Intent ในหน้า Bot ของแอปพลิเคชันบน Discord Developer Portal OpenClaw จะตั้งต้นข้อมูลสมาชิกที่ออนไลน์อยู่ในปัจจุบันจากสแนปช็อต GUILD_CREATE ที่สมบูรณ์แต่ละรายการ กำหนดเส้นทางการเปลี่ยนสถานะจากออฟไลน์เป็นออนไลน์ที่ตรวจพบ และถือว่าสัญญาณออนไลน์ครั้งแรกในภายหลังของสมาชิกที่ยังไม่เคยพบเป็นการพร้อมใช้งานใหม่ด้วย สมาชิกดังกล่าวอาจเพิ่งออนไลน์หรือเข้าร่วมหลังจากสแนปช็อต ดังนั้นเหตุการณ์จึงไม่ได้ยืนยันสถานะก่อนหน้าที่แน่นอน เฉพาะผู้ใช้ที่เป็นมนุษย์และสามารถดู channelId เท่านั้นที่มีสิทธิ์: ช่องและเธรดสาธารณะต้องมี View Channel ในช่องหรือช่องแม่ ส่วนเธรดส่วนตัวยังต้องเป็นสมาชิกหรือมี Manage Threads เพิ่มเติม users สามารถจำกัดกลุ่มผู้ชมนี้ให้แคบลงอีก OpenClaw จะไม่สนใจบอตและสถานะออนไลน์ที่ไม่เปลี่ยนแปลง และคงช่วงพักต่อผู้ใช้เป็นเวลาแปดชั่วโมงไว้แม้ Gateway รีสตาร์ต เมื่อ Discord สร้างเซสชัน Gateway ใหม่และส่ง READY OpenClaw จะระงับเหตุการณ์ที่มาจากสถานะการแสดงตนเป็นเวลา reconnectSuppressSeconds (ค่าเริ่มต้น 300 โดย 0 จะปิดใช้งาน) ระหว่างสร้างสถานะการแสดงตนของกิลด์ใหม่ เพื่อไม่ให้สมาชิกที่ตรวจพบซ้ำปลุกเอเจนต์ทีละคน นอกจากนี้ ยังจำกัดอัตราเหตุการณ์ที่เข้าคิวสำเร็จต่อกิลด์ไว้ที่ burstLimit เหตุการณ์ (ค่าเริ่มต้น 8) ต่อหน้าต่างเลื่อน burstWindowSeconds (ค่าเริ่มต้น 60) โดยบันทึกแต่ละช่วงการระงับของกิลด์ลงในบันทึกเพียงครั้งเดียว เซสชันที่กลับมาทำงานต่อจะไม่ถือเป็นเซสชันใหม่ Discord จำกัดสแนปช็อตสำหรับกิลด์ที่มีสมาชิกมากกว่า 75,000 คน ในกรณีดังกล่าว OpenClaw ต้องได้รับการอัปเดตสถานะออฟไลน์อย่างชัดเจนก่อนส่งคำทักทาย เหตุการณ์ของระบบจะมี ID ผู้ใช้ กิลด์ และช่องที่เปลี่ยนแปลงไม่ได้ โดยไม่ฝังชื่อที่แสดงซึ่งเปลี่ยนแปลงได้ เอเจนต์เป็นผู้ตัดสินใจว่าจะทักทายหรือไม่และอย่างไร
รีแอ็กชันตอบรับ
ackReaction จะส่งอีโมจิตอบรับระหว่างที่ OpenClaw ประมวลผลข้อความขาเข้า
ลำดับการตัดสินค่า:
channels.discord.accounts.<accountId>.ackReactionchannels.discord.ackReactionmessages.ackReaction- ใช้อีโมจิประจำตัวเอเจนต์เป็นค่าทดแทน (
agents.list[].identity.emojiมิฉะนั้นใช้ "👀")
หมายเหตุ:
- Discord รองรับอีโมจิ Unicode หรือชื่ออีโมจิแบบกำหนดเอง
- ใช้
""เพื่อปิดใช้งานรีแอ็กชันสำหรับช่องหรือบัญชี
ขอบเขต (messages.ackReactionScope):
ค่า: "all" (DM + กลุ่ม รวมถึงเหตุการณ์ห้องแบบแวดล้อม), "direct" (เฉพาะ DM), "group-all" (ทุกข้อความกลุ่มยกเว้นเหตุการณ์ห้องแบบแวดล้อม และไม่รวม DM), "group-mentions" (กลุ่มเมื่อมีการกล่าวถึงบอต; ไม่รวม DM และเป็นค่าเริ่มต้น), "off" / "none" (ปิดใช้งาน)
การเขียนการกำหนดค่า
การเขียนการกำหนดค่าที่เริ่มต้นจากช่องจะเปิดใช้งานโดยค่าเริ่มต้น การตั้งค่านี้ส่งผลต่อขั้นตอน /config set|unset (เมื่อเปิดใช้งานคุณสมบัติคำสั่ง)
ปิดใช้งาน:
{channels: {discord: { configWrites: false,},},}พร็อกซี Gateway
กำหนดเส้นทางทราฟฟิก WebSocket ของ Gateway Discord และการค้นหาผ่าน REST ตอนเริ่มต้น (ID แอปพลิเคชัน + การแปลงรายการอนุญาต) ผ่านพร็อกซี HTTP(S) ด้วย channels.discord.proxy
การใช้พร็อกซีกับ WebSocket ของ Gateway Discord ต้องกำหนดอย่างชัดเจน การเชื่อมต่อ WebSocket จะไม่สืบทอดตัวแปรสภาพแวดล้อมพร็อกซีโดยรอบจากกระบวนการ Gateway การค้นหาผ่าน REST ตอนเริ่มต้นจะใช้พร็อกซีนี้เมื่อกำหนดค่า channels.discord.proxy
{channels: {discord: { proxy: "http://proxy.example:8080",},},}การแทนค่าระดับบัญชี:
{channels: {discord: { accounts: { primary: { proxy: "http://proxy.example:8080", }, },},},}การรองรับ PluralKit
เปิดใช้งานการแปลงค่า PluralKit เพื่อจับคู่ข้อความที่ส่งผ่านพร็อกซีกับข้อมูลประจำตัวของสมาชิกในระบบ:
{channels: {discord: { pluralkit: { enabled: true, token: "pk_live_...", // ไม่บังคับ; จำเป็นสำหรับระบบส่วนตัว },},},}หมายเหตุ:
- รายการอนุญาตสามารถใช้
pk:<memberId> - ชื่อที่แสดงของสมาชิกจะจับคู่ด้วยชื่อ/slug เฉพาะเมื่อ
channels.discord.dangerouslyAllowNameMatching: true - การค้นหาจะเรียกใช้ API ของ PluralKit ด้วย ID ข้อความต้นฉบับ
- หากการค้นหาล้มเหลว ข้อความที่ส่งผ่านพร็อกซีจะถือเป็นข้อความจากบอตและถูกละทิ้ง เว้นแต่
allowBotsจะอนุญาตให้ผ่าน
นามแฝงการกล่าวถึงขาออก
ใช้ mentionAliases เมื่อเอเจนต์ต้องการการกล่าวถึงขาออกที่กำหนดผลลัพธ์ได้แน่นอนสำหรับผู้ใช้ Discord ที่รู้จัก คีย์คือแฮนเดิลที่ไม่มี @ นำหน้า ส่วนค่าคือ ID ผู้ใช้ Discord แฮนเดิลที่ไม่รู้จัก, @everyone, @here และการกล่าวถึงภายในช่วงโค้ด Markdown จะคงไว้โดยไม่เปลี่ยนแปลง
{channels: {discord: { mentionAliases: { SupportLead: "123456789012345678", }, accounts: { ops: { mentionAliases: { OpsLead: "234567890123456789", }, }, },},},}การกำหนดค่าสถานะการแสดงตน
ระบบจะใช้การอัปเดตสถานะการแสดงตนเมื่อกำหนดฟิลด์สถานะหรือกิจกรรม หรือเมื่อเปิดใช้งานสถานะการแสดงตนอัตโนมัติ
เฉพาะสถานะ:
{channels: {discord: { status: "idle",},},}กิจกรรม (สถานะแบบกำหนดเองเป็นประเภทกิจกรรมเริ่มต้นเมื่อตั้งค่า activity):
{channels: {discord: { activity: "ช่วงเวลาใช้สมาธิ", activityType: 4,},},}การสตรีม:
{channels: {discord: { activity: "เขียนโค้ดสด", activityType: 1, activityUrl: "https://twitch.tv/openclaw",},},}ตารางจับคู่ประเภทกิจกรรม:
- 0: กำลังเล่น
- 1: กำลังสตรีม (ต้องมี
activityUrl; และactivityUrlต้องมีactivityType: 1) - 2: กำลังฟัง
- 3: กำลังรับชม
- 4: กำหนดเอง (ใช้ข้อความกิจกรรมเป็นค่าสถานะ โดยไม่จำเป็นต้องมีอีโมจิ)
- 5: กำลังแข่งขัน
สถานะการแสดงตนอัตโนมัติ (สัญญาณสุขภาพของรันไทม์):
{channels: {discord: { autoPresence: { enabled: true, intervalMs: 30000, minUpdateIntervalMs: 15000, exhaustedText: "โทเค็นหมด", },},},}สถานะการแสดงตนอัตโนมัติจะจับคู่ความพร้อมใช้งานของรันไทม์กับสถานะ Discord: ปกติ => ออนไลน์, ประสิทธิภาพลดลงหรือไม่ทราบ => ไม่อยู่, ทรัพยากรหมดหรือไม่พร้อมใช้งาน => ห้ามรบกวน ค่าเริ่มต้น: intervalMs 30000, minUpdateIntervalMs 15000 (ต้องน้อยกว่าหรือเท่ากับ intervalMs) การแทนค่าข้อความที่ไม่บังคับ:
autoPresence.healthyTextautoPresence.degradedTextautoPresence.exhaustedText(รองรับตัวยึดตำแหน่ง{reason})
การอนุมัติใน Discord
Discord รองรับการจัดการการอนุมัติด้วยปุ่มใน DM และสามารถเลือกโพสต์ข้อความแจ้งการอนุมัติในช่องต้นทางได้
พาธการกำหนดค่า:
channels.discord.execApprovals.enabledchannels.discord.execApprovals.approvers(ไม่บังคับ; ใช้commands.ownerAllowFromเป็นค่าทดแทนเมื่อทำได้)channels.discord.execApprovals.target(dm|channel|both, ค่าเริ่มต้น:dm)agentFilter,sessionFilter,cleanupAfterResolve
Discord จะเปิดใช้งานการอนุมัติการดำเนินการแบบเนทีฟโดยอัตโนมัติเมื่อไม่ได้ตั้งค่า enabled หรือเป็น "auto" และสามารถแปลงค่าผู้อนุมัติได้อย่างน้อยหนึ่งคน ไม่ว่าจะจาก execApprovals.approvers หรือจาก commands.ownerAllowFrom Discord จะไม่อนุมานผู้อนุมัติการดำเนินการจาก allowFrom ของช่อง, dm.allowFrom แบบเดิม หรือ defaultTo ของข้อความโดยตรง ตั้งค่า enabled: false เพื่อปิดใช้งาน Discord ในฐานะไคลเอนต์การอนุมัติแบบเนทีฟอย่างชัดเจน
สำหรับคำสั่งกลุ่มที่ละเอียดอ่อนและจำกัดเฉพาะเจ้าของ เช่น /diagnostics และ /export-trajectory OpenClaw จะส่งข้อความแจ้งการอนุมัติและผลลัพธ์สุดท้ายแบบส่วนตัว โดยจะลองใช้ DM ของ Discord ก่อนเมื่อเจ้าของที่เรียกใช้มีเส้นทางเจ้าของใน Discord มิฉะนั้นจะใช้เส้นทางเจ้าของแรกที่พร้อมใช้งานจาก commands.ownerAllowFrom เป็นค่าทดแทน เช่น Telegram
เมื่อ target เป็น channel หรือ both ข้อความแจ้งการอนุมัติจะมองเห็นได้ในช่อง เฉพาะผู้อนุมัติที่แปลงค่าได้เท่านั้นที่ใช้ปุ่มได้ ผู้ใช้อื่นจะได้รับข้อความปฏิเสธแบบชั่วคราว ข้อความแจ้งการอนุมัติมีข้อความคำสั่งรวมอยู่ด้วย ดังนั้นควรเปิดใช้งานการส่งไปยังช่องเฉพาะในช่องที่เชื่อถือได้ หากไม่สามารถหา ID ช่องจากคีย์เซสชันได้ OpenClaw จะใช้การส่งผ่าน DM เป็นค่าทดแทน
Discord จะแสดงปุ่มอนุมัติร่วมที่ช่องแชตอื่นใช้ อะแดปเตอร์ Discord แบบเนทีฟมีหน้าที่หลักในการเพิ่มการกำหนดเส้นทาง DM ไปยังผู้อนุมัติและกระจายข้อความไปยังช่องต่าง ๆ เมื่อมีปุ่มเหล่านี้ ปุ่มจะเป็น UX หลักสำหรับการอนุมัติ OpenClaw ควรแสดงคำสั่ง /approve แบบดำเนินการด้วยตนเองเฉพาะเมื่อผลลัพธ์ของเครื่องมือระบุว่าไม่สามารถอนุมัติผ่านแชตได้ หรือการอนุมัติด้วยตนเองเป็นเส้นทางเดียว หากรันไทม์การอนุมัติแบบเนทีฟของ Discord ไม่ทำงาน OpenClaw จะคงข้อความแจ้ง /approve <id> <decision> แบบกำหนดผลลัพธ์ได้แน่นอนไว้ให้มองเห็น หากรันไทม์ทำงานอยู่แต่ไม่สามารถส่งการ์ดแบบเนทีฟไปยังเป้าหมายใดได้ OpenClaw จะส่งข้อความแจ้งทดแทนในแชตเดียวกัน พร้อมคำสั่ง /approve ที่ตรงกันจากการอนุมัติที่รอดำเนินการ
การยืนยันตัวตนของ Gateway และการแปลงค่าการอนุมัติเป็นไปตามสัญญาไคลเอนต์ Gateway ร่วม (ID plugin: แปลงค่าผ่าน plugin.approval.resolve; ID อื่นแปลงค่าผ่าน exec.approval.resolve) การอนุมัติจะหมดอายุหลังจาก 30 นาทีโดยค่าเริ่มต้น
เครื่องมือและเกตการดำเนินการ
การดำเนินการกับข้อความ Discord ครอบคลุมการรับส่งข้อความ การดูแลช่อง การควบคุมเนื้อหา สถานะการแสดงตน และข้อมูลเมตา
ตัวอย่างหลัก:
- การรับส่งข้อความ:
sendMessage,readMessages,editMessage,deleteMessage,threadReply - รีแอ็กชัน:
react,reactions,emojiList - การควบคุมเนื้อหา:
timeout,kick,ban - สถานะการแสดงตน:
setPresence
การดำเนินการ event-create รับพารามิเตอร์ image ที่ไม่บังคับ (URL หรือพาธไฟล์ภายในเครื่อง) เพื่อตั้งค่าภาพหน้าปกของกิจกรรมที่กำหนดเวลาไว้
เกตการดำเนินการอยู่ภายใต้ channels.discord.actions.*
ลักษณะการทำงานเริ่มต้นของเกต:
| กลุ่มการดำเนินการ | ค่าเริ่มต้น |
|---|---|
| reactions, messages, threads, pins, polls, search, memberInfo, roleInfo, channelInfo, channels, voiceStatus, events, stickers, emojiUploads, stickerUploads, permissions | เปิดใช้งาน |
| roles | ปิดใช้งาน |
| moderation | ปิดใช้งาน |
| presence | ปิดใช้งาน |
UI ของ Components v2
OpenClaw ใช้คอมโพเนนต์ v2 ของ Discord สำหรับการอนุมัติการดำเนินการและเครื่องหมายข้ามบริบท การดำเนินการกับข้อความ Discord ยังสามารถรับ components สำหรับ UI แบบกำหนดเองได้ (ขั้นสูง ต้องสร้างเพย์โหลดคอมโพเนนต์ผ่านเครื่องมือ discord) ขณะที่ embeds แบบเดิมยังคงใช้งานได้ แต่ไม่แนะนำ
channels.discord.ui.components.accentColorกำหนดสีเน้นที่คอนเทนเนอร์คอมโพเนนต์ของ Discord ใช้ (เลขฐานสิบหก) แยกตามบัญชี:channels.discord.accounts.<id>.ui.components.accentColorchannels.discord.agentComponents.ttlMsควบคุมระยะเวลาที่คอลแบ็กของคอมโพเนนต์ Discord ที่ส่งแล้วจะยังคงลงทะเบียนอยู่ (ค่าเริ่มต้น1800000, สูงสุด86400000) แยกตามบัญชี:channels.discord.accounts.<id>.agentComponents.ttlMsembedsจะถูกละเว้นเมื่อมีคอมโพเนนต์ v2- โดยค่าเริ่มต้น ระบบจะระงับตัวอย่าง URL แบบธรรมดา ตั้งค่า
suppressEmbeds: falseในการดำเนินการกับข้อความเมื่อต้องการให้ลิงก์ขาออกเพียงลิงก์เดียวแสดงตัวอย่างแบบขยาย
ตัวอย่าง:
{ channels: { discord: { ui: { components: { accentColor: "#5865F2", }, }, }, },}เสียง
Discord มีพื้นผิวเสียงสองแบบที่แตกต่างกัน ได้แก่ ช่องเสียง แบบเรียลไทม์ (การสนทนาต่อเนื่อง) และ ไฟล์แนบข้อความเสียง (รูปแบบตัวอย่างคลื่นเสียง) Gateway รองรับทั้งสองแบบ
ช่องเสียง
รายการตรวจสอบการตั้งค่า:
- เปิดใช้งาน Message Content Intent ใน Discord Developer Portal
- เปิดใช้งาน Server Members Intent เมื่อใช้รายการอนุญาตตามบทบาท/ผู้ใช้
- เชิญบอตโดยใช้ขอบเขต
botและapplications.commands - ให้สิทธิ์ Connect, Speak, Send Messages และ Read Message History ในช่องเสียงเป้าหมาย
- เปิดใช้งานคำสั่งเนทีฟ (
commands.nativeหรือchannels.discord.commands.native) - กำหนดค่า
channels.discord.voice
ใช้ /vc join|leave|status เพื่อควบคุมเซสชัน คำสั่งนี้ใช้เอเจนต์เริ่มต้นของบัญชีและปฏิบัติตามกฎรายการอนุญาตและนโยบายกลุ่มเดียวกับคำสั่ง Discord อื่นๆ
/vc join channel:<voice-channel-id>/vc status/vc leaveหากต้องการตรวจสอบสิทธิ์ที่มีผลจริงของบอตก่อนเข้าร่วม:
openclaw channels capabilities --channel discord --target channel:<voice-channel-id>ตัวอย่างการเข้าร่วมอัตโนมัติ:
{ channels: { discord: { voice: { enabled: true, model: "openai/gpt-5.6-sol", autoJoin: [ { guildId: "123456789012345678", channelId: "234567890123456789", }, ], allowedChannels: [ { guildId: "123456789012345678", channelId: "234567890123456789", }, ], daveEncryption: true, decryptionFailureTolerance: 24, connectTimeoutMs: 30000, reconnectGraceMs: 15000, realtime: { provider: "openai", model: "gpt-realtime-2.1", speakerVoice: "cedar", }, }, }, },}หมายเหตุ:
- เสียง Discord เป็นแบบเลือกเปิดใช้สำหรับการกำหนดค่าที่รองรับเฉพาะข้อความ ให้ตั้งค่า
channels.discord.voice.enabled=true(หรือคงบล็อกchannels.discord.voiceที่มีอยู่ไว้) เพื่อเปิดใช้คำสั่ง/vcรันไทม์เสียง และ gateway intentGuildVoiceStatesโดยchannels.discord.intents.voiceStatesสามารถเขียนทับการสมัครรับ intent อย่างชัดเจนได้ หากไม่ตั้งค่า ระบบจะทำตามสถานะการเปิดใช้เสียงที่มีผล voice.modeควบคุมเส้นทางการสนทนา ค่าเริ่มต้นคือagent-proxy: ส่วนหน้าสำหรับเสียงแบบเรียลไทม์จัดการจังหวะการผลัดกันพูด การขัดจังหวะ และการเล่นเสียง มอบหมายงานที่มีสาระให้เอเจนต์ OpenClaw ที่กำหนดเส้นทางไว้ผ่านopenclaw_agent_consultและถือว่าผลลัพธ์เป็นพรอมต์ Discord แบบพิมพ์จากผู้พูดคนนั้น ส่วนstt-ttsจะคงโฟลว์ STT แบบแบตช์ร่วมกับ TTS รุ่นเก่าไว้ และbidiช่วยให้โมเดลเรียลไทม์สนทนาได้โดยตรง พร้อมเปิดให้ใช้openclaw_agent_consultสำหรับสมอง OpenClawvoice.agentSessionควบคุมว่าการสนทนา OpenClaw ใดจะรับช่วงการพูดผ่านเสียง หากไม่ตั้งค่า จะใช้เซสชันของช่องเสียงเอง หรือตั้งเป็น{ mode: "target", target: "channel:<text-channel-id>" }เพื่อให้ช่องเสียงทำหน้าที่เป็นส่วนขยายไมโครโฟน/ลำโพงของเซสชันช่องข้อความ Discord ที่มีอยู่ เช่น#maintainersvoice.modelเขียนทับสมองเอเจนต์ OpenClaw สำหรับการตอบกลับด้วยเสียงใน Discord และการปรึกษาแบบเรียลไทม์ หากไม่ตั้งค่า จะสืบทอดโมเดลเอเจนต์ที่กำหนดเส้นทางไว้ ค่านี้แยกจากvoice.realtime.modelvoice.followUsersช่วยให้บอทเข้าร่วม ย้าย และออกจากเสียง Discord ตามผู้ใช้ที่เลือก ดู ติดตามผู้ใช้ในช่องเสียงagent-proxyกำหนดเส้นทางเสียงพูดผ่านdiscord-voiceซึ่งคงการตรวจสอบสิทธิ์ของเจ้าของ/เครื่องมือตามปกติสำหรับผู้พูดและเซสชันเป้าหมาย แต่ซ่อนเครื่องมือttsของเอเจนต์ เนื่องจากเสียง Discord เป็นผู้ควบคุมการเล่นเสียง ตามค่าเริ่มต้นagent-proxyจะให้สิทธิ์เข้าถึงเครื่องมือแก่การปรึกษาเทียบเท่าเจ้าของอย่างสมบูรณ์สำหรับผู้พูดที่เป็นเจ้าของ (voice.realtime.toolPolicy: "owner") และให้ความสำคัญอย่างมากกับการปรึกษาเอเจนต์ OpenClaw ก่อนตอบคำถามที่มีสาระ (voice.realtime.consultPolicy: "always") ในโหมดalwaysเริ่มต้นนี้ เลเยอร์เรียลไทม์จะไม่พูดถ้อยคำคั่นเวลาโดยอัตโนมัติก่อนคำตอบจากการปรึกษา แต่จะบันทึกและถอดเสียงคำพูด จากนั้นจึงพูดคำตอบจาก OpenClaw ที่กำหนดเส้นทางไว้ หากคำตอบจากการปรึกษาแบบบังคับหลายรายการเสร็จสิ้นในขณะที่ Discord ยังคงเล่นคำตอบแรก คำตอบแบบข้อความตรงตัวรายการหลังจะเข้าคิวจนกว่าการเล่นเสียงจะว่าง แทนที่จะแทนที่เสียงพูดกลางประโยค- ในโหมด
stt-ttsSTT ใช้tools.media.audio;voice.modelไม่มีผลต่อการถอดเสียง - ในโหมดเรียลไทม์
voice.realtime.provider,voice.realtime.modelและvoice.realtime.speakerVoiceใช้กำหนดค่าเซสชันเสียงเรียลไทม์ สำหรับ OpenAI Realtime 2.1 ร่วมกับสมอง Codex ให้ใช้voice.realtime.model: "gpt-realtime-2.1"และvoice.model: "openai/gpt-5.6-sol" - ตามค่าเริ่มต้น โหมดเสียงเรียลไทม์จะรวมไฟล์โปรไฟล์ขนาดเล็ก
IDENTITY.md,USER.mdและSOUL.mdไว้ในคำสั่งสำหรับผู้ให้บริการเรียลไทม์ เพื่อให้ช่วงการสนทนาโดยตรงที่รวดเร็วยังคงใช้อัตลักษณ์ การยึดโยงกับผู้ใช้ และบุคลิกเดียวกับเอเจนต์ OpenClaw ที่กำหนดเส้นทางไว้ ตั้งค่าvoice.realtime.bootstrapContextFilesเป็นชุดย่อยเพื่อปรับแต่ง หรือใช้[]เพื่อปิดใช้ รองรับเฉพาะไฟล์โปรไฟล์เหล่านั้น ส่วนAGENTS.mdจะยังคงอยู่ในบริบทเอเจนต์ตามปกติ บริบทโปรไฟล์ที่แทรกเข้ามาไม่สามารถใช้แทนopenclaw_agent_consultสำหรับงานในพื้นที่ทำงาน ข้อเท็จจริงปัจจุบัน การค้นหาหน่วยความจำ หรือการดำเนินการที่มีเครื่องมือรองรับ - ในโหมดเรียลไทม์
agent-proxyของ OpenAI การควบคุมด้วยชื่อเรียกปลุกจะปรับตามห้องโดยอัตโนมัติเป็นค่าเริ่มต้น กล่าวคือ เมื่อมีมนุษย์หนึ่งคนจะพูดได้อย่างเป็นธรรมชาติโดยไม่ต้องใช้ชื่อเรียกปลุก แต่เมื่อมีมนุษย์ตั้งแต่สองคนขึ้นไป ต้องเริ่มต้นหรือจบช่วงการพูดด้วยชื่อเรียกปลุกหนึ่งชื่อ บอทอื่นจะไม่ถูกนับเป็นคน ตั้งค่าvoice.realtime.requireWakeName: trueให้ต้องใช้ชื่อเรียกปลุกเสมอ หรือfalseเพื่อไม่ต้องใช้เลย ชื่อเรียกปลุกที่กำหนดค่าต้องมีหนึ่งหรือสองคำ หากไม่ได้ตั้งค่าvoice.realtime.wakeNamesOpenClaw จะใช้nameของเอเจนต์ที่กำหนดเส้นทางไว้ร่วมกับOpenClawและหากใช้ไม่ได้จะใช้รหัสเอเจนต์ร่วมกับOpenClawเมื่อการควบคุมด้วยชื่อเรียกปลุกทำงาน ระบบจะปิดการตอบกลับอัตโนมัติของผู้ให้บริการเรียลไทม์ กำหนดเส้นทางช่วงการพูดที่ยอมรับผ่านเส้นทางการปรึกษาเอเจนต์ OpenClaw และพูดคำตอบรับสั้นๆ เมื่อระบบตรวจพบชื่อเรียกปลุกที่ต้นข้อความจากการถอดเสียงบางส่วน ก่อนที่ข้อความถอดเสียงฉบับสมบูรณ์จะมาถึง นโยบายจะปรับตามการเข้าร่วมและออกจากห้องแบบสดโดยไม่ต้องเชื่อมต่อเสียงใหม่ - ผู้ให้บริการเรียลไทม์ของ OpenAI ยอมรับชื่อเหตุการณ์ Realtime 2 ปัจจุบันและนามแฝงเดิมที่เข้ากันได้กับ Codex สำหรับเหตุการณ์เสียงเอาต์พุตและข้อความถอดเสียง ดังนั้นสแนปช็อตผู้ให้บริการที่เข้ากันได้จึงเปลี่ยนแปลงคลาดเคลื่อนได้โดยไม่ทำให้เสียงของผู้ช่วยสูญหาย
voice.realtime.bargeInควบคุมว่าเหตุการณ์เริ่มพูดของผู้พูดใน Discord จะขัดจังหวะการเล่นเสียงเรียลไทม์ที่กำลังทำงานหรือไม่ หากไม่ตั้งค่า จะเป็นไปตามการตั้งค่าการขัดจังหวะด้วยเสียงอินพุตของผู้ให้บริการเรียลไทม์voice.realtime.minBargeInAudioEndMsควบคุมระยะเวลาขั้นต่ำที่เสียงผู้ช่วยต้องเล่น ก่อนที่การแทรกพูดในโหมดเรียลไทม์ของ OpenAI จะตัดเสียง ค่าเริ่มต้น:250ตั้งค่า0เพื่อขัดจังหวะทันทีในห้องที่มีเสียงสะท้อนต่ำ หรือเพิ่มค่านี้สำหรับการตั้งค่าลำโพงที่มีเสียงสะท้อนมากvoice.ttsเขียนทับmessages.ttsเฉพาะสำหรับการเล่นเสียงstt-tts; โหมดเรียลไทม์จะใช้voice.realtime.speakerVoiceแทน สำหรับเสียง OpenAI ในการเล่นผ่าน Discord ให้ตั้งค่าvoice.tts.provider: "openai"และเลือกเสียง Text-to-speech ภายใต้voice.tts.providers.openai.speakerVoiceโดยcedarเป็นตัวเลือกที่ดีซึ่งให้เสียงโทนผู้ชายบนโมเดล TTS ปัจจุบันของ OpenAI- การเขียนทับ
systemPromptของ Discord รายช่องจะมีผลกับช่วงข้อความถอดเสียงสำหรับช่องเสียงนั้น - เมื่อ OpenClaw เข้าร่วมช่องเสียง เซสชันเอเจนต์ที่กำหนดเส้นทางไว้จะได้รับเหตุการณ์ระบบแบบเงียบพร้อมรายชื่อผู้เข้าร่วมปัจจุบัน การเข้าร่วมและออกของผู้เข้าร่วมในภายหลังจะอัปเดตเซสชันนั้นโดยไม่เรียกให้เกิดการตอบกลับด้วยเสียงที่ไม่ได้ร้องขอ และชื่อที่แสดงใน Discord จะถือเป็นป้ายกำกับที่ไม่น่าเชื่อถือ ช่วงการพูดผ่านเสียงที่ได้รับอนุญาตจะได้รับสแนปช็อตรายชื่อผู้เข้าร่วมล่าสุดด้วย
- ช่วงข้อความถอดเสียงและคำสั่ง
/vcใช้รายการ Discord ในcommands.ownerAllowFromเพื่อกำหนดสถานะเจ้าของ เมื่อไม่ได้กำหนดเจ้าของคำสั่ง Discord ค่าallowFrom(หรือdm.allowFromแบบเดิม) ของบัญชี Discord ที่เลือกยังสามารถอนุญาตการเข้าถึงเสียงได้โดยไม่ให้สถานะเจ้าของ การมองเห็นเครื่องมือของเอเจนต์เป็นไปตามนโยบายเครื่องมือที่กำหนดค่าสำหรับเซสชันที่กำหนดเส้นทางไว้ - หาก
voice.autoJoinมีหลายรายการสำหรับกิลด์เดียวกัน OpenClaw จะเข้าร่วมช่องสุดท้ายที่กำหนดค่าไว้สำหรับกิลด์นั้น voice.allowedChannelsเป็นรายการอนุญาตสำหรับการคงอยู่ที่ไม่บังคับ หากไม่ตั้งค่า จะอนุญาตให้/vc joinเข้าสู่ช่องเสียง Discord ใดๆ ที่ได้รับอนุญาต เมื่อตั้งค่าแล้ว/vc joinการเข้าร่วมอัตโนมัติเมื่อเริ่มต้น และการย้ายสถานะเสียงของบอทจะถูกจำกัดไว้เฉพาะรายการ{ guildId, channelId }ที่ระบุ ตั้งค่าเป็นอาร์เรย์ว่างเพื่อปฏิเสธการเข้าร่วมเสียง Discord ทั้งหมด หาก Discord ย้ายบอทออกนอกรายการอนุญาต OpenClaw จะออกจากช่องนั้นและกลับเข้าร่วมเป้าหมายการเข้าร่วมอัตโนมัติที่กำหนดค่าไว้ หากมีเป้าหมายดังกล่าวvoice.daveEncryptionและvoice.decryptionFailureToleranceจะถูกส่งผ่านไปยังตัวเลือกการเข้าร่วมของ@discordjs/voice; ค่าเริ่มต้นจากต้นทางคือdaveEncryption=trueและdecryptionFailureTolerance=24- OpenClaw ใช้ตัวแปลงสัญญาณ
libopus-wasmที่รวมมาให้สำหรับการรับเสียง Discord และการเล่น PCM ดิบแบบเรียลไทม์ โดยมาพร้อมบิลด์ WebAssembly ของ libopus ที่ตรึงเวอร์ชันไว้ และไม่ต้องใช้ส่วนเสริม opus แบบเนทีฟ voice.connectTimeoutMsควบคุมการรอ Ready ครั้งแรกของ@discordjs/voiceสำหรับ/vc joinและความพยายามเข้าร่วมอัตโนมัติ ค่าเริ่มต้น:30000voice.reconnectGraceMsควบคุมระยะเวลาที่ OpenClaw รอให้เซสชันเสียงที่ตัดการเชื่อมต่อเริ่มเชื่อมต่อใหม่ก่อนทำลายเซสชัน ค่าเริ่มต้น:15000- ในโหมด
stt-ttsการเล่นเสียงจะไม่หยุดเพียงเพราะผู้ใช้อื่นเริ่มพูด เพื่อหลีกเลี่ยงวงจรป้อนกลับ OpenClaw จะไม่รับเสียงใหม่ขณะที่ TTS กำลังเล่น โปรดพูดหลังการเล่นเสียงเสร็จสิ้นสำหรับช่วงถัดไป โหมดเรียลไทม์จะส่งต่อการเริ่มพูดของผู้พูดเป็นสัญญาณแทรกพูดไปยังผู้ให้บริการเรียลไทม์ - ในโหมดเรียลไทม์ เสียงสะท้อนจากลำโพงที่เข้าสู่ไมโครโฟนซึ่งเปิดอยู่ อาจดูเหมือนการแทรกพูดและขัดจังหวะการเล่นเสียง สำหรับห้อง Discord ที่มีเสียงสะท้อนมาก ให้ตั้งค่า
voice.realtime.providers.openai.interruptResponseOnInputAudio: falseเพื่อป้องกันไม่ให้ OpenAI ขัดจังหวะอัตโนมัติเมื่อมีเสียงอินพุต เพิ่มvoice.realtime.bargeIn: trueหากยังต้องการให้เหตุการณ์เริ่มพูดของผู้พูดใน Discord ขัดจังหวะการเล่นเสียงที่กำลังทำงาน บริดจ์เรียลไทม์ของ OpenAI จะละเว้นการตัดการเล่นเสียงที่สั้นกว่าvoice.realtime.minBargeInAudioEndMsโดยถือว่าน่าจะเป็นเสียงสะท้อน/เสียงรบกวน และบันทึกว่าได้ข้ามแทนที่จะล้างการเล่นเสียงของ Discord voice.captureSilenceGraceMsควบคุมระยะเวลาที่ OpenClaw รอหลังจาก Discord รายงานว่าผู้พูดหยุดพูด ก่อนสรุปส่วนเสียงนั้นเพื่อส่งให้ STT ค่าเริ่มต้น:2000; เพิ่มค่านี้หาก Discord แบ่งช่วงหยุดตามปกติเป็นข้อความถอดเสียงบางส่วนที่ขาดเป็นห้วงๆ- เมื่อเลือก ElevenLabs เป็นผู้ให้บริการ TTS การเล่นเสียง Discord จะใช้ TTS แบบสตรีมและเริ่มเล่นจากสตรีมการตอบกลับของผู้ให้บริการ ผู้ให้บริการที่ไม่รองรับการสตรีมจะย้อนกลับไปใช้เส้นทางไฟล์ชั่วคราวที่สังเคราะห์แล้ว
- OpenClaw เฝ้าดูความล้มเหลวในการถอดรหัสข้อมูลที่รับ และกู้คืนอัตโนมัติโดยออกจากช่องเสียงแล้วเข้าร่วมใหม่ หลังเกิดความล้มเหลวซ้ำหลายครั้งภายในช่วงเวลาสั้นๆ
- หากบันทึกการรับแสดง
DecryptionFailed(UnencryptedWhenPassthroughDisabled)ซ้ำๆ หลังอัปเดต ให้รวบรวมรายงานการขึ้นต่อกันและบันทึก บรรทัด@discordjs/voiceที่รวมมาให้มีการแก้ไขการเติมข้อมูลจากต้นทางใน discord.js PR #11449 ซึ่งปิด discord.js issue #11419 - เหตุการณ์การรับ
The operation was abortedเป็นสิ่งที่คาดหมายเมื่อ OpenClaw สรุปส่วนเสียงของผู้พูดที่บันทึกไว้ เหตุการณ์เหล่านี้เป็นข้อมูลวินิจฉัยแบบละเอียด ไม่ใช่คำเตือน - บันทึกเสียง Discord แบบละเอียดมีตัวอย่างข้อความถอดเสียง STT หนึ่งบรรทัดที่จำกัดความยาวสำหรับแต่ละส่วนของผู้พูดที่ยอมรับ เพื่อให้การดีบักแสดงทั้งฝั่งผู้ใช้และฝั่งคำตอบของเอเจนต์ โดยไม่ทิ้งข้อความถอดเสียงที่ไม่จำกัดความยาว
- ในโหมด
agent-proxyกลไกสำรองของการปรึกษาแบบบังคับจะข้ามส่วนข้อความถอดเสียงที่น่าจะไม่สมบูรณ์ เช่น ข้อความที่ลงท้ายด้วย...หรือคำเชื่อมท้ายอย่าง "และ" รวมถึงคำปิดท้ายที่เห็นได้ชัดว่าไม่ต้องดำเนินการ เช่น "เดี๋ยวกลับมา" หรือ "ลาก่อน" บันทึกจะแสดงforced agent consult skipped reason=...เมื่อกลไกนี้ป้องกันคำตอบเก่าที่ค้างอยู่ในคิว
ติดตามผู้ใช้ในช่องเสียง
ใช้ voice.followUsers เมื่อต้องการให้บอทเสียง Discord อยู่กับผู้ใช้ Discord ที่รู้จักอย่างน้อยหนึ่งคน แทนการเข้าร่วมช่องคงที่เมื่อเริ่มต้นหรือรอ /vc join
{ channels: { discord: { voice: { enabled: true, followUsersEnabled: true, followUsers: ["discord:123456789012345678"], allowedChannels: [ { guildId: "123456789012345678", channelId: "234567890123456789", }, ], }, }, },}ลักษณะการทำงาน:
followUsersรองรับ ID ผู้ใช้ Discord แบบดิบและค่าdiscord:<id>OpenClaw จะปรับทั้งสองรูปแบบให้เป็นมาตรฐานก่อนจับคู่เหตุการณ์สถานะเสียงfollowUsersEnabledมีค่าเริ่มต้นเป็นtrueเมื่อกำหนดค่าfollowUsersตั้งค่าเป็นfalseเพื่อเก็บรายการที่บันทึกไว้ แต่หยุดการติดตามเสียงโดยอัตโนมัติfollowUsersควบคุมเฉพาะการคงอยู่ในช่องเสียงเท่านั้น โดยไม่ได้ให้สิทธิ์เข้าถึงในฐานะผู้พูดหรืออำนาจเจ้าของ โปรดกำหนดค่าcommands.ownerAllowFromรวมถึงผู้ใช้และบทบาทของกิลด์หรือช่องแยกต่างหาก- เมื่อผู้ใช้ที่ติดตามเข้าร่วมช่องเสียงที่อนุญาต OpenClaw จะเข้าร่วมช่องนั้น เมื่อผู้ใช้ย้าย OpenClaw จะย้ายตาม และเมื่อผู้ใช้ที่กำลังติดตามอยู่ตัดการเชื่อมต่อ OpenClaw จะออกจากช่อง
- หากมีผู้ใช้ที่ติดตามหลายคนอยู่ในกิลด์เดียวกันและผู้ใช้ที่กำลังติดตามอยู่ออกจากช่อง OpenClaw จะย้ายไปยังช่องของผู้ใช้ที่ติดตามและกำลังถูกเฝ้าติดตามอีกคนก่อนออกจากกิลด์ หากผู้ใช้ที่ติดตามหลายคนย้ายพร้อมกัน เหตุการณ์สถานะเสียงที่ตรวจพบล่าสุดจะมีผล
allowedChannelsยังคงมีผล ผู้ใช้ที่ติดตามซึ่งอยู่ในช่องที่ไม่อนุญาตจะถูกละเว้น และเซสชันที่เป็นของการติดตามจะย้ายไปหาผู้ใช้ที่ติดตามคนอื่นหรือออกจากช่อง- OpenClaw จะปรับสถานะเหตุการณ์เสียงที่พลาดไปให้สอดคล้องกันเมื่อเริ่มต้นระบบและตามช่วงเวลาที่มีขอบเขตจำกัด การปรับสถานะให้สอดคล้องจะสุ่มตรวจสอบกิลด์ที่กำหนดค่าไว้และจำกัดจำนวนการค้นหาผ่าน REST ต่อการทำงานหนึ่งรอบ ดังนั้นรายการ
followUsersที่มีขนาดใหญ่มากอาจต้องใช้มากกว่าหนึ่งช่วงเวลากว่าจะเข้าสู่สถานะที่สอดคล้องกัน - หาก Discord หรือผู้ดูแลระบบย้ายบอตขณะที่กำลังติดตามผู้ใช้ OpenClaw จะสร้างเซสชันเสียงใหม่และคงความเป็นเจ้าของโดยการติดตามไว้เมื่อปลายทางได้รับอนุญาต หากบอตถูกย้ายออกนอก
allowedChannelsOpenClaw จะออกและกลับเข้าร่วมเป้าหมายที่กำหนดค่าไว้เมื่อมีเป้าหมายดังกล่าว - การกู้คืนการรับ DAVE อาจออกและกลับเข้าร่วมช่องเดิมหลังการถอดรหัสล้มเหลวซ้ำหลายครั้ง เซสชันที่เป็นของการติดตามจะคงความเป็นเจ้าของโดยการติดตามไว้ตลอดเส้นทางการกู้คืนนี้ ดังนั้นเมื่อผู้ใช้ที่ติดตามตัดการเชื่อมต่อในภายหลัง ระบบจะยังคงออกจากช่อง
เลือกระหว่างโหมดการเข้าร่วม:
- ใช้
followUsersสำหรับการตั้งค่าส่วนบุคคลหรือของผู้ดำเนินการ ซึ่งบอตควรอยู่ในช่องเสียงโดยอัตโนมัติเมื่อคุณอยู่ในช่องเสียง - ใช้
autoJoinสำหรับบอตประจำห้องที่ควรอยู่ในช่องแม้ไม่มีผู้ใช้ที่ถูกติดตามอยู่ในช่องเสียง - ใช้
/vc joinสำหรับการเข้าร่วมเพียงครั้งเดียวหรือห้องที่การปรากฏตัวในช่องเสียงโดยอัตโนมัติอาจไม่เป็นไปตามที่คาดหมาย
โคเดกเสียงของ Discord:
- บันทึกการรับเสียงจะแสดง
discord voice: opus decoder: libopus-wasm - การเล่นแบบเรียลไทม์จะเข้ารหัส PCM สเตอริโอดิบ 48 kHz เป็น Opus ด้วยแพ็กเกจ
libopus-wasmที่รวมมาให้ชุดเดียวกัน ก่อนส่งแพ็กเก็ตให้@discordjs/voice - การเล่นไฟล์และสตรีมจากผู้ให้บริการจะแปลงเป็น PCM สเตอริโอดิบ 48 kHz ด้วย ffmpeg จากนั้นใช้
libopus-wasmสำหรับสตรีมแพ็กเก็ต Opus ที่ส่งไปยัง Discord
ไปป์ไลน์ STT และ TTS:
- การบันทึก PCM จาก Discord จะถูกแปลงเป็นไฟล์ WAV ชั่วคราว
tools.media.audioจัดการ STT เช่นopenai/gpt-4o-mini-transcribe- บทถอดเสียงจะถูกส่งผ่านทางเข้ารับและการกำหนดเส้นทางของ Discord ขณะที่ LLM สำหรับการตอบกลับทำงานด้วยนโยบายเอาต์พุตเสียงที่ซ่อนเครื่องมือ
ttsของเอเจนต์และขอข้อความที่ส่งกลับ เนื่องจากเสียงของ Discord เป็นผู้ควบคุมการเล่น TTS ขั้นสุดท้าย voice.modelเมื่อกำหนดค่าไว้ จะแทนที่เฉพาะ LLM สำหรับการตอบกลับในรอบของช่องเสียงนี้voice.ttsจะถูกผสานทับmessages.ttsผู้ให้บริการที่รองรับการสตรีมจะส่งข้อมูลเข้าสู่โปรแกรมเล่นโดยตรง มิฉะนั้นไฟล์เสียงที่ได้จะถูกเล่นในช่องที่เข้าร่วม
ตัวอย่างเซสชันช่องเสียงแบบพร็อกซีเอเจนต์เริ่มต้น:
{ channels: { discord: { voice: { enabled: true, model: "openai/gpt-5.6-sol", followUsersEnabled: true, followUsers: ["123456789012345678"], realtime: { provider: "openai", model: "gpt-realtime-2.1", speakerVoice: "cedar", }, }, }, },}เมื่อไม่มีบล็อก voice.agentSession ช่องเสียงแต่ละช่องจะมีเซสชัน OpenClaw ที่กำหนดเส้นทางของตัวเอง ตัวอย่างเช่น /vc join channel:234567890123456789 จะสื่อสารกับเซสชันของช่องเสียง Discord นั้น โมเดลเรียลไทม์เป็นเพียงส่วนหน้าสำหรับเสียง ส่วนคำขอที่มีสาระสำคัญจะถูกส่งต่อไปยังเอเจนต์ OpenClaw ที่กำหนดค่าไว้ หากโมเดลเรียลไทม์สร้างบทถอดเสียงสุดท้ายโดยไม่เรียกเครื่องมือปรึกษา OpenClaw จะบังคับให้เรียกการปรึกษาเป็นทางเลือกสำรอง เพื่อให้ค่าเริ่มต้นยังคงทำงานเสมือนการสนทนากับเอเจนต์
ตัวอย่าง STT และ TTS แบบเดิม:
{ channels: { discord: { voice: { enabled: true, mode: "stt-tts", model: "openai/gpt-5.4-mini", tts: { provider: "openai", providers: { openai: { model: "gpt-4o-mini-tts", speakerVoice: "cedar", }, }, }, }, }, },}ตัวอย่างเรียลไทม์แบบสองทิศทาง:
{ channels: { discord: { voice: { enabled: true, mode: "bidi", model: "openai/gpt-5.6-sol", realtime: { provider: "openai", model: "gpt-realtime-2.1", speakerVoice: "cedar", toolPolicy: "safe-read-only", consultPolicy: "always", }, }, }, },}เสียงในฐานะส่วนขยายของเซสชันช่อง Discord ที่มีอยู่:
{ channels: { discord: { voice: { enabled: true, mode: "agent-proxy", model: "openai/gpt-5.6-sol", agentSession: { mode: "target", target: "channel:123456789012345678", }, realtime: { provider: "openai", model: "gpt-realtime-2.1", speakerVoice: "cedar", }, }, }, },}ในโหมด agent-proxy บอตจะเข้าร่วมช่องเสียงที่กำหนดค่าไว้ แต่รอบการทำงานของเอเจนต์ OpenClaw จะใช้เซสชันและเอเจนต์ที่กำหนดเส้นทางตามปกติของช่องเป้าหมาย เซสชันเสียงเรียลไทม์จะพูดผลลัพธ์ที่ส่งกลับในช่องเสียง เอเจนต์ผู้ควบคุมยังคงใช้เครื่องมือส่งข้อความตามปกติได้ตามนโยบายเครื่องมือ รวมถึงส่งข้อความ Discord แยกต่างหากหากเป็นการดำเนินการที่เหมาะสม
ขณะที่การทำงาน OpenClaw ที่มอบหมายกำลังดำเนินอยู่ บทถอดเสียงใหม่จากช่องเสียง Discord จะถูกใช้เป็นการควบคุมการทำงานแบบสดก่อนเริ่มรอบการทำงานของเอเจนต์อีกครั้ง วลีอย่าง "สถานะ" "ยกเลิกสิ่งนั้น" "ใช้วิธีแก้ที่เล็กกว่า" หรือ "เมื่อเสร็จแล้วให้ตรวจสอบการทดสอบด้วย" จะถูกจำแนกเป็นข้อมูลนำเข้าสำหรับการตรวจสอบสถานะ การยกเลิก การปรับทิศทาง หรือการติดตามผลของเซสชันที่กำลังทำงาน ผลลัพธ์ของสถานะ การยกเลิก การปรับทิศทางที่ยอมรับ และการติดตามผลจะถูกพูดกลับในช่องเสียง เพื่อให้ผู้เรียกทราบว่า OpenClaw จัดการคำขอแล้วหรือไม่
รูปแบบเป้าหมายที่มีประโยชน์:
target: "channel:123456789012345678"กำหนดเส้นทางผ่านเซสชันช่องข้อความ Discordtarget: "123456789012345678"จะถูกมองเป็นเป้าหมายช่องtarget: "dm:123456789012345678"หรือtarget: "user:123456789012345678"กำหนดเส้นทางผ่านเซสชันข้อความโดยตรงนั้น
ตัวอย่าง OpenAI Realtime สำหรับสภาพแวดล้อมที่มีเสียงสะท้อนมาก:
{ channels: { discord: { voice: { enabled: true, mode: "bidi", model: "openai/gpt-5.6-sol", realtime: { provider: "openai", model: "gpt-realtime-2.1", speakerVoice: "cedar", bargeIn: true, minBargeInAudioEndMs: 500, consultPolicy: "always", providers: { openai: { interruptResponseOnInputAudio: false, }, }, }, }, }, },}ใช้รูปแบบนี้เมื่อโมเดลได้ยินเสียงที่ Discord เล่นออกมาของตัวเองผ่านไมโครโฟนที่เปิดอยู่ แต่ยังต้องการให้สามารถพูดแทรกเพื่อขัดจังหวะได้ OpenClaw จะป้องกันไม่ให้ OpenAI ขัดจังหวะโดยอัตโนมัติจากเสียงอินพุตดิบ ขณะที่ bargeIn: true ช่วยให้เหตุการณ์เริ่มต้นของผู้พูดใน Discord และเสียงของผู้พูดที่ทำงานอยู่แล้วสามารถยกเลิกการตอบกลับแบบเรียลไทม์ที่กำลังทำงาน ก่อนที่รอบเสียงที่บันทึกถัดไปจะไปถึง OpenAI สัญญาณพูดแทรกที่เกิดเร็วมากโดยมี audioEndMs ต่ำกว่า minBargeInAudioEndMs จะถูกมองว่าอาจเป็นเสียงสะท้อนหรือสัญญาณรบกวนและถูกละเว้น เพื่อไม่ให้โมเดลหยุดพูดตั้งแต่เฟรมแรกที่เริ่มเล่น
บันทึกเสียงที่คาดว่าจะพบ:
- เมื่อเข้าร่วม:
discord voice: joining ... voiceSession=... supervisorSession=... agentSessionMode=... voiceModel=... realtimeModel=... - เมื่อเริ่มเรียลไทม์:
discord voice: realtime bridge starting ... autoRespond=false interruptResponse=false bargeIn=false minBargeInAudioEndMs=... - เมื่อมีเสียงจากผู้พูด:
discord voice: realtime speaker turn opened ...,discord voice: realtime input audio started ... outputAudioMs=... outputActive=...และdiscord voice: realtime speaker turn closed ... chunks=... discordBytes=... realtimeBytes=... interruptedPlayback=... - เมื่อข้ามเสียงพูดที่ล้าสมัย:
discord voice: realtime forced agent consult skipped reason=incomplete-transcript ...หรือreason=non-actionable-closing ... - เมื่อการตอบกลับแบบเรียลไทม์เสร็จสมบูรณ์:
discord voice: realtime audio playback finishing reason=response.done ... audioMs=... chunks=... - เมื่อหยุดหรือรีเซ็ตการเล่น:
discord voice: realtime audio playback stopped reason=... audioMs=... elapsedMs=... chunks=... - เมื่อปรึกษาแบบเรียลไทม์:
discord voice: realtime consult requested ... voiceSession=... supervisorSession=... question=... - เมื่อเอเจนต์ตอบ:
discord voice: agent turn answer ... - เมื่อจัดคิวเสียงพูดแบบตรงตามข้อความ:
discord voice: realtime exact speech queued ... queued=... outputAudioMs=... outputActive=...ตามด้วยdiscord voice: realtime exact speech dequeued reason=player-idle ... - เมื่อตรวจพบการพูดแทรก:
discord voice: realtime barge-in detected source=speaker-start ...หรือdiscord voice: realtime barge-in detected source=active-speaker-audio ...ตามด้วยdiscord voice: realtime barge-in requested reason=... outputAudioMs=... outputActive=... - เมื่อขัดจังหวะแบบเรียลไทม์:
discord voice: realtime model interrupt requested client:response.cancel reason=barge-inตามด้วยdiscord voice: realtime model audio truncated client:conversation.item.truncate reason=barge-in audioEndMs=...หรือdiscord voice: realtime model interrupt confirmed server:response.done status=cancelled ... - เมื่อละเว้นเสียงสะท้อนหรือสัญญาณรบกวน:
discord voice: realtime model interrupt ignored client:conversation.item.truncate.skipped reason=barge-in audioEndMs=0 minAudioEndMs=250 - เมื่อปิดใช้งานการพูดแทรก:
discord voice: realtime capture ignored during playback (barge-in disabled) ... - เมื่อการเล่นไม่มีการใช้งาน:
discord voice: realtime barge-in ignored reason=... outputActive=false ... playbackChunks=0
หากต้องการแก้ไขข้อบกพร่องของเสียงที่ถูกตัด ให้อ่านบันทึกเสียงเรียลไทม์เป็นลำดับเวลา:
realtime audio playback startedหมายความว่า Discord เริ่มเล่นเสียงของผู้ช่วยแล้ว บริดจ์จะเริ่มนับส่วนข้อมูลเอาต์พุตของผู้ช่วย จำนวนไบต์ PCM ของ Discord จำนวนไบต์เรียลไทม์ของผู้ให้บริการ และระยะเวลาเสียงที่สังเคราะห์ตั้งแต่จุดนี้realtime speaker turn openedระบุว่าผู้พูดใน Discord เริ่มทำงาน หากกำลังเล่นเสียงอยู่แล้วและเปิดใช้งานbargeInเหตุการณ์นี้อาจตามด้วยbarge-in detected source=speaker-startrealtime input audio startedระบุเฟรมเสียงจริงเฟรมแรกที่ได้รับสำหรับรอบของผู้พูดนั้น การมีoutputActive=trueหรือoutputAudioMsที่ไม่เป็นศูนย์ ณ จุดนี้หมายความว่าไมโครโฟนกำลังส่งอินพุตขณะที่ยังเล่นเสียงของผู้ช่วยอยู่barge-in detected source=active-speaker-audioหมายความว่า OpenClaw ตรวจพบเสียงสดจากผู้พูดขณะที่กำลังเล่นเสียงของผู้ช่วย ซึ่งมีประโยชน์ในการแยกแยะการขัดจังหวะจริงออกจากเหตุการณ์เริ่มต้นของผู้พูดใน Discord ที่ไม่มีเสียงซึ่งใช้งานได้barge-in requested reason=...หมายความว่า OpenClaw ขอให้ผู้ให้บริการเรียลไทม์ยกเลิกหรือตัดการตอบกลับที่กำลังทำงาน โดยมีoutputAudioMs,outputActiveและplaybackChunksรวมอยู่ด้วย เพื่อให้ดูได้ว่ามีการเล่นเสียงของผู้ช่วยจริงไปมากเพียงใดก่อนถูกขัดจังหวะrealtime audio playback stopped reason=...คือจุดรีเซ็ตการเล่น Discord ภายในเครื่อง เหตุผลจะระบุว่าใครหยุดการเล่น:barge-in,player-idle,provider-clear-audio,forced-agent-consult,stream-closeหรือsession-closerealtime speaker turn closedสรุปรอบอินพุตที่บันทึกไว้chunks=0หรือhasAudio=falseหมายความว่ารอบของผู้พูดเริ่มขึ้น แต่ไม่มีเสียงที่ใช้งานได้ส่งถึงบริดจ์เรียลไทม์interruptedPlayback=trueหมายความว่ารอบอินพุตนั้นทับซ้อนกับเอาต์พุตของผู้ช่วยและกระตุ้นตรรกะการพูดแทรก
ฟิลด์ที่มีประโยชน์:
outputAudioMs: ระยะเวลาเสียงของผู้ช่วยที่ผู้ให้บริการเรียลไทม์สร้างขึ้นก่อนบรรทัดบันทึกนี้audioMs: ระยะเวลาเสียงของผู้ช่วยที่ OpenClaw นับได้ก่อนหยุดการเล่นelapsedMs: เวลาตามนาฬิกาจริงระหว่างการเปิดและปิดสตรีมการเล่นหรือรอบของผู้พูดdiscordBytes: จำนวนไบต์ PCM สเตอริโอ 48 kHz ที่ส่งไปยังหรือรับจากเสียง DiscordrealtimeBytes: จำนวนไบต์ PCM ในรูปแบบของผู้ให้บริการที่ส่งไปยังหรือรับจากผู้ให้บริการเรียลไทม์playbackChunks: จำนวนส่วนข้อมูลเสียงของผู้ช่วยที่ส่งต่อไปยัง Discord สำหรับการตอบกลับที่กำลังทำงานsinceLastAudioMs: ช่วงห่างระหว่างเฟรมเสียงล่าสุดของผู้พูดที่บันทึกได้กับการปิดรอบของผู้พูด
รูปแบบทั่วไป:
- การตัดเสียงทันทีร่วมกับ
source=active-speaker-audioค่าoutputAudioMsต่ำ และมีผู้ใช้คนเดิมอยู่ใกล้ ๆ มักบ่งชี้ว่าเสียงสะท้อนจากลำโพงเข้าสู่ไมโครโฟน ให้เพิ่มvoice.realtime.minBargeInAudioEndMsลดระดับเสียงลำโพง ใช้หูฟัง หรือตั้งค่าvoice.realtime.providers.openai.interruptResponseOnInputAudio: false source=speaker-startตามด้วยspeaker turn closed ... hasAudio=falseหมายความว่า Discord รายงานว่าผู้พูดเริ่มพูด แต่ไม่มีเสียงส่งถึง OpenClaw สาเหตุอาจเป็นเหตุการณ์เสียงชั่วคราวของ Discord พฤติกรรมของตัวตัดสัญญาณรบกวน หรือไคลเอนต์เปิดไมโครโฟนชั่วขณะaudio playback stopped reason=stream-closeที่ไม่มีการพูดแทรกหรือprovider-clear-audioอยู่ใกล้เคียง หมายความว่าสตรีมการเล่นเสียง Discord ภายในเครื่องสิ้นสุดลงโดยไม่คาดคิด ให้ตรวจสอบบันทึกของผู้ให้บริการและโปรแกรมเล่น Discord ก่อนหน้าcapture ignored during playback (barge-in disabled)หมายความว่า OpenClaw จงใจทิ้งอินพุตขณะที่เสียงของผู้ช่วยกำลังทำงาน เปิดใช้voice.realtime.bargeInหากต้องการให้เสียงพูดขัดจังหวะการเล่นเสียงbarge-in ignored ... outputActive=falseหมายความว่า Discord หรือ VAD ของผู้ให้บริการรายงานเสียงพูด แต่ OpenClaw ไม่มีการเล่นเสียงที่กำลังทำงานให้ขัดจังหวะ กรณีนี้ไม่ควรตัดเสียง
ข้อมูลรับรองจะได้รับการแก้ไขแยกตามคอมโพเนนต์ ได้แก่ การตรวจสอบสิทธิ์เส้นทาง LLM สำหรับ voice.model การตรวจสอบสิทธิ์ STT สำหรับ tools.media.audio การตรวจสอบสิทธิ์ TTS สำหรับ messages.tts/voice.tts และการตรวจสอบสิทธิ์ผู้ให้บริการแบบเรียลไทม์สำหรับ voice.realtime.providers หรือการกำหนดค่าการตรวจสอบสิทธิ์ปกติของผู้ให้บริการ
ข้อความเสียง
ข้อความเสียงของ Discord จะแสดงตัวอย่างรูปคลื่นและต้องใช้เสียง OGG/Opus OpenClaw สร้างรูปคลื่นโดยอัตโนมัติ แต่ต้องมี ffmpeg และ ffprobe บนโฮสต์ Gateway เพื่อตรวจสอบและแปลงไฟล์
- ระบุ พาธไฟล์ภายในเครื่อง (ไม่ยอมรับ URL)
- ไม่ต้องระบุเนื้อหาข้อความ (Discord ไม่ยอมรับข้อความและข้อความเสียงในเพย์โหลดเดียวกัน)
- ยอมรับรูปแบบเสียงทุกประเภท OpenClaw จะแปลงเป็น OGG/Opus ตามความจำเป็น
message(action="send", channel="discord", target="channel:123", path="/path/to/audio.mp3", asVoice=true)การแก้ไขปัญหา
ใช้ Intent ที่ไม่อนุญาต หรือบอตไม่เห็นข้อความในกิลด์
- เปิดใช้ Message Content Intent
- เปิดใช้ Server Members Intent เมื่อต้องใช้การระบุผู้ใช้/สมาชิก
- รีสตาร์ต Gateway หลังเปลี่ยน Intent
ข้อความในกิลด์ถูกบล็อกโดยไม่คาดคิด
- ตรวจสอบ
groupPolicy - ตรวจสอบรายการที่อนุญาตของกิลด์ภายใต้
channels.discord.guilds - หากมีแมป
channelsของกิลด์ จะอนุญาตเฉพาะช่องที่ระบุไว้เท่านั้น - ตรวจสอบพฤติกรรมของ
requireMentionและรูปแบบการกล่าวถึง
การตรวจสอบที่เป็นประโยชน์:
openclaw doctoropenclaw channels status --probeopenclaw logs --followตั้งค่าไม่ให้ต้องกล่าวถึงแล้ว แต่ยังคงถูกบล็อก
สาเหตุที่พบบ่อย:
groupPolicy="allowlist"โดยไม่มีรายการที่อนุญาตของกิลด์/ช่องที่ตรงกัน- กำหนดค่า
requireMentionผิดตำแหน่ง (ต้องอยู่ภายใต้channels.discord.guildsหรือรายการของช่อง) - ผู้ส่งถูกบล็อกโดยรายการที่อนุญาต
usersของกิลด์/ช่อง
รอบการทำงานของ Discord ใช้เวลานานหรือมีการตอบซ้ำ
บันทึกที่พบบ่อย:
Slow listener detected ...stuck session: sessionKey=agent:...:discord:... state=processing ...
Discord ไม่ใช้การหมดเวลาที่ช่องเป็นเจ้าของกับรอบการทำงานของเอเจนต์ที่อยู่ในคิว ตัวรับฟังข้อความจะส่งต่องานทันที และการทำงานของ Discord ที่อยู่ในคิวจะรักษาลำดับภายในแต่ละเซสชันจนกว่าวงจรชีวิตของเซสชัน/เครื่องมือ/รันไทม์จะเสร็จสมบูรณ์หรือยกเลิกงาน
คำเตือนการหมดเวลาขณะค้นหาข้อมูลเมตาของ Gateway
OpenClaw ดึงข้อมูลเมตา /gateway/bot ของ Discord ก่อนเชื่อมต่อ หากเกิดความล้มเหลวชั่วคราว ระบบจะใช้ URL Gateway เริ่มต้นของ Discord และจำกัดอัตราการบันทึก
เวลาหมดอายุของข้อมูลเมตาเริ่มต้นอยู่ที่ 30 วินาที OPENCLAW_DISCORD_GATEWAY_INFO_TIMEOUT_MS สามารถแทนที่ค่านี้สำหรับสภาพแวดล้อมโฮสต์ที่ผิดปกติ
Gateway รีสตาร์ตเนื่องจากหมดเวลารอ READY
OpenClaw รอเหตุการณ์ READY ของ Gateway จาก Discord ระหว่างการเริ่มต้นและหลังจากรันไทม์เชื่อมต่อใหม่ การตั้งค่าหลายบัญชีที่หน่วงเวลาเริ่มต้นอาจต้องใช้ช่วงเวลารอ READY ระหว่างเริ่มต้นนานกว่าค่าเริ่มต้น
การเริ่มต้นจะรอ 15 วินาที และการเชื่อมต่อใหม่ของรันไทม์จะรอ 30 วินาที OPENCLAW_DISCORD_READY_TIMEOUT_MS และ OPENCLAW_DISCORD_RUNTIME_READY_TIMEOUT_MS ยังคงใช้ได้สำหรับสภาพแวดล้อมโฮสต์ที่ผิดปกติ
ผลการตรวจสอบสิทธิ์ไม่ตรงกัน
การตรวจสอบสิทธิ์ channels status --probe ใช้ได้เฉพาะกับ ID ช่องที่เป็นตัวเลข
หากใช้คีย์แบบ slug การจับคู่ขณะรันไทม์อาจยังทำงานได้ แต่การตรวจสอบไม่สามารถยืนยันสิทธิ์ได้อย่างสมบูรณ์
ปัญหา DM และการจับคู่
- ปิดใช้ DM:
channels.discord.dm.enabled=false - ปิดใช้นโยบาย DM:
channels.discord.dmPolicy="disabled"(แบบเดิม:channels.discord.dm.policy) - กำลังรอการอนุมัติการจับคู่ในโหมด
pairing
ลูประหว่างบอต
โดยค่าเริ่มต้น ระบบจะละเว้นข้อความที่บอตเป็นผู้เขียน
หากตั้งค่า channels.discord.allowBots=true ให้ใช้กฎการกล่าวถึงและรายการที่อนุญาตอย่างเข้มงวดเพื่อหลีกเลี่ยงพฤติกรรมวนซ้ำ
แนะนำให้ใช้ channels.discord.allowBots="mentions" เพื่อยอมรับเฉพาะข้อความจากบอตที่กล่าวถึงบอตนี้เท่านั้น
OpenClaw ยังมาพร้อมกับ การป้องกันลูปของบอต แบบใช้ร่วมกัน เมื่อใดก็ตามที่ allowBots อนุญาตให้ข้อความที่บอตเป็นผู้เขียนส่งถึงการจัดส่ง Discord จะแมปเหตุการณ์ขาเข้าเป็นข้อเท็จจริง (account, channel, bot pair) และตัวป้องกันคู่ทั่วไปจะระงับคู่ดังกล่าวหลังจากใช้เกินงบประมาณเหตุการณ์ที่กำหนด ตัวป้องกันนี้ป้องกันลูปสองบอตที่ควบคุมไม่ได้ ซึ่งก่อนหน้านี้ต้องหยุดด้วยขีดจำกัดอัตราของ Discord โดยไม่ส่งผลต่อการปรับใช้บอตตัวเดียวหรือการตอบกลับของบอตแบบครั้งเดียวที่ยังไม่เกินงบประมาณ
การตั้งค่าเริ่มต้น (ทำงานเมื่อตั้งค่า allowBots):
maxEventsPerWindow: 20-- คู่บอตสามารถแลกเปลี่ยนข้อความ 20 ข้อความภายในกรอบเวลาแบบเลื่อนwindowSeconds: 60-- ความยาวของกรอบเวลาแบบเลื่อนcooldownSeconds: 60-- เมื่องบประมาณถึงขีดจำกัด ข้อความระหว่างบอตเพิ่มเติมทุกข้อความในทั้งสองทิศทางจะถูกทิ้งเป็นเวลาหนึ่งนาที
กำหนดค่าเริ่มต้นแบบใช้ร่วมกันเพียงครั้งเดียวภายใต้ channels.defaults.botLoopProtection แล้วแทนที่ค่าของ Discord เมื่อเวิร์กโฟลว์ที่ถูกต้องต้องการขีดจำกัดที่มากขึ้น ลำดับความสำคัญคือ:
channels.discord.accounts.<account>.botLoopProtectionchannels.discord.botLoopProtectionchannels.defaults.botLoopProtection- ค่าเริ่มต้นในตัว
Discord ใช้คีย์ทั่วไป maxEventsPerWindow, windowSeconds และ cooldownSeconds
{channels: {defaults: { botLoopProtection: { maxEventsPerWindow: 20, windowSeconds: 60, cooldownSeconds: 60, },},discord: { // ตัวเลือกสำหรับแทนที่ค่าทั่วทั้ง Discord บล็อกบัญชีจะแทนที่แต่ละฟิลด์ // และสืบทอดฟิลด์ที่ไม่ได้ระบุจากที่นี่ botLoopProtection: { maxEventsPerWindow: 4, }, accounts: { alpha: { // Alpha รับฟังบอตอื่นเฉพาะเมื่อบอตเหล่านั้นกล่าวถึง Alpha allowBots: "mentions", }, bravo: { // Bravo รับฟังข้อความ Discord ทั้งหมดที่บอตเป็นผู้เขียน allowBots: true, mentionAliases: { // อนุญาตให้ Bravo เขียนการกล่าวถึง Alpha บน Discord ด้วย ID ผู้ใช้ที่กำหนดค่าไว้ Alpha: "ALPHA_DISCORD_USER_ID", }, botLoopProtection: { // อนุญาตสูงสุดห้าข้อความต่อนาทีก่อนระงับคู่บอต maxEventsPerWindow: 5, windowSeconds: 60, cooldownSeconds: 90, }, }, },},},}เสียง STT หลุดพร้อม DecryptionFailed(...)
- อัปเดต OpenClaw ให้เป็นเวอร์ชันปัจจุบัน (
openclaw update) เพื่อให้มีตรรกะการกู้คืนการรับเสียงของ Discord - ยืนยัน
channels.discord.voice.daveEncryption=true(ค่าเริ่มต้น) - เริ่มจาก
channels.discord.voice.decryptionFailureTolerance=24(ค่าเริ่มต้นจากต้นทาง) และปรับแต่งเมื่อจำเป็นเท่านั้น - ตรวจสอบบันทึกเพื่อหา:
discord voice: DAVE decrypt failures detecteddiscord voice: repeated decrypt failures; attempting rejoin
- หากยังคงเกิดความล้มเหลวหลังจากเข้าร่วมใหม่โดยอัตโนมัติ ให้รวบรวมบันทึกและเปรียบเทียบกับประวัติการรับ DAVE จากต้นทางใน discord.js #11419 และ discord.js #11449
ข้อมูลอ้างอิงการกำหนดค่า
ข้อมูลอ้างอิงหลัก: ข้อมูลอ้างอิงการกำหนดค่า - Discord
ฟิลด์ Discord ที่มีข้อมูลสำคัญ
- การเริ่มต้น/การตรวจสอบสิทธิ์:
enabled,token,applicationId,accounts.*,allowBots - นโยบาย:
groupPolicy,dmPolicy,allowFrom,dm.*,guilds.*,guilds.*.channels.* - คำสั่ง:
commands.native,commands.useAccessGroups(ส่วนกลาง),configWrites,slashCommand.ephemeral - Gateway:
proxy - การตอบกลับ/ประวัติ:
replyToMode,historyLimit,dmHistoryLimit,dms.*.historyLimit - การส่ง:
textChunkLimit(ค่าเริ่มต้น2000),maxLinesPerMessage(ค่าเริ่มต้น17) - การสตรีม:
streaming.mode,streaming.chunkMode,streaming.preview.*,streaming.progress.*,streaming.block.*(คีย์แบบแบนเดิมstreamMode,draftChunk,blockStreaming,blockStreamingCoalesce,chunkModeจะถูกย้ายไปยังstreaming.*โดยopenclaw doctor --fix) - สื่อ:
mediaMaxMb(จำกัดการอัปโหลดขาออกของ Discord ค่าเริ่มต้น100) - การดำเนินการ:
actions.* - สถานะการแสดงตน:
activity,status,activityType,activityUrl,autoPresence.* - UI:
ui.components.accentColor - ฟีเจอร์:
threadBindings,bindings[]ระดับบนสุด (type: "acp"),pluralkit,execApprovals,intents,agentComponents.enabled,agentComponents.ttlMs,activities,heartbeat,responsePrefix
Discord Activities
ตั้งค่า channels.discord.activities เพื่อให้เอเจนต์โพสต์วิดเจ็ต HTML แบบสมบูรณ์ในตัวที่เปิดภายใน Discord ได้ บล็อกนี้ต้องเลือกเปิดใช้ เมื่อไม่มีบล็อกนี้ OpenClaw จะไม่ลงทะเบียนเส้นทาง Activity เครื่องมือ หรือตัวจัดการการโต้ตอบ โปรดดู Discord Activities สำหรับการตั้งค่า Developer Portal, ทันเนล, ความปลอดภัย และการแก้ไขปัญหา
activities.clientSecret: ข้อมูลลับไคลเอนต์ OAuth2 สำหรับแอปพลิเคชัน Discord หากไม่มีจะใช้DISCORD_CLIENT_SECRETactivities.applicationId: ID แอปพลิเคชัน Activity ที่ระบุหรือไม่ก็ได้ ค่าเริ่มต้นคือ ID แอปพลิเคชันบอตที่ได้รับระหว่างการเริ่มต้น Gateway
ความปลอดภัยและการปฏิบัติการ
- ถือว่าโทเค็นบอตเป็นข้อมูลลับ (แนะนำให้ใช้
DISCORD_BOT_TOKENในสภาพแวดล้อมที่มีการควบคุมดูแล) - ให้สิทธิ์ Discord เท่าที่จำเป็น
- หากสถานะการปรับใช้/คำสั่งล้าสมัย ให้รีสตาร์ต Gateway และตรวจสอบอีกครั้งด้วย
openclaw channels status --probe
ที่เกี่ยวข้อง
เปิดวิดเจ็ต HTML แบบโต้ตอบภายใน Discord
จับคู่ผู้ใช้ Discord กับ Gateway
พฤติกรรมการแชตกลุ่มและรายการที่อนุญาต
กำหนดเส้นทางข้อความขาเข้าไปยังเอเจนต์
แบบจำลองภัยคุกคามและการเสริมความแข็งแกร่ง
แมปกิลด์และช่องไปยังเอเจนต์
พฤติกรรมคำสั่งแบบเนทีฟ