Mainstream messaging
Telegram
พร้อมใช้งานจริงสำหรับ DM ของบอตและกลุ่มผ่าน grammY โหมดเริ่มต้นคือการโพลระยะยาว ส่วนโหมด Webhook เป็นตัวเลือกเสริม
นโยบาย DM เริ่มต้นสำหรับ Telegram คือการจับคู่
การวินิจฉัยข้ามช่องทางและคู่มือการซ่อมแซม
รูปแบบและตัวอย่างการกำหนดค่าช่องทางแบบครบถ้วน
การตั้งค่าอย่างรวดเร็ว
สร้างโทเค็นบอตใน BotFather
เปิด Telegram แล้วแชทกับ @BotFather (ยืนยันว่าแฮนเดิลตรงกับ @BotFather ทุกประการ)
เรียกใช้ /newbot ทำตามพรอมป์ แล้วบันทึกโทเค็นไว้
กำหนดค่าโทเค็นและนโยบาย DM
{channels: {telegram: { enabled: true, botToken: "123:abc", dmPolicy: "pairing", groups: { "*": { requireMention: true } },},},}ค่าสำรองจาก env: TELEGRAM_BOT_TOKEN=... (เฉพาะบัญชีเริ่มต้น)
Telegram ไม่ ใช้ openclaw channels login telegram; ให้กำหนดค่าโทเค็นใน config/env แล้วเริ่ม gateway
เริ่ม gateway และอนุมัติ DM แรก
openclaw gatewayopenclaw pairing list telegramopenclaw pairing approve telegram <CODE>รหัสจับคู่หมดอายุหลังจาก 1 ชั่วโมง
เพิ่มบอตเข้าในกลุ่ม
เพิ่มบอตเข้าในกลุ่มของคุณ จากนั้นรับ ID ทั้งสองรายการที่การเข้าถึงกลุ่มต้องใช้:
- ID ผู้ใช้ Telegram ของคุณ ใช้ใน
allowFrom/groupAllowFrom - ID แชทกลุ่ม Telegram ใช้เป็นคีย์ใต้
channels.telegram.groups
สำหรับการตั้งค่าครั้งแรก ให้รับ ID แชทกลุ่มจาก openclaw logs --follow, บอต forwarded-ID หรือ Bot API getUpdates หลังจากอนุญาตกลุ่มแล้ว /whoami@<bot_username> สามารถยืนยัน ID ผู้ใช้และกลุ่มได้
ID ของ supergroup ใน Telegram ที่เป็นค่าลบและขึ้นต้นด้วย -100 คือ ID แชทกลุ่ม ให้วางไว้ใต้ channels.telegram.groups ไม่ใช่ใต้ groupAllowFrom
การตั้งค่าฝั่ง Telegram
โหมดความเป็นส่วนตัวและการมองเห็นในกลุ่ม
บอต Telegram จะใช้ โหมดความเป็นส่วนตัว เป็นค่าเริ่มต้น ซึ่งจำกัดข้อความกลุ่มที่บอตได้รับ
หากบอตต้องเห็นข้อความกลุ่มทั้งหมด ให้ทำอย่างใดอย่างหนึ่ง:
- ปิดโหมดความเป็นส่วนตัวผ่าน
/setprivacyหรือ - ตั้งบอตเป็นผู้ดูแลกลุ่ม
เมื่อสลับโหมดความเป็นส่วนตัว ให้ลบและเพิ่มบอตกลับเข้าไปใหม่ในแต่ละกลุ่ม เพื่อให้ Telegram นำการเปลี่ยนแปลงไปใช้
สิทธิ์ของกลุ่ม
สถานะผู้ดูแลถูกควบคุมในการตั้งค่ากลุ่ม Telegram
บอตที่เป็นผู้ดูแลจะได้รับข้อความกลุ่มทั้งหมด ซึ่งมีประโยชน์สำหรับพฤติกรรมกลุ่มที่ทำงานตลอดเวลา
ตัวสลับ BotFather ที่มีประโยชน์
/setjoingroupsเพื่ออนุญาต/ปฏิเสธการเพิ่มเข้ากลุ่ม/setprivacyสำหรับพฤติกรรมการมองเห็นในกลุ่ม
การควบคุมการเข้าถึงและการเปิดใช้งาน
ตัวตนบอตในกลุ่ม
ในกลุ่ม Telegram และหัวข้อฟอรัม การกล่าวถึงแฮนเดิลบอตที่กำหนดไว้อย่างชัดเจน (เช่น @my_bot) จะถือว่าเป็นการส่งถึงเอเจนต์ OpenClaw ที่เลือก แม้ชื่อบุคลิกของเอเจนต์จะแตกต่างจากชื่อผู้ใช้ Telegram ก็ตาม นโยบายปิดเสียงของกลุ่มยังคงใช้กับทราฟฟิกกลุ่มที่ไม่เกี่ยวข้อง แต่ตัวแฮนเดิลของบอตเองจะไม่ถือว่าเป็น "คนอื่น"
นโยบาย DM
channels.telegram.dmPolicy ควบคุมการเข้าถึงข้อความโดยตรง:
pairing(ค่าเริ่มต้น)allowlist(ต้องมี ID ผู้ส่งอย่างน้อยหนึ่งรายการในallowFrom)open(ต้องให้allowFromรวม"*")disabled
dmPolicy: "open" พร้อม allowFrom: ["*"] ทำให้บัญชี Telegram ใดก็ตามที่พบหรือเดาชื่อผู้ใช้ของบอตได้สามารถสั่งงานบอตได้ ใช้เฉพาะกับบอตสาธารณะที่ตั้งใจเปิดและจำกัดเครื่องมืออย่างเข้มงวดเท่านั้น บอตเจ้าของคนเดียวควรใช้ allowlist พร้อม ID ผู้ใช้แบบตัวเลข
channels.telegram.allowFrom รับ ID ผู้ใช้ Telegram แบบตัวเลข รองรับคำนำหน้า telegram: / tg: และจะถูกทำให้เป็นรูปแบบมาตรฐาน
ใน config หลายบัญชี channels.telegram.allowFrom ระดับบนที่เข้มงวดจะถูกถือเป็นขอบเขตความปลอดภัย: รายการระดับบัญชี allowFrom: ["*"] จะไม่ทำให้บัญชีนั้นเป็นสาธารณะ เว้นแต่ allowlist ที่มีผลของบัญชียังคงมี wildcard ที่ระบุชัดเจนหลังจากผสานแล้ว
dmPolicy: "allowlist" พร้อม allowFrom ว่างจะบล็อก DM ทั้งหมดและถูกปฏิเสธโดยการตรวจสอบ config
การตั้งค่าจะถามหาเฉพาะ ID ผู้ใช้แบบตัวเลข
หากคุณอัปเกรดแล้ว config ของคุณมีรายการ allowlist แบบ @username ให้เรียกใช้ openclaw doctor --fix เพื่อแก้ค่าเหล่านั้น (พยายามให้ดีที่สุด; ต้องใช้โทเค็นบอต Telegram)
หากก่อนหน้านี้คุณพึ่งพาไฟล์ allowlist ของ pairing-store, openclaw doctor --fix สามารถกู้รายการเข้าไปใน channels.telegram.allowFrom ในโฟลว์ allowlist ได้ (เช่น เมื่อ dmPolicy: "allowlist" ยังไม่มี ID ที่ระบุชัดเจน)
สำหรับบอตเจ้าของคนเดียว ให้เลือกใช้ dmPolicy: "allowlist" พร้อม ID แบบตัวเลขที่ระบุชัดเจนใน allowFrom เพื่อให้นโยบายการเข้าถึงคงทนใน config (แทนที่จะพึ่งพาการอนุมัติการจับคู่ก่อนหน้า)
ความสับสนที่พบบ่อย: การอนุมัติการจับคู่ DM ไม่ได้หมายความว่า "ผู้ส่งรายนี้ได้รับอนุญาตทุกที่"
การจับคู่ให้สิทธิ์เข้าถึง DM หากยังไม่มีเจ้าของคำสั่ง การจับคู่ที่อนุมัติครั้งแรกจะตั้งค่า commands.ownerAllowFrom ด้วย เพื่อให้คำสั่งเฉพาะเจ้าของและการอนุมัติ exec มีบัญชีผู้ปฏิบัติการที่ชัดเจน
การอนุญาตผู้ส่งในกลุ่มยังคงมาจาก allowlist ใน config ที่ระบุชัดเจน
หากคุณต้องการ "ฉันได้รับอนุญาตครั้งเดียว แล้วทั้ง DM และคำสั่งกลุ่มใช้งานได้" ให้วาง ID ผู้ใช้ Telegram แบบตัวเลขของคุณใน channels.telegram.allowFrom; สำหรับคำสั่งเฉพาะเจ้าของ ตรวจสอบให้แน่ใจว่า commands.ownerAllowFrom มี telegram:<your user id>
การค้นหา ID ผู้ใช้ Telegram ของคุณ
ปลอดภัยกว่า (ไม่มีบอตบุคคลที่สาม):
- ส่ง DM ถึงบอตของคุณ
- เรียกใช้
openclaw logs --follow - อ่าน
from.id
วิธีทางการของ Bot API:
curl "https://api.telegram.org/bot<bot_token>/getUpdates"วิธีจากบุคคลที่สาม (เป็นส่วนตัวน้อยกว่า): @userinfobot หรือ @getidsbot
นโยบายกลุ่มและรายการอนุญาต
มีตัวควบคุมสองอย่างที่ใช้ร่วมกัน:
-
กลุ่มใดบ้างที่ได้รับอนุญาต (
channels.telegram.groups)- ไม่มี config
groups:- เมื่อใช้
groupPolicy: "open": กลุ่มใดก็ผ่านการตรวจ ID กลุ่มได้ - เมื่อใช้
groupPolicy: "allowlist"(ค่าเริ่มต้น): กลุ่มจะถูกบล็อกจนกว่าคุณจะเพิ่มรายการgroups(หรือ"*")
- เมื่อใช้
- กำหนดค่า
groupsแล้ว: ทำหน้าที่เป็น allowlist (ID ที่ระบุชัดเจนหรือ"*")
- ไม่มี config
-
ผู้ส่งใดบ้างที่ได้รับอนุญาตในกลุ่ม (
channels.telegram.groupPolicy)openallowlist(ค่าเริ่มต้น)disabled
groupAllowFrom ใช้สำหรับกรองผู้ส่งในกลุ่ม หากไม่ได้ตั้งค่า Telegram จะย้อนกลับไปใช้ allowFrom
รายการ groupAllowFrom ควรเป็น ID ผู้ใช้ Telegram แบบตัวเลข (คำนำหน้า telegram: / tg: จะถูกทำให้เป็นรูปแบบมาตรฐาน)
อย่าวาง ID แชทกลุ่มหรือ supergroup ของ Telegram ใน groupAllowFrom ID แชทค่าลบควรอยู่ใต้ channels.telegram.groups
รายการที่ไม่ใช่ตัวเลขจะถูกละเว้นสำหรับการอนุญาตผู้ส่ง
ขอบเขตความปลอดภัย (2026.2.25+): การตรวจสิทธิ์ผู้ส่งในกลุ่ม ไม่ สืบทอดการอนุมัติ pairing-store ของ DM
การจับคู่ยังคงเป็น DM เท่านั้น สำหรับกลุ่ม ให้ตั้งค่า groupAllowFrom หรือ allowFrom รายกลุ่ม/รายหัวข้อ
หากไม่ได้ตั้งค่า groupAllowFrom, Telegram จะย้อนกลับไปใช้ config allowFrom ไม่ใช่ pairing store
รูปแบบใช้งานจริงสำหรับบอตเจ้าของคนเดียว: ตั้ง ID ผู้ใช้ของคุณใน channels.telegram.allowFrom, ปล่อย groupAllowFrom ว่างไว้ และอนุญาตกลุ่มเป้าหมายใต้ channels.telegram.groups
หมายเหตุรันไทม์: หาก channels.telegram หายไปทั้งหมด รันไทม์จะใช้ค่าเริ่มต้นแบบ fail-closed groupPolicy="allowlist" เว้นแต่จะตั้งค่า channels.defaults.groupPolicy ไว้อย่างชัดเจน
การตั้งค่ากลุ่มเฉพาะเจ้าของ:
{channels: {telegram: { enabled: true, dmPolicy: "pairing", allowFrom: ["<YOUR_TELEGRAM_USER_ID>"], groupPolicy: "allowlist", groups: { "<GROUP_CHAT_ID>": { requireMention: true, }, },},},}ทดสอบจากกลุ่มด้วย @<bot_username> ping ข้อความกลุ่มธรรมดาจะไม่ทริกเกอร์บอตขณะที่ requireMention: true
ตัวอย่าง: อนุญาตสมาชิกใดก็ได้ในกลุ่มเฉพาะหนึ่งกลุ่ม:
{channels: {telegram: { groups: { "-1001234567890": { groupPolicy: "open", requireMention: false, }, },},},}ตัวอย่าง: อนุญาตเฉพาะผู้ใช้บางคนภายในกลุ่มเฉพาะหนึ่งกลุ่ม:
{channels: {telegram: { groups: { "-1001234567890": { requireMention: true, allowFrom: ["8734062810", "745123456"], }, },},},}พฤติกรรมการกล่าวถึง
การตอบกลับในกลุ่มต้องมีการกล่าวถึงเป็นค่าเริ่มต้น
การกล่าวถึงอาจมาจาก:
- การกล่าวถึงแบบเนทีฟ
@botusernameหรือ - รูปแบบการกล่าวถึงใน:
agents.list[].groupChat.mentionPatternsmessages.groupChat.mentionPatterns
ตัวสลับคำสั่งระดับเซสชัน:
/activation always/activation mention
สิ่งเหล่านี้อัปเดตเฉพาะสถานะเซสชัน ใช้ config สำหรับการคงค่า
ตัวอย่าง config แบบคงค่า:
{channels: {telegram: { groups: { "*": { requireMention: false }, },},},}บริบทประวัติกลุ่มมีค่าเริ่มต้นเป็น mention-only: ข้อความกลุ่มก่อนหน้า
จะถูกรวมเฉพาะเมื่อข้อความนั้นส่งถึงบอต เป็นการตอบกลับบอต
หรือเป็นข้อความของบอตเอง ตั้งค่า includeGroupHistoryContext: "recent" เพื่อ
รวมประวัติห้องล่าสุดสำหรับกลุ่มที่เชื่อถือได้ ตั้งค่า
includeGroupHistoryContext: "none" เพื่อไม่ส่งประวัติกลุ่ม Telegram ก่อนหน้า
ไปกับรอบถัดไป
{channels: {telegram: { includeGroupHistoryContext: "recent",},},}การรับ ID แชทกลุ่ม:
- ส่งต่อข้อความกลุ่มไปที่
@userinfobot/@getidsbot - หรืออ่าน
chat.idจากopenclaw logs --follow - หรือตรวจสอบ Bot API
getUpdates - หลังจากอนุญาตกลุ่มแล้ว ให้เรียกใช้
/whoami@<bot_username>หากเปิดใช้คำสั่งเนทีฟ
พฤติกรรมรันไทม์
- Telegram เป็นเจ้าของโดยกระบวนการ Gateway
- การกำหนดเส้นทางเป็นแบบกำหนดแน่นอน: ข้อความขาเข้าของ Telegram จะตอบกลับไปยัง Telegram (โมเดลไม่ได้เลือกช่องทาง)
- ข้อความขาเข้าจะถูกทำให้เป็นรูปแบบมาตรฐานในซองช่องทางที่ใช้ร่วมกัน พร้อมเมตาดาตาการตอบกลับ ตัวแทนตำแหน่งสื่อ และบริบทสายการตอบกลับที่คงอยู่สำหรับการตอบกลับของ Telegram ที่ Gateway สังเกตเห็น
- เซสชันกลุ่มถูกแยกตาม ID กลุ่ม หัวข้อฟอรัมจะต่อท้าย
:topic:<threadId>เพื่อแยกหัวข้อออกจากกัน - ข้อความ DM สามารถมี
message_thread_id; OpenClaw จะคงค่าไว้สำหรับการตอบกลับ เซสชันหัวข้อ DM จะแยกเฉพาะเมื่อ TelegramgetMeรายงานhas_topics_enabled: trueสำหรับบอท; มิฉะนั้น DM จะยังคงอยู่ในเซสชันแบบแบน - การทำ long polling ใช้ grammY runner พร้อมการจัดลำดับต่อแชท/ต่อเธรด ความพร้อมกันของ runner sink โดยรวมใช้
agents.defaults.maxConcurrent - การเริ่มต้นหลายบัญชีจำกัดการ probe
getMeของ Telegram ที่เกิดพร้อมกัน เพื่อให้ fleet บอทขนาดใหญ่ไม่กระจายการ probe ทุกบัญชีพร้อมกัน - Long polling ถูกป้องกันภายในแต่ละกระบวนการ Gateway เพื่อให้มี poller ที่ใช้งานอยู่เพียงตัวเดียวใช้ token ของบอทได้ในเวลาเดียวกัน หากคุณยังเห็นข้อขัดแย้ง
getUpdates409 แสดงว่า Gateway ของ OpenClaw ตัวอื่น สคริปต์ หรือ poller ภายนอกน่าจะกำลังใช้ token เดียวกันอยู่ - การรีสตาร์ทจาก watchdog ของ long-polling จะถูกทริกเกอร์โดยค่าเริ่มต้นหลังจาก 120 วินาทีโดยไม่มี liveness ของ
getUpdatesที่เสร็จสมบูรณ์ เพิ่มchannels.telegram.pollingStallThresholdMsเฉพาะเมื่อ deployment ของคุณยังเห็นการรีสตาร์ท polling-stall แบบ false ระหว่างงานที่รันนาน ค่านี้อยู่ในหน่วยมิลลิวินาทีและอนุญาตตั้งแต่30000ถึง600000; รองรับการ override ต่อบัญชี - Telegram Bot API ไม่รองรับ read-receipt (
sendReadReceiptsไม่ใช้กับกรณีนี้)
อ้างอิงฟีเจอร์
ตัวอย่างสตรีมสด (การแก้ไขข้อความ)
OpenClaw สามารถสตรีมคำตอบบางส่วนแบบเรียลไทม์ได้:
- แชทโดยตรง: ข้อความตัวอย่าง +
editMessageText - กลุ่ม/หัวข้อ: ข้อความตัวอย่าง +
editMessageText
ข้อกำหนด:
channels.telegram.streamingคือoff | partial | block | progress(ค่าเริ่มต้น:partial)- ตัวอย่างคำตอบเริ่มต้นสั้น ๆ จะถูก debounce แล้ว materialize หลังจากความหน่วงที่มีขอบเขต หาก run ยัง active อยู่
progressจะคง draft สถานะที่แก้ไขได้หนึ่งรายการสำหรับความคืบหน้าของเครื่องมือ แสดงป้ายสถานะที่เสถียรเมื่อมีกิจกรรมคำตอบมาถึงก่อนความคืบหน้าของเครื่องมือ ล้างออกเมื่อเสร็จสิ้น และส่งคำตอบสุดท้ายเป็นข้อความปกติstreaming.preview.toolProgressควบคุมว่าการอัปเดตเครื่องมือ/ความคืบหน้าจะใช้ข้อความตัวอย่างที่แก้ไขเดียวกันซ้ำหรือไม่ (ค่าเริ่มต้น:trueเมื่อ preview streaming เปิดใช้งานอยู่)streaming.preview.commandTextควบคุมรายละเอียดคำสั่ง/exec ภายในบรรทัด tool-progress เหล่านั้น:raw(ค่าเริ่มต้น, คงพฤติกรรมที่เผยแพร่แล้วไว้) หรือstatus(ป้ายเครื่องมือเท่านั้น)streaming.progress.commentary(ค่าเริ่มต้น:false) เลือกเปิดข้อความ commentary/preamble ของ assistant ใน draft ความคืบหน้าชั่วคราว- legacy
channels.telegram.streamMode, ค่า boolean ของstreaming, และ key native draft preview ที่เลิกใช้แล้วจะถูกตรวจพบ; รันopenclaw doctor --fixเพื่อ migrate ไปยัง config การสตรีมปัจจุบัน
การอัปเดตตัวอย่าง tool-progress คือบรรทัดสถานะสั้น ๆ ที่แสดงขณะเครื่องมือทำงาน เช่น การรันคำสั่ง การอ่านไฟล์ การอัปเดตการวางแผน สรุป patch หรือข้อความ preamble/commentary ของ Codex ในโหมด Codex app-server Telegram เปิดสิ่งเหล่านี้ไว้โดยค่าเริ่มต้นเพื่อให้ตรงกับพฤติกรรม OpenClaw ที่เผยแพร่ตั้งแต่ v2026.4.22 เป็นต้นไป
หากต้องการคงตัวอย่างที่แก้ไขได้สำหรับข้อความคำตอบแต่ซ่อนบรรทัด tool-progress ให้ตั้งค่า:
{ "channels": { "telegram": { "streaming": { "mode": "partial", "preview": { "toolProgress": false } } } }}หากต้องการให้ tool-progress มองเห็นได้แต่ซ่อนข้อความคำสั่ง/exec ให้ตั้งค่า:
{ "channels": { "telegram": { "streaming": { "mode": "partial", "preview": { "commandText": "status" } } } }}ใช้โหมด progress เมื่อคุณต้องการความคืบหน้าของเครื่องมือที่มองเห็นได้โดยไม่แก้ไขคำตอบสุดท้ายเข้าไปในข้อความเดียวกันนั้น วางนโยบาย command-text ไว้ใต้ streaming.progress:
{ "channels": { "telegram": { "streaming": { "mode": "progress", "progress": { "toolProgress": true, "commandText": "status" } } } }}ใช้ streaming.mode: "off" เฉพาะเมื่อคุณต้องการส่งเฉพาะผลลัพธ์สุดท้าย: การแก้ไขตัวอย่างของ Telegram จะถูกปิดใช้งาน และข้อความสถานะเครื่องมือ/ความคืบหน้าทั่วไปจะถูกระงับแทนที่จะส่งเป็นข้อความสถานะแยกต่างหาก prompt การอนุมัติ payload สื่อ และข้อผิดพลาดยังคงส่งผ่านการส่งผลลัพธ์สุดท้ายตามปกติ ใช้ streaming.preview.toolProgress: false เมื่อคุณต้องการคงการแก้ไขตัวอย่างคำตอบไว้เท่านั้นพร้อมซ่อนบรรทัดสถานะ tool-progress
สำหรับการตอบกลับแบบข้อความเท่านั้น:
- ตัวอย่าง DM/กลุ่ม/หัวข้อแบบสั้น: OpenClaw จะคงข้อความตัวอย่างเดิมไว้และทำการแก้ไขสุดท้ายในที่เดิม
- ผลลัพธ์สุดท้ายแบบข้อความยาวที่แยกเป็นข้อความ Telegram หลายข้อความจะใช้ตัวอย่างที่มีอยู่เป็น chunk สุดท้ายแรกเมื่อทำได้ แล้วส่งเฉพาะ chunk ที่เหลือ
- ผลลัพธ์สุดท้ายในโหมด progress จะล้าง draft สถานะและใช้การส่งผลลัพธ์สุดท้ายตามปกติแทนการแก้ไข draft ให้เป็นคำตอบ
- หากการแก้ไขสุดท้ายล้มเหลวก่อนยืนยันข้อความที่เสร็จสมบูรณ์ OpenClaw จะใช้การส่งผลลัพธ์สุดท้ายตามปกติและล้างตัวอย่างที่ค้างอยู่
สำหรับการตอบกลับที่ซับซ้อน (เช่น payload สื่อ) OpenClaw จะ fallback ไปใช้การส่งผลลัพธ์สุดท้ายตามปกติแล้วล้างข้อความตัวอย่าง
Preview streaming แยกจาก block streaming เมื่อเปิดใช้ block streaming สำหรับ Telegram อย่างชัดเจน OpenClaw จะข้าม preview stream เพื่อหลีกเลี่ยงการสตรีมซ้ำสอง
พฤติกรรม reasoning stream:
/reasoning streamใช้เส้นทาง reasoning-preview ของช่องทางที่รองรับ; บน Telegram จะสตรีม reasoning เข้าไปใน live preview ระหว่างสร้างคำตอบ- reasoning preview จะถูกลบหลังจากส่งผลลัพธ์สุดท้าย; ใช้
/reasoning onเมื่อควรให้ reasoning ยังคงมองเห็นได้ - คำตอบสุดท้ายถูกส่งโดยไม่มีข้อความ reasoning
การจัดรูปแบบข้อความแบบ Rich
ข้อความขาออกใช้ข้อความ Telegram HTML มาตรฐานโดยค่าเริ่มต้น เพื่อให้คำตอบยังอ่านได้ใน client ของ Telegram ปัจจุบัน โหมดความเข้ากันได้นี้รองรับตัวหนา ตัวเอียง ลิงก์ โค้ด สปอยเลอร์ และ quote ตามปกติ แต่ไม่รองรับบล็อกแบบ rich-only ของ Bot API 10.1 เช่น ตารางดั้งเดิม details สื่อ rich และสูตร
ตั้งค่า channels.telegram.richMessages: true เพื่อเลือกใช้ข้อความ rich ของ Bot API 10.1:
{channels: {telegram: { richMessages: true,},},}เมื่อเปิดใช้งาน:
- agent จะได้รับแจ้งว่าข้อความ rich ของ Telegram พร้อมใช้งานสำหรับบอท/บัญชีนี้
- ข้อความ Markdown จะถูก render ผ่าน Markdown IR ของ OpenClaw และส่งเป็น Telegram rich HTML
- payload rich HTML แบบชัดเจนจะคง tag ของ Bot API 10.1 ที่รองรับไว้ เช่น heading, table, details, rich media และ formula
- caption ของสื่อยังคงใช้ Telegram HTML captions เพราะข้อความ rich ไม่ได้แทนที่ caption
วิธีนี้ช่วยให้ข้อความของโมเดลอยู่ห่างจาก sigil ของ Telegram Rich Markdown ดังนั้นสกุลเงินอย่าง $400-600K จะไม่ถูก parse เป็นคณิตศาสตร์ ข้อความ rich ที่ยาวจะถูกแยกอัตโนมัติตามขีดจำกัด rich text และ rich block ของ Telegram ตารางที่เกินขีดจำกัดคอลัมน์ของ Telegram จะถูกส่งเป็น code block
ค่าเริ่มต้น: ปิดเพื่อความเข้ากันได้ของ client ข้อความ rich ต้องใช้ client ของ Telegram ที่เข้ากันได้; client Desktop, Web, Android และ third-party ปัจจุบันบางตัวแสดงข้อความ rich ที่รับแล้วเป็น unsupported ปิดตัวเลือกนี้ไว้ เว้นแต่ client ทุกตัวที่ใช้กับบอทสามารถ render ได้ /status แสดงว่าเซสชัน Telegram ปัจจุบันเปิดหรือปิดข้อความ rich อยู่
Link preview เปิดใช้งานโดยค่าเริ่มต้น channels.telegram.linkPreview: false จะข้ามการตรวจจับ entity อัตโนมัติสำหรับ rich text
คำสั่งดั้งเดิมและคำสั่งกำหนดเอง
การลงทะเบียนเมนูคำสั่ง Telegram ถูกจัดการตอนเริ่มต้นด้วย setMyCommands
ค่าเริ่มต้นของคำสั่งดั้งเดิม:
commands.native: "auto"เปิดใช้คำสั่งดั้งเดิมสำหรับ Telegram
เพิ่มรายการเมนูคำสั่งกำหนดเอง:
{channels: {telegram: { customCommands: [ { command: "backup", description: "Git backup" }, { command: "generate", description: "Create an image" }, ],},},}กฎ:
- ชื่อจะถูก normalize (ตัด
/นำหน้าออก, แปลงเป็นตัวพิมพ์เล็ก) - pattern ที่ถูกต้อง:
a-z,0-9,_, ความยาว1..32 - คำสั่งกำหนดเองไม่สามารถ override คำสั่งดั้งเดิมได้
- ข้อขัดแย้ง/รายการซ้ำจะถูกข้ามและบันทึก log
หมายเหตุ:
- คำสั่งกำหนดเองเป็นเพียงรายการเมนูเท่านั้น; ไม่ได้ implement พฤติกรรมอัตโนมัติ
- คำสั่งของ plugin/skill ยังทำงานได้เมื่อพิมพ์ แม้จะไม่แสดงในเมนู Telegram
หากปิดใช้งานคำสั่งดั้งเดิม built-in จะถูกลบ คำสั่ง custom/plugin อาจยังลงทะเบียนได้หากกำหนดค่าไว้
ความล้มเหลวในการตั้งค่าที่พบบ่อย:
setMyCommands failedพร้อมBOT_COMMANDS_TOO_MUCHหมายความว่าเมนู Telegram ยังล้นหลังจากตัดรายการแล้ว; ลดคำสั่ง plugin/skill/custom หรือปิดchannels.telegram.commands.nativedeleteWebhook,deleteMyCommandsหรือsetMyCommandsล้มเหลวพร้อม404: Not Foundขณะที่คำสั่ง curl ของ Bot API โดยตรงทำงานได้ อาจหมายความว่าchannels.telegram.apiRootถูกตั้งเป็น endpoint/bot<TOKEN>แบบเต็มapiRootต้องเป็นเพียง root ของ Bot API เท่านั้น และopenclaw doctor --fixจะลบ/bot<TOKEN>ต่อท้ายที่เกิดขึ้นโดยไม่ตั้งใจgetMe returned 401หมายความว่า Telegram ปฏิเสธ token ของบอทที่กำหนดค่าไว้ อัปเดตbotToken,tokenFileหรือTELEGRAM_BOT_TOKENด้วย token ปัจจุบันจาก BotFather; OpenClaw จะหยุดก่อน polling ดังนั้นกรณีนี้จะไม่ถูกรายงานเป็นความล้มเหลวในการล้าง webhooksetMyCommands failedพร้อมข้อผิดพลาด network/fetch มักหมายความว่า outbound DNS/HTTPS ไปยังapi.telegram.orgถูกบล็อก
คำสั่งจับคู่อุปกรณ์ (plugin device-pair)
เมื่อ plugin device-pair ติดตั้งอยู่:
/pairสร้างโค้ดตั้งค่า- วางโค้ดในแอป iOS
/pair pendingแสดงรายการคำขอที่รอดำเนินการ (รวม role/scopes)- อนุมัติคำขอ:
/pair approve <requestId>สำหรับการอนุมัติแบบระบุชัดเจน/pair approveเมื่อมีคำขอที่รอดำเนินการเพียงรายการเดียว/pair approve latestสำหรับรายการล่าสุด
โค้ดตั้งค่ามี bootstrap token อายุสั้น bootstrap ด้วย setup-code ในตัวเป็นแบบ node-only: การเชื่อมต่อครั้งแรกจะสร้างคำขอ node ที่รอดำเนินการ และหลังอนุมัติ Gateway จะคืน token ของ node ที่คงทนพร้อม scopes: [] ไม่ได้คืน token ผู้ปฏิบัติงานที่ hand off แล้ว; การเข้าถึงของผู้ปฏิบัติงานต้องใช้การจับคู่ผู้ปฏิบัติงานที่อนุมัติแยกต่างหากหรือ flow token แยกต่างหาก
หากอุปกรณ์ลองใหม่ด้วยรายละเอียด auth ที่เปลี่ยนไป (เช่น role/scopes/public key) คำขอที่รอดำเนินการก่อนหน้าจะถูก supersede และคำขอใหม่จะใช้ requestId อื่น รัน /pair pending อีกครั้งก่อนอนุมัติ
รายละเอียดเพิ่มเติม: การจับคู่.
ปุ่มแบบอินไลน์
กำหนดค่าขอบเขตแป้นพิมพ์แบบอินไลน์:
{channels: {telegram: { capabilities: { inlineButtons: "allowlist", },},},}การแทนที่ต่อบัญชี:
{channels: {telegram: { accounts: { main: { capabilities: { inlineButtons: "allowlist", }, }, },},},}ขอบเขต:
offdmgroupallallowlist(ค่าเริ่มต้น)
capabilities: ["inlineButtons"] แบบเดิมจะแมปเป็น inlineButtons: "all"
ตัวอย่างการดำเนินการกับข้อความ:
{action: "send",channel: "telegram",to: "123456789",message: "Choose an option:",buttons: [[ { text: "Yes", callback_data: "yes" }, { text: "No", callback_data: "no" },],[{ text: "Cancel", callback_data: "cancel" }],],}ตัวอย่างปุ่ม Mini App:
{action: "send",channel: "telegram",to: "123456789",message: "Open app:",presentation: {blocks: [ { type: "buttons", buttons: [{ label: "Launch", web_app: { url: "https://example.com/app" } }], },],},}ปุ่ม Telegram web_app ทำงานเฉพาะในแชตส่วนตัวระหว่างผู้ใช้กับ
บอตเท่านั้น
การคลิกคอลแบ็กจะถูกส่งให้เอเจนต์เป็นข้อความ:
callback_data: <value>
การดำเนินการกับข้อความ Telegram สำหรับเอเจนต์และระบบอัตโนมัติ
การดำเนินการของเครื่องมือ Telegram ประกอบด้วย:
sendMessage(to,content, ตัวเลือกmediaUrl,replyToMessageId,messageThreadId)react(chatId,messageId,emoji)deleteMessage(chatId,messageId)editMessage(chatId,messageId,contentหรือcaption, ตัวเลือกปุ่มอินไลน์presentation; การแก้ไขเฉพาะปุ่มจะอัปเดตมาร์กอัปการตอบกลับ)createForumTopic(chatId,name, ตัวเลือกiconColor,iconCustomEmojiId)
การดำเนินการกับข้อความของช่องทางแสดงนามแฝงที่ใช้งานง่าย (send, react, delete, edit, sticker, sticker-search, topic-create)
การควบคุมเกต:
channels.telegram.actions.sendMessagechannels.telegram.actions.deleteMessagechannels.telegram.actions.reactionschannels.telegram.actions.sticker(ค่าเริ่มต้น: ปิดใช้งาน)
หมายเหตุ: ขณะนี้ edit และ topic-create เปิดใช้งานโดยค่าเริ่มต้น และไม่มีตัวสลับ channels.telegram.actions.* แยกต่างหาก
การส่งขณะรันไทม์ใช้สแนปช็อตการกำหนดค่า/ความลับที่ใช้งานอยู่ (เริ่มต้น/โหลดใหม่) ดังนั้นเส้นทางการดำเนินการจะไม่ทำการแก้ค่า SecretRef แบบเฉพาะกิจซ้ำต่อการส่งแต่ละครั้ง
ความหมายของการลบรีแอ็กชัน: /tools/reactions
แท็กเธรดการตอบกลับ
Telegram รองรับแท็กเธรดการตอบกลับแบบชัดเจนในเอาต์พุตที่สร้างขึ้น:
[[reply_to_current]]ตอบกลับข้อความที่ทริกเกอร์[[reply_to:<id>]]ตอบกลับ ID ข้อความ Telegram ที่ระบุ
channels.telegram.replyToMode ควบคุมการจัดการ:
off(ค่าเริ่มต้น)firstall
เมื่อเปิดใช้งานเธรดการตอบกลับและมีข้อความหรือคำบรรยาย Telegram ต้นฉบับ OpenClaw จะรวมข้อความอ้างอิง Telegram แบบเนทีฟโดยอัตโนมัติ Telegram จำกัดข้อความอ้างอิงเนทีฟไว้ที่ 1024 หน่วยรหัส UTF-16 ดังนั้นข้อความที่ยาวกว่าจะถูกอ้างอิงจากจุดเริ่มต้น และจะถอยกลับเป็นการตอบกลับแบบธรรมดาหาก Telegram ปฏิเสธการอ้างอิง
หมายเหตุ: off ปิดใช้งานเธรดการตอบกลับโดยนัย แท็ก [[reply_to_*]] แบบชัดเจนยังคงได้รับการปฏิบัติตาม
หัวข้อฟอรัมและพฤติกรรมของเธรด
ซูเปอร์กรุ๊ปแบบฟอรัม:
- คีย์เซสชันของหัวข้อเติม
:topic:<threadId>ต่อท้าย - การตอบกลับและการแสดงสถานะกำลังพิมพ์มุ่งไปยังเธรดหัวข้อ
- เส้นทางการกำหนดค่าหัวข้อ:
channels.telegram.groups.<chatId>.topics.<threadId>
กรณีพิเศษของหัวข้อทั่วไป (threadId=1):
- การส่งข้อความละเว้น
message_thread_id(Telegram ปฏิเสธsendMessage(...thread_id=1)) - การดำเนินการกำลังพิมพ์ยังคงรวม
message_thread_id
การสืบทอดของหัวข้อ: รายการหัวข้อสืบทอดการตั้งค่ากลุ่ม เว้นแต่จะถูกแทนที่ (requireMention, allowFrom, skills, systemPrompt, enabled, groupPolicy)
agentId ใช้เฉพาะหัวข้อและไม่สืบทอดจากค่าเริ่มต้นของกลุ่ม
topics."*" ตั้งค่าเริ่มต้นสำหรับทุกหัวข้อในกลุ่มนั้น; ID หัวข้อที่ตรงกันยังคงมีลำดับความสำคัญเหนือ "*"
การกำหนดเส้นทางเอเจนต์ต่อหัวข้อ: แต่ละหัวข้อสามารถกำหนดเส้นทางไปยังเอเจนต์คนละตัวได้ด้วยการตั้งค่า agentId ในการกำหนดค่าหัวข้อ สิ่งนี้ทำให้แต่ละหัวข้อมีเวิร์กสเปซ หน่วยความจำ และเซสชันที่แยกจากกัน ตัวอย่าง:
{ channels: { telegram: { groups: { "-1001234567890": { topics: { "1": { agentId: "main" }, // General topic → main agent "3": { agentId: "zu" }, // Dev topic → zu agent "5": { agentId: "coder" } // Code review → coder agent } } } } }}จากนั้นแต่ละหัวข้อจะมีคีย์เซสชันของตนเอง: agent:zu:telegram:group:-1001234567890:topic:3
การผูกหัวข้อ ACP แบบถาวร: หัวข้อฟอรัมสามารถปักหมุดเซสชันฮาร์เนส ACP ผ่านการผูก ACP แบบมีชนิดที่ระดับบนสุด (bindings[] พร้อม type: "acp" และ match.channel: "telegram", peer.kind: "group" และ ID ที่ระบุหัวข้อ เช่น -1001234567890:topic:42) ขณะนี้จำกัดขอบเขตไว้ที่หัวข้อฟอรัมในกลุ่ม/ซูเปอร์กรุ๊ป ดู เอเจนต์ ACP
การสปอว์น ACP ที่ผูกกับเธรดจากแชต: /acp spawn <agent> --thread here|auto ผูกหัวข้อปัจจุบันกับเซสชัน ACP ใหม่; ข้อความติดตามผลจะกำหนดเส้นทางไปที่นั่นโดยตรง OpenClaw ปักหมุดการยืนยันการสปอว์นไว้ในหัวข้อ ต้องให้ channels.telegram.threadBindings.spawnSessions ยังคงเปิดใช้งานอยู่ (ค่าเริ่มต้น: true)
บริบทเทมเพลตแสดง MessageThreadId และ IsForum แชต DM ที่มี message_thread_id จะเก็บเมทาดาทาการตอบกลับไว้; แชตเหล่านั้นใช้คีย์เซสชันที่รับรู้เธรดเฉพาะเมื่อ Telegram getMe รายงาน has_topics_enabled: true สำหรับบอตเท่านั้น
การแทนที่ dm.threadReplies และ direct.*.threadReplies เดิมถูกปลดออกโดยตั้งใจ; ใช้โหมดเธรดของ BotFather เป็นแหล่งความจริงเดียว และรัน openclaw doctor --fix เพื่อลบคีย์การกำหนดค่าที่ล้าสมัย
เสียง วิดีโอ และสติกเกอร์
ข้อความเสียง
Telegram แยกความแตกต่างระหว่างบันทึกเสียงกับไฟล์เสียง
- ค่าเริ่มต้น: พฤติกรรมแบบไฟล์เสียง
- แท็ก
[[audio_as_voice]]ในการตอบกลับของเอเจนต์เพื่อบังคับให้ส่งเป็นบันทึกเสียง - ทรานสคริปต์บันทึกเสียงขาเข้าถูกจัดกรอบเป็นข้อความที่สร้างโดยเครื่อง และไม่น่าเชื่อถือในบริบทของเอเจนต์; การตรวจจับการกล่าวถึงยังคงใช้ ทรานสคริปต์ดิบ ดังนั้นข้อความเสียงที่ถูกเกตด้วยการกล่าวถึงจึงยังทำงานต่อไป
ตัวอย่างการดำเนินการกับข้อความ:
{action: "send",channel: "telegram",to: "123456789",media: "https://example.com/voice.ogg",asVoice: true,}ข้อความวิดีโอ
Telegram แยกความแตกต่างระหว่างไฟล์วิดีโอกับโน้ตวิดีโอ
ตัวอย่างการดำเนินการของข้อความ:
{action: "send",channel: "telegram",to: "123456789",media: "https://example.com/video.mp4",asVideoNote: true,}โน้ตวิดีโอไม่รองรับคำบรรยายประกอบ ข้อความที่ระบุไว้จะถูกส่งแยกต่างหาก
สติกเกอร์
การจัดการสติกเกอร์ขาเข้า:
- WEBP แบบคงที่: ดาวน์โหลดและประมวลผล (placeholder
<media:sticker>) - TGS แบบเคลื่อนไหว: ข้าม
- WEBM วิดีโอ: ข้าม
ฟิลด์บริบทของสติกเกอร์:
Sticker.emojiSticker.setNameSticker.fileIdSticker.fileUniqueIdSticker.cachedDescription
คำอธิบายสติกเกอร์ถูกแคชไว้ในสถานะ Plugin ของ OpenClaw SQLite เพื่อลดการเรียกใช้งานวิชันซ้ำ
เปิดใช้การดำเนินการสติกเกอร์:
{channels: {telegram: { actions: { sticker: true, },},},}การดำเนินการส่งสติกเกอร์:
{action: "sticker",channel: "telegram",to: "123456789",fileId: "CAACAgIAAxkBAAI...",}ค้นหาสติกเกอร์ที่แคชไว้:
{action: "sticker-search",channel: "telegram",query: "cat waving",limit: 5,}การแจ้งเตือนรีแอ็กชัน
รีแอ็กชันของ Telegram เข้ามาเป็นการอัปเดต message_reaction (แยกจากเพย์โหลดข้อความ)
เมื่อเปิดใช้งาน OpenClaw จะจัดคิวเหตุการณ์ระบบ เช่น:
Telegram reaction added: 👍 by Alice (@alice) on msg 42
การกำหนดค่า:
channels.telegram.reactionNotifications:off | own | all(ค่าเริ่มต้น:own)channels.telegram.reactionLevel:off | ack | minimal | extensive(ค่าเริ่มต้น:minimal)
หมายเหตุ:
ownหมายถึงรีแอ็กชันของผู้ใช้ต่อข้อความที่บอตส่งเท่านั้น (แบบพยายามให้ดีที่สุดผ่านแคชข้อความที่ส่งแล้ว)- เหตุการณ์รีแอ็กชันยังคงเคารพการควบคุมการเข้าถึงของ Telegram (
dmPolicy,allowFrom,groupPolicy,groupAllowFrom); ผู้ส่งที่ไม่ได้รับอนุญาตจะถูกทิ้ง - Telegram ไม่ให้รหัสเธรดในการอัปเดตรีแอ็กชัน
- กลุ่มที่ไม่ใช่ฟอรัมจะส่งต่อไปยังเซสชันแชตกลุ่ม
- กลุ่มฟอรัมจะส่งต่อไปยังเซสชันหัวข้อทั่วไปของกลุ่ม (
:topic:1) ไม่ใช่หัวข้อต้นทางที่แน่นอน
allowed_updates สำหรับการโพล/Webhook จะรวม message_reaction โดยอัตโนมัติ
รีแอ็กชันรับทราบ
ackReaction ส่งอีโมจิรับทราบขณะที่ OpenClaw กำลังประมวลผลข้อความขาเข้า ackReactionScope ตัดสินว่าอีโมจินั้นจะถูกส่งจริง เมื่อใด
ลำดับการแก้ค่าอีโมจิ (ackReaction):
channels.telegram.accounts.<accountId>.ackReactionchannels.telegram.ackReactionmessages.ackReaction- อีโมจิสำรองจากตัวตนของเอเจนต์ (
agents.list[].identity.emojiมิฉะนั้นใช้ "👀")
หมายเหตุ:
- Telegram คาดหวังอีโมจิยูนิโค้ด (เช่น "👀")
- ใช้
""เพื่อปิดใช้งานรีแอ็กชันสำหรับแชนเนลหรือบัญชี
ขอบเขต (messages.ackReactionScope):
ผู้ให้บริการ Telegram อ่านขอบเขตจาก messages.ackReactionScope (ค่าเริ่มต้น "group-mentions") ปัจจุบันไม่มีการ override ระดับบัญชี Telegram หรือระดับแชนเนล Telegram
ค่า: "all" (ข้อความส่วนตัว + กลุ่ม), "direct" (เฉพาะข้อความส่วนตัว), "group-all" (ทุกข้อความกลุ่ม ไม่มีข้อความส่วนตัว), "group-mentions" (กลุ่มเมื่อมีการกล่าวถึงบอต; ไม่มีข้อความส่วนตัว — นี่คือค่าเริ่มต้น), "off" / "none" (ปิดใช้งาน)
การเขียนการกำหนดค่าจากเหตุการณ์และคำสั่งของ Telegram
การเขียนการกำหนดค่าแชนเนลเปิดใช้งานโดยค่าเริ่มต้น (configWrites !== false)
การเขียนที่ถูกทริกเกอร์โดย Telegram รวมถึง:
- เหตุการณ์การย้ายกลุ่ม (
migrate_to_chat_id) เพื่ออัปเดตchannels.telegram.groups /config setและ/config unset(ต้องเปิดใช้งานคำสั่ง)
ปิดใช้งาน:
{channels: {telegram: { configWrites: false,},},}การโพลแบบยาวเทียบกับ Webhook
ค่าเริ่มต้นคือการโพลแบบยาว สำหรับโหมด Webhook ให้ตั้ง channels.telegram.webhookUrl และ channels.telegram.webhookSecret; ตัวเลือกเสริมคือ webhookPath, webhookHost, webhookPort (ค่าเริ่มต้น /telegram-webhook, 127.0.0.1, 8787)
ในโหมดการโพลแบบยาว OpenClaw จะคง watermark สำหรับการรีสตาร์ตไว้หลังจากส่งต่อการอัปเดตสำเร็จแล้วเท่านั้น หากตัวจัดการล้มเหลว การอัปเดตนั้นจะยังลองซ้ำได้ในโปรเซสเดียวกัน และจะไม่ถูกเขียนว่าเสร็จสมบูรณ์สำหรับการตัดซ้ำหลังรีสตาร์ต
ตัวรับฟังในเครื่องผูกกับ 127.0.0.1:8787 สำหรับทางเข้าจากสาธารณะ ให้ตั้ง reverse proxy ไว้หน้า local port หรือตั้ง webhookHost: "0.0.0.0" อย่างตั้งใจ
โหมด Webhook ตรวจสอบ guard ของคำขอ โทเค็นลับของ Telegram และเนื้อหา JSON ก่อนส่งคืน 200 ให้ Telegram
จากนั้น OpenClaw จะประมวลผลการอัปเดตแบบอะซิงโครนัสผ่านเลนบอตต่อแชต/ต่อหัวข้อเดียวกับที่ใช้ในการโพลแบบยาว ดังนั้นเทิร์นของเอเจนต์ที่ช้าจะไม่ทำให้ ACK การส่งของ Telegram ค้าง
ขีดจำกัด การลองใหม่ และเป้าหมาย CLI
- ค่าเริ่มต้นของ
channels.telegram.textChunkLimitคือ 4000 channels.telegram.chunkMode="newline"จะเลือกขอบเขตย่อหน้า (บรรทัดว่าง) ก่อนการแยกตามความยาวchannels.telegram.mediaMaxMb(ค่าเริ่มต้น 100) จำกัดขนาดสื่อ Telegram ขาเข้าและขาออกchannels.telegram.mediaGroupFlushMs(ค่าเริ่มต้น 500) ควบคุมระยะเวลาที่อัลบั้ม/กลุ่มสื่อของ Telegram จะถูกบัฟเฟอร์ไว้ก่อนที่ OpenClaw จะส่งออกเป็นข้อความขาเข้าเดียว เพิ่มค่านี้หากส่วนต่าง ๆ ของอัลบั้มมาถึงช้า ลดค่านี้เพื่อลดเวลาแฝงของการตอบกลับอัลบั้มchannels.telegram.timeoutSecondsแทนที่ timeout ของไคลเอนต์ Telegram API (หากไม่ได้ตั้งค่า จะใช้ค่าเริ่มต้นของ grammY) ไคลเอนต์บอทจะจำกัดค่าที่ตั้งไว้ให้อยู่ต่ำกว่า guard คำขอข้อความ/การพิมพ์ขาออก 60 วินาที เพื่อให้ grammY ไม่ยกเลิกการส่งคำตอบที่มองเห็นได้ก่อนที่ transport guard และ fallback ของ OpenClaw จะทำงานได้ Long polling ยังคงใช้ guard คำขอgetUpdates45 วินาที เพื่อไม่ให้ poll ที่ว่างอยู่ถูกทิ้งไว้อย่างไม่มีกำหนดchannels.telegram.pollingStallThresholdMsมีค่าเริ่มต้นเป็น120000; ปรับค่าระหว่าง30000ถึง600000เฉพาะสำหรับการรีสตาร์ท polling-stall ที่เป็นผลบวกเทียม- ประวัติบริบทกลุ่มใช้
channels.telegram.historyLimitหรือmessages.groupChat.historyLimit(ค่าเริ่มต้น 50);0ปิดใช้งาน - บริบทเสริมจากการตอบกลับ/อ้างอิง/ส่งต่อจะถูกทำให้เป็นมาตรฐานเข้าในหน้าต่างบริบทการสนทนาที่เลือกไว้หนึ่งรายการ เมื่อ gateway สังเกตเห็นข้อความแม่แล้ว แคชข้อความที่สังเกตเห็นอยู่ในสถานะ Plugin SQLite ของ OpenClaw และ
openclaw doctor --fixจะนำเข้า sidecar รุ่นเก่า Telegram รวมreply_to_messageแบบตื้นเพียงหนึ่งรายการในอัปเดตเท่านั้น ดังนั้นเชนที่เก่ากว่าแคชจะถูกจำกัดตาม payload อัปเดตปัจจุบันของ Telegram - allowlist ของ Telegram ใช้กำกับเป็นหลักว่าใครสามารถทริกเกอร์ agent ได้ ไม่ใช่ขอบเขตการปกปิดบริบทเสริมแบบเต็ม
- การควบคุมประวัติ DM:
channels.telegram.dmHistoryLimitchannels.telegram.dms["<user_id>"].historyLimit
- คอนฟิก
channels.telegram.retryใช้กับตัวช่วยส่งของ Telegram (CLI/tools/actions) สำหรับข้อผิดพลาด API ขาออกที่กู้คืนได้ การส่งคำตอบสุดท้ายขาเข้ายังใช้การลองส่งซ้ำแบบ safe-send ที่มีขอบเขตสำหรับความล้มเหลวก่อนเชื่อมต่อของ Telegram แต่จะไม่ลองซ้ำกับซองเครือข่ายหลังส่งที่กำกวม ซึ่งอาจทำให้ข้อความที่มองเห็นได้ซ้ำกัน
เป้าหมายการส่งของ CLI และ message-tool สามารถเป็น chat ID แบบตัวเลข username หรือเป้าหมาย forum topic:
openclaw message send --channel telegram --target 123456789 --message "hi"openclaw message send --channel telegram --target @name --message "hi"openclaw message send --channel telegram --target -1001234567890:topic:42 --message "hi topic"poll ของ Telegram ใช้ openclaw message poll และรองรับ forum topic:
openclaw message poll --channel telegram --target 123456789 \--poll-question "Ship it?" --poll-option "Yes" --poll-option "No"openclaw message poll --channel telegram --target -1001234567890:topic:42 \--poll-question "Pick a time" --poll-option "10am" --poll-option "2pm" \--poll-duration-seconds 300 --poll-publicflag poll เฉพาะ Telegram:
--poll-duration-seconds(5-600)--poll-anonymous--poll-public--thread-idสำหรับ forum topic (หรือใช้เป้าหมาย:topic:)
การส่งของ Telegram ยังรองรับ:
--presentationพร้อมบล็อกbuttonsสำหรับ inline keyboard เมื่อchannels.telegram.capabilities.inlineButtonsอนุญาต--pinหรือ--delivery '{"pin":true}'เพื่อขอการส่งแบบปักหมุดเมื่อบอทสามารถปักหมุดในแชตนั้นได้--force-documentเพื่อส่งรูปภาพ GIF และวิดีโอขาออกเป็นเอกสารแทนการอัปโหลดเป็นรูปภาพที่บีบอัด สื่อแบบเคลื่อนไหว หรือวิดีโอ
การกำกับ action:
channels.telegram.actions.sendMessage=falseปิดใช้งานข้อความ Telegram ขาออก รวมถึง pollchannels.telegram.actions.poll=falseปิดใช้งานการสร้าง poll ของ Telegram โดยยังเปิดใช้การส่งปกติไว้
การอนุมัติ exec ใน Telegram
Telegram รองรับการอนุมัติ exec ใน DM ของผู้อนุมัติ และสามารถโพสต์ prompt ในแชตหรือตัว topic ต้นทางได้ตามตัวเลือก ผู้อนุมัติต้องเป็น Telegram user ID แบบตัวเลข
เส้นทางคอนฟิก:
channels.telegram.execApprovals.enabled(เปิดใช้อัตโนมัติเมื่อ resolve ผู้อนุมัติได้อย่างน้อยหนึ่งคน)channels.telegram.execApprovals.approvers(fallback ไปยัง owner ID แบบตัวเลขจากcommands.ownerAllowFrom)channels.telegram.execApprovals.target:dm(ค่าเริ่มต้น) |channel|bothagentFilter,sessionFilter
channels.telegram.allowFrom, groupAllowFrom และ defaultTo ควบคุมว่าใครคุยกับบอทได้และบอทส่งคำตอบปกติไปที่ใด สิ่งเหล่านี้ไม่ได้ทำให้ใครเป็นผู้อนุมัติ exec การจับคู่ DM ที่อนุมัติครั้งแรกจะ bootstrap commands.ownerAllowFrom เมื่อยังไม่มีเจ้าของคำสั่ง ดังนั้นการตั้งค่าแบบเจ้าของหนึ่งคนยังทำงานได้โดยไม่ต้องทำ ID ซ้ำใต้ execApprovals.approvers
การส่งในช่องจะแสดงข้อความคำสั่งในแชต เปิดใช้ channel หรือ both เฉพาะในกลุ่ม/topic ที่เชื่อถือได้ เมื่อ prompt ไปถึง forum topic OpenClaw จะคง topic นั้นไว้สำหรับ prompt อนุมัติและการติดตามผล การอนุมัติ exec จะหมดอายุหลัง 30 นาทีตามค่าเริ่มต้น
ปุ่มอนุมัติแบบ inline ยังต้องให้ channels.telegram.capabilities.inlineButtons อนุญาตพื้นผิวเป้าหมาย (dm, group หรือ all) ด้วย ID การอนุมัติที่ขึ้นต้นด้วย plugin: จะ resolve ผ่านการอนุมัติของ plugin; รายการอื่นจะ resolve ผ่านการอนุมัติ exec ก่อน
การควบคุมการตอบกลับข้อผิดพลาด
เมื่อ agent พบข้อผิดพลาดด้านการส่งหรือ provider Telegram สามารถตอบกลับด้วยข้อความข้อผิดพลาดหรือปิดการแสดงผลได้ คีย์คอนฟิกสองรายการควบคุมพฤติกรรมนี้:
| คีย์ | ค่า | ค่าเริ่มต้น | คำอธิบาย |
|---|---|---|---|
channels.telegram.errorPolicy |
reply, silent |
reply |
reply ส่งข้อความข้อผิดพลาดที่เป็นมิตรไปยังแชต silent ปิดการตอบกลับข้อผิดพลาดทั้งหมด |
channels.telegram.errorCooldownMs |
number (ms) | 60000 |
เวลาขั้นต่ำระหว่างการตอบกลับข้อผิดพลาดไปยังแชตเดียวกัน ป้องกันสแปมข้อผิดพลาดระหว่างเหตุขัดข้อง |
รองรับการแทนที่รายบัญชี รายกลุ่ม และราย topic (ใช้การสืบทอดเดียวกับคีย์คอนฟิก Telegram อื่น ๆ)
{ channels: { telegram: { errorPolicy: "reply", errorCooldownMs: 120000, groups: { "-1001234567890": { errorPolicy: "silent", // suppress errors in this group }, }, }, },}การแก้ปัญหา
บอทไม่ตอบกลับข้อความกลุ่มที่ไม่ได้ mention
- หาก
requireMention=falseโหมดความเป็นส่วนตัวของ Telegram ต้องอนุญาตการมองเห็นแบบเต็ม- BotFather:
/setprivacy-> Disable - จากนั้นลบ + เพิ่มบอทกลับเข้าไปในกลุ่ม
- BotFather:
openclaw channels statusจะเตือนเมื่อคอนฟิกคาดหวังข้อความกลุ่มที่ไม่ได้ mentionopenclaw channels status --probeสามารถตรวจสอบ group ID แบบตัวเลขที่ระบุชัดเจนได้; wildcard"*"ไม่สามารถ probe membership ได้- การทดสอบเซสชันแบบเร็ว:
/activation always
บอทไม่เห็นข้อความกลุ่มเลย
- เมื่อมี
channels.telegram.groupsกลุ่มต้องถูกระบุไว้ (หรือรวม"*") - ตรวจสอบ membership ของบอทในกลุ่ม
- ตรวจสอบ log:
openclaw logs --followเพื่อดูเหตุผลการข้าม
คำสั่งทำงานบางส่วนหรือไม่ทำงานเลย
- อนุญาตตัวตนผู้ส่งของคุณ (การจับคู่และ/หรือ
allowFromแบบตัวเลข) - การอนุญาตคำสั่งยังคงมีผลแม้นโยบายกลุ่มจะเป็น
open setMyCommands failedพร้อมBOT_COMMANDS_TOO_MUCHหมายความว่าเมนู native มีรายการมากเกินไป; ลดคำสั่งของ plugin/skill/custom หรือปิดเมนู native- การเรียก startup
deleteMyCommands/setMyCommandsและการเรียก typingsendChatActionถูกจำกัดขอบเขตและลองใหม่หนึ่งครั้งผ่าน transport fallback ของ Telegram เมื่อคำขอ timeout ข้อผิดพลาด network/fetch ที่เกิดซ้ำมักบ่งชี้ปัญหาการเข้าถึง DNS/HTTPS ไปยังapi.telegram.org
Startup รายงาน token ที่ไม่ได้รับอนุญาต
getMe returned 401คือความล้มเหลวในการยืนยันตัวตนของ Telegram สำหรับ bot token ที่ตั้งค่าไว้- คัดลอกใหม่หรือสร้าง bot token ใหม่ใน BotFather แล้วอัปเดต
channels.telegram.botToken,channels.telegram.tokenFile,channels.telegram.accounts.<id>.botTokenหรือTELEGRAM_BOT_TOKENสำหรับบัญชีเริ่มต้น deleteWebhook 401 Unauthorizedระหว่าง startup ก็เป็นความล้มเหลวด้าน auth เช่นกัน; การปฏิบัติต่อมันเหมือน "ไม่มี webhook อยู่" จะเพียงเลื่อนความล้มเหลวจาก bad-token เดิมไปยังการเรียก API ภายหลังเท่านั้น
Polling หรือเครือข่ายไม่เสถียร
- Node 22+ + fetch/proxy แบบกำหนดเองอาจทริกเกอร์พฤติกรรม abort ทันทีหากชนิด AbortSignal ไม่ตรงกัน
- host บางตัว resolve
api.telegram.orgเป็น IPv6 ก่อน; egress IPv6 ที่เสียอาจทำให้ Telegram API ล้มเหลวเป็นครั้งคราว - หาก log มี
TypeError: fetch failedหรือNetwork request for 'getUpdates' failed!ตอนนี้ OpenClaw จะลองใหม่กับรายการเหล่านี้ในฐานะข้อผิดพลาดเครือข่ายที่กู้คืนได้ - ระหว่าง polling startup OpenClaw จะใช้ probe startup
getMeที่สำเร็จซ้ำสำหรับ grammY เพื่อให้ runner ไม่ต้องใช้getMeครั้งที่สองก่อนgetUpdatesครั้งแรก - หาก
deleteWebhookล้มเหลวด้วยข้อผิดพลาดเครือข่ายชั่วคราวระหว่าง polling startup OpenClaw จะดำเนินต่อเข้าสู่ long polling แทนการเรียก control-plane ก่อน poll อีกครั้ง webhook ที่ยัง active อยู่จะแสดงเป็น conflict ของgetUpdates; จากนั้น OpenClaw จะสร้าง transport ของ Telegram ใหม่และลอง cleanup webhook ใหม่ - หาก socket ของ Telegram ถูก recycle ในรอบเวลาคงที่สั้น ๆ ให้ตรวจสอบ
channels.telegram.timeoutSecondsที่ต่ำ; ไคลเอนต์บอทจะจำกัดค่าที่ตั้งไว้ให้อยู่ต่ำกว่า guard คำขอขาออกและgetUpdatesแต่ release เก่ากว่าอาจ abort ทุก poll หรือคำตอบเมื่อค่านี้ถูกตั้งไว้ต่ำกว่า guard เหล่านั้น - หาก log มี
Polling stall detectedOpenClaw จะรีสตาร์ท polling และสร้าง transport ของ Telegram ใหม่หลังจากไม่มี liveness ของ long-poll ที่เสร็จสมบูรณ์เป็นเวลา 120 วินาทีตามค่าเริ่มต้น openclaw channels status --probeและopenclaw doctorจะเตือนเมื่อบัญชี polling ที่กำลังทำงานยังทำgetUpdatesไม่เสร็จหลัง startup grace, เมื่อบัญชี webhook ที่กำลังทำงานยังทำsetWebhookไม่เสร็จหลัง startup grace หรือเมื่อกิจกรรม transport polling ที่สำเร็จล่าสุดเก่าเกินไป- เพิ่ม
channels.telegram.pollingStallThresholdMsเฉพาะเมื่อการเรียกgetUpdatesที่รันนานยังปกติแต่ host ของคุณยังรายงานการรีสตาร์ท polling-stall แบบผลบวกเทียม stall ที่เกิดซ้ำมักชี้ไปที่ปัญหา proxy, DNS, IPv6 หรือ TLS egress ระหว่าง host กับapi.telegram.org - Telegram ยังเคารพ env proxy ของ process สำหรับ transport ของ Bot API รวมถึง
HTTP_PROXY,HTTPS_PROXY,ALL_PROXYและตัวแปรแบบตัวพิมพ์เล็กของแต่ละรายการNO_PROXY/no_proxyยังสามารถ bypassapi.telegram.orgได้ - หาก proxy ที่ OpenClaw จัดการถูกตั้งค่าผ่าน
OPENCLAW_PROXY_URLสำหรับสภาพแวดล้อมบริการ และไม่มี env proxy มาตรฐานอยู่ Telegram จะใช้ URL นั้นสำหรับ transport ของ Bot API ด้วย - บน host VPS ที่ egress/TLS ตรงไม่เสถียร ให้ route การเรียก Telegram API ผ่าน
channels.telegram.proxy:
channels:telegram:proxy: socks5://<user>:<password>@proxy-host:1080- Node 22+ มีค่าเริ่มต้นเป็น
autoSelectFamily=true(ยกเว้น WSL2) ลำดับผลลัพธ์ DNS ของ Telegram เคารพOPENCLAW_TELEGRAM_DNS_RESULT_ORDERจากนั้นchannels.telegram.network.dnsResultOrderจากนั้นค่าเริ่มต้นของ process เช่นNODE_OPTIONS=--dns-result-order=ipv4first; หากไม่มีรายการใดมีผล Node 22+ จะ fallback ไปที่ipv4first - หาก host ของคุณเป็น WSL2 หรือทำงานได้ดีกว่าอย่างชัดเจนกับพฤติกรรม IPv4-only ให้บังคับการเลือก family:
channels:telegram:network: autoSelectFamily: false- อนุญาตคำตอบช่วงเบนช์มาร์ก RFC 2544 (
198.18.0.0/15) สำหรับการดาวน์โหลดสื่อของ Telegram อยู่แล้วตามค่าเริ่มต้น หาก fake-IP ที่เชื่อถือได้หรือพร็อกซีแบบโปร่งใสเขียนapi.telegram.orgใหม่เป็นที่อยู่ private/internal/special-use อื่นระหว่างการดาวน์โหลดสื่อ คุณสามารถเลือกเปิดใช้การข้ามเฉพาะ Telegram ได้ดังนี้:
channels:telegram:network: dangerouslyAllowPrivateNetwork: true- การเลือกเปิดใช้แบบเดียวกันมีให้ต่อบัญชีที่
channels.telegram.accounts.<accountId>.network.dangerouslyAllowPrivateNetwork - หากพร็อกซีของคุณ resolve โฮสต์สื่อของ Telegram เป็น
198.18.x.xให้ปิด แฟล็กอันตรายไว้ก่อน สื่อของ Telegram อนุญาตช่วงเบนช์มาร์ก RFC 2544 อยู่แล้วตามค่าเริ่มต้น
- การแทนที่ผ่านสภาพแวดล้อม (ชั่วคราว):
OPENCLAW_TELEGRAM_DISABLE_AUTO_SELECT_FAMILY=1OPENCLAW_TELEGRAM_ENABLE_AUTO_SELECT_FAMILY=1OPENCLAW_TELEGRAM_DNS_RESULT_ORDER=ipv4first
- ตรวจสอบคำตอบ DNS:
dig +short api.telegram.org Adig +short api.telegram.org AAAAความช่วยเหลือเพิ่มเติม: การแก้ปัญหา Channel
ข้อมูลอ้างอิงการกำหนดค่า
ข้อมูลอ้างอิงหลัก: ข้อมูลอ้างอิงการกำหนดค่า - Telegram
High-signal Telegram fields
- การเริ่มต้น/การยืนยันตัวตน:
enabled,botToken,tokenFile,accounts.*(tokenFileต้องชี้ไปยังไฟล์ปกติ; symlink จะถูกปฏิเสธ) - การควบคุมการเข้าถึง:
dmPolicy,allowFrom,groupPolicy,groupAllowFrom,groups,groups.*.topics.*,bindings[]ระดับบนสุด (type: "acp") - ค่าเริ่มต้นของหัวข้อ:
groups.<chatId>.topics."*"ใช้กับหัวข้อฟอรัมที่ไม่ตรงกัน; ID หัวข้อแบบตรงตัวจะเขียนทับค่านี้ - การอนุมัติ exec:
execApprovals,accounts.*.execApprovals - คำสั่ง/เมนู:
commands.native,commands.nativeSkills,customCommands - เธรด/การตอบกลับ:
replyToMode - การสตรีม:
streaming(ตัวอย่าง),streaming.preview.toolProgress,blockStreaming - การจัดรูปแบบ/การส่ง:
textChunkLimit,chunkMode,richMessages,linkPreview,responsePrefix - สื่อ/เครือข่าย:
mediaMaxMb,mediaGroupFlushMs,timeoutSeconds,pollingStallThresholdMs,retry,network.autoSelectFamily,network.dangerouslyAllowPrivateNetwork,proxy - root API แบบกำหนดเอง:
apiRoot(root ของ Bot API เท่านั้น; อย่าใส่/bot<TOKEN>) - Webhook:
webhookUrl,webhookSecret,webhookPath,webhookHost - การดำเนินการ/ความสามารถ:
capabilities.inlineButtons,actions.sendMessage|editMessage|deleteMessage|reactions|sticker - reaction:
reactionNotifications,reactionLevel - ข้อผิดพลาด:
errorPolicy,errorCooldownMs - การเขียน/ประวัติ:
configWrites,historyLimit,dmHistoryLimit,dms.*.historyLimit