---
read_when:
    - การพัฒนาฟีเจอร์หรือ Webhook ของ Telegram
summary: สถานะการรองรับ ความสามารถ และการกำหนดค่าบอต Telegram
title: Telegram
x-i18n:
    generated_at: "2026-07-16T18:56:51Z"
    model: gpt-5.6
    postprocess_version: locale-links-v1
    prompt_version: 32
    provider: openai
    source_hash: 51c155afeb147b92a55f181be269ce13c4fd6b609a94d680cd7e091cd4a7c236
    source_path: channels/telegram.md
    workflow: 16
---

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

<CardGroup cols={3}>
  <Card title="การจับคู่" icon="link" href="/th/channels/pairing">
    นโยบาย DM เริ่มต้นสำหรับ Telegram คือการจับคู่
  </Card>
  <Card title="การแก้ไขปัญหาช่องทาง" icon="wrench" href="/th/channels/troubleshooting">
    คู่มือวินิจฉัยและแก้ไขปัญหาข้ามช่องทาง
  </Card>
  <Card title="การกำหนดค่า Gateway" icon="settings" href="/th/gateway/configuration">
    รูปแบบและตัวอย่างการกำหนดค่าช่องทางทั้งหมด
  </Card>
</CardGroup>

## ตั้งค่าด่วน

