---
read_when:
    - อธิบายว่าข้อความขาเข้ากลายเป็นการตอบกลับได้อย่างไร
    - การชี้แจงเซสชัน โหมดการจัดคิว หรือพฤติกรรมการสตรีม
    - การจัดทำเอกสารเกี่ยวกับการมองเห็นการให้เหตุผลและผลกระทบต่อการใช้งาน
summary: โฟลว์ข้อความ เซสชัน การจัดคิว และการมองเห็นการให้เหตุผล
title: ข้อความ
x-i18n:
    generated_at: "2026-05-10T19:33:29Z"
    model: gpt-5.5
    provider: openai
    source_hash: 053ff7b2ecca07e99057aed2f9ba199a6c1a07f15e865915045d25d128db984b
    source_path: concepts/messages.md
    workflow: 16
---

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

## โฟลว์ข้อความ (ภาพรวมระดับสูง)

```
Inbound message
  -> routing/bindings -> session key
  -> queue (if a run is active)
  -> agent run (streaming + tools)
  -> outbound replies (channel limits + chunking)
```

ปุ่มปรับหลักอยู่ในการกำหนดค่า:

- `messages.*` สำหรับคำนำหน้า การเข้าคิว และพฤติกรรมของกลุ่ม
- `agents.defaults.*` สำหรับค่าเริ่มต้นของการสตรีมแบบบล็อกและการแบ่งชิ้นข้อความ
- การแทนที่ตามช่องทาง (`channels.whatsapp.*`, `channels.telegram.*` ฯลฯ) สำหรับเพดานจำกัดและสวิตช์การสตรีม

ดูสคีมาฉบับเต็มได้ที่ [การกำหนดค่า](/th/gateway/configuration)

## การตัดข้อความขาเข้าซ้ำ

ช่องทางอาจส่งข้อความเดิมซ้ำหลังจากเชื่อมต่อใหม่ OpenClaw เก็บแคชอายุสั้นที่ใช้ channel/account/peer/session/message id เป็นคีย์ เพื่อไม่ให้การส่งซ้ำทริกเกอร์การรันเอเจนต์อีกครั้ง

## การ debounce ข้อความขาเข้า

ข้อความที่ส่งต่อเนื่องอย่างรวดเร็วจาก **ผู้ส่งคนเดียวกัน** สามารถถูกรวมเป็นเทิร์นเอเจนต์เดียวได้ผ่าน `messages.inbound` การ debounce มีขอบเขตต่อช่องทาง + บทสนทนา และใช้ข้อความล่าสุดสำหรับ threading/ID ของการตอบกลับ

การกำหนดค่า (ค่าเริ่มต้นส่วนกลาง + การแทนที่รายช่องทาง):

```json5
{
  messages: {
    inbound: {
      debounceMs: 2000,
      byChannel: {
        whatsapp: 5000,
        slack: 1500,
        discord: 1500,
      },
    },
  },
}
```

หมายเหตุ:

- Debounce ใช้กับข้อความ **ข้อความล้วน** เท่านั้น สื่อ/ไฟล์แนบจะ flush ทันที
- คำสั่งควบคุมจะข้ามการ debounce เพื่อให้ยังคงเป็นรายการเดี่ยว ช่องทางที่เลือกใช้การรวม DM จากผู้ส่งเดียวกันอย่างชัดเจนสามารถเก็บคำสั่ง DM ไว้ในช่วง debounce ได้ เพื่อให้ payload ที่ถูกแยกส่งเข้าร่วมเทิร์นเอเจนต์เดียวกันได้

## เซสชันและอุปกรณ์

เซสชันเป็นของ Gateway ไม่ใช่ของไคลเอนต์

- แชทโดยตรงจะถูกรวมเข้าเป็นคีย์เซสชันหลักของเอเจนต์
- กลุ่ม/ช่องทางจะได้คีย์เซสชันของตัวเอง
- ที่เก็บเซสชันและทรานสคริปต์อยู่บนโฮสต์ Gateway

