---
read_when:
    - การดีบักหรือกำหนดค่าการเข้าถึง WebChat
summary: การใช้โฮสต์แบบสแตติกของ WebChat บนลูปแบ็กและ Gateway WS สำหรับ UI แชต
title: เว็บแชต
x-i18n:
    generated_at: "2026-07-19T07:39:16Z"
    model: gpt-5.6
    postprocess_version: locale-links-v1
    prompt_version: 32
    provider: openai
    source_hash: 05309caff8e3fe5d14627ea9bc50667c5154a2f493ef4fd1e813d9d9bf82fbc4
    source_path: web/webchat.md
    workflow: 16
---

สถานะ: UI แชต SwiftUI บน macOS/iOS สื่อสารกับ Gateway WebSocket โดยตรง ไม่มีเบราว์เซอร์แบบฝังและไม่มีเซิร์ฟเวอร์สแตติกภายในเครื่อง

## คืออะไร

- UI แชตแบบเนทีฟสำหรับ Gateway
- ใช้เซสชันและกฎการกำหนดเส้นทางเดียวกับช่องทางอื่น
- การกำหนดเส้นทางแบบกำหนดผลลัพธ์แน่นอน: การตอบกลับจะกลับไปยัง WebChat เสมอ
- ประวัติจะถูกดึงจาก Gateway เสมอ (ไม่มีการเฝ้าดูไฟล์ภายในเครื่อง) หากไม่สามารถเข้าถึง Gateway ได้ WebChat จะเป็นแบบอ่านอย่างเดียว

## เริ่มต้นอย่างรวดเร็ว

1. เริ่ม Gateway
2. เปิด UI ของ WebChat (แอป macOS/iOS) หรือแท็บแชตของ Control UI
3. ตรวจสอบว่าได้กำหนดค่าเส้นทางการยืนยันตัวตนของ Gateway ที่ถูกต้องแล้ว (ค่าเริ่มต้นใช้ข้อมูลลับร่วมกัน แม้จะเชื่อมต่อผ่านลูปแบ็ก)

## วิธีการทำงาน

