---
read_when:
    - การกำหนดค่าไบนารีที่ปลอดภัยหรือโปรไฟล์ไบนารีที่ปลอดภัยแบบกำหนดเอง
    - ส่งต่อคำขออนุมัติไปยัง Slack/Discord/Telegram หรือช่องทางแชทอื่นๆ
    - การใช้งานไคลเอนต์การอนุมัติแบบเนทีฟสำหรับช่องทาง
summary: 'การอนุมัติ exec ขั้นสูง: ไบนารีที่ปลอดภัย การผูกอินเทอร์พรีเตอร์ การส่งต่อการอนุมัติ และการส่งมอบแบบเนทีฟ'
title: การอนุมัติการดำเนินการ — ขั้นสูง
x-i18n:
    generated_at: "2026-07-19T18:22:04Z"
    model: gpt-5.6
    postprocess_version: locale-links-v1
    prompt_version: 32
    provider: openai
    source_hash: 628f695f2a005d537b11966bab7f6626aa87d473b1f1d5d72319a57aa7d9b24c
    source_path: tools/exec-approvals-advanced.md
    workflow: 16
---

หัวข้อขั้นสูงเกี่ยวกับการอนุมัติ exec: เส้นทางด่วน `safeBins`, การผูกกับ interpreter/runtime
และการส่งต่อคำขออนุมัติไปยังช่องทางแชต (รวมถึงการนำส่งแบบเนทีฟ)
สำหรับนโยบายหลักและขั้นตอนการอนุมัติ โปรดดู [การอนุมัติ Exec](/th/tools/exec-approvals)

## Safe bins (เฉพาะ stdin)

`tools.exec.safeBins` ระบุไบนารีที่ใช้ได้ **เฉพาะ stdin** (ตัวอย่างเช่น `cut`) ซึ่ง
ทำงานในโหมด allowlist **โดยไม่ต้องมี** รายการ allowlist อย่างชัดเจน Safe bins จะปฏิเสธ
อาร์กิวเมนต์ไฟล์แบบระบุตำแหน่งและโทเค็นที่มีลักษณะคล้ายพาธ ดังนั้นจึงทำงานได้เฉพาะกับ
สตรีมขาเข้าเท่านั้น ให้ถือว่านี่เป็นเส้นทางด่วนแบบจำกัดสำหรับตัวกรองสตรีม ไม่ใช่
รายการที่เชื่อถือได้ทั่วไป

<Warning>
อย่าเพิ่มไบนารี interpreter หรือ runtime (ตัวอย่างเช่น `python3`, `node`,
`ruby`, `bash`, `sh`, `zsh`) ลงใน `safeBins` **โดยเด็ดขาด** หากคำสั่งสามารถประเมินโค้ด
เรียกใช้คำสั่งย่อย หรืออ่านไฟล์ได้โดยการออกแบบ ให้ใช้รายการ allowlist อย่างชัดเจน
และเปิดใช้พรอมต์การอนุมัติไว้ Safe bins ที่กำหนดเองต้องกำหนด
โปรไฟล์อย่างชัดเจนใน `tools.exec.safeBinProfiles.<bin>`
</Warning>

Safe bins เริ่มต้น:

