Plugin SDK reference
จุดเข้าใช้งานของ Plugin
Plugin ทุกตัวส่งออกออบเจ็กต์ entry เริ่มต้น SDK มีตัวช่วยสำหรับ สร้างออบเจ็กต์เหล่านี้
สำหรับ Plugin ที่ติดตั้งแล้ว package.json ควรชี้การโหลด runtime ไปยัง
JavaScript ที่ build แล้วเมื่อมี:
{ "openclaw": { "extensions": ["./src/index.ts"], "runtimeExtensions": ["./dist/index.js"], "setupEntry": "./src/setup-entry.ts", "runtimeSetupEntry": "./dist/setup-entry.js" }}extensions และ setupEntry ยังคงเป็น source entry ที่ใช้ได้สำหรับการพัฒนา
ใน workspace และ git checkout ส่วน runtimeExtensions และ runtimeSetupEntry
เป็นตัวเลือกที่แนะนำเมื่อ OpenClaw โหลดแพ็กเกจที่ติดตั้งแล้ว และช่วยให้แพ็กเกจ npm
หลีกเลี่ยงการ compile TypeScript ตอน runtime ได้ ต้องระบุ runtime entries
อย่างชัดเจน: runtimeSetupEntry ต้องมี setupEntry และ artifact ของ
runtimeExtensions หรือ runtimeSetupEntry ที่หายไปจะทำให้ install/discovery
ล้มเหลวแทนที่จะ fallback ไปยัง source อย่างเงียบๆ หากแพ็กเกจที่ติดตั้งแล้ว
ประกาศเฉพาะ TypeScript source entry, OpenClaw จะใช้ peer dist/*.js
ที่ build แล้วซึ่งตรงกันเมื่อมีอยู่ จากนั้นจึง fallback ไปยัง TypeScript source
เส้นทาง entry ทั้งหมดต้องอยู่ภายในไดเรกทอรีแพ็กเกจของ Plugin เท่านั้น Runtime entries
และ inferred built JavaScript peers ไม่ทำให้ source path ของ extensions หรือ
setupEntry ที่หลุดออกนอกแพ็กเกจกลายเป็นเส้นทางที่ใช้ได้
defineToolPlugin
Import: openclaw/plugin-sdk/tool-plugin
สำหรับ Plugin แบบง่ายที่เพิ่มเฉพาะเครื่องมือของ agent เท่านั้น defineToolPlugin ช่วยให้
source สำหรับเขียนมีขนาดเล็ก, infer ประเภท config และพารามิเตอร์เครื่องมือจาก schema ของ TypeBox,
ห่อ return value ธรรมดาให้อยู่ในรูปแบบ tool-result ของ OpenClaw, และ
เปิดเผย metadata แบบ static ที่ openclaw plugins build เขียนลงใน manifest ของ Plugin
export default defineToolPlugin({ id: "stock-quotes", name: "Stock Quotes", description: "Fetch stock quotes.", configSchema: Type.Object({ apiKey: Type.Optional(Type.String({ description: "API key." })), }), tools: (tool) => [ tool({ name: "quote", label: "Quote", description: "Fetch a quote.", parameters: Type.Object({ symbol: Type.String({ description: "Ticker symbol." }), }), execute: async ({ symbol }, config) => ({ symbol, hasKey: Boolean(config.apiKey) }), }), ],});configSchemaเป็นตัวเลือก หากละไว้ OpenClaw จะใช้ schema วัตถุว่างแบบเข้มงวด และ manifest ที่สร้างขึ้นจะยังรวมconfigSchemaexecuteส่งคืน string ธรรมดาหรือค่าที่ serialize เป็น JSON ได้ ตัวช่วยจะห่อ ค่านั้นเป็นผลลัพธ์เครื่องมือแบบ text พร้อมdetails- ชื่อเครื่องมือเป็นแบบ static
openclaw plugins buildderivecontracts.toolsจากเครื่องมือที่ประกาศไว้ ดังนั้นผู้เขียนไม่ต้องทำชื่อซ้ำด้วยตนเอง - การโหลด runtime ยังคงเข้มงวด Plugin ที่ติดตั้งแล้วยังต้องมี
openclaw.plugin.jsonและpackage.jsonopenclaw.extensions; OpenClaw จะไม่ execute โค้ด Plugin เพื่อ infer ข้อมูล manifest ที่ขาดหายไป
definePluginEntry
Import: openclaw/plugin-sdk/plugin-entry
สำหรับ provider plugins, tool plugins ขั้นสูง, hook plugins, และทุกอย่างที่ ไม่ใช่ ช่องทางส่งข้อความ
export default definePluginEntry({ id: "my-plugin", name: "My Plugin", description: "Short summary", register(api) { api.registerProvider({ /* ... */ }); api.registerTool({ /* ... */ }); },});| ฟิลด์ | ประเภท | จำเป็น | ค่าเริ่มต้น |
|---|---|---|---|
id |
string |
ใช่ | - |
name |
string |
ใช่ | - |
description |
string |
ใช่ | - |
kind |
string |
ไม่ | - |
configSchema |
OpenClawPluginConfigSchema | () => OpenClawPluginConfigSchema |
ไม่ | Schema วัตถุว่าง |
register |
(api: OpenClawPluginApi) => void |
ใช่ | - |
idต้องตรงกับ manifestopenclaw.plugin.jsonของคุณkindใช้สำหรับช่องแบบ exclusive:"memory"หรือ"context-engine"configSchemaเป็น function ได้เพื่อการประเมินแบบ lazy- OpenClaw resolve และ memoize schema นั้นในการเข้าถึงครั้งแรก ดังนั้นตัวสร้าง schema ที่มีค่าใช้จ่ายสูงจะทำงานเพียงครั้งเดียว
defineChannelPluginEntry
Import: openclaw/plugin-sdk/channel-core
ห่อ definePluginEntry พร้อม wiring เฉพาะ channel เรียก
api.registerChannel({ plugin }) โดยอัตโนมัติ, เปิดเผย seam ของ metadata CLI
สำหรับ root-help ที่เป็นตัวเลือก, และ gate registerFull ตามโหมดการลงทะเบียน
export default defineChannelPluginEntry({ id: "my-channel", name: "My Channel", description: "Short summary", plugin: myChannelPlugin, setRuntime: setMyRuntime, registerCliMetadata(api) { api.registerCli(/* ... */); }, registerFull(api) { api.registerGatewayMethod(/* ... */); },});| ฟิลด์ | ประเภท | จำเป็น | ค่าเริ่มต้น |
|---|---|---|---|
id |
string |
ใช่ | - |
name |
string |
ใช่ | - |
description |
string |
ใช่ | - |
plugin |
ChannelPlugin |
ใช่ | - |
configSchema |
OpenClawPluginConfigSchema | () => OpenClawPluginConfigSchema |
ไม่ | Schema วัตถุว่าง |
setRuntime |
(runtime: PluginRuntime) => void |
ไม่ | - |
registerCliMetadata |
(api: OpenClawPluginApi) => void |
ไม่ | - |
registerFull |
(api: OpenClawPluginApi) => void |
ไม่ | - |
setRuntimeถูกเรียกระหว่างการลงทะเบียน เพื่อให้คุณเก็บ reference ของ runtime ได้ (โดยทั่วไปผ่านcreatePluginRuntimeStore) และจะถูกข้ามระหว่างการ capture metadata ของ CLIregisterCliMetadataทำงานระหว่างapi.registrationMode === "cli-metadata",api.registrationMode === "discovery", และapi.registrationMode === "full"ใช้เป็นตำแหน่ง canonical สำหรับ CLI descriptors ที่ channel เป็นเจ้าของ เพื่อให้ root help ไม่กระตุ้นการเปิดใช้งาน, discovery snapshots รวม metadata คำสั่งแบบ static, และ การลงทะเบียนคำสั่ง CLI ปกติยังเข้ากันได้กับการโหลด Plugin แบบเต็ม- การลงทะเบียน discovery เป็นแบบไม่กระตุ้นการเปิดใช้งาน ไม่ใช่แบบไม่ import OpenClaw อาจ
ประเมิน entry ของ Plugin ที่เชื่อถือได้และโมดูล channel plugin เพื่อสร้าง
snapshot ดังนั้นควรรักษา top-level imports ให้ไม่มี side effect และวาง sockets,
clients, workers, และ services ไว้หลัง path ที่ใช้เฉพาะ
"full" registerFullทำงานเฉพาะเมื่อapi.registrationMode === "full"และจะถูกข้าม ระหว่างการโหลดแบบ setup-only- เช่นเดียวกับ
definePluginEntry,configSchemaเป็น lazy factory ได้ และ OpenClaw memoize schema ที่ resolve แล้วในการเข้าถึงครั้งแรก - สำหรับคำสั่ง root CLI ที่ Plugin เป็นเจ้าของ ให้เลือกใช้
api.registerCli(..., { descriptors: [...] })เมื่อคุณต้องการให้คำสั่งยังคง lazy-loaded โดยไม่หายไปจาก parse tree ของ root CLI สำหรับคำสั่ง feature แบบ paired-node ให้เลือกใช้api.registerNodeCliFeature(...)เพื่อให้คำสั่งไปอยู่ภายใต้openclaw nodesสำหรับคำสั่ง Plugin แบบซ้อนอื่นๆ ให้เพิ่มparentPathและลงทะเบียนคำสั่งบน ออบเจ็กต์programที่ส่งให้ registrar; OpenClaw จะ resolve ไปยัง parent command ก่อนเรียก Plugin สำหรับ channel plugins ให้เลือก ลงทะเบียน descriptors เหล่านั้นจากregisterCliMetadata(...)และให้registerFull(...)มุ่งเน้นงานเฉพาะ runtime - หาก
registerFull(...)ลงทะเบียนเมธอด RPC ของ Gateway ด้วย ให้เก็บไว้บน prefix เฉพาะ Plugin namespace สำหรับ core admin ที่สงวนไว้ (config.*,exec.approvals.*,wizard.*,update.*) จะถูก coerce เป็นoperator.adminเสมอ
defineSetupPluginEntry
Import: openclaw/plugin-sdk/channel-core
สำหรับไฟล์ setup-entry.ts แบบ lightweight ส่งคืนเพียง { plugin } โดยไม่มี
runtime หรือ CLI wiring
export default defineSetupPluginEntry(myChannelPlugin);OpenClaw โหลดสิ่งนี้แทน entry แบบเต็มเมื่อ channel ถูกปิดใช้งาน, ยังไม่ได้กำหนดค่า, หรือเมื่อเปิดใช้งาน deferred loading ดู Setup and Config เพื่อดูว่าเรื่องนี้สำคัญเมื่อใด
ในทางปฏิบัติ ให้จับคู่ defineSetupPluginEntry(...) กับกลุ่มตัวช่วย setup
แบบแคบ:
openclaw/plugin-sdk/setup-runtimeสำหรับตัวช่วย setup ที่ปลอดภัยสำหรับ runtime เช่นcreateSetupTranslator, setup patch adapters ที่ import-safe, output แบบ lookup-note,promptResolvedAllowFrom,splitSetupEntries, และ delegated setup proxiesopenclaw/plugin-sdk/channel-setupสำหรับพื้นผิว setup ของ optional-installopenclaw/plugin-sdk/setup-toolsสำหรับตัวช่วย CLI/archive/docs ด้าน setup/install
เก็บ SDK หนักๆ, การลงทะเบียน CLI, และบริการ runtime ที่มีอายุยาวไว้ใน entry แบบเต็ม
Workspace channels ที่ bundle มาด้วยซึ่งแยกพื้นผิว setup และ runtime สามารถใช้
defineBundledChannelSetupEntry(...) จาก
openclaw/plugin-sdk/channel-entry-contract แทนได้ contract นั้นช่วยให้
setup entry เก็บ exports ของ plugin/secrets ที่ setup-safe ได้ ขณะยังเปิดเผย
runtime setter:
export default defineBundledChannelSetupEntry({ importMetaUrl: import.meta.url, plugin: { specifier: "./channel-plugin-api.js", exportName: "myChannelPlugin", }, runtime: { specifier: "./runtime-api.js", exportName: "setMyChannelRuntime", }, registerSetupRuntime(api) { api.registerHttpRoute({ path: "/my-channel/events", auth: "plugin", handler: async (req, res) => { /* setup-safe route */ }, }); },});ใช้ bundled contract นั้นเฉพาะเมื่อ flow ของ setup ต้องการ runtime
setter แบบ lightweight หรือพื้นผิว Gateway ที่ setup-safe ก่อนที่ channel entry แบบเต็มจะโหลดจริงๆ
registerSetupRuntime ทำงานเฉพาะสำหรับการโหลด "setup-runtime" เท่านั้น; จำกัดไว้ที่
route หรือ method เฉพาะ config ที่ต้องมีอยู่ก่อนการเปิดใช้งานแบบเต็มที่ defer ไว้
โหมดการลงทะเบียน
api.registrationMode บอก Plugin ของคุณว่าถูกโหลดอย่างไร:
| โหมด | เมื่อใด | สิ่งที่ต้องลงทะเบียน |
|---|---|---|
"full" |
การเริ่มต้น Gateway ตามปกติ | ทุกอย่าง |
"discovery" |
การค้นหาความสามารถแบบอ่านอย่างเดียว | การลงทะเบียนช่องทางพร้อมตัวอธิบาย CLI แบบคงที่; โค้ดจุดเข้าอาจโหลดได้ แต่ให้ข้ามซ็อกเก็ต, เวิร์กเกอร์, ไคลเอนต์ และบริการ |
"setup-only" |
ช่องทางที่ปิดใช้งาน/ยังไม่ได้กำหนดค่า | การลงทะเบียนช่องทางเท่านั้น |
"setup-runtime" |
โฟลว์การตั้งค่าที่มีรันไทม์พร้อมใช้งาน | การลงทะเบียนช่องทางพร้อมเฉพาะรันไทม์ขนาดเบาที่จำเป็นก่อนโหลดจุดเข้าแบบเต็ม |
"cli-metadata" |
การจับข้อมูลวิธีใช้รูท / เมทาดาทา CLI | ตัวอธิบาย CLI เท่านั้น |
defineChannelPluginEntry จัดการการแยกนี้โดยอัตโนมัติ หากคุณใช้
definePluginEntry โดยตรงสำหรับช่องทาง ให้ตรวจสอบโหมดเอง:
register(api) { if ( api.registrationMode === "cli-metadata" || api.registrationMode === "discovery" || api.registrationMode === "full" ) { api.registerCli(/* ... */); if (api.registrationMode === "cli-metadata") return; } api.registerChannel({ plugin: myPlugin }); if (api.registrationMode !== "full") return; // Heavy runtime-only registrations api.registerService(/* ... */);}โหมด Discovery สร้างสแนปช็อตรีจิสทรีที่ไม่ทำให้เกิดการเปิดใช้งาน โดยยังอาจประเมิน จุดเข้า Plugin และออบเจกต์ Plugin ของช่องทาง เพื่อให้ OpenClaw สามารถลงทะเบียน ความสามารถของช่องทางและตัวอธิบาย CLI แบบคงที่ได้ ให้ถือว่าการประเมินโมดูลใน Discovery เชื่อถือได้แต่ต้องเบา: ไม่มีไคลเอนต์เครือข่าย, โพรเซสย่อย, ตัวรับฟัง, การเชื่อมต่อฐานข้อมูล, เวิร์กเกอร์เบื้องหลัง, การอ่านข้อมูลรับรอง หรือผลข้างเคียงอื่นของรันไทม์จริงที่ระดับบนสุด
ให้ถือว่า "setup-runtime" เป็นช่วงเวลาที่พื้นผิวการเริ่มต้นแบบตั้งค่าเท่านั้นต้อง
มีอยู่ได้โดยไม่ย้อนเข้าไปยังรันไทม์ช่องทางแบบบันเดิลเต็มอีกครั้ง สิ่งที่เหมาะสมคือ
การลงทะเบียนช่องทาง, เส้นทาง HTTP ที่ปลอดภัยสำหรับการตั้งค่า, เมธอด Gateway ที่ปลอดภัยสำหรับการตั้งค่า และ
ตัวช่วยตั้งค่าที่มอบหมายต่อไป ส่วนบริการเบื้องหลังขนาดใหญ่, ตัวลงทะเบียน CLI และ
การบูตสแตรป SDK ของผู้ให้บริการ/ไคลเอนต์ยังคงอยู่ใน "full"
สำหรับตัวลงทะเบียน CLI โดยเฉพาะ:
- ใช้
descriptorsเมื่อตัวลงทะเบียนเป็นเจ้าของคำสั่งรูทหนึ่งรายการขึ้นไป และคุณ ต้องการให้ OpenClaw โหลดโมดูล CLI จริงแบบ lazy-load เมื่อถูกเรียกใช้ครั้งแรก - ตรวจสอบให้แน่ใจว่าตัวอธิบายเหล่านั้นครอบคลุมรูทคำสั่งระดับบนสุดทุกตัวที่ ตัวลงทะเบียนเปิดเผย
- จำกัดชื่อคำสั่งของตัวอธิบายให้มีเฉพาะตัวอักษร, ตัวเลข, ยัติภังค์ และขีดล่าง โดยขึ้นต้นด้วยตัวอักษรหรือตัวเลข; OpenClaw จะปฏิเสธชื่อตัวอธิบายที่อยู่นอก รูปแบบนั้น และจะตัดลำดับควบคุมเทอร์มินัลออกจากคำอธิบายก่อน แสดงวิธีใช้
- ใช้
commandsเพียงอย่างเดียวเฉพาะกับเส้นทางความเข้ากันได้แบบ eager เท่านั้น
รูปแบบ Plugin
OpenClaw จำแนก Plugin ที่โหลดแล้วตามพฤติกรรมการลงทะเบียน:
| รูปแบบ | คำอธิบาย |
|---|---|
| plain-capability | ประเภทความสามารถเดียว (เช่น เฉพาะผู้ให้บริการ) |
| hybrid-capability | หลายประเภทความสามารถ (เช่น ผู้ให้บริการ + เสียงพูด) |
| hook-only | เฉพาะ hooks ไม่มีความสามารถ |
| non-capability | เครื่องมือ/คำสั่ง/บริการ แต่ไม่มีความสามารถ |
ใช้ openclaw plugins inspect <id> เพื่อดูรูปแบบของ Plugin
ที่เกี่ยวข้อง
- ภาพรวม SDK - API การลงทะเบียนและข้อมูลอ้างอิง subpath
- ตัวช่วยรันไทม์ -
api.runtimeและcreatePluginRuntimeStore - การตั้งค่าและ Config - manifest, จุดเข้าการตั้งค่า, การโหลดแบบเลื่อนเวลา
- Plugin ช่องทาง - การสร้างออบเจกต์
ChannelPlugin - Plugin ผู้ให้บริการ - การลงทะเบียนผู้ให้บริการและ hooks