- UI เชื่อมต่อกับ Gateway WebSocket และใช้เมธอด RPC `chat.history`, `chat.send`, `chat.inject` และ `chat.message.get`
- `chat.history` มีการจำกัดขนาดเพื่อความเสถียร: Gateway อาจตัดทอนช่องข้อความที่ยาว ละเว้นเมทาดาทาขนาดใหญ่ และแทนที่รายการที่มีขนาดเกินด้วย `[chat.history omitted: message too large]` ไคลเอนต์ API สามารถส่ง `maxChars` ต่อคำขอเพื่อแทนที่ขีดจำกัดเริ่มต้นสำหรับการเรียกหนึ่งครั้ง
- เมื่อข้อความผู้ช่วยที่มองเห็นได้ถูกตัดทอนใน `chat.history` Control UI สามารถเปิดแผงอ่านด้านข้างและดึงรายการฉบับเต็มที่ปรับรูปแบบเพื่อการแสดงผลแล้วตามคำขอผ่าน `chat.message.get` โดยไม่เพิ่มเพย์โหลดประวัติเริ่มต้น `chat.message.get` ใช้สาขาทรานสคริปต์และกฎการแสดงผลเดียวกับ `chat.history` แต่ระบุเป้าหมายเป็นรายการเดียวด้วย `messageId` และส่งคืนเหตุผลที่ตรงไปตรงมาว่าไม่พร้อมใช้งาน เมื่อไม่สามารถส่งคืนเนื้อหาฉบับเต็มได้อีกต่อไป
- `chat.history` ติดตามสาขาทรานสคริปต์ที่ใช้งานอยู่สำหรับไฟล์เซสชันแบบเพิ่มต่อท้ายเท่านั้น ดังนั้นสาขาที่เลิกใช้จากการเขียนใหม่และสำเนาพรอมต์ที่ถูกแทนที่จะไม่แสดงผลใน WebChat
- รายการ Compaction จะแสดงเป็นตัวแบ่ง "ประวัติที่ผ่านการ Compaction" ซึ่งอธิบายว่าทรานสคริปต์ที่ผ่านการ Compaction ถูกเก็บรักษาไว้เป็นจุดตรวจ พร้อมการดำเนินการเพื่อเปิดจุดตรวจของเซสชัน (สร้างสาขาหรือกู้คืน เมื่อสิทธิ์อนุญาต)
- Control UI จดจำ `sessionId` ของ Gateway ที่รองรับอยู่ซึ่งส่งคืนโดย `chat.history` และรวมค่าไว้ในการเรียก `chat.send` ครั้งถัดไป ดังนั้นการเชื่อมต่อใหม่และการรีเฟรชหน้าจะดำเนินการสนทนาที่จัดเก็บไว้เดิมต่อไป เว้นแต่ผู้ใช้จะเริ่มหรือรีเซ็ตเซสชัน
- `chat.send` รับคีย์ไอดอมโพเทนซี (Control UI ใช้ ID การรัน) Gateway จะกำจัดคำขอซ้ำที่ใช้คีย์เดียวกัน ดังนั้นการส่งที่ลองใหม่หรือซ้ำซึ่งยังอยู่ระหว่างดำเนินการสำหรับเซสชัน/ข้อความ/ไฟล์แนบเดียวกันจะไม่สร้างการรันครั้งที่สอง
- การตอบกลับข้อความที่ระบุ (คลิกขวา → Reply) จะส่ง ID ทรานสคริปต์ของเป้าหมายเป็น `replyToId` บน `chat.send` Gateway จะค้นหาข้อความนั้นจากประวัติเซสชันและเติมเมทาดาทาบริบทการตอบกลับแบบไม่ขึ้นกับช่องทางชุดเดียวกับที่การตอบกลับของ Discord ใช้: เอเจนต์จะเห็น `has_reply_context` พร้อมบล็อก "เป้าหมายการตอบกลับของข้อความผู้ใช้ปัจจุบัน" ที่ไม่น่าเชื่อถือ ซึ่งมีป้ายกำกับผู้ส่งและเนื้อหาข้อความ (พรอมต์ Webchat ยังคงระงับ ID การสนทนาที่เปลี่ยนแปลงได้ เช่น `reply_to_id` ตามนโยบายพรอมต์ที่รักษาไบต์ให้คงที่ซึ่งมีอยู่แล้วสำหรับเซสชัน Webchat โดยตรง) เป้าหมายการตอบกลับที่ไม่มี ID ทรานสคริปต์ที่จัดเก็บถาวร (เช่น การส่งที่รอดำเนินการ) จะใช้ข้อความอ้างอิงแบบอินไลน์ในเนื้อหาข้อความแทน
- ไฟล์เริ่มต้นของเวิร์กสเปซและคำสั่ง `BOOTSTRAP.md` ที่รอดำเนินการจะถูกส่งผ่านส่วน `# Project Context` ของพรอมต์ระบบเอเจนต์ ไม่ได้คัดลอกลงในข้อความผู้ใช้ของ WebChat หากเนื้อหาบูตสแตรปถูกตัดทอน พรอมต์ระบบจะได้รับ "ประกาศเกี่ยวกับบริบทบูตสแตรป" แบบสั้นแทน ส่วนจำนวนโดยละเอียดและตัวเลือกการกำหนดค่าจะยังคงอยู่บนพื้นผิวการวินิจฉัย
- การปรับรูปแบบเพื่อการแสดงผลใน `chat.history` จะตัดสิ่งต่อไปนี้ออก: บริบท OpenClaw ที่ใช้เฉพาะขณะรันไทม์ ตัวห่อเอนเวโลปขาเข้า แท็กคำสั่งการส่งแบบอินไลน์ เช่น `[[reply_to_current]]`, `[[reply_to:<id>]]` และ `[[audio_as_voice]]`, เพย์โหลด XML ของการเรียกเครื่องมือแบบข้อความล้วน (`<tool_call>`, `<function_call>`, `<tool_calls>`, `<function_calls>` รวมถึงบล็อกที่ถูกตัดทอน) และโทเค็นควบคุมโมเดลแบบ ASCII/ตัวเต็มที่รั่วไหล รายการผู้ช่วยที่ข้อความซึ่งมองเห็นได้ทั้งหมดมีเพียงโทเค็นเงียบ `NO_REPLY` (ไม่คำนึงถึงตัวพิมพ์เล็กและใหญ่) จะถูกละเว้น
- เพย์โหลดการตอบกลับที่มีแฟล็กการให้เหตุผล (`isReasoning: true`) จะถูกแยกออกจากเนื้อหาผู้ช่วยของ WebChat ข้อความการเล่นทรานสคริปต์ซ้ำ และบล็อกเนื้อหาเสียง ดังนั้นเพย์โหลดที่มีเฉพาะกระบวนการคิดจะไม่ปรากฏเป็นข้อความผู้ช่วยที่มองเห็นได้หรือเสียงที่เล่นได้
- `chat.inject` เพิ่มหมายเหตุของผู้ช่วยต่อท้ายทรานสคริปต์โดยตรงและเผยแพร่ไปยัง UI (ไม่มีการรันเอเจนต์)
- การรันที่ถูกยกเลิกสามารถคงเอาต์พุตบางส่วนของผู้ช่วยให้มองเห็นได้ใน UI Gateway จะจัดเก็บข้อความบางส่วนนั้นลงในประวัติทรานสคริปต์เมื่อมีเอาต์พุตในบัฟเฟอร์ และทำเครื่องหมายรายการด้วยเมทาดาทาการยกเลิก