อุปกรณ์/ช่องทางหลายรายการสามารถแมปไปยังเซสชันเดียวกันได้ แต่ประวัติจะไม่ถูกซิงก์กลับไปยังไคลเอนต์ทุกตัวอย่างครบถ้วน คำแนะนำ: ใช้อุปกรณ์หลักเครื่องเดียวสำหรับบทสนทนายาว ๆ เพื่อหลีกเลี่ยงบริบทที่แตกต่างกัน Control UI และ TUI จะแสดงทรานสคริปต์เซสชันที่อิงกับ Gateway เสมอ ดังนั้นจึงเป็นแหล่งข้อมูลจริง

รายละเอียด: [การจัดการเซสชัน](/th/concepts/session)

## เมตาดาตาผลลัพธ์เครื่องมือ

`content` ของผลลัพธ์เครื่องมือคือผลลัพธ์ที่โมเดลมองเห็น `details` ของผลลัพธ์เครื่องมือคือเมตาดาตารันไทม์สำหรับการเรนเดอร์ UI การวินิจฉัย การส่งสื่อ และ Plugin

OpenClaw รักษาขอบเขตนั้นไว้อย่างชัดเจน:

- `toolResult.details` จะถูกลบออกก่อนการ replay ของผู้ให้บริการและอินพุตของ Compaction
- ทรานสคริปต์เซสชันที่คงอยู่จะเก็บเฉพาะ `details` ที่มีขอบเขต เมตาดาตาที่ใหญ่เกินไปจะถูกแทนที่ด้วยสรุปขนาดกะทัดรัดที่ทำเครื่องหมาย `persistedDetailsTruncated: true`
- Plugin และเครื่องมือควรใส่ข้อความที่โมเดลต้องอ่านไว้ใน `content` ไม่ใช่เฉพาะใน `details`

## เนื้อความขาเข้าและบริบทประวัติ

OpenClaw แยก **เนื้อความพรอมป์** ออกจาก **เนื้อความคำสั่ง**:

- `BodyForAgent`: ข้อความหลักที่ส่งให้โมเดลสำหรับข้อความปัจจุบัน Plugin ช่องทางควรรักษาส่วนนี้ให้โฟกัสที่ข้อความปัจจุบันของผู้ส่งซึ่งมีพรอมป์อยู่
- `Body`: fallback พรอมป์แบบเดิม ส่วนนี้อาจมีซองห่อของช่องทางและ wrapper ประวัติที่เลือกใช้ได้ แต่ช่องทางปัจจุบันไม่ควรพึ่งพาส่วนนี้เป็นอินพุตหลักของโมเดลเมื่อมี `BodyForAgent`
- `CommandBody`: ข้อความผู้ใช้ดิบสำหรับการแยกวิเคราะห์ directive/คำสั่ง
- `RawBody`: alias แบบเดิมของ `CommandBody` (เก็บไว้เพื่อความเข้ากันได้)

เมื่อช่องทางส่งประวัติมา จะใช้ wrapper ร่วมกัน:

- `[Chat messages since your last reply - for context]`
- `[Current message - respond to this]`

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

บัฟเฟอร์ประวัติเป็นแบบ **pending-only**: จะรวมข้อความกลุ่มที่ _ไม่ได้_ ทริกเกอร์การรัน (เช่น ข้อความที่ถูกกั้นด้วยการ mention) และ **ไม่รวม** ข้อความที่อยู่ในทรานสคริปต์เซสชันแล้ว

