Mainstream messaging

Telegram

พร้อมใช้งานจริงสำหรับ DM และกลุ่มของบอตผ่าน grammY โดยใช้ long polling เป็นการรับส่งข้อมูลเริ่มต้น และเลือกใช้โหมด Webhook ได้

การตั้งค่าอย่างรวดเร็ว

  • สร้างโทเค็นบอตใน BotFather

    ทั้งสองวิธีจะให้โทเค็นที่นำไปวางใน OpenClaw ให้เลือกวิธีใดวิธีหนึ่ง:

    • วิธีผ่านแชต: เปิด Telegram แล้วแชตกับ @BotFather (ตรวจสอบว่าแฮนเดิลเป็น @BotFather ตรงตามนี้) เรียกใช้ /newbot ทำตามข้อความแจ้ง แล้วบันทึกโทเค็น
    • วิธีผ่านเว็บ: เปิดเว็บแอปของ BotFather ซึ่งทำงานได้ในไคลเอนต์ Telegram ทุกตัว รวมถึง web.telegram.org จากนั้นสร้างบอตใน UI แล้วคัดลอกโทเค็น
  • กำหนดค่าโทเค็นและนโยบาย DM

    json5
    {channels: {telegram: {  enabled: true,  botToken: "123:abc",  dmPolicy: "pairing",  groups: { "*": { requireMention: true } },},},}

    ตัวเลือกสำรองจากสภาพแวดล้อม: TELEGRAM_BOT_TOKEN (เฉพาะบัญชีเริ่มต้น บัญชีที่มีชื่อต้องใช้ botToken หรือ tokenFile) Telegram ไม่ ใช้ openclaw channels login telegram ให้ตั้งค่าโทเค็นใน config/env แล้วเริ่ม Gateway

  • เริ่ม Gateway และอนุมัติ DM แรก

    bash
    openclaw gatewayopenclaw pairing list telegramopenclaw pairing approve telegram <CODE>

    รหัสการจับคู่จะหมดอายุหลังจาก 1 ชั่วโมง

  • เพิ่มบอตลงในกลุ่ม

    เพิ่มบอตลงในกลุ่ม แล้วรับ ID สองรายการที่จำเป็นสำหรับการเข้าถึงกลุ่ม:

    • ID ผู้ใช้ Telegram ของคุณ สำหรับ allowFrom / groupAllowFrom
    • ID แชตกลุ่ม Telegram เพื่อใช้เป็นคีย์ภายใต้ channels.telegram.groups

    รับ ID แชตกลุ่มจาก openclaw logs --follow, บอตสำหรับดู ID จากข้อความที่ส่งต่อ หรือ Bot API getUpdates หลังจากอนุญาตกลุ่มแล้ว /whoami@<bot_username> จะยืนยัน ID ผู้ใช้และกลุ่ม

    ID ซูเปอร์กรุ๊ปที่เป็นค่าลบและขึ้นต้นด้วย -100 คือ ID แชตกลุ่ม โดยต้องใส่ไว้ใต้ channels.telegram.groups ไม่ใช่ groupAllowFrom

  • การตั้งค่าฝั่ง Telegram

    โหมดความเป็นส่วนตัวและการมองเห็นในกลุ่ม

    บอต Telegram ใช้ Privacy Mode เป็นค่าเริ่มต้น ซึ่งจำกัดข้อความในกลุ่มที่บอตจะได้รับ

    หากต้องการให้เห็นข้อความทั้งหมดในกลุ่ม ให้เลือกวิธีใดวิธีหนึ่ง:

    • ปิดโหมดความเป็นส่วนตัวผ่าน /setprivacy หรือ
    • ตั้งบอตเป็นผู้ดูแลกลุ่ม

    หลังจากสลับโหมดความเป็นส่วนตัวแล้ว ให้นำบอตออกและเพิ่มกลับเข้าไปใหม่ในแต่ละกลุ่ม เพื่อให้ Telegram นำการเปลี่ยนแปลงไปใช้

    สิทธิ์ในกลุ่ม

    สถานะผู้ดูแลควบคุมผ่านการตั้งค่ากลุ่ม Telegram บอตที่เป็นผู้ดูแลจะได้รับข้อความทั้งหมดในกลุ่ม ซึ่งเหมาะสำหรับการทำงานในกลุ่มแบบพร้อมใช้งานตลอดเวลา

    ตัวเลือก BotFather ที่มีประโยชน์
    • /setjoingroups — อนุญาต/ปฏิเสธการเพิ่มลงในกลุ่ม
    • /setprivacy — ลักษณะการมองเห็นในกลุ่ม

    การตั้งค่าเดียวกันนี้มีในเว็บแอปของ BotFather หากต้องการใช้ UI แทนคำสั่งแชต

    Mini App แดชบอร์ด

    เรียกใช้ /dashboard ใน DM กับบอต เพื่อเปิดแดชบอร์ด OpenClaw ภายใน Telegram

    ข้อกำหนด:

    • gateway.tailscale.mode: "serve" หรือ "funnel" สำหรับ URL HTTPS ของ Mini App ที่เผยแพร่แล้ว
    • ID ผู้ใช้ Telegram แบบตัวเลขของคุณต้องอยู่ใน allowFrom ที่มีผลของบัญชีที่เลือก หรืออยู่ใน commands.ownerAllowFrom
    • ใช้ DM ในกลุ่ม /dashboard จะตอบกลับด้วย open this in a DM with the bot และไม่ส่งปุ่ม
    • การติดตั้งด้วย Docker: โหมด Serve/Funnel กำหนดให้ Gateway ผูกกับ loopback ถัดจาก tailscaled ซึ่งเครือข่ายแบบบริดจ์ที่เผยแพร่พอร์ตไม่สามารถรองรับได้ ให้เรียกใช้คอนเทนเนอร์ Gateway ด้วย network_mode: host และเมานต์ซ็อกเก็ต tailscaled ของโฮสต์ (/var/run/tailscale) พร้อมกับ CLI tailscale เข้าไปในคอนเทนเนอร์

    Mini App เป็นพาธ v1 ที่ใช้ได้ผ่าน Tailscale เท่านั้น และไม่รองรับ iframe ของ Telegram Web

    การควบคุมการเข้าถึงและการเปิดใช้งาน

    ข้อมูลประจำตัวของบอตในกลุ่ม

    ในกลุ่มและหัวข้อฟอรัม การกล่าวถึงแฮนเดิลบอตที่กำหนดค่าไว้อย่างชัดเจน (เช่น @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: ["*"] ระดับบัญชีจะไม่ทำให้บัญชีนั้นเป็นสาธารณะ เว้นแต่รายการอนุญาตที่มีผลหลังผสานแล้วยังคงมีไวลด์การ์ดอย่างชัดเจน dmPolicy: "allowlist" ที่มี allowFrom ว่างเปล่าจะบล็อก DM ทั้งหมด และจะถูกปฏิเสธโดยการตรวจสอบ config การตั้งค่าจะขอเฉพาะ ID ผู้ใช้แบบตัวเลข หาก config มีรายการในรายการอนุญาต @username จากการตั้งค่ารุ่นเก่า ให้เรียกใช้ openclaw doctor --fix เพื่อแปลงเป็น ID แบบตัวเลข (พยายามดำเนินการให้ได้มากที่สุด และต้องมีโทเค็นบอต Telegram) หากก่อนหน้านี้ใช้ไฟล์รายการอนุญาตจากที่เก็บการจับคู่ openclaw doctor --fix สามารถกู้คืนรายการเข้าสู่ channels.telegram.allowFrom สำหรับขั้นตอนที่ใช้รายการอนุญาตได้ (เช่น เมื่อ dmPolicy: "allowlist" ยังไม่มี ID ที่ระบุไว้อย่างชัดเจน)

    สำหรับบอตที่มีเจ้าของคนเดียว ควรใช้ dmPolicy: "allowlist" พร้อม ID allowFrom แบบตัวเลขที่ระบุไว้อย่างชัดเจน แทนการพึ่งพาการอนุมัติการจับคู่ก่อนหน้า

    ความสับสนที่พบบ่อย: การอนุมัติการจับคู่ DM ไม่ได้หมายความว่า "ผู้ส่งรายนี้ได้รับอนุญาตทุกที่" การจับคู่ให้สิทธิ์เข้าถึง DM เท่านั้น หากยังไม่มีเจ้าของคำสั่ง การจับคู่ครั้งแรกที่ได้รับอนุมัติจะตั้งค่า commands.ownerAllowFrom ด้วย ทำให้คำสั่งสำหรับเจ้าของเท่านั้นและการอนุมัติ exec มีบัญชีผู้ปฏิบัติงานที่ระบุไว้อย่างชัดเจน การอนุญาตผู้ส่งในกลุ่มยังคงมาจากรายการอนุญาตใน config ที่ระบุไว้อย่างชัดเจน หากต้องการให้ข้อมูลประจำตัวเดียวได้รับอนุญาตทั้ง DM และคำสั่งในกลุ่ม: ใส่ ID ผู้ใช้ Telegram แบบตัวเลขของคุณใน channels.telegram.allowFrom และสำหรับคำสั่งที่ใช้ได้เฉพาะเจ้าของ ให้ตรวจสอบว่า commands.ownerAllowFrom มี telegram:<your user id>

    การค้นหา ID ผู้ใช้ Telegram ของคุณ

    ปลอดภัยกว่า (ไม่ใช้บอตของบุคคลที่สาม): ส่ง DM ถึงบอตของคุณ เรียกใช้ openclaw logs --follow แล้วอ่าน from.id

    วิธีผ่าน Bot API อย่างเป็นทางการ:

    bash
    curl "https://api.telegram.org/bot<bot_token>/getUpdates"

    บุคคลที่สาม (เป็นส่วนตัวน้อยกว่า): @userinfobot หรือ @getidsbot

    นโยบายกลุ่มและรายการอนุญาต

    ใช้ตัวควบคุมสองรายการร่วมกัน:

    1. กลุ่มใดได้รับอนุญาต (channels.telegram.groups)

      • ไม่มี config groups, groupPolicy: "open": ทุกกลุ่มผ่านการตรวจสอบ ID กลุ่ม
      • ไม่มี config groups, groupPolicy: "allowlist" (ค่าเริ่มต้น): บล็อกทุกกลุ่มจนกว่าจะเพิ่มรายการ groups (หรือ "*")
      • กำหนดค่า groups แล้ว: ทำหน้าที่เป็นรายการอนุญาต (ID ที่ระบุไว้อย่างชัดเจนหรือ "*")
    2. ผู้ส่งรายใดได้รับอนุญาตในกลุ่ม (channels.telegram.groupPolicy)

      • open / allowlist (ค่าเริ่มต้น) / disabled

    groupAllowFrom กรองผู้ส่งในกลุ่ม หากไม่ได้ตั้งค่า Telegram จะใช้ allowFrom เป็นค่าทดแทน (ไม่ใช่ที่เก็บการจับคู่ เพราะการตรวจสอบสิทธิ์ผู้ส่งในกลุ่มจะไม่สืบทอดการอนุมัติจากที่เก็บการจับคู่ DM ซึ่งเป็นขอบเขตความปลอดภัยตั้งแต่ 2026.2.25) รายการ groupAllowFrom ควรเป็น ID ผู้ใช้ Telegram แบบตัวเลข (คำนำหน้า telegram: / tg: จะถูกปรับให้อยู่ในรูปแบบมาตรฐาน) ระบบจะเพิกเฉยรายการที่ไม่ใช่ตัวเลข อย่าใส่ ID แชตของกลุ่มหรือซูเปอร์กรุ๊ปที่นี่ เพราะ ID แชตที่เป็นค่าลบต้องอยู่ใต้ channels.telegram.groups รูปแบบที่ใช้ได้จริงสำหรับบอตที่มีเจ้าของคนเดียว: ตั้งค่า ID ผู้ใช้ของคุณใน channels.telegram.allowFrom ไม่ต้องตั้งค่า groupAllowFrom และอนุญาตกลุ่มเป้าหมายภายใต้ channels.telegram.groups หาก channels.telegram ไม่มีอยู่ใน config เลย รันไทม์จะใช้ groupPolicy="allowlist" แบบปิดเมื่อเกิดข้อผิดพลาดเป็นค่าเริ่มต้น เว้นแต่จะตั้งค่า channels.defaults.groupPolicy ไว้อย่างชัดเจน

    การตั้งค่ากลุ่มสำหรับเจ้าของเท่านั้น:

    json5
    {channels: {telegram: {  enabled: true,  dmPolicy: "pairing",  allowFrom: ["&lt;YOUR_TELEGRAM_USER_ID&gt;"],  groupPolicy: "allowlist",  groups: {    "&lt;GROUP_CHAT_ID&gt;": {      requireMention: true,    },  },},},}

    ทดสอบจากกลุ่มด้วย @<bot_username> ping ข้อความกลุ่มทั่วไปจะไม่เรียกบอตขณะที่ requireMention: true

    อนุญาตสมาชิกทุกคนในกลุ่มหนึ่งที่ระบุ:

    json5
    {channels: {telegram: {  groups: {    "-1001234567890": {      groupPolicy: "open",      requireMention: false,    },  },},},}

    อนุญาตเฉพาะผู้ใช้ที่ระบุภายในกลุ่มหนึ่งที่ระบุ:

    json5
    {channels: {telegram: {  groups: {    "-1001234567890": {      requireMention: true,      allowFrom: ["8734062810", "745123456"],    },  },},},}

    ลักษณะการกล่าวถึง

    การตอบกลับในกลุ่มกำหนดให้มีการกล่าวถึงเป็นค่าเริ่มต้น การกล่าวถึงอาจมาจาก:

    • การกล่าวถึง @botusername แบบเนทีฟ หรือ
    • รูปแบบการกล่าวถึงใน agents.list[].groupChat.mentionPatterns หรือ messages.groupChat.mentionPatterns

    ตัวเลือกสลับระดับเซสชัน (เฉพาะสถานะ ไม่คงอยู่ถาวร): /activation always, /activation mention ใช้ config หากต้องการให้คงอยู่ถาวร:

    json5
    {channels: {telegram: {  groups: {    "*": { requireMention: false },  },},},}

    บริบทประวัติกลุ่มจะเปิดอยู่เสมอและถูกจำกัดด้วย historyLimit ตั้งค่า channels.telegram.historyLimit: 0 เพื่อปิดใช้งานหน้าต่างประวัติกลุ่ม openclaw doctor --fix จะนำคีย์ includeGroupHistoryContext ที่เลิกใช้แล้วออก

    การรับ ID แชตกลุ่ม: ส่งต่อข้อความกลุ่มไปยัง @userinfobot / @getidsbot อ่าน chat.id จาก openclaw logs --follow ตรวจสอบ Bot API getUpdates หรือเรียกใช้ /whoami@<bot_username> เมื่อกลุ่มได้รับอนุญาตแล้ว

    ลักษณะการทำงานขณะรันไทม์

    • Telegram ทำงานภายในกระบวนการ Gateway
    • การกำหนดเส้นทางเป็นแบบกำหนดแน่นอน: ข้อความขาเข้าจาก Telegram จะตอบกลับไปยัง Telegram (โมเดลไม่ได้เลือกช่องทาง)
    • ข้อความขาเข้าจะถูกปรับให้อยู่ในซองข้อมูลช่องทางที่ใช้ร่วมกัน พร้อมเมทาดาทาการตอบกลับ ตัวยึดตำแหน่งสื่อ และบริบทสายการตอบกลับที่บันทึกไว้สำหรับข้อความตอบกลับที่ Gateway ตรวจพบ
    • เซสชันกลุ่มแยกจากกันตาม ID กลุ่ม หัวข้อฟอรัมจะต่อท้าย :topic:<threadId>
    • ข้อความ DM สามารถมี message_thread_id; OpenClaw จะเก็บค่านี้ไว้สำหรับการตอบกลับ เซสชันหัวข้อ DM จะแยกเฉพาะเมื่อ Telegram getMe รายงาน has_topics_enabled: true สำหรับบอต มิฉะนั้น DM จะยังคงอยู่ในเซสชันแบบราบ
    • Long polling ใช้ตัวรัน grammY พร้อมการจัดลำดับแยกตามแชต/เธรด ภาวะพร้อมกันของ sink ในตัวรันใช้ agents.defaults.maxConcurrent
    • การเริ่มต้นหลายบัญชีจำกัดจำนวนโพรบ getMe ที่ทำพร้อมกัน เพื่อไม่ให้กลุ่มบอตขนาดใหญ่กระจายโพรบของทุกบัญชีออกไปพร้อมกัน
    • แต่ละกระบวนการ Gateway ป้องกัน long polling เพื่อให้มี poller ที่ทำงานอยู่เพียงตัวเดียวใช้โทเค็นบอตได้ในแต่ละครั้ง ข้อขัดแย้ง 409 ของ getUpdates ที่เกิดขึ้นต่อเนื่องบ่งชี้ว่ามี Gateway ของ OpenClaw, สคริปต์ หรือ poller ภายนอกอื่นกำลังใช้โทเค็นเดียวกัน
    • ตัวเฝ้าระวังการ polling จะเริ่มใหม่หลังจากไม่มีการตรวจสอบความพร้อมใช้งานของ getUpdates ที่เสร็จสมบูรณ์เป็นเวลา 120 วินาที
    • Telegram Bot API ไม่รองรับใบตอบรับการอ่าน (sendReadReceipts ใช้ไม่ได้)

    ข้อมูลอ้างอิงฟีเจอร์

    ตัวอย่างสตรีมสด (การแก้ไขข้อความ)

    OpenClaw สตรีมคำตอบบางส่วนแบบเรียลไทม์ในแชตส่วนตัว กลุ่ม และหัวข้อ: ส่งข้อความตัวอย่าง จากนั้นเรียก editMessageText ซ้ำ ๆ และปรับเป็นข้อความสุดท้ายในตำแหน่งเดิม

    • channels.telegram.streaming คือ off | partial | block | progress (ค่าเริ่มต้น: partial)
    • ตัวอย่างคำตอบเริ่มต้นแบบสั้นจะถูกหน่วงเพื่อลดการเรียกถี่ จากนั้นจะแสดงผลหลังจากช่วงเวลาหน่วงที่จำกัด หากการทำงานยังดำเนินอยู่
    • progress จะเก็บร่างสถานะที่แก้ไขได้หนึ่งรายการสำหรับความคืบหน้าของเครื่องมือ แสดงป้ายสถานะคงที่เมื่อกิจกรรมคำตอบมาถึงก่อนความคืบหน้าของเครื่องมือ ล้างร่างเมื่อเสร็จสิ้น และส่งคำตอบสุดท้ายเป็นข้อความปกติ
    • streaming.preview.toolProgress ควบคุมว่าการอัปเดตเครื่องมือ/ความคืบหน้าจะใช้ข้อความตัวอย่างที่แก้ไขรายการเดิมหรือไม่ (ค่าเริ่มต้น: true เมื่อการสตรีมตัวอย่างทำงานอยู่)
    • streaming.preview.commandText ควบคุมรายละเอียดคำสั่ง/การดำเนินการภายในบรรทัดเหล่านั้น: raw (ค่าเริ่มต้น) หรือ status (เฉพาะป้ายเครื่องมือ)
    • streaming.progress.commentary (ค่าเริ่มต้น: false) เลือกเปิดใช้ข้อความคำอธิบาย/คำนำของผู้ช่วยในร่างความคืบหน้าชั่วคราว
    • ระบบจะตรวจพบ channels.telegram.streamMode แบบเดิม ค่า streaming ชนิดบูลีน และคีย์ตัวอย่างร่างแบบเนทีฟที่เลิกใช้แล้ว ให้เรียกใช้ openclaw doctor --fix เพื่อย้ายข้อมูล

    บรรทัดความคืบหน้าของเครื่องมือคือการอัปเดตสถานะแบบสั้นที่แสดงระหว่างเครื่องมือทำงาน (การดำเนินคำสั่ง การอ่านไฟล์ การอัปเดตแผน สรุปแพตช์ คำนำ/คำอธิบายของ Codex ในโหมด app-server) Telegram เปิดใช้สิ่งเหล่านี้เป็นค่าเริ่มต้น (ตรงกับลักษณะการทำงานในรุ่นที่เผยแพร่ตั้งแต่ v2026.4.22 เป็นต้นไป)

    คงการแก้ไขตัวอย่างคำตอบไว้ แต่ซ่อนบรรทัดความคืบหน้าของเครื่องมือ:

    json
    {  "channels": {    "telegram": {      "streaming": {        "mode": "partial",        "preview": { "toolProgress": false }      }    }  }}

    คงการแสดงความคืบหน้าของเครื่องมือไว้ แต่ซ่อนข้อความคำสั่ง/การดำเนินการ:

    json
    {  "channels": {    "telegram": {      "streaming": {        "mode": "partial",        "preview": { "commandText": "status" }      }    }  }}

    โหมด progress แสดงความคืบหน้าของเครื่องมือโดยไม่แก้ไขคำตอบสุดท้ายลงในข้อความนั้น วางนโยบายข้อความคำสั่งไว้ภายใต้ streaming.progress:

    json
    {  "channels": {    "telegram": {      "streaming": {        "mode": "progress",        "progress": {          "toolProgress": true,          "commandText": "status"        }      }    }  }}

    streaming.mode: "off" ปิดใช้การแก้ไขตัวอย่างและระงับข้อความทั่วไปเกี่ยวกับเครื่องมือ/ความคืบหน้า แทนที่จะส่งเป็นข้อความสถานะแยกต่างหาก ส่วนพรอมต์ขออนุมัติ สื่อ และข้อผิดพลาดยังคงส่งผ่านการนำส่งขั้นสุดท้ายตามปกติ streaming.preview.toolProgress: false จะคงไว้เฉพาะการแก้ไขตัวอย่างคำตอบ

    สำหรับคำตอบที่มีเฉพาะข้อความ: ตัวอย่างแบบสั้นจะถูกแก้ไขเป็นข้อความสุดท้ายในตำแหน่งเดิม ส่วนข้อความสุดท้ายแบบยาวที่แบ่งเป็นหลายข้อความจะใช้ตัวอย่างเป็นส่วนแรก แล้วส่งเฉพาะส่วนที่เหลือ ข้อความสุดท้ายในโหมดความคืบหน้าจะล้างร่างสถานะและใช้การนำส่งขั้นสุดท้ายตามปกติ หากการแก้ไขขั้นสุดท้ายล้มเหลวก่อนยืนยันว่าเสร็จสมบูรณ์ OpenClaw จะเปลี่ยนไปใช้การนำส่งขั้นสุดท้ายตามปกติและล้างตัวอย่างที่ค้างอยู่ สำหรับคำตอบที่ซับซ้อน (เพย์โหลดสื่อ) OpenClaw จะเปลี่ยนไปใช้การนำส่งขั้นสุดท้ายตามปกติและล้างตัวอย่างเสมอ

    การสตรีมตัวอย่างและการสตรีมแบบบล็อกไม่สามารถใช้ร่วมกันได้ — เมื่อเปิดใช้การสตรีมแบบบล็อกอย่างชัดเจน OpenClaw จะข้ามสตรีมตัวอย่างเพื่อหลีกเลี่ยงการสตรีมซ้ำซ้อน

    การให้เหตุผล: /reasoning stream จะสตรีมการให้เหตุผลลงในตัวอย่างสดระหว่างการสร้าง จากนั้นลบตัวอย่างการให้เหตุผลหลังการนำส่งขั้นสุดท้าย (ใช้ /reasoning on เพื่อคงให้มองเห็นได้) คำตอบสุดท้ายจะถูกส่งโดยไม่มีข้อความการให้เหตุผล

    การจัดรูปแบบข้อความแบบสมบูรณ์

    ข้อความขาออกใช้ข้อความ HTML มาตรฐานของ Telegram เป็นค่าเริ่มต้น ซึ่งอ่านได้ในไคลเอนต์ปัจจุบัน: ตัวหนา ตัวเอียง ลิงก์ โค้ด สปอยเลอร์ คำพูด — ไม่ใช่บล็อกแบบสมบูรณ์เฉพาะ Bot API 10.2 (ตารางเนทีฟ รายละเอียด สื่อแบบสมบูรณ์ สูตร)

    เลือกเปิดใช้ข้อความแบบสมบูรณ์ของ Bot API 10.2:

    json5
    {channels: {telegram: {  richMessages: true,},},}

    เมื่อเปิดใช้: เอเจนต์จะได้รับแจ้งว่าบอต/บัญชีนี้รองรับข้อความแบบสมบูรณ์ (พร้อมสัญญาการเขียน Markdown + HTML-island ที่รองรับ) ข้อความ Markdown จะแสดงผลผ่าน Markdown IR ของ OpenClaw เป็นบล็อกแบบสมบูรณ์ชนิดต่าง ๆ ของ Bot API 10.2 (หัวเรื่อง ตาราง รายละเอียด รายการตรวจสอบ สื่อแบบสมบูรณ์ สูตร แผนที่ คอลลาจ) ส่วนคำบรรยายสื่อยังคงใช้คำบรรยาย HTML ของ Telegram (ข้อความแบบสมบูรณ์ไม่ได้แทนที่คำบรรยาย และคำบรรยายจำกัดไว้ที่ 1024 อักขระ)

    วิธีนี้ช่วยไม่ให้ข้อความจากโมเดลใช้สัญลักษณ์ rich-Markdown ของ Telegram จึงไม่แปลค่าสกุลเงินอย่าง $400-600K เป็นนิพจน์คณิตศาสตร์ ข้อความแบบสมบูรณ์ที่ยาวจะแบ่งโดยอัตโนมัติตามขีดจำกัดของ Telegram ตารางที่เกินขีดจำกัด 20 คอลัมน์จะเปลี่ยนไปใช้บล็อกโค้ด

    ค่าเริ่มต้น: ปิด เพื่อความเข้ากันได้กับไคลเอนต์ — ไคลเอนต์ Desktop, Web, Android และไคลเอนต์บุคคลที่สามบางรายการในปัจจุบันแสดงข้อความแบบสมบูรณ์ที่ยอมรับแล้วว่าไม่รองรับ คงการตั้งค่านี้เป็นปิดไว้ เว้นแต่ไคลเอนต์ทุกตัวที่ใช้กับบอตจะแสดงผลได้ /status แสดงว่าเซสชันปัจจุบันเปิดหรือปิดข้อความแบบสมบูรณ์อยู่

    ตัวอย่างลิงก์เปิดอยู่เป็นค่าเริ่มต้น channels.telegram.linkPreview: false ปิดใช้การตรวจหาเอนทิตีอัตโนมัติสำหรับข้อความแบบสมบูรณ์

    คำสั่งเนทีฟและคำสั่งกำหนดเอง

    เมนูคำสั่งของ Telegram จะลงทะเบียนเมื่อเริ่มต้นด้วย setMyCommands ส่วน commands.native: "auto" เปิดใช้คำสั่งเนทีฟสำหรับ Telegram

    เพิ่มรายการเมนูคำสั่งกำหนดเอง:

    json5
    {channels: {telegram: {  customCommands: [    { command: "backup", description: "Git backup" },    { command: "generate", description: "Create an image" },  ],},},}

    กฎ: ชื่อจะถูกปรับให้เป็นรูปแบบมาตรฐาน (ตัด / ที่นำหน้าออก เปลี่ยนเป็นตัวพิมพ์เล็ก) รูปแบบที่ใช้ได้คือ a-z, 0-9, _ ความยาว 1-32 อักขระ คำสั่งกำหนดเองไม่สามารถแทนที่คำสั่งเนทีฟได้ รายการที่ขัดแย้ง/ซ้ำกันจะถูกข้ามและบันทึกในล็อก

    คำสั่งกำหนดเองเป็นเพียงรายการในเมนู — ไม่ได้นำลักษณะการทำงานไปใช้โดยอัตโนมัติ คำสั่ง Plugin/skill ยังสามารถทำงานได้เมื่อพิมพ์ แม้จะไม่แสดงในเมนู Telegram หากปิดใช้คำสั่งเนทีฟ คำสั่งในตัวจะถูกนำออก ส่วนคำสั่งกำหนดเอง/Plugin อาจยังลงทะเบียนได้หากกำหนดค่าไว้

    ความล้มเหลวในการตั้งค่าที่พบบ่อย:

    • setMyCommands failed พร้อม BOT_COMMANDS_TOO_MUCH หลังลองตัดแต่งใหม่ หมายความว่าเมนูยังมีรายการมากเกินขีดจำกัด ให้ลดคำสั่ง Plugin/skill/กำหนดเอง หรือปิดใช้ channels.telegram.commands.native
    • หาก deleteWebhook, deleteMyCommands หรือ setMyCommands ล้มเหลวด้วย 404: Not Found ขณะที่คำสั่ง curl ของ Bot API โดยตรงทำงานได้ โดยทั่วไปหมายความว่า channels.telegram.apiRoot ถูกตั้งค่าเป็นปลายทาง /bot&lt;TOKEN&gt; แบบเต็ม apiRoot ต้องเป็นเฉพาะรากของ Bot API เท่านั้น ส่วน openclaw doctor --fix จะนำ /bot&lt;TOKEN&gt; ที่ต่อท้ายโดยไม่ตั้งใจออก
    • getMe returned 401 หมายความว่า Telegram ปฏิเสธโทเค็นบอตที่กำหนดค่าไว้ อัปเดต botToken, tokenFile หรือ TELEGRAM_BOT_TOKEN (บัญชีเริ่มต้น) ด้วยโทเค็น BotFather ปัจจุบัน OpenClaw จะหยุดก่อน polling จึงไม่มีการรายงานสิ่งนี้เป็นความล้มเหลวในการล้าง Webhook
    • setMyCommands failed พร้อมข้อผิดพลาดเครือข่าย/การดึงข้อมูล โดยทั่วไปหมายความว่า DNS/HTTPS ขาออกไปยัง api.telegram.org ถูกบล็อก

    คำสั่งจับคู่อุปกรณ์ (Plugin device-pair)

    เมื่อติดตั้งแล้ว:

    1. /pair สร้างรหัสตั้งค่า
    2. วางรหัสในแอป iOS
    3. /pair pending แสดงรายการคำขอที่รอดำเนินการ (รวมบทบาท/ขอบเขต)
    4. อนุมัติ: /pair approve <requestId>, /pair approve (เฉพาะคำขอที่รอดำเนินการ) หรือ /pair approve latest

    หากอุปกรณ์ลองใหม่โดยเปลี่ยนรายละเอียดการยืนยันตัวตน (บทบาท ขอบเขต คีย์สาธารณะ) คำขอที่รอดำเนินการก่อนหน้าจะถูกแทนที่ด้วย requestId ใหม่ ให้เรียก /pair pending อีกครั้งก่อนอนุมัติ

    รายละเอียดเพิ่มเติม: การจับคู่

    ปุ่มอินไลน์

    กำหนดค่าขอบเขตแป้นพิมพ์อินไลน์:

    json5
    {channels: {telegram: {  capabilities: {    inlineButtons: "allowlist",  },},},}

    การแทนที่ต่อบัญชี:

    json5
    {channels: {telegram: {  accounts: {    main: {      capabilities: {        inlineButtons: "allowlist",      },    },  },},},}

    ขอบเขต: off, dm, group, all, allowlist (ค่าเริ่มต้น) capabilities: ["inlineButtons"] แบบเดิมจะแมปไปยัง "all"

    ตัวอย่างการดำเนินการกับข้อความ:

    json5
    {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:

    json5
    {action: "send",channel: "telegram",to: "123456789",message: "Open app:",presentation: {blocks: [  {    type: "buttons",    buttons: [{ label: "Launch", web_app: { url: "https://example.com/app" } }],  },],},}

    ปุ่ม web_app ใช้งานได้เฉพาะในแชตส่วนตัวระหว่างผู้ใช้กับบอต

    การคลิก callback ที่ไม่มีตัวจัดการแบบโต้ตอบของ Plugin ที่ลงทะเบียนไว้อ้างสิทธิ์ จะถูกส่งไปยังเอเจนต์เป็นข้อความ: callback_data: <value>

    การดำเนินการกับข้อความ 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.sendMessage, deleteMessage, reactions, sticker (ค่าเริ่มต้น: ปิดใช้งาน) โดยค่าเริ่มต้น edit, createForumTopic และ editForumTopic จะเปิดใช้งานโดยไม่มีตัวสลับเฉพาะ การส่งขณะรันไทม์ใช้สแนปช็อตการกำหนดค่า/ข้อมูลลับที่ใช้งานอยู่จากการเริ่มต้น/โหลดใหม่ ดังนั้นเส้นทางการดำเนินการจึงไม่แก้ไขค่า SecretRef ใหม่ในการส่งแต่ละครั้ง

    ความหมายของการนำปฏิกิริยาออก: /tools/reactions

    แท็กเธรดการตอบกลับ

    แท็กเธรดการตอบกลับแบบระบุชัดเจนในเอาต์พุตที่สร้างขึ้น:

    • [[reply_to_current]] — ตอบกลับข้อความที่ทริกเกอร์
    • [[reply_to:<id>]] — ตอบกลับ ID ข้อความที่ระบุ

    channels.telegram.replyToMode: off (ค่าเริ่มต้น), first, all

    เมื่อเปิดใช้เธรดการตอบกลับและมีข้อความ/คำบรรยายเดิม OpenClaw จะเพิ่มข้อความอ้างอิงแบบเนทีฟโดยอัตโนมัติ 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 ในการกำหนดค่าหัวข้อ ทำให้แต่ละหัวข้อมีพื้นที่ทำงาน หน่วยความจำ และเซสชันเป็นของตนเอง:

    json5
    {  channels: {    telegram: {      groups: {        "-1001234567890": {          topics: {            "1": { agentId: "main" },      // หัวข้อทั่วไป -> เอเจนต์หลัก            "3": { agentId: "zu" },        // หัวข้อการพัฒนา -> เอเจนต์ zu            "5": { agentId: "coder" }      // การรีวิวโค้ด -> เอเจนต์ coder          }        }      }    }  }}

    จากนั้นแต่ละหัวข้อจะมีคีย์เซสชันเป็นของตนเอง เช่น agent:zu:telegram:group:-1001234567890:topic:3

    การผูกหัวข้อ 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 จะเก็บข้อมูลเมตาของการตอบกลับไว้ แต่ใช้คีย์เซสชันที่รับรู้เธรดเฉพาะเมื่อ getMe ของ Telegram รายงาน has_topics_enabled: true การเขียนทับ dm.threadReplies และ direct.*.threadReplies ที่เลิกใช้แล้วถูกนำออก; โหมดเธรดของ BotFather เป็นแหล่งข้อมูลจริงเพียงแหล่งเดียว เรียกใช้ openclaw doctor --fix เพื่อนำคีย์การกำหนดค่าที่ค้างอยู่ออก

    เสียง วิดีโอ และสติกเกอร์

    ข้อความเสียง

    Telegram แยกความแตกต่างระหว่างข้อความเสียงกับไฟล์เสียง ค่าเริ่มต้น: ลักษณะการทำงานแบบไฟล์เสียง; ใส่แท็ก [[audio_as_voice]] ในการตอบกลับของเอเจนต์เพื่อบังคับให้ส่งเป็นข้อความเสียง การถอดเสียงข้อความเสียงขาเข้าจะถูกจัดกรอบเป็นข้อความที่เครื่องสร้างขึ้นและไม่น่าเชื่อถือในบริบทของเอเจนต์ แต่การตรวจจับการกล่าวถึงยังคงใช้ข้อความถอดเสียงดิบ เพื่อให้ข้อความเสียงที่มีเงื่อนไขการกล่าวถึงยังคงทำงานได้

    json5
    {action: "send",channel: "telegram",to: "123456789",media: "https://example.com/voice.ogg",asVoice: true,}

    ข้อความวิดีโอ

    Telegram แยกความแตกต่างระหว่างไฟล์วิดีโอกับข้อความวิดีโอ ข้อความวิดีโอไม่รองรับคำบรรยาย; ข้อความที่ให้มาจะถูกส่งแยกต่างหาก

    json5
    {action: "send",channel: "telegram",to: "123456789",media: "https://example.com/video.mp4",asVideoNote: true,}

    ตำแหน่งและสถานที่

    ใช้การดำเนินการ send ที่มีอยู่กับออบเจ็กต์ location แบบเดี่ยวหนึ่งรายการ พิกัดจะส่งหมุดแบบเนทีฟ; การเพิ่มทั้ง name และ address จะส่งการ์ดสถานที่แบบเนทีฟ การส่งตำแหน่งไม่สามารถใช้ร่วมกับข้อความหรือสื่อได้

    json5
    {action: "send",channel: "telegram",to: "123456789",location: {latitude: 48.858844,longitude: 2.294351,accuracy: 12,name: "หอไอเฟล",address: "ช็องเดอมาร์ส ปารีส",},}

    สติกเกอร์

    ขาเข้า: ระบบจะดาวน์โหลดและประมวลผล WEBP แบบภาพนิ่ง (ตัวยึดตำแหน่ง <media:sticker>); ส่วน TGS แบบเคลื่อนไหวและ WEBM แบบวิดีโอจะถูกข้าม

    ฟิลด์บริบทของสติกเกอร์: Sticker.emoji, Sticker.setName, Sticker.fileId, Sticker.fileUniqueId, Sticker.cachedDescription คำอธิบายจะถูกแคชไว้ในสถานะ Plugin SQLite ของ OpenClaw เพื่อลดการเรียกใช้การมองเห็นซ้ำ

    เปิดใช้การดำเนินการกับสติกเกอร์:

    json5
    {channels: {telegram: {  actions: {    sticker: true,  },},},}

    ส่ง:

    json5
    {action: "sticker",channel: "telegram",to: "123456789",fileId: "CAACAgIAAxkBAAI...",}

    ค้นหาสติกเกอร์ที่แคชไว้:

    json5
    {action: "sticker-search",channel: "telegram",query: "แมวโบกมือ",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 ไม่ระบุ ID เธรดในการอัปเดตปฏิกิริยา: กลุ่มที่ไม่ใช่ฟอรัมจะกำหนดเส้นทางไปยังเซสชันแชตของกลุ่ม; กลุ่มแบบฟอรัมจะกำหนดเส้นทางไปยังเซสชันหัวข้อทั่วไป (:topic:1) ไม่ใช่หัวข้อต้นทางที่ตรงกัน

    allowed_updates สำหรับการโพล/Webhook จะรวม message_reaction โดยอัตโนมัติ

    ปฏิกิริยาตอบรับ

    ackReaction ส่งอีโมจิตอบรับระหว่างที่ OpenClaw ประมวลผลข้อความขาเข้า messages.ackReactionScope กำหนดว่าอีโมจิจะถูกส่ง เมื่อใด

    ลำดับการเลือกอีโมจิ:

    • channels.telegram.accounts.<accountId>.ackReaction
    • channels.telegram.ackReaction
    • messages.ackReaction
    • ใช้อีโมจิประจำตัวของเอเจนต์เป็นค่าทดแทน (agents.list[].identity.emoji มิฉะนั้นใช้ "👀")

    Telegram ต้องการอีโมจิ Unicode (เช่น "👀"); ใช้ "" เพื่อปิดใช้งานปฏิกิริยาสำหรับช่องทางหรือบัญชี

    ขอบเขต (messages.ackReactionScope, ค่าเริ่มต้น "group-mentions"; ปัจจุบันไม่มีการเขียนทับระดับบัญชี Telegram หรือช่องทาง Telegram):

    all (DM + กลุ่ม รวมถึงเหตุการณ์ห้องโดยรอบ), direct (เฉพาะ DM), group-all (ทุกข้อความในกลุ่มยกเว้นเหตุการณ์ห้องโดยรอบ ไม่มี DM), group-mentions (กลุ่มเมื่อมีการกล่าวถึงบอต; ไม่มี DM — ค่าเริ่มต้น), off / none (ปิดใช้งาน)

    การเขียนการกำหนดค่าจากเหตุการณ์และคำสั่ง Telegram

    การเขียนการกำหนดค่าช่องทางเปิดใช้งานโดยค่าเริ่มต้น (configWrites !== false) การเขียนที่ทริกเกอร์โดย Telegram ได้แก่ เหตุการณ์ย้ายกลุ่ม (migrate_to_chat_id, อัปเดต channels.telegram.groups) และ /config set / /config unset (ต้องเปิดใช้งานคำสั่ง)

    ปิดใช้งาน:

    json5
    {channels: {telegram: {  configWrites: false,},},}
    การโพลระยะยาวเทียบกับ Webhook

    ค่าเริ่มต้นคือการโพลระยะยาว สำหรับโหมด Webhook ให้ตั้งค่า channels.telegram.webhookUrl และ channels.telegram.webhookSecret; ตัวเลือกที่ไม่บังคับ ได้แก่ webhookPath (ค่าเริ่มต้น /telegram-webhook), webhookHost (ค่าเริ่มต้น 127.0.0.1), webhookPort (ค่าเริ่มต้น 8787), webhookCertPath (ใบรับรอง PEM ที่ลงนามด้วยตนเองสำหรับการตั้งค่าแบบใช้ IP โดยตรงหรือไม่มีโดเมน)

    ในโหมดการโพลระยะยาว OpenClaw จะบันทึกลายน้ำการรีสตาร์ตแบบถาวรหลังจากส่งการอัปเดตสำเร็จเท่านั้น; ตัวจัดการที่ล้มเหลวจะทำให้การอัปเดตนั้นลองใหม่ได้ในโพรเซสเดิม แทนที่จะทำเครื่องหมายว่าเสร็จสมบูรณ์

    ลิสเซนเนอร์ภายในเครื่องจะผูกกับ 127.0.0.1:8787 โดยค่าเริ่มต้น สำหรับการรับทราฟฟิกสาธารณะ ให้วางพร็อกซีย้อนกลับไว้หน้าพอร์ตภายในเครื่อง หรือตั้งค่า webhookHost: "0.0.0.0" โดยตั้งใจ

    โหมด Webhook จะตรวจสอบตัวป้องกันคำขอ โทเค็นลับของ Telegram และเนื้อหา JSON จากนั้นบันทึกการอัปเดตลงในคิวรับเข้าที่คงทนก่อนส่งคืน 200 ว่าง การรับเข้าอย่างคงทนที่สำเร็จจะรวม x-openclaw-delivery-accepted: durable; การตอบสนองด้านสถานะความพร้อมใช้งาน การกำหนดเส้นทาง การตรวจสอบสิทธิ์ การตรวจสอบความถูกต้อง และข้อผิดพลาดพื้นที่จัดเก็บจะละเว้นส่วนหัวนี้ พร็อกซีย้อนกลับและตัวควบคุมโฮสต์สามารถกำหนดให้ต้องมีส่วนหัวนี้ เพื่อแยกแยะการรับเข้าของ OpenClaw จาก 200 ว่างทั่วไปโดยไม่ต้องอนุมานการยอมรับจากระยะเวลาการตอบสนอง

    หลังจากเขียนข้อมูลแบบคงทนแล้ว OpenClaw จะอ้างสิทธิ์และประมวลผลการอัปเดตผ่านการระบายข้อมูลรับเข้าของช่องทางหลัก (เลนแยกตามแชต/หัวข้อ, เสร็จสมบูรณ์เมื่อรับช่วงการทำงาน, หมดเวลาการหยุดชะงักก่อนรับช่วง) รอบการทำงานของเอเจนต์ที่ช้าจะไม่ทำให้ ACK การส่งของ Telegram ค้างอยู่

    ขีดจำกัดและเป้าหมาย CLI
    • channels.telegram.textChunkLimit มีค่าเริ่มต้นเป็น 4000; streaming.chunkMode="newline" จะเลือกแบ่งตามขอบเขตย่อหน้า (บรรทัดว่าง) ก่อนแบ่งตามความยาว
    • channels.telegram.mediaMaxMb (ค่าเริ่มต้น 100) จำกัดขนาดสื่อขาเข้าและขาออก
    • ประวัติบริบทของกลุ่มใช้ channels.telegram.historyLimit หรือ messages.groupChat.historyLimit (ค่าเริ่มต้น 50); 0 ใช้ปิดใช้งาน
    • บริบทเสริมจากการตอบกลับ/อ้างอิง/ส่งต่อจะถูกรวมให้อยู่ในหน้าต่างบริบทการสนทนาที่เลือกเพียงหนึ่งหน้าต่าง เมื่อ Gateway ตรวจพบข้อความต้นทางแล้ว; แคชข้อความที่ตรวจพบจะอยู่ในสถานะ Plugin ของ OpenClaw SQLite และ openclaw doctor --fix จะนำเข้าไฟล์เสริมแบบเดิม Telegram จะรวม reply_to_message แบบตื้นเพียงหนึ่งรายการต่อการอัปเดต ดังนั้นสายข้อความที่เก่ากว่าแคชจะจำกัดอยู่เพียงเพย์โหลดนั้น
    • รายการอนุญาตของ Telegram ใช้ควบคุมเป็นหลักว่าใครสามารถเรียกใช้เอเจนต์ได้ ไม่ใช่ขอบเขตการปกปิดบริบทเสริมอย่างสมบูรณ์
    • ประวัติ DM: channels.telegram.dmHistoryLimit, channels.telegram.dms["<user_id>"].historyLimit

    เป้าหมายการส่งของ CLI และเครื่องมือข้อความรองรับ ID แชตแบบตัวเลข ชื่อผู้ใช้ หรือเป้าหมายหัวข้อฟอรัม:

    bash
    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"

    แบบสำรวจใช้ openclaw message poll และรองรับหัวข้อฟอรัม:

    bash
    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-public

    แฟล็กแบบสำรวจเฉพาะ Telegram: --poll-duration-seconds (5-600), --poll-anonymous, --poll-public, --thread-id (หรือเป้าหมาย :topic:) --poll-option ทำซ้ำได้ 2-12 ครั้ง (ขีดจำกัดตัวเลือกของ Telegram)

    การส่งผ่าน Telegram ยังรองรับ --presentation พร้อมบล็อก buttons สำหรับแป้นพิมพ์แบบอินไลน์ (เมื่อ channels.telegram.capabilities.inlineButtons อนุญาต), --pin หรือ --delivery '{"pin":true}' เพื่อขอให้ตรึงข้อความที่ส่งเมื่อบอตสามารถตรึงข้อความในแชตนั้นได้ และ --force-document เพื่อส่งรูปภาพ GIF และวิดีโอขาออกเป็นเอกสารแทนการอัปโหลดแบบบีบอัด/ภาพเคลื่อนไหว/วิดีโอ

    การควบคุมการดำเนินการ: channels.telegram.actions.sendMessage=false ปิดใช้งานข้อความขาออกทั้งหมดรวมถึงแบบสำรวจ; channels.telegram.actions.poll=false ปิดใช้งานการสร้างแบบสำรวจโดยยังคงเปิดใช้งานการส่งปกติ

    การอนุมัติการเรียกใช้คำสั่งใน Telegram

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

    • channels.telegram.execApprovals.enabled ("auto" เปิดใช้งานเมื่อระบุผู้อนุมัติได้อย่างน้อยหนึ่งราย)
    • channels.telegram.execApprovals.approvers (ใช้ ID เจ้าของแบบตัวเลขจาก commands.ownerAllowFrom เป็นค่าทดแทน)
    • channels.telegram.execApprovals.target: dm (ค่าเริ่มต้น) | channel | both
    • agentFilter, sessionFilter

    channels.telegram.allowFrom, groupAllowFrom และ defaultTo ควบคุมว่าใครสามารถสื่อสารกับบอตได้และบอตจะส่งคำตอบปกติไปที่ใด แต่ไม่ได้ทำให้บุคคลนั้นเป็นผู้อนุมัติการเรียกใช้คำสั่ง การจับคู่ DM ที่ได้รับอนุมัติครั้งแรกจะตั้งค่าเริ่มต้นให้ commands.ownerAllowFrom เมื่อยังไม่มีเจ้าของคำสั่ง ทำให้การตั้งค่าแบบเจ้าของรายเดียวทำงานได้โดยไม่ต้องระบุ ID ซ้ำภายใต้ execApprovals.approvers

    การส่งไปยังช่องทางจะแสดงข้อความคำสั่งในแชต; เปิดใช้งาน channel หรือ both เฉพาะในกลุ่ม/หัวข้อที่เชื่อถือได้ เมื่อคำขอไปถึงหัวข้อฟอรัม OpenClaw จะคงหัวข้อนั้นไว้สำหรับคำขออนุมัติและการติดตามผล การอนุมัติการเรียกใช้คำสั่งจะหมดอายุหลังจาก 30 นาทีโดยค่าเริ่มต้น

    ปุ่มอนุมัติแบบอินไลน์ยังกำหนดให้ channels.telegram.capabilities.inlineButtons อนุญาตพื้นผิวเป้าหมาย (dm, group หรือ all) ID การอนุมัติที่ขึ้นต้นด้วย plugin: จะถูกแก้ไขผ่านการอนุมัติของ Plugin; ส่วน ID อื่นจะถูกแก้ไขผ่านการอนุมัติการเรียกใช้คำสั่งก่อน

    ดู การอนุมัติการเรียกใช้คำสั่ง

    การควบคุมการตอบกลับข้อผิดพลาด

    เมื่อเอเจนต์พบข้อผิดพลาดจากการส่งหรือผู้ให้บริการ นโยบายข้อผิดพลาดจะควบคุมว่าจะส่งข้อความข้อผิดพลาดไปยังแชต Telegram หรือไม่:

    คีย์ ค่า ค่าเริ่มต้น คำอธิบาย
    channels.telegram.errorPolicy always, once, silent always always ส่งข้อความข้อผิดพลาดทั้งหมดไปยังแชต once ส่งข้อความข้อผิดพลาดที่ไม่ซ้ำแต่ละรายการหนึ่งครั้งต่อช่วงพักการส่งในตัว silent จะไม่ส่งข้อความข้อผิดพลาดไปยังแชต

    รองรับการกำหนดค่าทับแยกตามบัญชี กลุ่ม และหัวข้อ (ใช้การสืบทอดแบบเดียวกับคีย์การกำหนดค่า Telegram อื่นๆ)

    json5
    {  channels: {    telegram: {      errorPolicy: "always",      groups: {        "-1001234567890": {          errorPolicy: "silent", // ระงับข้อผิดพลาดในกลุ่มนี้        },      },    },  },}

    การแก้ไขปัญหา

    บอตไม่ตอบกลับข้อความในกลุ่มที่ไม่ได้กล่าวถึง
    • หาก requireMention=false โหมดความเป็นส่วนตัวของ Telegram ต้องอนุญาตให้มองเห็นทั้งหมด: BotFather /setprivacy -> Disable จากนั้นนำบอตออกแล้วเพิ่มกลับเข้าไปในกลุ่ม
    • openclaw channels status จะแจ้งเตือนเมื่อการกำหนดค่าคาดว่าจะได้รับข้อความในกลุ่มที่ไม่ได้กล่าวถึง
    • openclaw channels status --probe ตรวจสอบ ID กลุ่มแบบตัวเลขที่ระบุชัดเจน; ไวลด์การ์ด "*" ไม่สามารถตรวจสอบการเป็นสมาชิกได้
    • การทดสอบเซสชันอย่างรวดเร็ว: /activation always
    บอตไม่เห็นข้อความในกลุ่มเลย
    • เมื่อมี channels.telegram.groups ต้องระบุกลุ่มไว้ในรายการ (หรือรวม "*")
    • ตรวจสอบว่าบอตเป็นสมาชิกของกลุ่ม
    • ตรวจสอบ openclaw logs --follow เพื่อดูสาเหตุที่ข้าม
    คำสั่งทำงานเพียงบางส่วนหรือไม่ทำงานเลย
    • อนุญาตข้อมูลประจำตัวของผู้ส่ง (การจับคู่และ/หรือ allowFrom แบบตัวเลข); การอนุญาตคำสั่งยังคงมีผลแม้นโยบายกลุ่มจะเป็น open
    • setMyCommands failed พร้อม BOT_COMMANDS_TOO_MUCH หมายความว่าเมนูแบบเนทีฟมีรายการมากเกินไป; ลดคำสั่งของ Plugin/Skills/คำสั่งกำหนดเอง หรือปิดใช้งานเมนูแบบเนทีฟ
    • การเรียกใช้ deleteMyCommands / setMyCommands ตอนเริ่มต้นและการเรียกใช้การพิมพ์ sendChatAction มีขอบเขตจำกัด และจะลองใหม่หนึ่งครั้งผ่านการขนส่งสำรองของ Telegram เมื่อคำขอหมดเวลา ข้อผิดพลาดด้านเครือข่าย/การดึงข้อมูลที่เกิดขึ้นต่อเนื่องมักหมายความว่าไม่สามารถเข้าถึง DNS/HTTPS ไปยัง api.telegram.org
    การเริ่มต้นรายงานว่าโทเค็นไม่ได้รับอนุญาต
    • getMe returned 401 คือข้อผิดพลาดการยืนยันตัวตนของ Telegram สำหรับโทเค็นบอตที่กำหนดค่าไว้ คัดลอกโทเค็นใหม่หรือสร้างโทเค็นใหม่ใน BotFather แล้วอัปเดต channels.telegram.botToken, tokenFile, accounts.<id>.botToken หรือ TELEGRAM_BOT_TOKEN (บัญชีเริ่มต้น)
    • deleteWebhook 401 Unauthorized ระหว่างการเริ่มต้นก็เป็นข้อผิดพลาดการยืนยันตัวตนเช่นกัน; การถือว่าเป็น "ไม่มี Webhook" จะเพียงเลื่อนข้อผิดพลาดจากโทเค็นที่ไม่ถูกต้องเดียวกันไปยังการเรียก API ในภายหลัง
    ความไม่เสถียรของการสำรวจหรือเครือข่าย
    • Node 22+ ที่ใช้ fetch/พร็อกซีแบบกำหนดเองอาจทำให้เกิดพฤติกรรมยกเลิกทันทีหากชนิดของ AbortSignal ไม่ตรงกัน
    • โฮสต์บางแห่งแปลง api.telegram.org เป็น IPv6 ก่อน; การส่งออก IPv6 ที่เสียหายทำให้ API ล้มเหลวเป็นระยะ
    • บันทึกที่มี TypeError: fetch failed หรือ Network request for 'getUpdates' failed! จะถูกลองใหม่ในฐานะข้อผิดพลาดเครือข่ายที่กู้คืนได้
    • ระหว่างการเริ่มต้นการสำรวจ OpenClaw จะนำโพรบ getMe ที่สำเร็จตอนเริ่มต้นกลับมาใช้กับ grammY เพื่อให้ตัวเรียกใช้ไม่ต้องใช้ getMe ครั้งที่สองก่อน getUpdates ครั้งแรก
    • หาก deleteWebhook ล้มเหลวด้วยข้อผิดพลาดเครือข่ายชั่วคราวระหว่างการเริ่มต้นการสำรวจ OpenClaw จะดำเนินการสำรวจแบบยาวต่อแทนการเรียกใช้ส่วนควบคุมก่อนการสำรวจอีกครั้ง จากนั้น Webhook ที่ยังทำงานอยู่จะแสดงเป็นข้อขัดแย้ง getUpdates; OpenClaw จะสร้างการขนส่งใหม่และลองล้าง Webhook อีกครั้ง
    • Polling stall detected ในบันทึกหมายความว่า OpenClaw เริ่มการสำรวจใหม่และสร้างการขนส่งใหม่ หลังจากไม่มีการตรวจพบว่ายังทำงานจากการสำรวจแบบยาวที่เสร็จสมบูรณ์เป็นเวลา 120 วินาทีโดยค่าเริ่มต้น
    • openclaw channels status --probe และ openclaw doctor จะแจ้งเตือนเมื่อบัญชีการสำรวจที่กำลังทำงานยังไม่เสร็จสิ้น getUpdates หลังช่วงผ่อนผันการเริ่มต้น, บัญชี Webhook ที่กำลังทำงานยังไม่เสร็จสิ้น setWebhook หลังช่วงผ่อนผันการเริ่มต้น หรือกิจกรรมการขนส่งการสำรวจที่สำเร็จครั้งล่าสุดล้าสมัย
    • Telegram ใช้ env พร็อกซีของกระบวนการสำหรับการขนส่ง Bot API: HTTP_PROXY, HTTPS_PROXY, ALL_PROXY และรูปแบบตัวพิมพ์เล็ก NO_PROXY / no_proxy ยังคงสามารถข้าม api.telegram.org ได้
    • หากกำหนด OPENCLAW_PROXY_URL สำหรับสภาพแวดล้อมบริการและไม่มี env พร็อกซีมาตรฐาน Telegram จะใช้ URL นั้นสำหรับการขนส่ง Bot API ด้วย
    • บนโฮสต์ VPS ที่การส่งออกโดยตรง/TLS ไม่เสถียร ให้กำหนดเส้นทางการเรียก Telegram API ผ่านพร็อกซี:
    yaml
    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 แล้วจึงใช้ค่าเริ่มต้นของกระบวนการ (เช่น NODE_OPTIONS=--dns-result-order=ipv4first) และจะใช้ ipv4first เป็นค่าทดแทนบน Node 22+ หากไม่มีค่าใดใช้ได้
    • บน WSL2 หรือเมื่อพฤติกรรมแบบ IPv4 เท่านั้นทำงานได้ดีกว่า ให้บังคับการเลือกแฟมิลี:
    yaml
    channels:telegram:network:  autoSelectFamily: false
    • คำตอบในช่วงเกณฑ์มาตรฐาน RFC 2544 (198.18.0.0/15) ได้รับอนุญาตสำหรับการดาวน์โหลดสื่อ Telegram โดยค่าเริ่มต้นอยู่แล้ว หากพร็อกซี fake-IP หรือพร็อกซีแบบโปร่งใสที่เชื่อถือได้เขียน api.telegram.org ใหม่เป็นที่อยู่ส่วนตัว/ภายใน/การใช้งานพิเศษอื่นระหว่างการดาวน์โหลดสื่อ ให้เลือกใช้การข้ามเฉพาะ Telegram:
    yaml
    channels:telegram:network:  dangerouslyAllowPrivateNetwork: true
    • ตัวเลือกเดียวกันนี้ใช้ได้แยกตามบัญชีที่ channels.telegram.accounts.<accountId>.network.dangerouslyAllowPrivateNetwork
    • หากพร็อกซีของคุณแปลงโฮสต์สื่อ Telegram เป็น 198.18.x.x ให้ปิดแฟล็กอันตรายไว้ก่อน เพราะช่วงดังกล่าวได้รับอนุญาตโดยค่าเริ่มต้นอยู่แล้ว
    • ค่าทับสภาพแวดล้อมชั่วคราว: OPENCLAW_TELEGRAM_DISABLE_AUTO_SELECT_FAMILY=1, OPENCLAW_TELEGRAM_ENABLE_AUTO_SELECT_FAMILY=1, OPENCLAW_TELEGRAM_DNS_RESULT_ORDER=ipv4first
    • ตรวจสอบคำตอบ DNS:
    bash
    dig +short api.telegram.org Adig +short api.telegram.org AAAA

    ความช่วยเหลือเพิ่มเติม: การแก้ไขปัญหาช่องทาง

    เอกสารอ้างอิงการกำหนดค่า

    เอกสารอ้างอิงหลัก: เอกสารอ้างอิงการกำหนดค่า - Telegram

    ฟิลด์ Telegram ที่มีสัญญาณสำคัญ
    • การเริ่มต้น/การยืนยันตัวตน: enabled, botToken, tokenFile (ต้องเป็นไฟล์ปกติ ไม่รองรับ symlink), accounts.*
    • การควบคุมการเข้าถึง: dmPolicy, allowFrom, groupPolicy, groupAllowFrom, groups, groups.*.topics.*, bindings[] ระดับบนสุด (type: "acp")
    • ค่าเริ่มต้นของหัวข้อ: groups.<chatId>.topics."*" ใช้กับหัวข้อฟอรัมที่ไม่ตรงกัน โดย ID หัวข้อที่ตรงกันทุกประการจะมีสิทธิ์เหนือกว่า
    • การอนุมัติการดำเนินการ: execApprovals, accounts.*.execApprovals
    • คำสั่ง/เมนู: commands.native, commands.nativeSkills, customCommands
    • เธรด/การตอบกลับ: replyToMode, threadBindings
    • การสตรีม: streaming (โหมด off | partial | block | progress), streaming.preview.toolProgress
    • การจัดรูปแบบ/การส่ง: textChunkLimit, streaming.chunkMode, richMessages, markdown.tables (off | bullets | code | block), linkPreview, responsePrefix
    • สื่อ/เครือข่าย: mediaMaxMb, network.autoSelectFamily, network.dangerouslyAllowPrivateNetwork, proxy
    • รูท API แบบกำหนดเอง: apiRoot (เฉพาะรูท Bot API เท่านั้น ห้ามรวม /bot&lt;TOKEN&gt;), trustedLocalFileRoots (รูท file_path แบบสัมบูรณ์ของ Bot API ที่โฮสต์เอง)
    • Webhook: webhookUrl, webhookSecret, webhookPath, webhookHost, webhookPort, webhookCertPath
    • การดำเนินการ/ความสามารถ: capabilities.inlineButtons, actions.sendMessage|editMessage|deleteMessage|reactions|sticker|createForumTopic|editForumTopic
    • รีแอ็กชัน: reactionNotifications, reactionLevel
    • ข้อผิดพลาด: errorPolicy, silentErrorReplies
    • การเขียน/ประวัติ: configWrites, historyLimit, dmHistoryLimit, dms.*.historyLimit

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

    Was this useful?
    On this page

    On this page