### โมเดลทรานสคริปต์และการส่ง

WebChat มีเส้นทางข้อมูลแยกกันสองเส้นทาง:

- แถวทรานสคริปต์ SQLite เป็นทรานสคริปต์ถาวรของโมเดล/รันไทม์ สำหรับการรันเอเจนต์ปกติ รันไทม์ OpenClaw แบบฝังจะจัดเก็บข้อความ `user`, `assistant` และ `toolResult` ที่โมเดลมองเห็นผ่านตัวเข้าถึงเซสชัน WebChat จะไม่เขียนข้อความการส่ง สถานะ หรือข้อความช่วยเหลือตามอำเภอใจลงในทรานสคริปต์นั้น
- เหตุการณ์ `ReplyPayload` ของ Gateway คือการฉายภาพการส่งแบบสด: ปรับรูปแบบสำหรับการแสดงผล WebChat/ช่องทาง การสตรีมแบบบล็อก แท็กคำสั่ง การฝังสื่อ แฟล็ก TTS/เสียง และพฤติกรรมสำรองของ UI เหตุการณ์เหล่านี้ไม่ใช่บันทึกเซสชันหลักในตัวเอง
- ชุดทดสอบที่ต้องการการตอบกลับที่มองเห็นได้ผ่าน `tools.message` ยังคงใช้ WebChat เป็นปลายทางรับการตอบกลับจากแหล่งภายในสำหรับการรันปัจจุบัน `message.send` ที่ไม่มีเป้าหมายจากการรัน WebChat ที่ใช้งานอยู่นั้นจะถูกฉายเข้าไปในแชตเดียวกันและทำสำเนาไปยังทรานสคริปต์เซสชัน WebChat จะไม่กลายเป็นช่องทางขาออกที่นำกลับมาใช้ใหม่ได้และจะไม่สืบทอด `lastChannel`
- WebChat จะแทรกรายการทรานสคริปต์ของผู้ช่วยเฉพาะเมื่อ Gateway เป็นเจ้าของข้อความที่แสดงอยู่นอกเทิร์นเอเจนต์แบบฝังปกติ ได้แก่ `chat.inject` การตอบกลับคำสั่งที่ไม่ใช่เอเจนต์ เอาต์พุตบางส่วนที่ถูกยกเลิก และส่วนเสริมทรานสคริปต์สื่อที่ WebChat จัดการ
- หากข้อความผู้ช่วยแบบสดปรากฏระหว่างการรันแต่หายไปหลังโหลดประวัติใหม่ ให้ตรวจสอบตามลำดับดังนี้: ทรานสคริปต์ SQLite มีข้อความผู้ช่วยหรือไม่ การฉายภาพการแสดงผล `chat.history` ตัดข้อความนั้นออกหรือไม่ จากนั้นตรวจสอบว่าการผสานส่วนท้ายแบบคาดการณ์ล่วงหน้าของ Control UI แทนที่สถานะการส่งภายในเครื่องด้วยสแนปช็อตที่จัดเก็บถาวรหรือไม่

คำตอบสุดท้ายจากการรันเอเจนต์ปกติควรคงอยู่ถาวร เนื่องจากรันไทม์แบบฝังเขียน `message_end` ของผู้ช่วย ทางเลือกสำรองใด ๆ ที่ทำสำเนาเพย์โหลดสุดท้ายซึ่งส่งแล้วลงในทรานสคริปต์ ต้องหลีกเลี่ยงการทำซ้ำเทิร์นผู้ช่วยที่รันไทม์แบบฝังเขียนไว้แล้วก่อน