[//]: # "SAFE_BIN_DEFAULTS:START"

`cut`, `uniq`, `head`, `tail`, `tr`, `wc`

[//]: # "SAFE_BIN_DEFAULTS:END"

`grep` และ `sort` ไม่อยู่ในรายการเริ่มต้น หากเลือกใช้ ให้คงรายการ
allowlist อย่างชัดเจนสำหรับเวิร์กโฟลว์ที่ไม่ได้ใช้ stdin สำหรับ `grep` ในโหมด safe-bin
ให้ระบุรูปแบบด้วย `-e`/`--regexp`; ระบบจะปฏิเสธรูปแบบแพตเทิร์นแบบระบุตำแหน่ง
เพื่อไม่ให้แอบส่งโอเปอแรนด์ไฟล์มาเป็นค่าระบุตำแหน่งที่กำกวมได้

### การตรวจสอบ argv และแฟล็กที่ถูกปฏิเสธ

การตรวจสอบเป็นแบบกำหนดแน่นอนจากโครงสร้างของ argv เท่านั้น (ไม่มีการตรวจสอบ
การมีอยู่ของระบบไฟล์โฮสต์) ซึ่งป้องกันพฤติกรรมโอราเคิลตรวจสอบการมีอยู่ของไฟล์จาก
ความแตกต่างระหว่างการอนุญาต/ปฏิเสธ ตัวเลือกที่ทำงานกับไฟล์จะถูกปฏิเสธสำหรับ safe bins เริ่มต้น ส่วนตัวเลือกแบบยาว
จะตรวจสอบแบบ fail-closed (แฟล็กที่ไม่รู้จักและตัวย่อที่กำกวม
จะถูกปฏิเสธ) ระบบยอมรับแฟล็กบูลีนแบบอ่านอย่างเดียวที่รู้จักของไบนารีเริ่มต้น (ตัวอย่างเช่น
`wc -l`, `tr -d`, `uniq -c`) ขณะที่แฟล็กแบบสั้นที่ไม่รู้จักจะยังคง
เป็นแบบ fail-closed และเปลี่ยนไปใช้การอนุมัติด้วยตนเอง

แฟล็กที่ถูกปฏิเสธตามโปรไฟล์ safe-bin:

[//]: # "SAFE_BIN_DENIED_FLAGS:START"

- `grep`: `--dereference-recursive`, `--directories`, `--exclude-from`, `--file`, `--recursive`, `-R`, `-d`, `-f`, `-r`
- `jq`: `--argfile`, `--from-file`, `--library-path`, `--rawfile`, `--slurpfile`, `-L`, `-f`
- `sort`: `--compress-program`, `--files0-from`, `--output`, `--random-source`, `--temporary-directory`, `-T`, `-o`
- `tail`: `--follow`, `--retry`, `-F`, `-f`
- `wc`: `--files0-from`

[//]: # "SAFE_BIN_DENIED_FLAGS:END"

Safe bins ยังบังคับให้ถือว่าโทเค็น argv เป็น **ข้อความตามตัวอักษร** ณ เวลาเรียกใช้
(ไม่มีการขยาย glob และไม่มีการขยาย `$VARS`) สำหรับเซ็กเมนต์ที่ใช้เฉพาะ stdin ดังนั้น
จึงไม่สามารถใช้แพตเทิร์นอย่าง `*` หรือ `$HOME/...` เพื่อแอบอ่านไฟล์ได้ `awk`,
`sed` และ `jq` จะถูกปฏิเสธไม่ให้เป็น safe bins เสมอ เนื่องจากไม่สามารถ
ตรวจสอบความหมายของคำสั่งเหล่านี้ให้จำกัดเฉพาะ stdin ได้: `jq` สามารถอ่านข้อมูลสภาพแวดล้อมและโหลดโค้ด jq จาก
โมดูลหรือไฟล์เริ่มต้นได้ ให้ใช้รายการ allowlist อย่างชัดเจนหรือพรอมต์การอนุมัติสำหรับ
เครื่องมือเหล่านั้นแทน `safeBins`

### ไดเรกทอรีไบนารีที่เชื่อถือได้

Safe bins ต้องถูกแก้ไขตำแหน่งจากไดเรกทอรีไบนารีที่เชื่อถือได้ (ค่าเริ่มต้นของระบบ รวมถึง
`tools.exec.safeBinTrustedDirs` ที่เป็นตัวเลือก) รายการ `PATH` จะไม่ได้รับความเชื่อถือโดยอัตโนมัติ
ไดเรกทอรีเริ่มต้นที่เชื่อถือได้ถูกจำกัดไว้โดยตั้งใจ ได้แก่ `/bin`, `/usr/bin` หาก
ไฟล์ปฏิบัติการ safe-bin อยู่ในพาธของตัวจัดการแพ็กเกจ/ผู้ใช้ (ตัวอย่างเช่น
`/opt/homebrew/bin`, `/usr/local/bin`, `/opt/local/bin`, `/snap/bin`) ให้เพิ่มพาธเหล่านั้น
ลงใน `tools.exec.safeBinTrustedDirs` อย่างชัดเจน

### การเชื่อมคำสั่งเชลล์ แรปเปอร์ และมัลติเพล็กเซอร์

อนุญาตการเชื่อมคำสั่งเชลล์ (`&&`, `||`, `;`) เมื่อทุกเซ็กเมนต์ระดับบนสุด
เป็นไปตาม allowlist (รวมถึง safe bins หรือการอนุญาตอัตโนมัติของ skill) การเปลี่ยนเส้นทาง
ยังไม่รองรับในโหมด allowlist การแทนที่คำสั่ง (`$()` / backticks)
จะถูกปฏิเสธระหว่างการแยกวิเคราะห์ allowlist รวมถึงภายในเครื่องหมายคำพูดคู่ ให้ใช้เครื่องหมายคำพูดเดี่ยว
หากต้องการข้อความ `$()` ตามตัวอักษร

สำหรับการอนุมัติผ่านแอปคู่หูบน macOS ข้อความเชลล์ดิบที่มีไวยากรณ์ควบคุมหรือ
ขยายค่าของเชลล์ (`&&`, `||`, `;`, `|`, `` ` ``, `$`, `<`, `>`, `(`, `)`) จะ
ถือว่าไม่ตรงกับ allowlist เว้นแต่ไบนารีเชลล์นั้นจะอยู่ใน allowlist

สำหรับแรปเปอร์เชลล์ (`bash|sh|zsh ... -c/-lc`) การแทนที่ตัวแปรสภาพแวดล้อมเฉพาะคำขอจะ
ถูกลดให้เหลือ allowlist ขนาดเล็กที่ระบุไว้อย่างชัดเจน (`TERM`, `LANG`, `LC_*`, `COLORTERM`,
`NO_COLOR`, `FORCE_COLOR`)

สำหรับการตัดสินใจ `allow-always` ในโหมด allowlist แรปเปอร์ส่งต่อแบบโปร่งใส
(ตัวอย่างเช่น `env`, `flock`, `nice`, `nohup`, `stdbuf`, `timeout`) จะบันทึก
พาธไฟล์ปฏิบัติการภายในแทนพาธของแรปเปอร์ มัลติเพล็กเซอร์เชลล์
(`busybox`, `toybox`) จะถูกแกะแรปสำหรับแอปเพล็ตเชลล์ (`sh`, `ash` เป็นต้น) ด้วย
วิธีเดียวกัน หากไม่สามารถแกะแรปแรปเปอร์หรือมัลติเพล็กเซอร์ได้อย่างปลอดภัย ระบบจะไม่บันทึก
รายการ allowlist โดยอัตโนมัติ

หากเพิ่ม interpreter เช่น `python3` หรือ `node` ลงใน allowlist ให้เลือกใช้
`tools.exec.strictInlineEval=true` เพื่อให้การประเมินค่าแบบอินไลน์ยังคงต้องได้รับ
การอนุมัติอย่างชัดเจน ในโหมดเข้มงวด `allow-always` ยังสามารถบันทึก
การเรียกใช้ interpreter/สคริปต์ที่ไม่มีอันตรายได้ แต่ตัวพาการประเมินค่าแบบอินไลน์จะไม่ถูกบันทึก
โดยอัตโนมัติ

### Safe bins เทียบกับ allowlist

| หัวข้อ            | `tools.exec.safeBins`                                  | Allowlist (`exec-approvals.json`)                                                  |
| ---------------- | ------------------------------------------------------ | ---------------------------------------------------------------------------------- |
| เป้าหมาย             | อนุญาตตัวกรอง stdin ขอบเขตแคบโดยอัตโนมัติ                        | เชื่อถือไฟล์ปฏิบัติการที่ระบุอย่างชัดเจน                                              |
| ประเภทการจับคู่       | ชื่อไฟล์ปฏิบัติการ + นโยบาย argv ของ safe-bin                 | glob ของพาธไฟล์ปฏิบัติการที่แก้ไขแล้ว หรือ glob ของชื่อคำสั่งเปล่าสำหรับคำสั่งที่เรียกผ่าน PATH |
| ขอบเขตอาร์กิวเมนต์   | จำกัดโดยโปรไฟล์ safe-bin และกฎโทเค็นตามตัวอักษร | จับคู่พาธโดยค่าเริ่มต้น; `argPattern` ซึ่งเป็นตัวเลือกสามารถจำกัด argv ที่แยกวิเคราะห์แล้วได้              |
| ตัวอย่างทั่วไป | `head`, `tail`, `tr`, `wc`                             | `jq`, `python3`, `node`, `ffmpeg`, CLI ที่กำหนดเอง                                     |
| การใช้งานที่เหมาะสมที่สุด         | การแปลงข้อความความเสี่ยงต่ำในไปป์ไลน์                  | เครื่องมือใดก็ตามที่มีพฤติกรรมหรือผลข้างเคียงกว้างกว่า                                     |

ตำแหน่งการกำหนดค่า:

- `safeBins` มาจากการกำหนดค่า (`tools.exec.safeBins` หรือ `agents.list[].tools.exec.safeBins` รายเอเจนต์)
- `safeBinTrustedDirs` มาจากการกำหนดค่า (`tools.exec.safeBinTrustedDirs` หรือ `agents.list[].tools.exec.safeBinTrustedDirs` รายเอเจนต์)
- `safeBinProfiles` มาจากการกำหนดค่า (`tools.exec.safeBinProfiles` หรือ `agents.list[].tools.exec.safeBinProfiles` รายเอเจนต์) คีย์โปรไฟล์รายเอเจนต์จะแทนที่คีย์ส่วนกลาง
- รายการ allowlist อยู่ในไฟล์การอนุมัติเฉพาะโฮสต์ภายใต้ `agents.<id>.allowlist` (หรือผ่าน Control UI / `openclaw approvals allowlist ...`)
- `openclaw security audit` จะแจ้งเตือนด้วย `tools.exec.safe_bins_interpreter_unprofiled` เมื่อไบนารี interpreter/runtime ปรากฏใน `safeBins` โดยไม่มีโปรไฟล์ที่ระบุไว้อย่างชัดเจน
- `openclaw doctor --fix` สามารถสร้างโครงรายการ `safeBinProfiles.<bin>` แบบกำหนดเองที่ขาดหายไปเป็น `{}` (ตรวจสอบและจำกัดให้เข้มงวดขึ้นภายหลัง) ระบบจะไม่สร้างโครงไบนารี interpreter/runtime โดยอัตโนมัติ

ตัวอย่างโปรไฟล์แบบกำหนดเอง:

```json5
{
  tools: {
    exec: {
      safeBins: ["myfilter"],
      safeBinProfiles: {
        myfilter: {
          minPositional: 0,
          maxPositional: 0,
          allowedValueFlags: ["-n", "--limit"],
          deniedFlags: ["-f", "--file", "-c", "--command"],
        },
      },
    },
  },
}
```

## คำสั่ง interpreter/runtime

การเรียกใช้ interpreter/runtime ที่มีการอนุมัติรองรับจะเป็นแบบระมัดระวังโดยตั้งใจ:

- ผูกบริบท argv/cwd/env ที่ตรงกันทุกประการเสมอ
- รูปแบบสคริปต์เชลล์โดยตรงและไฟล์ runtime โดยตรงจะถูกผูกกับสแนปช็อตไฟล์ภายในเครื่องที่เป็นรูปธรรมหนึ่งไฟล์
  แบบพยายามให้ดีที่สุด
- รูปแบบแรปเปอร์ตัวจัดการแพ็กเกจทั่วไปที่ยังคงแก้ไขไปยังไฟล์ภายในเครื่องโดยตรงหนึ่งไฟล์ (ตัวอย่างเช่น
  `pnpm exec`, `pnpm node`, `npm exec`, `npx`) จะถูกแกะแรปก่อนการผูก
- หาก OpenClaw ไม่สามารถระบุไฟล์ภายในเครื่องที่เป็นรูปธรรมได้หนึ่งไฟล์พอดีสำหรับคำสั่ง interpreter/runtime
  (ตัวอย่างเช่น สคริปต์แพ็กเกจ รูปแบบ eval เชนตัวโหลดเฉพาะ runtime หรือรูปแบบหลายไฟล์
  ที่กำกวม) การดำเนินการที่มีการอนุมัติรองรับจะถูกปฏิเสธ แทนที่จะอ้างว่าครอบคลุมความหมายที่ระบบ
  ไม่ได้รองรับ
- สำหรับเวิร์กโฟลว์เหล่านั้น ให้ใช้ sandbox ขอบเขตโฮสต์ที่แยกต่างหาก หรือเวิร์กโฟลว์
  allowlist แบบเต็มที่เชื่อถืออย่างชัดเจน ซึ่งผู้ดำเนินการยอมรับความหมายของ runtime ที่กว้างกว่า

เมื่อต้องได้รับการอนุมัติ เครื่องมือ exec จะส่งคืนทันทีพร้อม ID การอนุมัติ ใช้ ID นั้นเพื่อ
เชื่อมโยงเหตุการณ์ระบบของการเรียกใช้ที่ได้รับอนุมัติในภายหลัง (`Exec finished` และ `Exec running` เมื่อกำหนดค่าไว้)
หากไม่มีการตัดสินใจก่อนหมดเวลา ระบบจะถือว่าคำขอหมดเวลารอการอนุมัติและ
แสดงเป็นการปฏิเสธคำสั่งโฮสต์ขั้นสุดท้าย สำหรับการอนุมัติแบบอะซิงโครนัสของเอเจนต์หลักที่มี
เซสชันต้นทาง OpenClaw จะดำเนินเซสชันนั้นต่อด้วยการติดตามผลภายใน เพื่อให้เอเจนต์รับรู้ว่า
คำสั่งไม่ได้ทำงาน แทนที่จะมาแก้ไขผลลัพธ์ที่ขาดหายไปในภายหลัง คำขออนุมัติ exec ที่รอดำเนินการจะหมดอายุ
หลังจาก 30 นาทีโดยค่าเริ่มต้น

### พฤติกรรมการนำส่งการติดตามผล

หลังจาก exec แบบอะซิงโครนัสที่ได้รับอนุมัติทำงานเสร็จ OpenClaw จะส่งเทิร์นติดตามผล `agent` ไปยังเซสชันเดียวกัน
การอนุมัติแบบอะซิงโครนัสที่ถูกปฏิเสธจะใช้เส้นทางติดตามผลของเซสชันหลักเดียวกันสำหรับสถานะการปฏิเสธ แต่จะ
ไม่ลงทะเบียนการส่งต่อ runtime ที่ยกระดับสิทธิ์และไม่เรียกใช้คำสั่ง การปฏิเสธที่ไม่มี
เซสชันหลักที่สามารถดำเนินต่อได้จะถูกระงับหรือรายงานผ่านเส้นทางตรงที่ปลอดภัยเมื่อมีเส้นทางดังกล่าว

- หากมีเป้าหมายการนำส่งภายนอกที่ถูกต้อง (ช่องทางที่นำส่งได้พร้อมเป้าหมาย `to`) การนำส่งการติดตามผลจะใช้ช่องทางนั้น
- ในโฟลว์ที่ใช้เฉพาะเว็บแชตหรือเซสชันภายในซึ่งไม่มีเป้าหมายภายนอก การนำส่งการติดตามผลจะอยู่ภายในเซสชันเท่านั้น (`deliver: false`)
- หากผู้เรียกขอการนำส่งภายนอกแบบเข้มงวดอย่างชัดเจนโดยไม่มีช่องทางภายนอกที่แก้ไขได้ คำขอจะล้มเหลวด้วย `INVALID_REQUEST`
- หากเปิดใช้ `bestEffortDeliver` และไม่สามารถแก้ไขช่องทางภายนอกได้ การนำส่งจะถูกลดระดับให้เป็นเฉพาะเซสชันแทนที่จะล้มเหลว

## ขอบเขตขั้นต่ำสำหรับไคลเอนต์บุคคลที่สาม

การแก้ไขการอนุมัติของ Gateway ได้รับการป้องกันด้วยขอบเขตเฉพาะ `operator.approvals` ซึ่งใช้กับทั้งเมธอดเฉพาะเจ้าของ `exec.approval.resolve` และเมธอดที่ไม่ขึ้นกับชนิด `approval.resolve`; `operator.write` ไม่ได้ครอบคลุมขอบเขตนี้ แดชบอร์ดและการผสานรวมควรขอเฉพาะขอบเขตที่เมธอดซึ่งใช้งานต้องการเท่านั้น ให้ถือว่าสิทธิ์เข้าถึงการแก้ไขการอนุมัติมีอำนาจระดับเดียวกับการเรียกใช้จากระยะไกล และมอบ `operator.approvals` อย่างรอบคอบ แม้ว่าไคลเอนต์จะแสดงเพียง UI การอนุมัติขนาดเล็กก็ตาม

## การส่งต่อคำขออนุมัติไปยังช่องทางแชต

คุณสามารถส่งต่อข้อความแจ้งขออนุมัติ exec ไปยังช่องแชตใดก็ได้ (รวมถึงช่องของ Plugin) และอนุมัติ
ผ่านช่องเหล่านั้นด้วย `/approve` โดยใช้ไปป์ไลน์การส่งออกตามปกติ

การกำหนดค่า:

```json5
{
  approvals: {
    exec: {
      enabled: true,
      mode: "session", // "session" | "targets" | "both"
      agentFilter: ["main"],
      sessionFilter: ["discord"], // substring or regex
      targets: [
        { channel: "slack", to: "U12345678" },
        { channel: "telegram", to: "123456789" },
      ],
    },
  },
}
```

ตอบกลับในแชต:

```
/approve <id> allow-once
/approve <id> allow-always
/approve <id> deny
```

คำสั่ง `/approve` รองรับทั้งการอนุมัติ exec และการอนุมัติ Plugin หาก ID ไม่ตรงกับการอนุมัติ exec ที่รอดำเนินการ ระบบจะตรวจสอบการอนุมัติ Plugin แทนโดยอัตโนมัติ กลไกสำรองนี้จำกัดเฉพาะความล้มเหลวแบบ "ไม่พบการอนุมัติ" เท่านั้น การปฏิเสธหรือข้อผิดพลาดจริงของการอนุมัติ exec จะไม่ลองใหม่แบบเงียบ ๆ ในฐานะการอนุมัติ Plugin

### การส่งต่อการอนุมัติ Plugin

การส่งต่อการอนุมัติ Plugin ใช้ไปป์ไลน์การส่งเดียวกับการอนุมัติ exec แต่มี
การกำหนดค่าแยกต่างหากภายใต้ `approvals.plugin` การเปิดหรือปิดรายการหนึ่งจะไม่ส่งผลต่ออีกรายการ
สำหรับพฤติกรรมการสร้าง Plugin ฟิลด์คำขอ และความหมายของการตัดสินใจ โปรดดู
[คำขอสิทธิ์ของ Plugin](/plugins/plugin-permission-requests)

```json5
{
  approvals: {
    plugin: {
      enabled: true,
      mode: "targets",
      agentFilter: ["main"],
      targets: [
        { channel: "slack", to: "U12345678" },
        { channel: "telegram", to: "123456789" },
      ],
    },
  },
}
```

รูปแบบการกำหนดค่าเหมือนกับ `approvals.exec`: `enabled`, `mode`, `agentFilter`,
`sessionFilter` และ `targets` ทำงานในลักษณะเดียวกัน

ช่องที่รองรับการตอบกลับแบบโต้ตอบร่วมกันจะแสดงปุ่มอนุมัติชุดเดียวกันสำหรับทั้งการอนุมัติ exec และ
การอนุมัติ Plugin ช่องที่ไม่มี UI แบบโต้ตอบร่วมกันจะใช้ข้อความธรรมดาพร้อมคำแนะนำ
`/approve` แทน คำขออนุมัติ Plugin อาจจำกัดตัวเลือกการตัดสินใจที่ใช้ได้: พื้นที่อนุมัติจะใช้
ชุดการตัดสินใจที่คำขอประกาศไว้ และ Gateway จะปฏิเสธความพยายามส่งการตัดสินใจที่
ไม่ได้เสนอไว้

### การอนุมัติในแชตเดียวกันบนทุกช่อง

เมื่อคำขออนุมัติ exec หรือ Plugin มีต้นทางจากพื้นที่แชตที่ส่งข้อความได้ แชตเดียวกันนั้น
สามารถอนุมัติด้วย `/approve` ได้โดยค่าเริ่มต้น การทำงานนี้ใช้กับ Slack, Matrix, Microsoft Teams และ
แชตลักษณะเดียวกันที่ส่งข้อความได้ นอกเหนือจากขั้นตอน Web UI และ UI เทอร์มินัลที่มีอยู่ โดยใช้
โมเดลการยืนยันตัวตนตามปกติของช่องสำหรับการสนทนานั้น หากแชตต้นทางสามารถส่งคำสั่ง
และรับการตอบกลับได้อยู่แล้ว คำขออนุมัติจะไม่ต้องใช้อะแดปเตอร์การส่งแบบเนทีฟแยกต่างหากเพียงเพื่อ
คงสถานะรอดำเนินการอีกต่อไป

Discord, Telegram และ QQ bot ยังรองรับ `/approve` ในแชตเดียวกันด้วย แต่ช่องเหล่านั้นยังคงใช้
รายชื่อผู้อนุมัติที่ได้รับการแก้ไขแล้วเพื่อให้สิทธิ์ แม้จะปิดใช้งานการส่งการอนุมัติแบบเนทีฟก็ตาม

### การส่งการอนุมัติแบบเนทีฟ

บางช่องสามารถทำหน้าที่เป็นไคลเอนต์การอนุมัติแบบเนทีฟได้ด้วย ได้แก่ Discord, Slack, Telegram, Matrix และ QQ bot
ไคลเอนต์แบบเนทีฟเพิ่ม DM ถึงผู้อนุมัติ การกระจายไปยังแชตต้นทาง และประสบการณ์การอนุมัติแบบโต้ตอบเฉพาะช่อง
ไว้เหนือขั้นตอน `/approve` ร่วมในแชตเดียวกัน

เมื่อมีการ์ดหรือปุ่มอนุมัติแบบเนทีฟ UI แบบเนทีฟนั้นเป็นช่องทางหลักที่ Agent ใช้งาน
Agent ไม่ควรส่งคำสั่งแชตแบบข้อความธรรมดา `/approve` ซ้ำอีก เว้นแต่ผลลัพธ์ของเครื่องมือระบุว่า
ไม่สามารถอนุมัติผ่านแชตได้ หรือการอนุมัติด้วยตนเองเป็นช่องทางเดียวที่เหลืออยู่

หากกำหนดค่าไคลเอนต์การอนุมัติแบบเนทีฟไว้ แต่ไม่มีรันไทม์แบบเนทีฟทำงานสำหรับช่อง
ต้นทาง OpenClaw จะยังแสดงข้อความแจ้ง `/approve` แบบกำหนดผลได้ในเครื่อง หากรันไทม์แบบเนทีฟ
ทำงานและพยายามส่ง แต่ไม่มีเป้าหมายใดได้รับการ์ด OpenClaw จะส่งข้อความแจ้งสำรอง
ในแชตเดียวกันพร้อมคำสั่ง `/approve <id> <decision>` ที่ตรงทุกประการ เพื่อให้ยังสามารถดำเนินการคำขอให้เสร็จสิ้นได้

โมเดลทั่วไป:

- นโยบาย exec ของโฮสต์ยังคงเป็นตัวตัดสินว่าจำเป็นต้องอนุมัติ exec หรือไม่
- `approvals.exec` ควบคุมการส่งต่อข้อความแจ้งขออนุมัติไปยังปลายทางแชตอื่น
- `channels.<channel>.execApprovals` ควบคุมว่าจะเปิดใช้งาน Discord, Slack, Telegram, QQ bot และไคลเอนต์แบบเนทีฟ
  เฉพาะช่องที่คล้ายกันหรือไม่
- การอนุมัติ Plugin ของ Slack สามารถใช้ไคลเอนต์การอนุมัติแบบเนทีฟของ Slack เมื่อคำขอมาจาก Slack
  และสามารถแก้ไขผู้อนุมัติ Plugin ของ Slack ได้ นอกจากนี้ `approvals.plugin` ยังสามารถกำหนดเส้นทางการอนุมัติ Plugin ไปยังเซสชัน
  หรือเป้าหมายของ Slack ได้ แม้จะปิดใช้งานการอนุมัติ exec ของ Slack
- การ์ดอนุมัติแบบเนทีฟของ Google Chat รองรับการอนุมัติ exec และ Plugin ที่มีต้นทางจากพื้นที่หรือเธรด
  Google Chat เมื่อสามารถแก้ไขผู้อนุมัติ `users/<id>` ที่เสถียรจาก `dm.allowFrom` หรือ
  `defaultTo` ได้ โดยจะไม่ใช้เหตุการณ์รีแอ็กชันในการตัดสินใจ
- การส่งการอนุมัติด้วยรีแอ็กชันของ WhatsApp และ Signal ถูกควบคุมด้วย `approvals.exec` และ
  `approvals.plugin` โดยไม่มีบล็อก `channels.<channel>.execApprovals`

ไคลเอนต์การอนุมัติแบบเนทีฟจะเปิดใช้การส่งไปยัง DM ก่อนโดยอัตโนมัติเมื่อเงื่อนไขทั้งหมดต่อไปนี้เป็นจริง:

- ช่องรองรับการส่งการอนุมัติแบบเนทีฟ
- สามารถแก้ไขผู้อนุมัติจาก `execApprovals.approvers` ที่ระบุไว้อย่างชัดเจน หรือจากข้อมูลประจำตัว
  ของเจ้าของ เช่น `commands.ownerAllowFrom`
- `channels.<channel>.execApprovals.enabled` ไม่ได้ตั้งค่าไว้ หรือเป็น `"auto"`

ตั้งค่า `enabled: false` เพื่อปิดใช้งานไคลเอนต์การอนุมัติแบบเนทีฟอย่างชัดเจน ตั้งค่า `enabled: true` เพื่อบังคับ
ให้เปิดใช้งานเมื่อสามารถแก้ไขผู้อนุมัติได้ การส่งไปยังแชตต้นทางแบบสาธารณะยังคงต้องกำหนดอย่างชัดเจนผ่าน
`channels.<channel>.execApprovals.target` เมื่อ `target` แบบเนทีฟเปิดใช้การส่งไปยังแชตต้นทาง
ข้อความแจ้งขออนุมัติจะมีข้อความคำสั่งรวมอยู่ด้วย

คำถามที่พบบ่อย: [เหตุใดจึงมีการกำหนดค่าการอนุมัติ exec สองชุดสำหรับการอนุมัติผ่านแชต?](/help/faq-first-run)

- Discord: `channels.discord.execApprovals.*`
- Slack: `channels.slack.execApprovals.*`
- Telegram: `channels.telegram.execApprovals.*`
- QQ bot: `channels.qqbot.execApprovals.*`
- Google Chat: กำหนดค่าผู้อนุมัติที่เสถียรด้วย `channels.googlechat.dm.allowFrom` หรือ
  `channels.googlechat.defaultTo` โดยไม่จำเป็นต้องมีบล็อก `execApprovals`
- WhatsApp: ใช้ `approvals.exec` และ `approvals.plugin` เพื่อกำหนดเส้นทางข้อความแจ้งขออนุมัติไปยัง WhatsApp
- Signal: ใช้ `approvals.exec` และ `approvals.plugin` เพื่อกำหนดเส้นทางข้อความแจ้งขออนุมัติไปยัง Signal

การกำหนดเส้นทางเฉพาะไคลเอนต์แบบเนทีฟ:

- Telegram ใช้ DM ถึงผู้อนุมัติเป็นค่าเริ่มต้น (`target: "dm"`) เปลี่ยนเป็น `channel` หรือ `both` เพื่อแสดง
  ข้อความแจ้งขออนุมัติในแชตหรือหัวข้อ Telegram ต้นทางด้วย สำหรับหัวข้อฟอรัม Telegram นั้น OpenClaw
  จะรักษาหัวข้อเดิมไว้สำหรับข้อความแจ้งขออนุมัติและการติดตามผลหลังการอนุมัติ
- ผู้อนุมัติของ Discord และ Telegram สามารถระบุไว้อย่างชัดเจน (`execApprovals.approvers`) หรืออนุมานจาก
  `commands.ownerAllowFrom` โดยมีเพียงผู้อนุมัติที่แก้ไขได้แล้วเท่านั้นที่สามารถอนุมัติหรือปฏิเสธ
- ผู้อนุมัติของ Slack สามารถระบุไว้อย่างชัดเจน (`execApprovals.approvers`) หรืออนุมานจาก
  `commands.ownerAllowFrom` DM การอนุมัติ Plugin ของ Slack ใช้ผู้อนุมัติ Plugin ของ Slack จาก `allowFrom`
  และการกำหนดเส้นทางเริ่มต้นของบัญชี ไม่ใช่ผู้อนุมัติ exec ของ Slack ปุ่มแบบเนทีฟของ Slack จะรักษาชนิดของ ID การอนุมัติไว้
  ดังนั้น ID `plugin:` จึงสามารถดำเนินการการอนุมัติ Plugin ให้เสร็จสิ้นได้โดยไม่ต้องมีชั้นกลไกสำรองภายใน Slack ชั้นที่สอง
- การ์ดแบบเนทีฟของ Google Chat จะรักษากลไกสำรอง `/approve` แบบดำเนินการด้วยตนเองไว้ในข้อความ แต่คอลแบ็ก
  ของปุ่มบนการ์ดจะส่งเฉพาะโทเค็นการดำเนินการแบบทึบเท่านั้น โดย ID การอนุมัติและการตัดสินใจจะถูกกู้คืนจาก
  สถานะรอดำเนินการฝั่งเซิร์ฟเวอร์
- การอนุมัติด้วยอีโมจิของ WhatsApp รองรับทั้งข้อความแจ้ง exec และ Plugin เมื่อกลุ่มการส่งต่อระดับบนสุด
  ที่ตรงกันกำหนดเส้นทางไปยัง WhatsApp ข้อความแจ้งจากต้นทางแบบเนทีฟจะผูกโดยตรง ส่วนการส่งในโหมดเป้าหมายร่วมกัน
  จะผูกข้อมูลเมตาการอนุมัติแบบระบุชนิดเดียวกันเข้ากับใบตอบรับข้อความ WhatsApp ที่ยอมรับแล้ว
- การอนุมัติด้วยรีแอ็กชันของ Signal รองรับทั้งข้อความแจ้ง exec และ Plugin เฉพาะเมื่อเปิดใช้กลุ่มการส่งต่อระดับบนสุด
  ที่ตรงกันและกำหนดเส้นทางไปยัง Signal เท่านั้น การอนุมัติ exec ของ Signal โดยตรงในแชตเดียวกันสามารถ
  ระงับกลไกสำรอง `/approve` ในเครื่องได้โดยไม่ต้องระบุผู้อนุมัติไว้อย่างชัดเจน แต่การดำเนินการรีแอ็กชันของ Signal
  ยังคงต้องใช้ผู้อนุมัติ Signal ที่ระบุไว้อย่างชัดเจนจาก `channels.signal.allowFrom` หรือ `defaultTo`
- การกำหนดเส้นทาง DM/ช่องแบบเนทีฟและทางลัดด้วยรีแอ็กชันของ Matrix รองรับทั้งการอนุมัติ exec และ Plugin
  โดยสิทธิ์การอนุมัติ Plugin ยังคงมาจาก `channels.matrix.dm.allowFrom` ข้อความแจ้งแบบเนทีฟของ Matrix
  จะมีเนื้อหาเหตุการณ์แบบกำหนดเอง `com.openclaw.approval` ในเหตุการณ์ข้อความแจ้งแรก เพื่อให้ไคลเอนต์
  Matrix ที่รองรับ OpenClaw สามารถอ่านสถานะการอนุมัติแบบมีโครงสร้าง ขณะที่ไคลเอนต์ทั่วไปยังคงใช้กลไกสำรอง
  `/approve` แบบข้อความธรรมดา
- ปุ่มอนุมัติแบบเนทีฟของ Discord และ Telegram จะส่งชนิดเจ้าของ exec หรือ Plugin ที่ระบุไว้อย่างชัดเจนใน
  ข้อมูลคอลแบ็กส่วนตัวของการขนส่ง และดำเนินการเฉพาะกับเจ้าของชนิดนั้น ตัวควบคุม `/approve` รุ่นเก่าที่ไม่มี
  ชนิดยังคงเป็นเส้นทางความเข้ากันได้ที่จำกัด โดยจะลองเฉพาะชนิดเจ้าของที่ผู้ดำเนินการมีสิทธิ์อนุมัติ
  ดำเนินการต่อเฉพาะหลังผลลัพธ์ว่าไม่พบการอนุมัติ และไม่อนุมานความเป็นเจ้าของจาก ID การอนุมัติ
- ผู้ส่งคำขอไม่จำเป็นต้องเป็นผู้อนุมัติ
- หากไม่มี UI สำหรับผู้ปฏิบัติงานหรือไคลเอนต์การอนุมัติที่กำหนดค่าไว้ซึ่งสามารถรับคำขอได้ ข้อความแจ้งจะใช้
  `askFallback` เป็นกลไกสำรอง

คำสั่งกลุ่มที่ละเอียดอ่อนและจำกัดเฉพาะเจ้าของ เช่น `/diagnostics` และ `/export-trajectory` ใช้
การกำหนดเส้นทางส่วนตัวของเจ้าของสำหรับข้อความแจ้งขออนุมัติและผลลัพธ์สุดท้าย ก่อนอื่น OpenClaw จะลองใช้เส้นทางส่วนตัวบน
พื้นที่เดียวกับที่เจ้าของเรียกใช้คำสั่ง หากพื้นที่นั้นไม่มีเส้นทางส่วนตัวของเจ้าของ ระบบจะใช้
เส้นทางเจ้าของแรกที่ใช้ได้จาก `commands.ownerAllowFrom` เป็นกลไกสำรอง ดังนั้นคำสั่งกลุ่มของ Discord
จึงยังสามารถส่งการอนุมัติและผลลัพธ์ไปยัง DM ของเจ้าของบน Telegram ได้ เมื่อ Telegram เป็น
อินเทอร์เฟซส่วนตัวหลักที่กำหนดค่าไว้ แชตกลุ่มจะได้รับเพียงข้อความรับทราบสั้น ๆ

ดูเพิ่มเติม:

- [Discord](/channels/discord)
- [Telegram](/channels/telegram)
- [QQ bot](/channels/qqbot)

### แอปผู้ปฏิบัติงานบนมือถืออย่างเป็นทางการ

แอป iOS และ Android อย่างเป็นทางการยังสามารถตรวจสอบการอนุมัติ exec ที่รอดำเนินการ
ซึ่ง Gateway เป็นเจ้าของได้ เมื่อใช้การเชื่อมต่อ `operator.admin` หรือเมื่ออุปกรณ์
`operator.approvals` ที่จับคู่กับแอปถูกระบุเป็นเป้าหมายของคำขออย่างชัดเจน แอปเหล่านี้จะอ่าน
ระเบียนถาวรที่ผ่านการกรองข้อมูลละเอียดอ่อนชุดเดียวกับที่
Control UI ใช้ ส่งการตัดสินใจแบบรับรู้ชนิด และแสดงผลลัพธ์คำตอบแรก
มาตรฐานของ Gateway Apple Watch จะแสดงข้อความแจ้งขออนุมัติเหล่านี้ผ่าน
iPhone ที่จับคู่ไว้ พร้อมการดำเนินการอนุญาตครั้งเดียวและปฏิเสธ โหมด Gateway โดยตรงบน Watch
ไม่รองรับการตรวจสอบการอนุมัติ

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

### ขั้นตอน IPC ของ macOS

```
Gateway -> Node Service (WS)
                 |  IPC (UDS + token + HMAC + TTL)
                 v
             Mac App (UI + approvals + system.run)
```

หมายเหตุด้านความปลอดภัย:

- โหมดซ็อกเก็ต Unix `0600` โดยจัดเก็บโทเค็นไว้ใน `exec-approvals.json`
- ตรวจสอบเพียร์ที่มี UID เดียวกัน
- การท้าทาย/ตอบกลับ (nonce + โทเค็น HMAC + แฮชคำขอ) + TTL ระยะสั้น

## คำถามที่พบบ่อย

### จะใช้ `accountId` และ `threadId` กับเป้าหมายการอนุมัติเมื่อใด

ใช้ `accountId` เมื่อช่องมีข้อมูลประจำตัวที่กำหนดค่าไว้หลายรายการ และข้อความแจ้งขออนุมัติต้อง
ส่งออกผ่านบัญชีเฉพาะบัญชีหนึ่ง ใช้ `threadId` เมื่อปลายทางรองรับหัวข้อหรือ
เธรด และข้อความแจ้งควรอยู่ภายในเธรดนั้นแทนแชตระดับบนสุด

กรณีตัวอย่างที่ชัดเจนของ Telegram คือซูเปอร์กรุ๊ปฝ่ายปฏิบัติการที่มีหัวข้อฟอรัมและบัญชีบอต
Telegram สองบัญชี ค่า `to` ระบุชื่อซูเปอร์กรุ๊ป `accountId` เลือกบัญชีบอต และ `threadId`
เลือกหัวข้อฟอรัม:

```json5
{
  approvals: {
    exec: {
      enabled: true,
      mode: "targets",
      targets: [
        {
          channel: "telegram",
          to: "-1001234567890",
          accountId: "ops-bot",
          threadId: "77",
        },
      ],
    },
  },
  channels: {
    telegram: {
      accounts: {
        default: {
          name: "Primary bot",
          botToken: "env:TELEGRAM_PRIMARY_BOT_TOKEN",
        },
        "ops-bot": {
          name: "Operations bot",
          botToken: "env:TELEGRAM_OPS_BOT_TOKEN",
        },
      },
    },
  },
}
```

เมื่อกำหนดค่าเช่นนี้ การอนุมัติการดำเนินการที่ส่งต่อจะถูกโพสต์โดยบัญชี Telegram `ops-bot` ไปยังหัวข้อ
`77` ของแชต `-1001234567890` เป้าหมายที่ไม่มี `accountId` จะใช้บัญชีเริ่มต้นของช่อง และ
เป้าหมายที่ไม่มี `threadId` จะโพสต์ไปยังปลายทางระดับบนสุด

### เมื่อส่งคำขออนุมัติไปยังเซสชัน ทุกคนในเซสชันนั้นสามารถอนุมัติได้หรือไม่

ไม่ได้ การส่งไปยังเซสชันควบคุมเพียงตำแหน่งที่ข้อความแจ้งปรากฏเท่านั้น โดยตัวมันเองไม่ได้ให้อำนาจแก่
ผู้เข้าร่วมทุกคนในแชตนั้นในการอนุมัติ

สำหรับ `/approve` ทั่วไปภายในแชตเดียวกัน ผู้ส่งต้องได้รับอนุญาตให้ใช้คำสั่งใน
เซสชันของช่องนั้นอยู่แล้ว หากช่องระบุผู้อนุมัติคำขออนุมัติไว้อย่างชัดเจน ผู้อนุมัติเหล่านั้นสามารถอนุมัติ
การดำเนินการ `/approve` ได้ แม้จะไม่ได้รับอนุญาตให้ใช้คำสั่งในเซสชันนั้นก็ตาม

บางช่องมีข้อกำหนดที่เข้มงวดกว่า Discord, Telegram, Matrix, DM การอนุมัติแบบเนทีฟของ Slack และ
ไคลเอนต์การอนุมัติแบบเนทีฟที่คล้ายกันจะใช้รายชื่อผู้อนุมัติที่ระบบกำหนดได้เพื่อให้สิทธิ์การอนุมัติ ตัวอย่างเช่น
ข้อความแจ้งการอนุมัติในหัวข้อฟอรัมของ Telegram อาจปรากฏให้ทุกคนในหัวข้อเห็น แต่เฉพาะ ID ผู้ใช้ Telegram
แบบตัวเลขที่กำหนดได้จาก `channels.telegram.execApprovals.approvers` หรือ
`commands.ownerAllowFrom` เท่านั้นที่สามารถอนุมัติหรือปฏิเสธได้

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

- [การอนุมัติการดำเนินการ](/th/tools/exec-approvals) — นโยบายหลักและขั้นตอนการอนุมัติ
- [เครื่องมือการดำเนินการ](/th/tools/exec)
- [โหมดยกระดับสิทธิ์](/th/tools/elevated)
- [Skills](/th/tools/skills) — พฤติกรรมการอนุญาตอัตโนมัติที่รองรับโดย Skills