<Steps>
  <Step title="สร้างโทเค็นบอตใน BotFather">
    ทั้งสองวิธีจะให้โทเค็นสำหรับวางใน OpenClaw — เลือกวิธีใดวิธีหนึ่ง:

    - **ผ่านแชต**: เปิด Telegram แชตกับ **@BotFather** (ยืนยันว่าแฮนเดิลเป็น `@BotFather` ตรงตามนี้) เรียกใช้ `/newbot` ทำตามข้อความแจ้ง และบันทึกโทเค็น
    - **ผ่านเว็บ**: เปิด [เว็บแอปของ BotFather](https://t.me/BotFather?startapp) — ใช้งานได้ในไคลเอนต์ Telegram ทุกตัว รวมถึง [web.telegram.org](https://web.telegram.org) — สร้างบอตใน UI แล้วคัดลอกโทเค็น

  </Step>

  <Step title="กำหนดค่าโทเค็นและนโยบาย DM">

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

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

  </Step>

  <Step title="เริ่ม Gateway และอนุมัติ DM แรก">

```bash
openclaw gateway
openclaw pairing list telegram
openclaw pairing approve telegram <CODE>
```

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

  </Step>

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

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

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

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

  </Step>
</Steps>

<Note>
การเลือกใช้โทเค็นคำนึงถึงบัญชี: `tokenFile` มีลำดับความสำคัญเหนือ `botToken` และค่าสภาพแวดล้อมตามลำดับ ส่วนค่ากำหนดจะมีลำดับความสำคัญเหนือ `TELEGRAM_BOT_TOKEN` เสมอ (ซึ่งใช้ได้เฉพาะบัญชีเริ่มต้น) หลังจากเริ่มทำงานสำเร็จ OpenClaw จะแคชข้อมูลประจำตัวของบอตไว้นานสูงสุด 24 ชั่วโมง เพื่อให้การเริ่มใหม่ข้ามการเรียก `getMe` เพิ่มเติม การเปลี่ยนหรือลบโทเค็นจะล้างแคชนี้
</Note>

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

<AccordionGroup>
  <Accordion title="โหมดความเป็นส่วนตัวและการมองเห็นในกลุ่ม">
    โดยค่าเริ่มต้น บอต Telegram ใช้ **Privacy Mode** ซึ่งจำกัดข้อความกลุ่มที่บอตได้รับ

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

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

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

  </Accordion>

  <Accordion title="สิทธิ์ของกลุ่ม">
    สถานะผู้ดูแลควบคุมผ่านการตั้งค่ากลุ่ม Telegram บอตที่เป็นผู้ดูแลจะได้รับข้อความกลุ่มทั้งหมด ซึ่งเหมาะสำหรับพฤติกรรมกลุ่มที่ทำงานตลอดเวลา
  </Accordion>

  <Accordion title="ตัวเลือก BotFather ที่เป็นประโยชน์">

    - `/setjoingroups` — อนุญาต/ปฏิเสธการเพิ่มลงในกลุ่ม
    - `/setprivacy` — พฤติกรรมการมองเห็นในกลุ่ม

    การตั้งค่าเดียวกันมีอยู่ใน [เว็บแอปของ BotFather](https://t.me/BotFather?startapp) หากต้องการใช้ UI แทนคำสั่งแชต

  </Accordion>
</AccordionGroup>

## 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 ก็ตาม นโยบายไม่ตอบสนองในกลุ่มยังคงมีผลกับข้อความที่ไม่เกี่ยวข้อง แต่แฮนเดิลของบอตเองจะไม่ถูกมองว่าเป็น "บุคคลอื่น"

<Tabs>
  <Tab title="นโยบาย DM">
    `channels.telegram.dmPolicy` ควบคุมการเข้าถึงข้อความโดยตรง:

    - `pairing` (ค่าเริ่มต้น)
    - `allowlist` (ต้องมี ID ผู้ส่งอย่างน้อยหนึ่งรายการใน `allowFrom`)
    - `open` (กำหนดให้ `allowFrom` มี `"*"`)
    - `disabled`

    `dmPolicy: "open"` ร่วมกับ `allowFrom: ["*"]` ทำให้บัญชี Telegram ใดก็ตามที่ค้นพบหรือเดาชื่อผู้ใช้ของบอตได้สามารถสั่งงานบอตได้ ใช้เฉพาะกับบอตสาธารณะที่ตั้งใจเปิดให้ใช้งานและจำกัดเครื่องมืออย่างเข้มงวดเท่านั้น บอตที่มีเจ้าของคนเดียวควรใช้ `allowlist` ร่วมกับ ID ผู้ใช้แบบตัวเลข

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

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

    จุดที่มักสับสน: การอนุมัติการจับคู่ DM ไม่ได้หมายความว่า "ผู้ส่งรายนี้ได้รับอนุญาตทุกที่" การจับคู่ให้สิทธิ์เข้าถึงเฉพาะ DM เท่านั้น หากยังไม่มีเจ้าของคำสั่ง การจับคู่ที่ได้รับอนุมัติครั้งแรกจะตั้งค่า `commands.ownerAllowFrom` ด้วย ทำให้คำสั่งสำหรับเจ้าของเท่านั้นและการอนุมัติการดำเนินการมีบัญชีผู้ดำเนินการที่ชัดเจน ส่วนการอนุญาตผู้ส่งในกลุ่มยังคงมาจากรายการอนุญาตที่ระบุอย่างชัดเจนในการกำหนดค่า
    หากต้องการให้ข้อมูลประจำตัวเดียวได้รับอนุญาตทั้งสำหรับ 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`

  </Tab>

  <Tab title="นโยบายกลุ่มและรายการอนุญาต">
    มีการควบคุมสองส่วนที่ใช้ร่วมกัน:

    1. **กลุ่มใดได้รับอนุญาต** (`channels.telegram.groups`)
       - ไม่มีค่ากำหนด `groups`, `groupPolicy: "open"`: ทุกกลุ่มผ่านการตรวจสอบ ID กลุ่ม
       - ไม่มีค่ากำหนด `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` ไม่มีอยู่ในการกำหนดค่าเลย รันไทม์จะใช้ค่าเริ่มต้นแบบปิดเมื่อเกิดข้อผิดพลาด `groupPolicy="allowlist"` เว้นแต่จะตั้งค่า `channels.defaults.groupPolicy` อย่างชัดเจน

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

```json5
{
  channels: {
    telegram: {
      enabled: true,
      dmPolicy: "pairing",
      allowFrom: ["<YOUR_TELEGRAM_USER_ID>"],
      groupPolicy: "allowlist",
      groups: {
        "<GROUP_CHAT_ID>": {
          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"],
        },
      },
    },
  },
}
```

    <Warning>
      ข้อผิดพลาดที่พบบ่อย: `groupAllowFrom` ไม่ใช่รายการอนุญาตกลุ่ม

      - ID แชตของกลุ่ม/ซูเปอร์กรุ๊ป Telegram ที่เป็นค่าลบ (`-1001234567890`) ต้องอยู่ภายใต้ `channels.telegram.groups`
      - ID ผู้ใช้ Telegram (`8734062810`) ต้องอยู่ภายใต้ `groupAllowFrom` เพื่อจำกัดว่าบุคคลใดภายในกลุ่มที่ได้รับอนุญาตสามารถเรียกใช้บอตได้
      - ใช้ `groupAllowFrom: ["*"]` เฉพาะเมื่อต้องการให้สมาชิกทุกคนของกลุ่มที่ได้รับอนุญาตสนทนากับบอตได้

    </Warning>

  </Tab>

  <Tab title="พฤติกรรมการกล่าวถึง">
    โดยค่าเริ่มต้น การตอบกลับในกลุ่มต้องมีการกล่าวถึง ซึ่งอาจมาจาก:

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

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

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

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

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

  </Tab>
</Tabs>

## พฤติกรรมขณะทำงาน

- 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 ภายนอกกำลังใช้โทเค็นเดียวกัน
- โดยค่าเริ่มต้น watchdog ของการทำ polling จะเริ่มใหม่หลังจากไม่มีการยืนยันความพร้อมใช้งานของ `getUpdates` ที่เสร็จสมบูรณ์เป็นเวลา 120 วินาที ให้เพิ่ม `channels.telegram.pollingStallThresholdMs` (30000-600000 รองรับการกำหนดทับรายบัญชี) เฉพาะเมื่อการปรับใช้ของคุณพบการเริ่มใหม่จากการตรวจจับ polling ค้างที่ผิดพลาดระหว่างงานที่ใช้เวลานาน
- Telegram Bot API ไม่รองรับใบตอบรับการอ่าน (`sendReadReceipts` ไม่มีผล)

<Note>
  `channels.telegram.dm.threadReplies` และ `channels.telegram.direct.<chatId>.threadReplies` ถูกนำออกแล้ว เรียกใช้ `openclaw doctor --fix` หลังอัปเกรด หากการกำหนดค่าของคุณยังมีคีย์เหล่านั้น ขณะนี้การกำหนดเส้นทางหัวข้อ DM เป็นไปตาม Telegram `getMe.has_topics_enabled` (ควบคุมโดยโหมดเธรดของ BotFather): บอตที่เปิดใช้หัวข้อจะใช้เซสชัน DM แบบกำหนดขอบเขตตามเธรดเมื่อ Telegram ส่ง `message_thread_id`; ส่วน DM อื่นจะยังคงอยู่ในเซสชันแบบแบน
</Note>

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

<AccordionGroup>
  <Accordion title="ตัวอย่างสตรีมสด (การแก้ไขข้อความ)">
    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` แบบเดิม ค่า boolean ของ `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` จะเก็บเฉพาะการแก้ไขตัวอย่างคำตอบ

    <Note>
      การตอบกลับข้อความอ้างอิงที่เลือกเป็นข้อยกเว้น เมื่อ `replyToMode` เป็น `first`, `all` หรือ `batched` และข้อความขาเข้ามีข้อความอ้างอิงที่เลือก OpenClaw จะส่งคำตอบสุดท้ายผ่านเส้นทางตอบกลับข้อความอ้างอิงแบบเนทีฟของ Telegram แทนการแก้ไขตัวอย่างคำตอบ ดังนั้น `streaming.preview.toolProgress` จึงไม่สามารถแสดงบรรทัดสถานะในการตอบครั้งนั้นได้ การตอบกลับข้อความปัจจุบันที่ไม่มีข้อความอ้างอิงที่เลือกยังคงสตรีมได้ ตั้งค่า `replyToMode: "off"` เมื่อการมองเห็นความคืบหน้าของเครื่องมือสำคัญกว่าการตอบกลับข้อความอ้างอิงแบบเนทีฟ หรือใช้ `streaming.preview.toolProgress: false` เพื่อยอมรับข้อแลกเปลี่ยนดังกล่าว
    </Note>

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

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

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

  </Accordion>

  <Accordion title="การจัดรูปแบบข้อความแบบสมบูรณ์">
    โดยค่าเริ่มต้น ข้อความขาออกใช้ข้อความ 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 อักขระ)

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

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

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

  </Accordion>

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

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

```json5
{
  channels: {
    telegram: {
      customCommands: [
        { command: "backup", description: "สำรองข้อมูล Git" },
        { command: "generate", description: "สร้างรูปภาพ" },
      ],
    },
  },
}
```

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

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

    ความล้มเหลวทั่วไปในการตั้งค่า:

    - `setMyCommands failed` พร้อม `BOT_COMMANDS_TOO_MUCH` หลังจากลองตัดรายการใหม่ หมายความว่าเมนูยังคงเกินขีดจำกัด; ลดคำสั่ง Plugin/Skills/กำหนดเอง หรือปิดใช้ `channels.telegram.commands.native`
    - เมื่อ `deleteWebhook`, `deleteMyCommands` หรือ `setMyCommands` ล้มเหลวด้วย `404: Not Found` ขณะที่คำสั่ง curl โดยตรงไปยัง Bot API ทำงานได้ โดยทั่วไปหมายความว่าตั้งค่า `channels.telegram.apiRoot` เป็น endpoint เต็มของ `/bot<TOKEN>` โดย `apiRoot` ต้องเป็นเฉพาะรากของ Bot API; `openclaw doctor --fix` จะลบ `/bot<TOKEN>` ที่ต่อท้ายโดยไม่ตั้งใจ
    - `getMe returned 401` หมายความว่า Telegram ปฏิเสธโทเค็นบอตที่กำหนดค่าไว้ อัปเดต `botToken`, `tokenFile` หรือ `TELEGRAM_BOT_TOKEN` (บัญชีเริ่มต้น) ด้วยโทเค็น BotFather ปัจจุบัน; OpenClaw จะหยุดก่อนเริ่ม polling ดังนั้นจึงไม่รายงานปัญหานี้เป็นความล้มเหลวในการล้าง Webhook
    - `setMyCommands failed` พร้อมข้อผิดพลาดเครือข่าย/fetch โดยทั่วไปหมายความว่า 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` อีกครั้งก่อนอนุมัติ

    รายละเอียดเพิ่มเติม: [การจับคู่](/th/channels/pairing#pair-via-telegram)

  </Accordion>

  <Accordion title="ปุ่มแบบอินไลน์">
    กำหนดค่าขอบเขตแป้นพิมพ์แบบอินไลน์:

```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: "เลือกตัวเลือก:",
  buttons: [
    [
      { text: "ใช่", callback_data: "yes" },
      { text: "ไม่", callback_data: "no" },
    ],
    [{ text: "ยกเลิก", callback_data: "cancel" }],
  ],
}
```

    ตัวอย่างปุ่ม Mini App:

```json5
{
  action: "send",
  channel: "telegram",
  to: "123456789",
  message: "เปิดแอป:",
  presentation: {
    blocks: [
      {
        type: "buttons",
        buttons: [{ label: "เปิดใช้งาน", web_app: { url: "https://example.com/app" } }],
      },
    ],
  },
}
```

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

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

  </Accordion>

  <Accordion title="การดำเนินการกับข้อความ 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](/th/tools/reactions)

  </Accordion>

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

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

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

    เมื่อเปิดใช้งานเธรดการตอบกลับและมีข้อความ/คำบรรยายต้นฉบับ OpenClaw จะเพิ่มข้อความที่ยกมาแบบเนทีฟโดยอัตโนมัติ Telegram จำกัดข้อความที่ยกมาแบบเนทีฟไว้ที่ 1024 หน่วยโค้ด UTF-16; ข้อความที่ยาวกว่าจะถูกยกมาตั้งแต่ต้น และจะย้อนกลับไปใช้การตอบกลับแบบธรรมดาหาก Telegram ปฏิเสธข้อความที่ยกมา

    `off` ปิดใช้งานเฉพาะเธรดการตอบกลับโดยนัยเท่านั้น โดยแท็ก `[[reply_to_*]]` ที่ระบุชัดเจนยังคงได้รับการใช้งาน

  </Accordion>

  <Accordion title="หัวข้อฟอรัมและลักษณะการทำงานของเธรด">
    ซูเปอร์กรุ๊ปแบบฟอรัม: คีย์เซสชันของหัวข้อจะต่อท้ายด้วย `: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](/th/tools/acp-agents)

    **การสร้าง 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` เพื่อลบคีย์การกำหนดค่าที่ค้างอยู่

  </Accordion>

  <Accordion title="เสียง วิดีโอ และสติกเกอร์">
    ### ข้อความเสียง

    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: "Eiffel Tower",
    address: "Champ de Mars, Paris",
  },
}
```

    ### สติกเกอร์

    ขาเข้า: ระบบจะดาวน์โหลดและประมวลผล 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: "cat waving",
  limit: 5,
}
```

  </Accordion>

  <Accordion title="การแจ้งเตือนรีแอ็กชัน">
    รีแอ็กชันของ 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` สำหรับการทำโพล/เว็บฮุกจะรวม `message_reaction` โดยอัตโนมัติ

  </Accordion>

  <Accordion title="รีแอ็กชันตอบรับ">
    `ackReaction` จะส่งอีโมจิตอบรับขณะที่ OpenClaw ประมวลผลข้อความขาเข้า `messages.ackReactionScope` กำหนดว่าให้ส่ง *เมื่อใด*

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

    - `channels.telegram.accounts.<accountId>.ackReaction`
    - `channels.telegram.ackReaction`
    - `messages.ackReaction`
    - ใช้อีโมจิประจำตัวของเอเจนต์เป็นตัวเลือกสำรอง (`agents.list[].identity.emoji` มิฉะนั้นใช้ "👀")

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

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

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

    <Note>
    ขอบเขตเริ่มต้น (`group-mentions`) จะไม่ส่งรีแอ็กชันตอบรับใน DM หรือเหตุการณ์ห้องแบบแวดล้อม ใช้ `direct` หรือ `all` สำหรับ DM; มีเพียง `all` เท่านั้นที่ตอบรับเหตุการณ์ห้องแบบแวดล้อม ค่านี้จะถูกอ่านเมื่อเริ่มต้นผู้ให้บริการ Telegram ดังนั้นจึงต้องรีสตาร์ต Gateway เพื่อให้การเปลี่ยนแปลงมีผล
    </Note>

  </Accordion>

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

    ปิดใช้งาน:

```json5
{
  channels: {
    telegram: {
      configWrites: false,
    },
  },
}
```

  </Accordion>

  <Accordion title="การทำโพลแบบยาวเทียบกับเว็บฮุก">
    ค่าเริ่มต้นคือการทำโพลแบบยาว สำหรับโหมดเว็บฮุก ให้ตั้งค่า `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"` โดยตั้งใจ

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

    จากนั้น OpenClaw จะประมวลผลการอัปเดตแบบอะซิงโครนัสผ่านเลนของบอตแยกตามแชต/หัวข้อชุดเดียวกับที่ใช้ในการทำโพลแบบยาว ดังนั้นรอบการทำงานของเอเจนต์ที่ช้าจึงไม่ทำให้ ACK การส่งของ Telegram ต้องรอ

  </Accordion>

  <Accordion title="ขีดจำกัด การลองใหม่ และเป้าหมาย CLI">
    - `channels.telegram.textChunkLimit` ค่าเริ่มต้นคือ 4000; `streaming.chunkMode="newline"` จะเลือกแบ่งที่ขอบเขตย่อหน้า (บรรทัดว่าง) ก่อนแบ่งตามความยาว
    - `channels.telegram.mediaMaxMb` (ค่าเริ่มต้น 100) จำกัดขนาดสื่อขาเข้าและขาออก
    - `channels.telegram.mediaGroupFlushMs` (ค่าเริ่มต้น 500, ช่วง 10-60000) ควบคุมระยะเวลาบัฟเฟอร์อัลบั้ม/กลุ่มสื่อก่อนที่ OpenClaw จะส่งต่อเป็นข้อความขาเข้าหนึ่งข้อความ เพิ่มค่านี้หากส่วนต่างๆ ของอัลบั้มมาถึงล่าช้า หรือลดค่าเพื่อลดเวลาแฝงในการตอบกลับอัลบั้ม
    - `channels.telegram.timeoutSeconds` แทนที่ระยะหมดเวลาของไคลเอนต์ API (หากไม่ได้ตั้งค่า จะใช้ค่าเริ่มต้นของ grammY) ไคลเอนต์บอตจะจำกัดค่าที่กำหนดไว้ซึ่งต่ำกว่าตัวควบคุมคำขอข้อความขาออก/การพิมพ์ที่ 60 วินาที เพื่อไม่ให้ grammY ยกเลิกการส่งคำตอบที่ผู้ใช้มองเห็นก่อนที่ตัวควบคุมการส่งและกลไกสำรองของ OpenClaw จะทำงานได้ การทำ long polling ยังคงใช้ตัวควบคุมคำขอ `getUpdates` ที่ 45 วินาที เพื่อไม่ให้ละทิ้งการโพลที่ไม่มีการใช้งานไปอย่างไม่มีกำหนด
    - `channels.telegram.pollingStallThresholdMs` มีค่าเริ่มต้นเป็น 120000; ปรับภายในช่วง 30000 ถึง 600000 เฉพาะกรณีการเริ่มการโพลใหม่จากการตรวจพบการหยุดชะงักที่เป็นผลบวกลวง
    - ประวัติบริบทของกลุ่มใช้ `channels.telegram.historyLimit` หรือ `messages.groupChat.historyLimit` (ค่าเริ่มต้น 50); `0` เป็นการปิดใช้งาน
    - บริบทเสริมของการตอบกลับ/การอ้างข้อความ/การส่งต่อจะถูกปรับให้อยู่ในหน้าต่างบริบทการสนทนาที่เลือกหนึ่งหน้าต่าง เมื่อ Gateway ตรวจพบข้อความต้นทางแล้ว; แคชข้อความที่ตรวจพบจะอยู่ในสถานะ Plugin SQLite ของ OpenClaw และ `openclaw doctor --fix` จะนำเข้าไฟล์ sidecar แบบเดิม Telegram ใส่ `reply_to_message` แบบตื้นเพียงหนึ่งรายการต่อการอัปเดต ดังนั้นสายข้อความที่เก่ากว่าแคชจึงจำกัดอยู่เพียงเพย์โหลดนั้น
    - รายการอนุญาตของ Telegram ใช้ควบคุมเป็นหลักว่าใครสามารถเรียกใช้เอเจนต์ได้ ไม่ใช่ขอบเขตการปกปิดข้อมูลของบริบทเสริมอย่างสมบูรณ์
    - ประวัติ DM: `channels.telegram.dmHistoryLimit`, `channels.telegram.dms["<user_id>"].historyLimit`
    - `channels.telegram.retry` ใช้กับตัวช่วยส่งของ Telegram (CLI/เครื่องมือ/การดำเนินการ) สำหรับข้อผิดพลาด API ขาออกที่กู้คืนได้ การส่งคำตอบสุดท้ายขาเข้าใช้การลองส่งแบบปลอดภัยซ้ำโดยมีขีดจำกัดสำหรับความล้มเหลวก่อนเชื่อมต่อ แต่จะไม่ลองซ้ำสำหรับซองข้อมูลเครือข่ายหลังส่งที่มีความกำกวม ซึ่งอาจทำให้ข้อความที่ผู้ใช้มองเห็นซ้ำกัน

    เป้าหมายการส่งของ 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` ปิดใช้งานการสร้างโพลโดยยังคงเปิดใช้งานการส่งตามปกติ

  </Accordion>

  <Accordion title="การอนุมัติการดำเนินการคำสั่งใน 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 อื่นจะถูกแก้ไขผ่านการอนุมัติการดำเนินการคำสั่งก่อน

    ดู[การอนุมัติการดำเนินการคำสั่ง](/th/tools/exec-approvals)

  </Accordion>
</AccordionGroup>

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

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

| คีย์                                 | ค่า                     | ค่าเริ่มต้น         | คำอธิบาย                                                                                                                                                                                              |
| ----------------------------------- | -------------------------- | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `channels.telegram.errorPolicy`     | `always`, `once`, `silent` | `always`        | `always` ส่งข้อความข้อผิดพลาดทุกข้อความไปยังแชต `once` ส่งข้อความข้อผิดพลาดแต่ละข้อความที่ไม่ซ้ำหนึ่งครั้งต่อช่วงพัก (ระงับข้อผิดพลาดซ้ำที่เหมือนกัน) `silent` จะไม่ส่งข้อความข้อผิดพลาดไปยังแชต |
| `channels.telegram.errorCooldownMs` | ตัวเลข (ms)                | `14400000` (4h) | ช่วงพักสำหรับนโยบาย `once` หลังส่งข้อผิดพลาดแล้ว ข้อความเดียวกันจะถูกระงับจนกว่าช่วงเวลานี้จะผ่านไป ช่วยป้องกันข้อความข้อผิดพลาดจำนวนมากระหว่างระบบขัดข้อง                                           |

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

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

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

<AccordionGroup>
  <Accordion title="บอตไม่ตอบกลับข้อความกลุ่มที่ไม่ได้กล่าวถึงบอต">

    - หาก `requireMention=false` โหมดความเป็นส่วนตัวของ Telegram ต้องอนุญาตให้มองเห็นได้ทั้งหมด: BotFather `/setprivacy` -> Disable จากนั้นนำบอตออกแล้วเพิ่มกลับเข้าไปในกลุ่ม
    - `openclaw channels status` จะแจ้งเตือนเมื่อการกำหนดค่าคาดว่าจะได้รับข้อความกลุ่มที่ไม่ได้กล่าวถึงบอต
    - `openclaw channels status --probe` ตรวจสอบ ID กลุ่มแบบตัวเลขที่ระบุอย่างชัดเจน; ไม่สามารถตรวจสอบการเป็นสมาชิกสำหรับอักขระตัวแทน `"*"` ได้
    - การทดสอบเซสชันแบบรวดเร็ว: `/activation always`

  </Accordion>

  <Accordion title="บอตไม่เห็นข้อความกลุ่มเลย">

    - เมื่อมี `channels.telegram.groups` ต้องระบุกลุ่มไว้ในรายการ (หรือมี `"*"`)
    - ตรวจสอบว่าบอตเป็นสมาชิกในกลุ่ม
    - ตรวจสอบ `openclaw logs --follow` เพื่อดูเหตุผลที่ข้าม

  </Accordion>

  <Accordion title="คำสั่งทำงานเพียงบางส่วนหรือไม่ทำงานเลย">

    - อนุญาตข้อมูลระบุตัวตนของผู้ส่ง (การจับคู่และ/หรือ `allowFrom` แบบตัวเลข); การอนุญาตคำสั่งยังคงมีผลแม้นโยบายกลุ่มจะเป็น `open`
    - `setMyCommands failed` พร้อม `BOT_COMMANDS_TOO_MUCH` หมายความว่าเมนูเนทีฟมีรายการมากเกินไป; ลดคำสั่ง Plugin/Skills/คำสั่งกำหนดเอง หรือปิดใช้งานเมนูเนทีฟ
    - การเรียกใช้ `deleteMyCommands` / `setMyCommands` เมื่อเริ่มทำงานและการเรียกใช้การพิมพ์ `sendChatAction` มีขีดจำกัดและจะลองใหม่หนึ่งครั้งผ่านกลไกสำรองของการส่ง Telegram เมื่อคำขอหมดเวลา ข้อผิดพลาดเครือข่าย/fetch ที่เกิดขึ้นต่อเนื่องมักหมายความว่าไม่สามารถเข้าถึง DNS/HTTPS ไปยัง `api.telegram.org` ได้

  </Accordion>

  <Accordion title="การเริ่มทำงานรายงานโทเค็นที่ไม่ได้รับอนุญาต">

    - `getMe returned 401` คือความล้มเหลวในการตรวจสอบสิทธิ์ Telegram สำหรับโทเค็นบอตที่กำหนดค่าไว้ คัดลอกหรือสร้างโทเค็นใหม่ใน BotFather จากนั้นอัปเดต `channels.telegram.botToken`, `tokenFile`, `accounts.<id>.botToken` หรือ `TELEGRAM_BOT_TOKEN` (บัญชีเริ่มต้น)
    - `deleteWebhook 401 Unauthorized` ระหว่างเริ่มทำงานก็เป็นความล้มเหลวในการตรวจสอบสิทธิ์เช่นกัน; การถือว่าเป็น "ไม่มี webhook อยู่" จะเพียงเลื่อนความล้มเหลวจากโทเค็นที่ไม่ถูกต้องเดียวกันไปยังการเรียก API ในภายหลัง

  </Accordion>

  <Accordion title="ความไม่เสถียรของการโพลหรือเครือข่าย">

    - 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 จะดำเนินการทำ long polling ต่อแทนการเรียก control plane ก่อนโพลอีกครั้ง จากนั้น webhook ที่ยังทำงานอยู่จะแสดงเป็นข้อขัดแย้ง `getUpdates`; OpenClaw จะสร้างการส่งขึ้นใหม่และลองล้าง webhook อีกครั้ง
    - หากซ็อกเก็ต Telegram ถูกสร้างใหม่ตามรอบเวลาคงที่สั้นๆ ให้ตรวจสอบ `channels.telegram.timeoutSeconds` ที่มีค่าต่ำ — ไคลเอนต์บอตจะจำกัดค่าที่กำหนดไว้ซึ่งต่ำกว่าตัวควบคุมคำขอขาออกและ `getUpdates` แต่รุ่นเก่าอาจยกเลิกทุกการโพลหรือคำตอบเมื่อตั้งค่านี้ต่ำกว่าตัวควบคุมเหล่านั้น
    - `Polling stall detected` ในบันทึกหมายความว่า OpenClaw เริ่มการโพลใหม่และสร้างการส่งขึ้นใหม่หลังจากไม่มีการตรวจสอบความพร้อมใช้งานของ long poll ที่เสร็จสมบูรณ์เป็นเวลา 120 วินาทีโดยค่าเริ่มต้น
    - `openclaw channels status --probe` และ `openclaw doctor` จะแจ้งเตือนเมื่อบัญชีการโพลที่กำลังทำงานยังไม่ดำเนินการ `getUpdates` ให้เสร็จหลังช่วงผ่อนผันการเริ่มทำงาน บัญชี webhook ที่กำลังทำงานยังไม่ดำเนินการ `setWebhook` ให้เสร็จหลังช่วงผ่อนผันการเริ่มทำงาน หรือกิจกรรมการส่งของการโพลที่สำเร็จล่าสุดล้าสมัย
    - เพิ่ม `channels.telegram.pollingStallThresholdMs` เฉพาะเมื่อการเรียก `getUpdates` ที่ทำงานเป็นเวลานานยังทำงานปกติ แต่โฮสต์ยังรายงานการเริ่มการโพลใหม่จากการตรวจพบการหยุดชะงักที่เป็นผลบวกลวง การหยุดชะงักต่อเนื่องมักชี้ถึงปัญหาการเชื่อมต่อขาออกของพร็อกซี DNS, IPv6 หรือ TLS ไปยัง `api.telegram.org`
    - Telegram ใช้ตัวแปรสภาพแวดล้อมพร็อกซีของกระบวนการสำหรับการส่ง Bot API: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY` และรูปแบบตัวพิมพ์เล็ก `NO_PROXY` / `no_proxy` ยังสามารถข้าม `api.telegram.org` ได้
    - หากตั้งค่า `OPENCLAW_PROXY_URL` สำหรับสภาพแวดล้อมบริการและไม่มีตัวแปรสภาพแวดล้อมพร็อกซีมาตรฐาน 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` ให้ปิดแฟล็กอันตรายไว้ก่อน เนื่องจากช่วงดังกล่าวได้รับอนุญาตโดยค่าเริ่มต้นอยู่แล้ว

    <Warning>
      `channels.telegram.network.dangerouslyAllowPrivateNetwork` ทำให้การป้องกัน SSRF สำหรับสื่อของ Telegram อ่อนลง ใช้เฉพาะในสภาพแวดล้อมพร็อกซีที่เชื่อถือได้และควบคุมโดยผู้ดำเนินการ (การกำหนดเส้นทาง fake-IP ของ Clash, Mihomo, Surge) ซึ่งสร้างคำตอบที่เป็นที่อยู่ส่วนตัวหรือสำหรับการใช้งานพิเศษนอกช่วงที่อยู่สำหรับการทดสอบประสิทธิภาพตาม RFC 2544 เท่านั้น ให้ปิดไว้สำหรับการเข้าถึง Telegram ผ่านอินเทอร์เน็ตสาธารณะตามปกติ
    </Warning>

    - การแทนที่ชั่วคราวด้วยตัวแปรสภาพแวดล้อม: `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 A
