ปลั๊กอิน(ส่วนขยาย)¶
เริ่มต้นอย่างรวดเร็ว(ใหม่กับปลั๊กอิน?)¶
ปลั๊กอินคือ โมดูลโค้ดขนาดเล็ก ที่ขยายความสามารถของOpenClawด้วยฟีเจอร์เพิ่มเติม (คำสั่ง เครื่องมือ และGatewayRPC)
โดยส่วนใหญ่คุณจะใช้ปลั๊กอินเมื่อคุณต้องการฟีเจอร์ที่ยังไม่ถูกรวมไว้ในOpenClawแกนหลัก (หรือคุณต้องการแยกฟีเจอร์เสริมออกจากการติดตั้งหลัก)
ทางลัด:
- ดูว่ามีอะไรถูกโหลดอยู่แล้ว:
openclaw plugins list
- ติดตั้งปลั๊กอินทางการ(ตัวอย่าง: Voice Call):
openclaw plugins install @openclaw/voice-call
- รีสตาร์ตGateway(เกตเวย์) จากนั้นกำหนดค่าภายใต้
plugins.entries.<id>.config.
ดู Voice Call เพื่อเป็นตัวอย่างปลั๊กอินแบบเป็นรูปธรรม
ปลั๊กอินที่มีให้ใช้งาน(ทางการ)¶
- Microsoft Teams เป็นแบบปลั๊กอินเท่านั้นตั้งแต่ 2026.1.15; ติดตั้ง
@openclaw/msteamsหากคุณใช้ Teams - Memory(Core) — ปลั๊กอินค้นหาหน่วยความจำที่มาพร้อมแพ็กเกจ(เปิดใช้งานเป็นค่าเริ่มต้นผ่าน
plugins.slots.memory) - Memory(LanceDB) — ปลั๊กอินหน่วยความจำระยะยาวที่มาพร้อมแพ็กเกจ(เรียกคืน/บันทึกอัตโนมัติ; ตั้งค่า
plugins.slots.memory = "memory-lancedb") - Voice Call —
@openclaw/voice-call - Zalo Personal —
@openclaw/zalouser - Matrix —
@openclaw/matrix - Nostr —
@openclaw/nostr - Zalo —
@openclaw/zalo - Microsoft Teams —
@openclaw/msteams - Google Antigravity OAuth(การยืนยันตัวตนผู้ให้บริการ) — มาพร้อมแพ็กเกจเป็น
google-antigravity-auth(ปิดใช้งานเป็นค่าเริ่มต้น) - Gemini CLI OAuth(การยืนยันตัวตนผู้ให้บริการ) — มาพร้อมแพ็กเกจเป็น
google-gemini-cli-auth(ปิดใช้งานเป็นค่าเริ่มต้น) - Qwen OAuth(การยืนยันตัวตนผู้ให้บริการ) — มาพร้อมแพ็กเกจเป็น
qwen-portal-auth(ปิดใช้งานเป็นค่าเริ่มต้น) - Copilot Proxy(การยืนยันตัวตนผู้ให้บริการ) — บริดจ์ Copilot Proxy ของ VS Code แบบโลคัล; แยกจากการล็อกอินอุปกรณ์
github-copilotที่มีมาในตัว(มาพร้อมแพ็กเกจ ปิดใช้งานเป็นค่าเริ่มต้น)
ปลั๊กอินของOpenClawเป็น โมดูลTypeScript ที่โหลดขณะรันผ่าน jiti การตรวจสอบคอนฟิกจะไม่รันโค้ดปลั๊กอิน; จะใช้ไฟล์แมนิฟेस्टของปลั๊กอินและJSON Schemaแทน ดู Plugin manifest การตรวจสอบความถูกต้องของคอนฟิกจะไม่รันโค้ดของปลั๊กอิน; แต่จะใช้ plugin manifest และ JSON Schema แทน ดูที่ Plugin manifest
ปลั๊กอินสามารถลงทะเบียนได้:
- เมธอดGatewayRPC
- แฮนด์เลอร์GatewayHTTP
- เครื่องมือเอเจนต์
- คำสั่งCLI
- บริการเบื้องหลัง
- การตรวจสอบคอนฟิก (ไม่บังคับ)
- Skills (โดยระบุไดเรกทอรี
skillsในแมนิฟেস্টของปลั๊กอิน) - คำสั่งตอบกลับอัตโนมัติ (รันโดยไม่เรียกเอเจนต์AI)
ปลั๊กอินรัน ในโปรเซสเดียว กับGateway(เกตเวย์) ดังนั้นควรมองว่าเป็นโค้ดที่เชื่อถือได้ คู่มือการเขียนเครื่องมือ: Plugin agent tools คู่มือการเขียนเครื่องมือ: Plugin agent tools
ตัวช่วยขณะรันไทม์¶
ปลั๊กอินสามารถเข้าถึงตัวช่วยแกนหลักที่คัดเลือกแล้วผ่าน api.runtime. สำหรับTTSด้านโทรศัพท์:
const result = await api.runtime.tts.textToSpeechTelephony({
text: "Hello from OpenClaw",
cfg: api.config,
});
หมายเหตุ:
- ใช้คอนฟิก
messages.ttsของแกนหลัก(OpenAI หรือ ElevenLabs) - คืนค่าเป็นบัฟเฟอร์เสียงPCM + อัตราการสุ่มตัวอย่าง ปลั๊กอินต้องรีแซมเปิล/เข้ารหัสให้ผู้ให้บริการ ปลั๊กอินต้องทำการ resample/encode สำหรับผู้ให้บริการ
- ไม่รองรับ Edge TTS สำหรับงานโทรศัพท์
การค้นหาและลำดับความสำคัญ¶
OpenClawจะสแกนตามลำดับ:
- เส้นทางคอนฟิก
plugins.load.paths(ไฟล์หรือไดเรกทอรี)
- ส่วนขยายเวิร์กสเปซ
<workspace>/.openclaw/extensions/*.ts<workspace>/.openclaw/extensions/*/index.ts
- ส่วนขยายส่วนกลาง
~/.openclaw/extensions/*.ts~/.openclaw/extensions/*/index.ts
- ส่วนขยายที่มาพร้อมแพ็กเกจ(ส่งมากับOpenClaw, ปิดใช้งานเป็นค่าเริ่มต้น)
<openclaw>/extensions/*
ปลั๊กอินที่มาพร้อมแพ็กเกจต้องเปิดใช้งานอย่างชัดเจนผ่าน plugins.entries.<id>.enabled
หรือ openclaw plugins enable <id>. ปลั๊กอินที่ติดตั้งแล้วจะเปิดใช้งานเป็นค่าเริ่มต้น
แต่สามารถปิดได้ด้วยวิธีเดียวกัน
ปลั๊กอินแต่ละตัวต้องมีไฟล์ openclaw.plugin.json อยู่ที่ราก หากเส้นทางชี้ไปที่ไฟล์
รากของปลั๊กอินคือไดเรกทอรีของไฟล์นั้นและต้องมีแมนิฟেস্ট หากพาธชี้ไปที่ไฟล์ รากของปลั๊กอินคือไดเรกทอรีของไฟล์นั้น และต้องมี manifest อยู่ภายใน
หากมีหลายปลั๊กอินที่ได้idเดียวกัน ตัวที่พบก่อนตามลำดับข้างต้นจะชนะ และสำเนาที่มีลำดับความสำคัญต่ำกว่าจะถูกละเว้น
แพ็กเกจแพ็ก¶
ไดเรกทอรีปลั๊กอินอาจมี package.json พร้อม openclaw.extensions:
{
"name": "my-pack",
"openclaw": {
"extensions": ["./src/safety.ts", "./src/tools.ts"]
}
}
แต่ละรายการจะกลายเป็นปลั๊กอินหนึ่งตัว แต่ละรายการจะกลายเป็นปลั๊กอิน หากแพ็กระบุส่วนขยายหลายรายการ idของปลั๊กอิน
จะเป็น name/<fileBase>.
หากปลั๊กอินของคุณนำเข้าdepsจากnpm ให้ติดตั้งไว้ในไดเรกทอรีนั้นเพื่อให้
node_modules ใช้งานได้ (npm install / pnpm install).
เมทาดาทาแคตตาล็อกช่องทาง¶
ปลั๊กอินช่องทางสามารถโฆษณาเมทาดาทาการเริ่มต้นใช้งานผ่าน openclaw.channel และ
คำแนะนำการติดตั้งผ่าน openclaw.install. วิธีนี้ทำให้แกนหลักไม่ต้องเก็บข้อมูลแคตตาล็อก
ตัวอย่าง:
{
"name": "@openclaw/nextcloud-talk",
"openclaw": {
"extensions": ["./index.ts"],
"channel": {
"id": "nextcloud-talk",
"label": "Nextcloud Talk",
"selectionLabel": "Nextcloud Talk (self-hosted)",
"docsPath": "/channels/nextcloud-talk",
"docsLabel": "nextcloud-talk",
"blurb": "Self-hosted chat via Nextcloud Talk webhook bots.",
"order": 65,
"aliases": ["nc-talk", "nc"]
},
"install": {
"npmSpec": "@openclaw/nextcloud-talk",
"localPath": "extensions/nextcloud-talk",
"defaultChoice": "npm"
}
}
}
OpenClawยังสามารถผสาน แคตตาล็อกช่องทางภายนอก ได้(เช่น เอ็กซ์พอร์ตจากรีจิสทรีMPM) วางไฟล์JSONไว้ที่หนึ่งในตำแหน่ง: วางไฟล์ JSON ไว้ที่หนึ่งในตำแหน่งต่อไปนี้:
~/.openclaw/mpm/plugins.json~/.openclaw/mpm/catalog.json~/.openclaw/plugins/catalog.json
หรือชี้ OPENCLAW_PLUGIN_CATALOG_PATHS(หรือ OPENCLAW_MPM_CATALOG_PATHS) ไปที่
ไฟล์JSONหนึ่งไฟล์หรือมากกว่า(คั่นด้วยคอมมา/เซมิโคลอน/PATH). แต่ละไฟล์ควร
มี { "entries": [ { "name": "@scope/pkg", "openclaw": { "channel": {...}, "install": {...} } } ] }.
IDของปลั๊กอิน¶
idเริ่มต้นของปลั๊กอิน:
- แพ็กเกจแพ็ก:
package.jsonname - ไฟล์เดี่ยว: ชื่อฐานของไฟล์(
~/.../voice-call.ts→voice-call)
หากปลั๊กอินเอ็กซ์พอร์ต id OpenClawจะใช้ค่าเหล่านั้นแต่จะเตือนเมื่อไม่ตรงกับ
idที่กำหนดค่าไว้
คอนฟิก¶
{
plugins: {
enabled: true,
allow: ["voice-call"],
deny: ["untrusted-plugin"],
load: { paths: ["~/Projects/oss/voice-call-extension"] },
entries: {
"voice-call": { enabled: true, config: { provider: "twilio" } },
},
},
}
ฟิลด์:
enabled: สวิตช์หลัก(ค่าเริ่มต้น: true)allow: allowlist(ไม่บังคับ)deny: denylist(ไม่บังคับ; denyมีสิทธิ์เหนือกว่า)load.paths: ไฟล์/ไดเรกทอรีปลั๊กอินเพิ่มเติมentries.<id>: สวิตช์ต่อปลั๊กอิน + คอนฟิก
การเปลี่ยนคอนฟิก ต้องรีสตาร์ตGateway(เกตเวย์).
กฎการตรวจสอบ(เข้มงวด):
- idปลั๊กอินที่ไม่รู้จักใน
entries,allow,deny, หรือslotsเป็น ข้อผิดพลาด. - คีย์
channels.<id>ที่ไม่รู้จักเป็น ข้อผิดพลาด เว้นแต่แมนิฟেস্টของปลั๊กอินจะประกาศ idของช่องทาง - คอนฟิกของปลั๊กอินถูกตรวจสอบด้วยJSON Schemaที่ฝังอยู่ใน
openclaw.plugin.json(configSchema). - หากปลั๊กอินถูกปิดใช้งาน คอนฟิกจะถูกเก็บไว้และจะมี คำเตือน.
สล็อตปลั๊กอิน(หมวดหมู่แบบเอกสิทธิ์)¶
หมวดหมู่ปลั๊กอินบางประเภทเป็นแบบ เอกสิทธิ์(เปิดใช้งานได้ครั้งละหนึ่ง) ใช้
plugins.slots เพื่อเลือกว่าปลั๊กอินใดเป็นเจ้าของสล็อต: ใช้ plugins.slots เพื่อเลือกว่าปลั๊กอินใดเป็นเจ้าของสล็อต:
{
plugins: {
slots: {
memory: "memory-core", // or "none" to disable memory plugins
},
},
}
หากมีหลายปลั๊กอินประกาศ kind: "memory" จะโหลดเฉพาะตัวที่ถูกเลือก ตัวอื่นจะถูกปิดใช้งาน
พร้อมการวินิจฉัย ตัวอื่น ๆ จะถูกปิดใช้งานพร้อมการวินิจฉัย
Control UI(schema + ป้ายกำกับ)¶
Control UIใช้ config.schema(JSON Schema + uiHints) เพื่อเรนเดอร์ฟอร์มที่ดีขึ้น
OpenClawจะเสริม uiHints ขณะรันไทม์ตามปลั๊กอินที่ค้นพบ:
- เพิ่มป้ายกำกับต่อปลั๊กอินสำหรับ
plugins.entries.<id>/.enabled/.config - ผสานคำใบ้ฟิลด์คอนฟิกที่ปลั๊กอินให้มาแบบไม่บังคับภายใต้:
plugins.entries.<id>.config.<field>
หากคุณต้องการให้ฟิลด์คอนฟิกของปลั๊กอินแสดงป้ายกำกับ/placeholderที่ดี(และทำเครื่องหมายความลับเป็นข้อมูลอ่อนไหว)
ให้จัดเตรียม uiHints ควบคู่กับJSON Schemaในแมนิฟেস্টของปลั๊กอิน
ตัวอย่าง:
{
"id": "my-plugin",
"configSchema": {
"type": "object",
"additionalProperties": false,
"properties": {
"apiKey": { "type": "string" },
"region": { "type": "string" }
}
},
"uiHints": {
"apiKey": { "label": "API Key", "sensitive": true },
"region": { "label": "Region", "placeholder": "us-east-1" }
}
}
CLI¶
openclaw plugins list
openclaw plugins info <id>
openclaw plugins install <path> # copy a local file/dir into ~/.openclaw/extensions/<id>
openclaw plugins install ./extensions/voice-call # relative path ok
openclaw plugins install ./plugin.tgz # install from a local tarball
openclaw plugins install ./plugin.zip # install from a local zip
openclaw plugins install -l ./extensions/voice-call # link (no copy) for dev
openclaw plugins install @openclaw/voice-call # install from npm
openclaw plugins update <id>
openclaw plugins update --all
openclaw plugins enable <id>
openclaw plugins disable <id>
openclaw plugins doctor
plugins update ใช้งานได้เฉพาะการติดตั้งnpmที่ถูกติดตามภายใต้ plugins.installs.
ปลั๊กอินยังสามารถลงทะเบียนคำสั่งระดับบนของตนเองได้(ตัวอย่าง: openclaw voicecall).
Plugin API(ภาพรวม)¶
ปลั๊กอินเอ็กซ์พอร์ตอย่างใดอย่างหนึ่ง:
- ฟังก์ชัน:
(api) => { ... } - อ็อบเจ็กต์:
{ id, name, configSchema, register(api) { ... } }
ฮุคของปลั๊กอิน¶
ปลั๊กอินสามารถส่ง hook มาและลงทะเบียนได้ในขณะรันไทม์ ปลั๊กอินสามารถบรรจุฮุคและลงทะเบียนขณะรันไทม์ได้ วิธีนี้ทำให้ปลั๊กอินรวมระบบอัตโนมัติแบบขับเคลื่อนด้วยอีเวนต์โดยไม่ต้องติดตั้งแพ็กฮุคแยกต่างหาก
ตัวอย่าง¶
import { registerPluginHooksFromDir } from "openclaw/plugin-sdk";
export default function register(api) {
registerPluginHooksFromDir(api, "./hooks");
}
หมายเหตุ:
- ไดเรกทอรีฮุคเป็นไปตามโครงสร้างฮุคปกติ(
HOOK.md+handler.ts). - กฎคุณสมบัติของฮุคยังคงมีผล(ข้อกำหนดOS/bin/env/config).
- ฮุคที่ปลั๊กอินจัดการจะแสดงใน
openclaw hooks listพร้อมplugin:<id>. - คุณไม่สามารถเปิด/ปิดฮุคที่ปลั๊กอินจัดการผ่าน
openclaw hooks; ให้เปิด/ปิดปลั๊กอินแทน
ปลั๊กอินผู้ให้บริการ(การยืนยันตัวตนโมเดล)¶
ปลั๊กอินสามารถลงทะเบียนโฟลว์ การยืนยันตัวตนผู้ให้บริการโมเดล เพื่อให้ผู้ใช้รันOAuthหรือการตั้งค่าAPI-keyภายในOpenClawได้(ไม่ต้องใช้สคริปต์ภายนอก)
ลงทะเบียนผู้ให้บริการผ่าน api.registerProvider(...). ผู้ให้บริการแต่ละรายเปิดเผยวิธีการยืนยันตัวตนหนึ่งอย่างหรือมากกว่า(OAuth, API key, device code ฯลฯ) วิธีเหล่านี้ขับเคลื่อน: เมธอดเหล่านี้ขับเคลื่อน:
openclaw models auth login --provider <id> [--method <id>]
ตัวอย่าง:
api.registerProvider({
id: "acme",
label: "AcmeAI",
auth: [
{
id: "oauth",
label: "OAuth",
kind: "oauth",
run: async (ctx) => {
// Run OAuth flow and return auth profiles.
return {
profiles: [
{
profileId: "acme:default",
credential: {
type: "oauth",
provider: "acme",
access: "...",
refresh: "...",
expires: Date.now() + 3600 * 1000,
},
},
],
defaultModel: "acme/opus-1",
};
},
},
],
});
หมายเหตุ:
runรับProviderAuthContextที่มีตัวช่วยprompter,runtime,openUrl, และoauth.createVpsAwareHandlers.- คืนค่า
configPatchเมื่อคุณต้องเพิ่มโมเดลเริ่มต้นหรือคอนฟิกผู้ให้บริการ - คืนค่า
defaultModelเพื่อให้--set-defaultอัปเดตค่าเริ่มต้นของเอเจนต์
ลงทะเบียนช่องทางข้อความ¶
ปลั๊กอินสามารถลงทะเบียน ปลั๊กอินช่องทาง ที่ทำงานเหมือนช่องทางที่มีมาในตัว
(WhatsApp, Telegram เป็นต้น) คอนฟิกช่องทางอยู่ภายใต้ channels.<id> คอนฟิกของช่องอยู่ภายใต้channels.
const myChannel = {
id: "acmechat",
meta: {
id: "acmechat",
label: "AcmeChat",
selectionLabel: "AcmeChat (API)",
docsPath: "/channels/acmechat",
blurb: "demo channel plugin.",
aliases: ["acme"],
},
capabilities: { chatTypes: ["direct"] },
config: {
listAccountIds: (cfg) => Object.keys(cfg.channels?.acmechat?.accounts ?? {}),
resolveAccount: (cfg, accountId) =>
cfg.channels?.acmechat?.accounts?.[accountId ?? "default"] ?? {
accountId,
},
},
outbound: {
deliveryMode: "direct",
sendText: async () => ({ ok: true }),
},
};
export default function (api) {
api.registerChannel({ plugin: myChannel });
}
หมายเหตุ:
- วางคอนฟิกไว้ภายใต้
channels.<id>(ไม่ใช่plugins.entries). meta.labelใช้เป็นป้ายกำกับในรายการCLI/UImeta.aliasesเพิ่มidทางเลือกสำหรับการทำ normalization และอินพุตCLImeta.preferOverระบุidช่องทางที่ให้ข้ามการเปิดใช้งานอัตโนมัติเมื่อทั้งคู่ถูกกำหนดค่าmeta.detailLabelและmeta.systemImageช่วยให้UIแสดงป้ายกำกับ/ไอคอนช่องทางที่สมบูรณ์ยิ่งขึ้น
เขียนช่องทางข้อความใหม่(ทีละขั้นตอน)¶
ใช้เมื่อคุณต้องการ พื้นผิวแชตใหม่(“ช่องทางข้อความ”) ไม่ใช่ผู้ให้บริการโมเดล
เอกสารผู้ให้บริการโมเดลอยู่ภายใต้ /providers/*.
เอกสารผู้ให้บริการโมเดลอยู่ที่ /providers/*
- เลือกid + รูปแบบคอนฟิก
- คอนฟิกช่องทางทั้งหมดอยู่ภายใต้
channels.<id>. - แนะนำ
channels.<id>.accounts.<accountId>สำหรับการตั้งค่าหลายบัญชี
- กำหนดเมทาดาทาช่องทาง
meta.label,meta.selectionLabel,meta.docsPath,meta.blurbควบคุมรายการCLI/UImeta.docsPathควรชี้ไปที่หน้าเอกสารอย่าง/channels/<id>meta.preferOverให้ปลั๊กอินแทนที่ช่องทางอื่น(การเปิดใช้งานอัตโนมัติจะให้ความสำคัญ)meta.detailLabelและmeta.systemImageใช้โดยUIสำหรับข้อความรายละเอียด/ไอคอน
- ติดตั้งอะแดปเตอร์ที่จำเป็น
config.listAccountIds+config.resolveAccountcapabilities(ชนิดแชต สื่อ เธรด ฯลฯ)outbound.deliveryMode+outbound.sendText(สำหรับการส่งพื้นฐาน)
- เพิ่มอะแดปเตอร์เสริมตามต้องการ
setup(วิซาร์ด),security(นโยบายDM),status(สุขภาพ/การวินิจฉัย)gateway(เริ่ม/หยุด/ล็อกอิน),mentions,threading,streamingactions(การกระทำข้อความ),commands(พฤติกรรมคำสั่งแบบเนทีฟ)
- ลงทะเบียนช่องทางในปลั๊กอินของคุณ
api.registerChannel({ plugin })
ตัวอย่างคอนฟิกขั้นต่ำ:
{
channels: {
acmechat: {
accounts: {
default: { token: "ACME_TOKEN", enabled: true },
},
},
},
}
ปลั๊กอินช่องทางขั้นต่ำ(ส่งออกอย่างเดียว):
const plugin = {
id: "acmechat",
meta: {
id: "acmechat",
label: "AcmeChat",
selectionLabel: "AcmeChat (API)",
docsPath: "/channels/acmechat",
blurb: "AcmeChat messaging channel.",
aliases: ["acme"],
},
capabilities: { chatTypes: ["direct"] },
config: {
listAccountIds: (cfg) => Object.keys(cfg.channels?.acmechat?.accounts ?? {}),
resolveAccount: (cfg, accountId) =>
cfg.channels?.acmechat?.accounts?.[accountId ?? "default"] ?? {
accountId,
},
},
outbound: {
deliveryMode: "direct",
sendText: async ({ text }) => {
// deliver `text` to your channel here
return { ok: true };
},
},
};
export default function (api) {
api.registerChannel({ plugin });
}
โหลดปลั๊กอิน(ไดเรกทอรีส่วนขยายหรือ plugins.load.paths), รีสตาร์ตGateway(เกตเวย์)
จากนั้นกำหนดค่า channels.<id> ในคอนฟิกของคุณ
เครื่องมือเอเจนต์¶
ดูคู่มือเฉพาะ: Plugin agent tools.
ลงทะเบียนเมธอดGatewayRPC¶
export default function (api) {
api.registerGatewayMethod("myplugin.status", ({ respond }) => {
respond(true, { ok: true });
});
}
ลงทะเบียนคำสั่งCLI¶
export default function (api) {
api.registerCli(
({ program }) => {
program.command("mycmd").action(() => {
console.log("Hello");
});
},
{ commands: ["mycmd"] },
);
}
ลงทะเบียนคำสั่งตอบกลับอัตโนมัติ¶
ปลั๊กอินสามารถลงทะเบียนคำสั่งสแลชแบบกำหนดเองที่รัน โดยไม่เรียกเอเจนต์AI เหมาะสำหรับคำสั่งสลับสถานะ การตรวจสอบสถานะ หรือการกระทำด่วนที่ไม่ต้องประมวลผลด้วยLLM สิ่งนี้มีประโยชน์สำหรับคำสั่งสลับ สถานะเช็ก หรือการกระทำด่วนที่ไม่ต้องการการประมวลผลจาก LLM
export default function (api) {
api.registerCommand({
name: "mystatus",
description: "Show plugin status",
handler: (ctx) => ({
text: `Plugin is running! Channel: ${ctx.channel}`,
}),
});
}
บริบทของตัวจัดการคำสั่ง:
senderId: IDของผู้ส่ง(ถ้ามี)channel: ช่องทางที่ส่งคำสั่งisAuthorizedSender: ผู้ส่งเป็นผู้ใช้ที่ได้รับอนุญาตหรือไม่args: อาร์กิวเมนต์ที่ส่งหลังคำสั่ง(ถ้าacceptsArgs: true)commandBody: ข้อความคำสั่งเต็มconfig: คอนฟิกOpenClawปัจจุบัน
ตัวเลือกคำสั่ง:
name: ชื่อคำสั่ง(ไม่รวม/นำหน้า)description: ข้อความช่วยเหลือที่แสดงในรายการคำสั่งacceptsArgs: คำสั่งรับอาร์กิวเมนต์หรือไม่(ค่าเริ่มต้น: false) หากเป็น false และมีการส่งอาร์กิวเมนต์ คำสั่งจะไม่ตรงและข้อความจะถูกส่งต่อไปยังตัวจัดการอื่น หากเป็น false และมีการส่งอาร์กิวเมนต์ คำสั่งจะไม่ตรงและข้อความจะถูกส่งต่อไปยังตัวจัดการอื่นrequireAuth: ต้องการผู้ส่งที่ได้รับอนุญาตหรือไม่(ค่าเริ่มต้น: true)handler: ฟังก์ชันที่คืนค่า{ text: string }(อาจเป็น async)
ตัวอย่างที่มีการยืนยันตัวตนและอาร์กิวเมนต์:
api.registerCommand({
name: "setmode",
description: "Set plugin mode",
acceptsArgs: true,
requireAuth: true,
handler: async (ctx) => {
const mode = ctx.args?.trim() || "default";
await saveMode(mode);
return { text: `Mode set to: ${mode}` };
},
});
หมายเหตุ:
- คำสั่งของปลั๊กอินจะถูกประมวลผล ก่อน คำสั่งที่มีมาในตัวและเอเจนต์AI
- คำสั่งถูกลงทะเบียนแบบส่วนกลางและใช้งานได้ทุกช่องทาง
- ชื่อคำสั่งไม่สนใจตัวพิมพ์เล็กใหญ่(
/MyStatusตรงกับ/mystatus) - ชื่อคำสั่งต้องขึ้นต้นด้วยตัวอักษรและมีได้เฉพาะตัวอักษร ตัวเลข ขีดกลาง และขีดล่าง
- ชื่อคำสั่งที่สงวนไว้(เช่น
help,status,resetเป็นต้น) ไม่สามารถถูกแทนที่โดยปลั๊กอินได้ ไม่สามารถถูก override โดยปลั๊กอินได้ - การลงทะเบียนคำสั่งซ้ำกันข้ามปลั๊กอินจะล้มเหลวพร้อมข้อผิดพลาดการวินิจฉัย
ลงทะเบียนบริการเบื้องหลัง¶
export default function (api) {
api.registerService({
id: "my-service",
start: () => api.logger.info("ready"),
stop: () => api.logger.info("bye"),
});
}
หลักเกณฑ์การตั้งชื่อ¶
- เมธอดGateway:
pluginId.action(ตัวอย่าง:voicecall.status) - เครื่องมือ:
snake_case(ตัวอย่าง:voice_call) - คำสั่งCLI: แบบkebabหรือcamel แต่หลีกเลี่ยงการชนกับคำสั่งแกนหลัก
Skills¶
ปลั๊กอินสามารถบรรจุสกิลไว้ในรีโป(skills/<name>/SKILL.md).
เปิดใช้งานด้วย plugins.entries.<id>.enabled(หรือเงื่อนไขคอนฟิกอื่น) และตรวจสอบให้แน่ใจว่า
มีอยู่ในตำแหน่งสกิลของเวิร์กสเปซ/ที่จัดการ
การแจกจ่าย(npm)¶
แพ็กเกจที่แนะนำ:
- แพ็กเกจหลัก:
openclaw(รีโปนี้) - ปลั๊กอิน: แพ็กเกจnpmแยกภายใต้
@openclaw/*(ตัวอย่าง:@openclaw/voice-call)
สัญญาการเผยแพร่:
package.jsonของปลั๊กอินต้องมีopenclaw.extensionsพร้อมไฟล์เริ่มต้นอย่างน้อยหนึ่งไฟล์- ไฟล์เริ่มต้นอาจเป็น
.jsหรือ.ts(jitiโหลดTSขณะรันไทม์) openclaw plugins install <npm-spec>ใช้npm packแตกไฟล์ไปยัง~/.openclaw/extensions/<id>/และเปิดใช้งานในคอนฟิก- ความเสถียรของคีย์คอนฟิก: แพ็กเกจที่มีสโคปจะถูกทำให้เป็นมาตรฐานเป็นid ไม่ติดสโคป สำหรับ
plugins.entries.*
ปลั๊กอินตัวอย่าง: Voice Call¶
รีโปนี้มีปลั๊กอินโทรด้วยเสียง(Twilioหรือโหมดสำรองแบบบันทึก):
- ซอร์ส:
extensions/voice-call - สกิล:
skills/voice-call - CLI:
openclaw voicecall start|status - เครื่องมือ:
voice_call - RPC:
voicecall.start,voicecall.status - คอนฟิก(twilio):
provider: "twilio"+twilio.accountSid/authToken/from(ไม่บังคับstatusCallbackUrl,twimlUrl) - คอนฟิก(dev):
provider: "log"(ไม่ใช้เครือข่าย)
ดู Voice Call และ extensions/voice-call/README.md สำหรับการตั้งค่าและการใช้งาน
หมายเหตุด้านความปลอดภัย¶
ปลั๊กอินทำงานแบบ in-process ร่วมกับ Gateway ให้ปฏิบัติกับมันเสมือนเป็นโค้ดที่เชื่อถือได้:
- ติดตั้งเฉพาะปลั๊กอินที่คุณเชื่อถือ
- แนะนำให้ใช้ allowlist
plugins.allow - รีสตาร์ตGateway(เกตเวย์)หลังการเปลี่ยนแปลง
การทดสอบปลั๊กอิน¶
ปลั๊กอินสามารถ(และควร)มีการทดสอบ:
- ปลั๊กอินในรีโปสามารถเก็บการทดสอบVitestไว้ภายใต้
src/**(ตัวอย่าง:src/plugins/voice-call.plugin.test.ts). - ปลั๊กอินที่เผยแพร่แยกควรรันCIของตนเอง(lint/build/test) และตรวจสอบว่า
openclaw.extensionsชี้ไปยังเอ็นทรีพอยต์ที่บิลด์แล้ว(dist/index.js).