## แผงเครื่องมือเอเจนต์ของ Control UI

- แผง Tools ของ `/agents` ใน Control UI มีมุมมอง "พร้อมใช้งานขณะนี้" ซึ่งรองรับโดย `tools.effective(sessionKey=...)`: การฉายภาพรายการเครื่องมือของเซสชันปัจจุบันแบบอ่านอย่างเดียวที่ได้มาจากเซิร์ฟเวอร์ รวมถึงเครื่องมือหลัก เครื่องมือของ Plugin เครื่องมือที่ช่องทางเป็นเจ้าของ และเครื่องมือเซิร์ฟเวอร์ MCP ที่ค้นพบแล้ว
- มุมมองแก้ไขการกำหนดค่าที่แยกต่างหาก (รองรับโดย `tools.catalog`) ครอบคลุมโปรไฟล์ การแทนที่รายเอเจนต์ และความหมายของแค็ตตาล็อก
- ความพร้อมใช้งานขณะรันไทม์มีขอบเขตระดับเซสชัน การสลับเซสชันบนเอเจนต์เดียวกันสามารถเปลี่ยนรายการ "พร้อมใช้งานขณะนี้" ได้ หากเซิร์ฟเวอร์ MCP ที่กำหนดค่าไว้ยังไม่ได้เชื่อมต่อหรือมีการเปลี่ยนแปลงนับจากการค้นพบครั้งล่าสุด แผงจะแสดงประกาศแทนที่จะเริ่มทรานสปอร์ต MCP จากเส้นทางการอ่านโดยไม่แจ้งให้ทราบ
- ตัวแก้ไขการกำหนดค่าไม่ได้หมายความว่าพร้อมใช้งานขณะรันไทม์ การเข้าถึงที่มีผลจริงยังคงเป็นไปตามลำดับความสำคัญของนโยบาย (`allow`/`deny` การแทนที่รายเอเจนต์และรายผู้ให้บริการ/ช่องทาง)

## การใช้งานระยะไกล

- โหมดระยะไกลสร้างทันเนลสำหรับ Gateway WebSocket ผ่าน SSH/Tailscale
- ไม่จำเป็นต้องเรียกใช้เซิร์ฟเวอร์ WebChat แยกต่างหาก

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

การกำหนดค่าฉบับเต็ม: [การกำหนดค่า](/th/gateway/configuration)

WebChat ไม่มีส่วนการกำหนดค่าที่จัดเก็บถาวร Gateway ใช้ขีดจำกัดการแสดงผล `chat.history` ในตัว ไคลเอนต์ API สามารถส่ง `maxChars` ต่อคำขอเพื่อแทนที่ขีดจำกัดดังกล่าวสำหรับการเรียกหนึ่งครั้ง การกำหนดค่า `channels.webchat` และ `gateway.webchat` แบบเดิมถูกยกเลิกแล้ว ให้เรียกใช้ `openclaw doctor --fix` เพื่อลบออก

ตัวเลือกส่วนกลางที่เกี่ยวข้อง:

- `gateway.port`, `gateway.bind`: โฮสต์/พอร์ต WebSocket
- `gateway.auth.mode`, `gateway.auth.token`, `gateway.auth.password`:
  การยืนยันตัวตน WebSocket ด้วยข้อมูลลับร่วมกัน
- `gateway.auth.allowTailscale`: แท็บแชต Control UI ในเบราว์เซอร์สามารถใช้ส่วนหัวข้อมูลประจำตัว
  ของ Tailscale Serve เมื่อเปิดใช้งาน
- `gateway.auth.mode: "trusted-proxy"`: การยืนยันตัวตนผ่านพร็อกซีย้อนกลับสำหรับไคลเอนต์เบราว์เซอร์ที่อยู่หลังแหล่งที่มาของพร็อกซี **ที่ไม่ใช่ลูปแบ็ก** ซึ่งรับรู้ข้อมูลประจำตัว (ดู [การยืนยันตัวตนของพร็อกซีที่เชื่อถือได้](/th/gateway/trusted-proxy-auth))
- `gateway.remote.url`, `gateway.remote.token`, `gateway.remote.password`: เป้าหมาย Gateway ระยะไกล
- `session.*`: พื้นที่จัดเก็บเซสชันและค่าเริ่มต้นของคีย์หลัก

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

- [Control UI](/th/web/control-ui)
- [แดชบอร์ด](/th/web/dashboard)