dig +short api.telegram.org AAAA
```

  </Accordion>
</AccordionGroup>

ความช่วยเหลือเพิ่มเติม: [การแก้ไขปัญหาช่องทาง](/th/channels/troubleshooting)

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

เอกสารอ้างอิงหลัก: [เอกสารอ้างอิงการกำหนดค่า - Telegram](/th/gateway/config-channels#telegram)

<Accordion title="ฟิลด์สำคัญของ Telegram">

- การเริ่มต้น/การยืนยันตัวตน: `enabled`, `botToken`, `tokenFile` (ต้องเป็นไฟล์ปกติ ไม่อนุญาตให้ใช้ลิงก์สัญลักษณ์), `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`, `mediaGroupFlushMs`, `timeoutSeconds`, `pollingStallThresholdMs`, `retry`, `network.autoSelectFamily`, `network.dangerouslyAllowPrivateNetwork`, `proxy`
- รูท API แบบกำหนดเอง: `apiRoot` (เฉพาะรูท Bot API อย่ารวม `/bot<TOKEN>`), `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`, `errorCooldownMs`, `silentErrorReplies`
- การเขียน/ประวัติ: `configWrites`, `historyLimit`, `dmHistoryLimit`, `dms.*.historyLimit`

</Accordion>

<Note>
ลำดับความสำคัญเมื่อใช้หลายบัญชี: เมื่อกำหนดค่า ID บัญชีตั้งแต่สองรายการขึ้นไป ให้ตั้งค่า `channels.telegram.defaultAccount` (หรือรวม `channels.telegram.accounts.default`) เพื่อระบุการกำหนดเส้นทางเริ่มต้นอย่างชัดเจน มิฉะนั้น OpenClaw จะใช้ ID บัญชีแรกที่ผ่านการปรับให้อยู่ในรูปแบบมาตรฐานเป็นค่าทดแทน และ `openclaw doctor` จะแสดงคำเตือน บัญชีที่มีชื่อจะสืบทอด `channels.telegram.allowFrom` / `groupAllowFrom` แต่จะไม่สืบทอดค่าของ `accounts.default.*`
</Note>

## เนื้อหาที่เกี่ยวข้อง

<CardGroup cols={2}>
  <Card title="การจับคู่" icon="link" href="/th/channels/pairing">
    จับคู่ผู้ใช้ Telegram กับ Gateway
  </Card>
  <Card title="กลุ่ม" icon="users" href="/th/channels/groups">
    ลักษณะการทำงานของรายการอนุญาตสำหรับกลุ่มและหัวข้อ
  </Card>
  <Card title="การกำหนดเส้นทางช่องทาง" icon="route" href="/th/channels/channel-routing">
    กำหนดเส้นทางข้อความขาเข้าไปยังเอเจนต์
  </Card>
  <Card title="ความปลอดภัย" icon="shield" href="/th/gateway/security">
    แบบจำลองภัยคุกคามและการเสริมความแข็งแกร่งด้านความปลอดภัย
  </Card>
  <Card title="การกำหนดเส้นทางแบบหลายเอเจนต์" icon="sitemap" href="/th/concepts/multi-agent">
    จับคู่กลุ่มและหัวข้อกับเอเจนต์
  </Card>
  <Card title="การแก้ไขปัญหา" icon="wrench" href="/th/channels/troubleshooting">
    การวินิจฉัยข้ามช่องทาง
  </Card>
</CardGroup>