การตัด directive ออกจะใช้กับส่วน **ข้อความปัจจุบัน** เท่านั้น เพื่อให้ประวัติยังคงครบถ้วน ช่องทางที่ห่อประวัติควรตั้ง `CommandBody` (หรือ `RawBody`) เป็นข้อความต้นฉบับ และเก็บ `Body` เป็นพรอมป์ที่รวมแล้ว ประวัติแบบมีโครงสร้าง การตอบกลับ ข้อความที่ส่งต่อ และเมตาดาตาช่องทางจะถูกเรนเดอร์เป็นบล็อกบริบทที่ไม่น่าเชื่อถือในบทบาทผู้ใช้ระหว่างการประกอบพรอมป์
บัฟเฟอร์ประวัติกำหนดค่าได้ผ่าน `messages.groupChat.historyLimit` (ค่าเริ่มต้นส่วนกลาง) และการแทนที่รายช่องทาง เช่น `channels.slack.historyLimit` หรือ `channels.telegram.accounts.<id>.historyLimit` (ตั้งเป็น `0` เพื่อปิดใช้งาน)

## การเข้าคิวและ followup

หากมีการรันที่กำลังทำงานอยู่แล้ว ข้อความขาเข้าสามารถถูกเข้าคิว ชี้นำเข้าในการรันปัจจุบัน หรือรวบรวมไว้สำหรับเทิร์น followup ได้

- กำหนดค่าผ่าน `messages.queue` (และ `messages.queue.byChannel`)
- โหมดเริ่มต้นคือ `steer` พร้อม debounce followup 500ms เมื่อการชี้นำ fallback ไปเป็นการส่ง followup ที่เข้าคิว
- โหมด: `steer`, `followup`, `collect`, `steer-backlog`, `interrupt` และโหมดเดิม `queue` ที่ทำทีละรายการ

รายละเอียด: [คิวคำสั่ง](/th/concepts/queue) และ [คิวการชี้นำ](/th/concepts/queue-steering)

## ความเป็นเจ้าของการรันของช่องทาง

Plugin ช่องทางอาจรักษาลำดับ debounce อินพุต และใช้ backpressure ของการขนส่งก่อนที่ข้อความจะเข้าสู่คิวเซสชัน ไม่ควรกำหนด timeout แยกต่างหากรอบเทิร์นเอเจนต์เอง เมื่อข้อความถูก route ไปยังเซสชันแล้ว งานที่ใช้เวลานานจะถูกควบคุมโดยวงจรชีวิตของเซสชัน เครื่องมือ และรันไทม์ เพื่อให้ทุกช่องทางรายงานและกู้คืนจากเทิร์นที่ช้าได้อย่างสอดคล้องกัน

## การสตรีม การแบ่งชิ้นข้อความ และการ batching

การสตรีมแบบบล็อกจะส่งการตอบกลับบางส่วนขณะที่โมเดลสร้างบล็อกข้อความ การแบ่งชิ้นข้อความเคารพขีดจำกัดข้อความของช่องทางและหลีกเลี่ยงการตัด fenced code

การตั้งค่าหลัก:

- `agents.defaults.blockStreamingDefault` (`on|off`, ค่าเริ่มต้นปิดอยู่)
- `agents.defaults.blockStreamingBreak` (`text_end|message_end`)
- `agents.defaults.blockStreamingChunk` (`minChars|maxChars|breakPreference`)
- `agents.defaults.blockStreamingCoalesce` (การ batching ตามช่วงว่าง)
- `agents.defaults.humanDelay` (การหยุดพักคล้ายมนุษย์ระหว่างการตอบกลับแบบบล็อก)
- การแทนที่ตามช่องทาง: `*.blockStreaming` และ `*.blockStreamingCoalesce` (ช่องทางที่ไม่ใช่ Telegram ต้องมี `*.blockStreaming: true` อย่างชัดเจน)

รายละเอียด: [การสตรีม + การแบ่งชิ้นข้อความ](/th/concepts/streaming)

## การมองเห็น reasoning และโทเค็น

OpenClaw สามารถแสดงหรือซ่อน reasoning ของโมเดลได้:

- `/reasoning on|off|stream` ควบคุมการมองเห็น
- เนื้อหา reasoning ยังคงนับรวมในการใช้โทเค็นเมื่อโมเดลสร้างขึ้น
- Telegram รองรับสตรีม reasoning เข้าไปในบับเบิลร่างชั่วคราวซึ่งจะถูกลบหลังส่งผลลัพธ์สุดท้าย ใช้ `/reasoning on` สำหรับเอาต์พุต reasoning แบบคงอยู่

รายละเอียด: [directive สำหรับ thinking + reasoning](/th/tools/thinking) และ [การใช้โทเค็น](/th/reference/token-use)

## คำนำหน้า threading และการตอบกลับ

การจัดรูปแบบข้อความขาออกถูกรวมศูนย์ไว้ใน `messages`:

- `messages.responsePrefix`, `channels.<channel>.responsePrefix` และ `channels.<channel>.accounts.<id>.responsePrefix` (ลำดับ cascade ของคำนำหน้าขาออก) รวมถึง `channels.whatsapp.messagePrefix` (คำนำหน้าขาเข้าของ WhatsApp)
- Reply threading ผ่าน `replyToMode` และค่าเริ่มต้นรายช่องทาง

รายละเอียด: [การกำหนดค่า](/th/gateway/config-agents#messages) และเอกสารช่องทาง

## การตอบกลับแบบเงียบ

โทเค็นเงียบที่ตรงตัว `NO_REPLY` / `no_reply` หมายถึง "อย่าส่งการตอบกลับที่ผู้ใช้มองเห็นได้"
เมื่อเทิร์นหนึ่งยังมีสื่อเครื่องมือที่รออยู่ เช่น เสียง TTS ที่สร้างขึ้น OpenClaw จะตัดข้อความเงียบออกแต่ยังส่งไฟล์แนบสื่อนั้น
OpenClaw แก้พฤติกรรมนั้นตามประเภทบทสนทนา:

- บทสนทนาโดยตรงไม่อนุญาตความเงียบโดยค่าเริ่มต้น และเขียนการตอบกลับเงียบล้วนใหม่เป็น fallback สั้น ๆ ที่มองเห็นได้
- กลุ่ม/ช่องทางอนุญาตความเงียบโดยค่าเริ่มต้น
- การประสานงานภายในอนุญาตความเงียบโดยค่าเริ่มต้น

OpenClaw ยังใช้การตอบกลับแบบเงียบสำหรับความล้มเหลวของ runner ภายในที่เกิดขึ้นก่อนมีการตอบกลับจาก assistant ในแชทที่ไม่ใช่แชทโดยตรง เพื่อให้กลุ่ม/ช่องทางไม่เห็นข้อความสำเร็จรูปข้อผิดพลาดของ Gateway แชทโดยตรงจะแสดงข้อความล้มเหลวแบบกะทัดรัดโดยค่าเริ่มต้น รายละเอียด runner ดิบจะแสดงเฉพาะเมื่อ `/verbose` เป็น `on` หรือ `full`

ค่าเริ่มต้นอยู่ภายใต้ `agents.defaults.silentReply` และ `agents.defaults.silentReplyRewrite`; `surfaces.<id>.silentReply` และ `surfaces.<id>.silentReplyRewrite` สามารถแทนที่เป็นราย surface ได้

เมื่อเซสชันแม่มีการรัน subagent ที่ spawn แล้วและรอดำเนินการอย่างน้อยหนึ่งรายการ การตอบกลับเงียบล้วนจะถูกทิ้งในทุก surface แทนที่จะถูกเขียนใหม่ เพื่อให้เซสชันแม่เงียบอยู่จนกว่าเหตุการณ์เสร็จสิ้นของ child จะส่งการตอบกลับจริง

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

- [การ refactor วงจรชีวิตข้อความ](/th/concepts/message-lifecycle-refactor) - การออกแบบเป้าหมายสำหรับการส่งและรับที่ทนทาน
- [การสตรีม](/th/concepts/streaming) — การส่งข้อความแบบเรียลไทม์
- [การลองซ้ำ](/th/concepts/retry) — พฤติกรรมการลองส่งข้อความซ้ำ
- [คิว](/th/concepts/queue) — คิวประมวลผลข้อความ
- [ช่องทาง](/th/channels) — การผสานรวมแพลตฟอร์มรับส่งข้อความ
