Pipeline pemuatan
Saat startup, OpenClaw secara kasar melakukan ini:- menemukan root Plugin kandidat
- membaca manifes bundle native atau kompatibel serta metadata package
- menolak kandidat yang tidak aman
- menormalkan config Plugin (
plugins.enabled,allow,deny,entries,slots,load.paths) - memutuskan pengaktifan untuk setiap kandidat
- memuat modul native yang diaktifkan: modul bawaan yang sudah dibangun menggunakan loader native; Plugin native yang belum dibangun menggunakan jiti
- memanggil hook native
register(api)dan mengumpulkan pendaftaran ke registry Plugin - mengekspos registry ke permukaan perintah/runtime
activate adalah alias legacy untuk register — loader meresolusikan yang mana pun yang ada (def.register ?? def.activate) dan memanggilnya pada titik yang sama. Semua Plugin bawaan menggunakan register; pilih register untuk Plugin baru.Perilaku manifest-first
Manifes adalah sumber kebenaran control-plane. OpenClaw menggunakannya untuk:- mengidentifikasi Plugin
- menemukan channel/Skills/skema config yang dideklarasikan atau kemampuan bundle
- memvalidasi
plugins.entries.<id>.config - menambah label/placeholder UI Control
- menampilkan metadata instalasi/katalog
- mempertahankan deskriptor aktivasi dan setup yang murah tanpa memuat runtime Plugin
activation dan setup opsional tetap berada di control plane.
Keduanya adalah deskriptor metadata saja untuk perencanaan aktivasi dan penemuan setup;
keduanya tidak menggantikan pendaftaran runtime, register(...), atau setupEntry.
Konsumen aktivasi live pertama sekarang menggunakan petunjuk manifes perintah, channel, dan provider
untuk mempersempit pemuatan Plugin sebelum materialisasi registry yang lebih luas:
- Pemuatan CLI dipersempit ke Plugin yang memiliki perintah utama yang diminta
- Resolusi setup/channel Plugin dipersempit ke Plugin yang memiliki id channel yang diminta
- Resolusi setup/runtime provider eksplisit dipersempit ke Plugin yang memiliki id provider yang diminta
activation.* eksplisit dari fallback kepemilikan manifes
seperti providers, channels, commandAliases, setup.providers,
contracts.tools, dan hooks. Pemisahan alasan itulah batas kompatibilitasnya:
metadata Plugin yang ada tetap bekerja, sementara kode baru dapat mendeteksi petunjuk luas
atau perilaku fallback tanpa mengubah semantik pemuatan runtime.
Penemuan setup sekarang lebih memilih id yang dimiliki deskriptor seperti setup.providers dan
setup.cliBackends untuk mempersempit Plugin kandidat sebelum fallback ke
setup-api bagi Plugin yang masih memerlukan hook runtime saat setup. Jika lebih dari
satu Plugin yang ditemukan mengklaim id setup provider atau backend CLI
ternormalisasi yang sama, lookup setup menolak pemilik ambigu tersebut alih-alih mengandalkan urutan penemuan.
Apa yang di-cache oleh loader
OpenClaw menyimpan cache pendek dalam proses untuk:- hasil penemuan
- data registry manifes
- registry Plugin yang dimuat
- Setel
OPENCLAW_DISABLE_PLUGIN_DISCOVERY_CACHE=1atauOPENCLAW_DISABLE_PLUGIN_MANIFEST_CACHE=1untuk menonaktifkan cache ini. - Sesuaikan jendela cache dengan
OPENCLAW_PLUGIN_DISCOVERY_CACHE_MSdanOPENCLAW_PLUGIN_MANIFEST_CACHE_MS.
Model registry
Plugin yang dimuat tidak langsung mengubah global inti secara acak. Plugin mendaftar ke registry Plugin pusat. Registry melacak:- record Plugin (identitas, sumber, origin, status, diagnostik)
- alat
- hook legacy dan hook bertipe
- channel
- provider
- handler RPC Gateway
- rute HTTP
- registrar CLI
- layanan latar belakang
- perintah milik Plugin
- modul Plugin -> pendaftaran registry
- runtime inti -> konsumsi registry
Callback binding percakapan
Plugin yang mengikat percakapan dapat bereaksi saat persetujuan diselesaikan. Gunakanapi.onConversationBindingResolved(...) untuk menerima callback setelah permintaan bind
disetujui atau ditolak:
status:"approved"atau"denied"decision:"allow-once","allow-always", atau"deny"binding: binding hasil resolusi untuk permintaan yang disetujuirequest: ringkasan permintaan asli, petunjuk detach, id pengirim, dan metadata percakapan
Hook runtime provider
Plugin provider memiliki tiga lapisan:- Metadata manifes untuk lookup pra-runtime yang murah:
providerAuthEnvVars,providerAuthAliases,providerAuthChoices, danchannelEnvVars. - Hook saat config:
catalog(legacydiscovery) plusapplyConfigDefaults. - Hook runtime: 40+ hook opsional yang mencakup auth, resolusi model, pembungkusan stream, thinking levels, kebijakan replay, dan endpoint penggunaan. Lihat daftar lengkap di Hook order and usage.
providerAuthEnvVars saat provider memiliki kredensial berbasis env
yang seharusnya terlihat oleh jalur auth/status/model-picker generik tanpa memuat runtime Plugin. Gunakan manifes providerAuthAliases saat satu id provider seharusnya menggunakan ulang env vars, profil auth, auth berbasis config, dan pilihan onboarding kunci API milik id provider lain. Gunakan manifes providerAuthChoices saat onboarding/permukaan CLI pilihan-auth
perlu mengetahui id pilihan provider, label grup, dan wiring auth satu-flag sederhana tanpa memuat runtime provider. Pertahankan envVars runtime provider untuk petunjuk yang menghadap operator seperti label onboarding atau var setup OAuth client-id/client-secret.
Gunakan manifes channelEnvVars saat channel memiliki auth atau setup yang digerakkan env
yang seharusnya terlihat oleh fallback shell-env generik, pemeriksaan config/status, atau prompt setup tanpa memuat runtime channel.
Urutan hook dan penggunaan
Untuk Plugin model/provider, OpenClaw memanggil hook dalam urutan kasar ini. Kolom “When to use” adalah panduan keputusan cepat.| # | Hook | What it does | When to use |
|---|---|---|---|
| 1 | catalog | Memublikasikan config provider ke models.providers selama pembuatan models.json | Provider memiliki katalog atau default baseUrl |
| 2 | applyConfigDefaults | Menerapkan default config global milik provider selama materialisasi config | Default bergantung pada mode auth, env, atau semantik keluarga model provider |
| — | (built-in model lookup) | OpenClaw mencoba jalur registry/katalog normal terlebih dahulu | (bukan hook Plugin) |
| 3 | normalizeModelId | Menormalkan alias model-id legacy atau preview sebelum lookup | Provider memiliki pembersihan alias sebelum resolusi model kanonis |
| 4 | normalizeTransport | Menormalkan keluarga provider api / baseUrl sebelum perakitan model generik | Provider memiliki pembersihan transport untuk id provider kustom dalam keluarga transport yang sama |
| 5 | normalizeConfig | Menormalkan models.providers.<id> sebelum resolusi runtime/provider | Provider membutuhkan pembersihan config yang seharusnya hidup bersama Plugin; helper keluarga Google bawaan juga menopang entri config Google yang didukung |
| 6 | applyNativeStreamingUsageCompat | Menerapkan penulisan ulang compat native streaming-usage ke provider config | Provider membutuhkan perbaikan metadata native streaming usage yang didorong endpoint |
| 7 | resolveConfigApiKey | Meresolusikan auth penanda-env untuk provider config sebelum pemuatan auth runtime | Provider memiliki resolusi API-key penanda-env milik provider; amazon-bedrock juga memiliki resolver penanda-env AWS bawaan di sini |
| 8 | resolveSyntheticAuth | Menampilkan auth lokal/self-hosted atau berbasis config tanpa mempersistenkan plaintext | Provider dapat beroperasi dengan penanda kredensial sintetis/lokal |
| 9 | resolveExternalAuthProfiles | Menumpangkan profil auth eksternal milik provider; default persistence adalah runtime-only untuk kredensial milik CLI/aplikasi | Provider menggunakan ulang kredensial auth eksternal tanpa mempersistenkan token refresh yang disalin; deklarasikan contracts.externalAuthProviders di manifes |
| 10 | shouldDeferSyntheticProfileAuth | Menurunkan placeholder profil sintetis yang disimpan di bawah auth berbasis env/config | Provider menyimpan profil placeholder sintetis yang tidak seharusnya menang dalam prioritas |
| 11 | resolveDynamicModel | Fallback sinkron untuk id model milik provider yang belum ada di registry lokal | Provider menerima id model upstream sebarang |
| 12 | prepareDynamicModel | Warm-up asinkron, lalu resolveDynamicModel dijalankan lagi | Provider membutuhkan metadata jaringan sebelum meresolusikan id yang tidak dikenal |
| 13 | normalizeResolvedModel | Penulisan ulang akhir sebelum embedded runner menggunakan model hasil resolusi | Provider membutuhkan penulisan ulang transport tetapi tetap menggunakan transport inti |
| 14 | contributeResolvedModelCompat | Menyumbangkan flag compat untuk model vendor di balik transport kompatibel lain | Provider mengenali modelnya sendiri pada transport proxy tanpa mengambil alih provider |
| 15 | capabilities | Metadata transkrip/tooling milik provider yang digunakan oleh logika inti bersama | Provider membutuhkan keanehan transkrip/keluarga provider |
| 16 | normalizeToolSchemas | Menormalkan skema alat sebelum embedded runner melihatnya | Provider membutuhkan pembersihan skema keluarga transport |
| 17 | inspectToolSchemas | Menampilkan diagnostik skema milik provider setelah normalisasi | Provider menginginkan peringatan keyword tanpa mengajari core aturan khusus provider |
| 18 | resolveReasoningOutputMode | Memilih kontrak output penalaran native vs bertag | Provider membutuhkan output penalaran/final bertag alih-alih field native |
| 19 | prepareExtraParams | Normalisasi param permintaan sebelum wrapper opsi stream generik | Provider membutuhkan param permintaan default atau pembersihan param per-provider |
| 20 | createStreamFn | Mengganti sepenuhnya jalur stream normal dengan transport kustom | Provider membutuhkan protokol wire kustom, bukan hanya wrapper |
| 21 | wrapStreamFn | Wrapper stream setelah wrapper generik diterapkan | Provider membutuhkan wrapper compat header/body/model permintaan tanpa transport kustom |
| 22 | resolveTransportTurnState | Melampirkan header atau metadata transport per-giliran native | Provider ingin transport generik mengirim identitas giliran native provider |
| 23 | resolveWebSocketSessionPolicy | Melampirkan header WebSocket native atau kebijakan cool-down sesi | Provider ingin transport WS generik menyetel header sesi atau kebijakan fallback |
| 24 | formatApiKey | Formatter auth-profile: profil tersimpan menjadi string apiKey runtime | Provider menyimpan metadata auth tambahan dan membutuhkan bentuk token runtime kustom |
| 25 | refreshOAuth | Override refresh OAuth untuk endpoint refresh kustom atau kebijakan gagal-refresh | Provider tidak cocok dengan refresher pi-ai bersama |
| 26 | buildAuthDoctorHint | Petunjuk perbaikan yang ditambahkan saat refresh OAuth gagal | Provider membutuhkan panduan perbaikan auth milik provider setelah kegagalan refresh |
| 27 | matchesContextOverflowError | Matcher overflow jendela konteks milik provider | Provider memiliki galat overflow mentah yang akan terlewat oleh heuristik generik |
| 28 | classifyFailoverReason | Klasifikasi alasan failover milik provider | Provider dapat memetakan galat API/transport mentah ke batas laju/kelebihan beban/dll. |
| 29 | isCacheTtlEligible | Kebijakan prompt-cache untuk provider proxy/backhaul | Provider membutuhkan gating TTL cache khusus proxy |
| 30 | buildMissingAuthMessage | Pengganti untuk pesan pemulihan auth-hilang generik | Provider membutuhkan petunjuk pemulihan auth-hilang khusus provider |
| 31 | suppressBuiltInModel | Penekanan model upstream yang basi plus petunjuk galat yang menghadap pengguna secara opsional | Provider perlu menyembunyikan baris upstream basi atau menggantinya dengan petunjuk vendor |
| 32 | augmentModelCatalog | Baris katalog sintetis/akhir yang ditambahkan setelah penemuan | Provider membutuhkan baris forward-compat sintetis di models list dan picker |
| 33 | resolveThinkingProfile | Set level /think, label tampilan, dan default yang spesifik model | Provider mengekspos tangga thinking kustom atau label biner untuk model tertentu |
| 34 | isBinaryThinking | Hook kompatibilitas toggle penalaran nyala/mati | Provider hanya mengekspos thinking biner nyala/mati |
| 35 | supportsXHighThinking | Hook kompatibilitas dukungan penalaran xhigh | Provider ingin xhigh hanya pada subset model tertentu |
| 36 | resolveDefaultThinkingLevel | Hook kompatibilitas level /think default | Provider memiliki kebijakan /think default untuk keluarga model |
| 37 | isModernModelRef | Matcher model-modern untuk filter profil live dan pemilihan smoke | Provider memiliki pencocokan model pilihan untuk live/smoke |
| 38 | prepareRuntimeAuth | Menukar kredensial yang dikonfigurasi menjadi token/kunci runtime aktual tepat sebelum inferensi | Provider membutuhkan pertukaran token atau kredensial permintaan berumur pendek |
| 39 | resolveUsageAuth | Meresolusikan kredensial usage/billing untuk /usage dan permukaan status terkait | Provider membutuhkan parsing token usage/kuota kustom atau kredensial usage yang berbeda |
| 40 | fetchUsageSnapshot | Mengambil dan menormalkan snapshot usage/kuota khusus provider setelah auth diresolusikan | Provider membutuhkan endpoint usage khusus provider atau parser payload |
| 41 | createEmbeddingProvider | Membangun adapter embedding milik provider untuk memory/search | Perilaku embedding memori seharusnya berada bersama Plugin provider |
| 42 | buildReplayPolicy | Mengembalikan kebijakan replay yang mengontrol penanganan transkrip untuk provider | Provider membutuhkan kebijakan transkrip kustom (misalnya, pengupasan blok thinking) |
| 43 | sanitizeReplayHistory | Menulis ulang riwayat replay setelah pembersihan transkrip generik | Provider membutuhkan penulisan ulang replay khusus provider di luar helper Compaction bersama |
| 44 | validateReplayTurns | Validasi atau pembentukan ulang giliran replay akhir sebelum embedded runner | Transport provider membutuhkan validasi giliran yang lebih ketat setelah sanitasi generik |
| 45 | onModelSelected | Menjalankan efek samping pasca-pemilihan milik provider | Provider membutuhkan telemetry atau state milik provider saat sebuah model menjadi aktif |
normalizeModelId, normalizeTransport, dan normalizeConfig pertama-tama memeriksa
Plugin provider yang cocok, lalu melanjutkan ke Plugin provider lain yang mampu menangani hook
sampai salah satunya benar-benar mengubah model id atau transport/config. Ini menjaga
shim alias/compat provider tetap bekerja tanpa mengharuskan pemanggil mengetahui Plugin bawaan mana yang memiliki penulisan ulang tersebut. Jika tidak ada hook provider yang menulis ulang entri config keluarga Google yang didukung, penormal config Google bawaan tetap menerapkan pembersihan kompatibilitas tersebut.
Jika provider membutuhkan protokol wire yang sepenuhnya kustom atau eksekutor permintaan kustom,
itu adalah kelas ekstensi yang berbeda. Hook ini ditujukan untuk perilaku provider
yang tetap berjalan pada loop inferensi normal OpenClaw.
Contoh provider
Contoh bawaan
Plugin provider bawaan menggabungkan hook di atas agar sesuai dengan kebutuhan katalog, auth, thinking, replay, dan usage masing-masing vendor. Kumpulan hook yang otoritatif hidup bersama setiap Plugin di bawahextensions/; halaman ini mengilustrasikan bentuknya alih-alih
mencerminkan daftarnya.
Provider katalog pass-through
Provider katalog pass-through
OpenRouter, Kilocode, Z.AI, xAI mendaftarkan
catalog plus
resolveDynamicModel / prepareDynamicModel sehingga mereka dapat menampilkan id model upstream lebih awal daripada katalog statis OpenClaw.Provider OAuth dan endpoint usage
Provider OAuth dan endpoint usage
GitHub Copilot, Gemini CLI, ChatGPT Codex, MiniMax, Xiaomi, z.ai memasangkan
prepareRuntimeAuth atau formatApiKey dengan resolveUsageAuth +
fetchUsageSnapshot untuk memiliki pertukaran token dan integrasi /usage.Keluarga replay dan pembersihan transkrip
Keluarga replay dan pembersihan transkrip
Keluarga bernama bersama (
google-gemini, passthrough-gemini,
anthropic-by-model, hybrid-anthropic-openai) memungkinkan provider memilih
kebijakan transkrip melalui buildReplayPolicy alih-alih setiap Plugin
mengimplementasikan ulang pembersihan.Provider hanya-katalog
Provider hanya-katalog
byteplus, cloudflare-ai-gateway, huggingface, kimi-coding, nvidia,
qianfan, synthetic, together, venice, vercel-ai-gateway, dan
volcengine hanya mendaftarkan catalog dan menggunakan loop inferensi bersama.Helper stream khusus Anthropic
Helper stream khusus Anthropic
Header beta,
/fast / serviceTier, dan context1m hidup di seam
api.ts / contract-api.ts publik milik Plugin Anthropic
(wrapAnthropicProviderStream, resolveAnthropicBetas,
resolveAnthropicFastMode, resolveAnthropicServiceTier) alih-alih di
SDK generik.Helper runtime
Plugin dapat mengakses helper inti tertentu melaluiapi.runtime. Untuk TTS:
textToSpeechmengembalikan payload output TTS inti normal untuk permukaan file/voice-note.- Menggunakan konfigurasi inti
messages.ttsdan pemilihan provider. - Mengembalikan buffer audio PCM + sample rate. Plugin harus melakukan resample/encode untuk provider.
listVoicesbersifat opsional per provider. Gunakan untuk picker suara atau alur setup milik vendor.- Daftar suara dapat menyertakan metadata yang lebih kaya seperti locale, gender, dan tag personality untuk picker yang sadar-provider.
- OpenAI dan ElevenLabs mendukung telephony saat ini. Microsoft tidak.
api.registerSpeechProvider(...).
- Pertahankan kebijakan TTS, fallback, dan pengiriman balasan di inti.
- Gunakan provider speech untuk perilaku sintesis milik vendor.
- Input legacy Microsoft
edgedinormalisasi ke id providermicrosoft. - Model kepemilikan yang disukai berorientasi perusahaan: satu Plugin vendor dapat memiliki provider teks, speech, gambar, dan media masa depan saat OpenClaw menambahkan kontrak kemampuan tersebut.
- Pertahankan orkestrasi, fallback, config, dan wiring channel di inti.
- Pertahankan perilaku vendor di Plugin provider.
- Ekspansi aditif seharusnya tetap bertipe: metode opsional baru, field hasil opsional baru, kemampuan opsional baru.
- Pembuatan video sudah mengikuti pola yang sama:
- inti memiliki kontrak kemampuan dan helper runtime
- Plugin vendor mendaftarkan
api.registerVideoGenerationProvider(...) - Plugin fitur/channel mengonsumsi
api.runtime.videoGeneration.*
api.runtime.mediaUnderstanding.*adalah permukaan bersama yang disukai untuk pemahaman gambar/audio/video.- Menggunakan konfigurasi audio media-understanding inti (
tools.media.audio) dan urutan fallback provider. - Mengembalikan
{ text: undefined }saat tidak ada output transkripsi yang dihasilkan (misalnya input dilewati/tidak didukung). api.runtime.stt.transcribeAudioFile(...)tetap ada sebagai alias kompatibilitas.
api.runtime.subagent:
providerdanmodeladalah override per-run opsional, bukan perubahan sesi persisten.- OpenClaw hanya menghormati field override tersebut untuk pemanggil tepercaya.
- Untuk run fallback milik Plugin, operator harus memilihnya secara opt-in dengan
plugins.entries.<id>.subagent.allowModelOverride: true. - Gunakan
plugins.entries.<id>.subagent.allowedModelsuntuk membatasi Plugin tepercaya ke target kanonisprovider/modeltertentu, atau"*"untuk mengizinkan target apa pun secara eksplisit. - Run subagen Plugin yang tidak tepercaya tetap berfungsi, tetapi permintaan override ditolak alih-alih diam-diam fallback.
api.registerWebSearchProvider(...).
Catatan:
- Pertahankan pemilihan provider, resolusi kredensial, dan semantik permintaan bersama di inti.
- Gunakan provider web-search untuk transport pencarian khusus vendor.
api.runtime.webSearch.*adalah permukaan bersama yang disukai untuk Plugin fitur/channel yang membutuhkan perilaku pencarian tanpa bergantung pada wrapper alat agen.
api.runtime.imageGeneration
generate(...): hasilkan gambar menggunakan rantai provider image-generation yang dikonfigurasi.listProviders(...): daftar provider image-generation yang tersedia dan kemampuannya.
Rute HTTP Gateway
Plugin dapat mengekspos endpoint HTTP denganapi.registerHttpRoute(...).
path: path rute di bawah server HTTP gateway.auth: wajib. Gunakan"gateway"untuk mewajibkan auth gateway normal, atau"plugin"untuk auth/verifikasi Webhook yang dikelola Plugin.match: opsional."exact"(default) atau"prefix".replaceExisting: opsional. Memungkinkan Plugin yang sama mengganti pendaftaran rute miliknya sendiri yang sudah ada.handler: kembalikantruesaat rute menangani permintaan.
api.registerHttpHandler(...)telah dihapus dan akan menyebabkan galat pemuatan Plugin. Gunakanapi.registerHttpRoute(...)sebagai gantinya.- Rute Plugin harus mendeklarasikan
authsecara eksplisit. - Konflik
path + matchyang persis ditolak kecualireplaceExisting: true, dan satu Plugin tidak dapat mengganti rute milik Plugin lain. - Rute yang tumpang tindih dengan level
authberbeda ditolak. Pertahankan rantai fallthroughexact/prefixhanya pada level auth yang sama. - Rute
auth: "plugin"tidak menerima scope runtime operator secara otomatis. Rute ini ditujukan untuk Webhook/verifikasi tanda tangan yang dikelola Plugin, bukan pemanggilan helper Gateway yang berhak istimewa. - Rute
auth: "gateway"berjalan di dalam scope runtime permintaan Gateway, tetapi scope itu sengaja konservatif:- auth bearer shared-secret (
gateway.auth.mode = "token"/"password") mempertahankan scope runtime rute-Plugin tetap dipaku keoperator.write, bahkan jika pemanggil mengirimx-openclaw-scopes - mode HTTP tepercaya pembawa identitas (misalnya
trusted-proxyataugateway.auth.mode = "none"pada ingress privat) menghormatix-openclaw-scopeshanya saat header itu memang ada secara eksplisit - jika
x-openclaw-scopestidak ada pada permintaan rute-Plugin pembawa identitas tersebut, scope runtime fallback keoperator.write
- auth bearer shared-secret (
- Aturan praktis: jangan menganggap rute Plugin ber-auth gateway sebagai permukaan admin implisit. Jika rute Anda membutuhkan perilaku khusus admin, wajibkan mode auth pembawa identitas dan dokumentasikan kontrak header
x-openclaw-scopesyang eksplisit.
Path impor SDK Plugin
Gunakan subpath SDK yang sempit alih-alih root barrel monolitikopenclaw/plugin-sdk
saat menulis Plugin baru. Subpath inti:
| Subpath | Purpose |
|---|---|
openclaw/plugin-sdk/plugin-entry | Primitive pendaftaran Plugin |
openclaw/plugin-sdk/channel-core | Helper entry/build channel |
openclaw/plugin-sdk/core | Helper bersama generik dan kontrak payung |
openclaw/plugin-sdk/config-schema | Skema Zod root openclaw.json (OpenClawSchema) |
channel-setup,
setup-runtime, setup-adapter-runtime, setup-tools, channel-pairing,
channel-contract, channel-feedback, channel-inbound, channel-lifecycle,
channel-reply-pipeline, command-auth, secret-input, webhook-ingress,
channel-targets, dan channel-actions. Perilaku persetujuan seharusnya dikonsolidasikan
pada satu kontrak approvalCapability alih-alih bercampur di field
Plugin yang tidak terkait. Lihat Channel plugins.
Helper runtime dan config hidup di bawah subpath *-runtime yang sesuai
(approval-runtime, config-runtime, infra-runtime, agent-runtime,
lazy-runtime, directory-runtime, text-runtime, runtime-store, dll.).
openclaw/plugin-sdk/channel-runtime sudah deprecated — shim kompatibilitas untuk
Plugin lama. Kode baru seharusnya mengimpor primitive generik yang lebih sempit.index.js— entry Plugin bawaanapi.js— barrel helper/tiperuntime-api.js— barrel khusus runtimesetup-entry.js— entry Plugin setup
openclaw/plugin-sdk/*. Jangan
pernah mengimpor src/* dari package Plugin lain dari core atau dari Plugin lain.
Entry point yang dimuat melalui facade lebih memilih snapshot config runtime aktif ketika ada,
lalu fallback ke file config yang diresolusikan di disk.
Subpath khusus kemampuan seperti image-generation, media-understanding,
dan speech ada karena Plugin bawaan menggunakannya saat ini. Subpath ini tidak
secara otomatis merupakan kontrak eksternal jangka panjang yang dibekukan — periksa
halaman referensi SDK yang relevan saat mengandalkannya.
Skema message tool
Plugin seharusnya memiliki kontribusi skemadescribeMessageTool(...) khusus channel
untuk primitive non-pesan seperti reaksi, pembacaan, dan polling.
Presentasi kirim bersama seharusnya menggunakan kontrak MessagePresentation generik
alih-alih field tombol, komponen, blok, atau kartu yang native provider.
Lihat Message Presentation untuk kontrak,
aturan fallback, pemetaan provider, dan checklist penulis Plugin.
Plugin yang mampu mengirim mendeklarasikan apa yang dapat mereka render melalui kemampuan pesan:
presentationuntuk blok presentasi semantik (text,context,divider,buttons,select)delivery-pinuntuk permintaan pengiriman yang dipin
Resolusi target channel
Plugin channel seharusnya memiliki semantik target khusus channel. Pertahankan host outbound bersama tetap generik dan gunakan permukaan adapter perpesanan untuk aturan provider:messaging.inferTargetChatType({ to })memutuskan apakah target ternormalisasi seharusnya diperlakukan sebagaidirect,group, atauchannelsebelum lookup direktori.messaging.targetResolver.looksLikeId(raw, normalized)memberi tahu core apakah suatu input harus langsung melompat ke resolusi mirip-id alih-alih pencarian direktori.messaging.targetResolver.resolveTarget(...)adalah fallback Plugin ketika core membutuhkan resolusi akhir milik provider setelah normalisasi atau setelah miss direktori.messaging.resolveOutboundSessionRoute(...)memiliki konstruksi rute sesi khusus provider setelah target diresolusikan.
- Gunakan
inferTargetChatTypeuntuk keputusan kategori yang seharusnya terjadi sebelum mencari peer/grup. - Gunakan
looksLikeIduntuk pemeriksaan “perlakukan ini sebagai id target eksplisit/native”. - Gunakan
resolveTargetuntuk fallback normalisasi khusus provider, bukan untuk pencarian direktori yang luas. - Pertahankan id native provider seperti id chat, id thread, JID, handle, dan id room
di dalam nilai
targetatau parameter khusus provider, bukan di field SDK generik.
Direktori berbasis config
Plugin yang menurunkan entri direktori dari config seharusnya mempertahankan logika itu di Plugin dan menggunakan kembali helper bersama dariopenclaw/plugin-sdk/directory-runtime.
Gunakan ini saat channel memerlukan peer/grup berbasis config seperti:
- peer DM yang didorong allowlist
- peta channel/grup yang dikonfigurasi
- fallback direktori statis yang dibatasi akun
directory-runtime hanya menangani operasi generik:
- pemfilteran kueri
- penerapan batas
- helper dedupe/normalisasi
- membangun
ChannelDirectoryEntry[]
Katalog provider
Plugin provider dapat mendefinisikan katalog model untuk inferensi denganregisterProvider({ catalog: { run(...) { ... } } }).
catalog.run(...) mengembalikan bentuk yang sama dengan yang ditulis OpenClaw ke
models.providers:
{ provider }untuk satu entri provider{ providers }untuk beberapa entri provider
catalog saat Plugin memiliki id model khusus provider, default baseUrl,
atau metadata model yang dibatasi auth.
catalog.order mengontrol kapan katalog Plugin digabungkan relatif terhadap provider implisit bawaan OpenClaw:
simple: provider biasa berbasis API-key atau envprofile: provider yang muncul saat profil auth adapaired: provider yang mensintesis beberapa entri provider terkaitlate: lintasan terakhir, setelah provider implisit lain
discoverytetap berfungsi sebagai alias legacy- jika
catalogdandiscoverykeduanya terdaftar, OpenClaw menggunakancatalog
Inspeksi channel hanya-baca
Jika Plugin Anda mendaftarkan sebuah channel, pilih mengimplementasikanplugin.config.inspectAccount(cfg, accountId) di samping resolveAccount(...).
Mengapa:
resolveAccount(...)adalah jalur runtime. Jalur ini boleh mengasumsikan kredensial sudah sepenuhnya termaterialisasi dan dapat gagal cepat ketika secret yang diperlukan hilang.- Jalur perintah hanya-baca seperti
openclaw status,openclaw status --all,openclaw channels status,openclaw channels resolve, dan alur perbaikan doctor/config seharusnya tidak perlu mematerialisasi kredensial runtime hanya untuk mendeskripsikan konfigurasi.
inspectAccount(...) yang direkomendasikan:
- Kembalikan hanya state akun yang deskriptif.
- Pertahankan
enableddanconfigured. - Sertakan field sumber/status kredensial bila relevan, seperti:
tokenSource,tokenStatusbotTokenSource,botTokenStatusappTokenSource,appTokenStatussigningSecretSource,signingSecretStatus
- Anda tidak perlu mengembalikan nilai token mentah hanya untuk melaporkan
ketersediaan baca-saja. Mengembalikan
tokenStatus: "available"(dan field sumber yang cocok) sudah cukup untuk perintah bergaya status. - Gunakan
configured_unavailableketika kredensial dikonfigurasi melalui SecretRef tetapi tidak tersedia di jalur perintah saat ini.
Pack package
Direktori Plugin dapat menyertakanpackage.json dengan openclaw.extensions:
name/<fileBase>.
Jika Plugin Anda mengimpor dependensi npm, instal dependensi tersebut di direktori itu agar
node_modules tersedia (npm install / pnpm install).
Guardrail keamanan: setiap entri openclaw.extensions harus tetap berada di dalam direktori Plugin
setelah resolusi symlink. Entri yang keluar dari direktori package akan
ditolak.
Catatan keamanan: openclaw plugins install menginstal dependensi Plugin dengan
npm install --omit=dev --ignore-scripts (tanpa lifecycle script, tanpa dependensi dev saat runtime). Pertahankan pohon dependensi Plugin tetap “pure JS/TS” dan hindari package yang memerlukan build postinstall.
Opsional: openclaw.setupEntry dapat menunjuk ke modul ringan khusus setup.
Saat OpenClaw membutuhkan permukaan setup untuk Plugin channel yang dinonaktifkan, atau
saat Plugin channel diaktifkan tetapi masih belum dikonfigurasi, OpenClaw memuat setupEntry
alih-alih entry Plugin penuh. Ini menjaga startup dan setup tetap lebih ringan
saat entry Plugin utama Anda juga memasang alat, hook, atau kode khusus runtime lainnya.
Opsional: openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen
dapat membuat sebuah Plugin channel memilih jalur setupEntry yang sama selama fase
startup pra-listen gateway, bahkan ketika channel sudah dikonfigurasi.
Gunakan ini hanya ketika setupEntry sepenuhnya mencakup permukaan startup yang harus ada
sebelum gateway mulai listening. Dalam praktiknya, ini berarti setup entry
harus mendaftarkan setiap kemampuan milik channel yang dibutuhkan startup, seperti:
- pendaftaran channel itu sendiri
- rute HTTP apa pun yang harus tersedia sebelum gateway mulai listening
- metode gateway, alat, atau layanan apa pun yang harus ada selama jendela yang sama
singleAccountKeysToMovenamedAccountPromotionKeysresolveSingleAccountPromotionTarget(...)
channels.<id>.accounts.* tanpa memuat entry Plugin penuh.
Matrix adalah contoh bawaan saat ini: hanya memindahkan kunci auth/bootstrap ke
akun yang dipromosikan bernama ketika akun bernama sudah ada, dan dapat
mempertahankan kunci akun default non-kanonis yang dikonfigurasi alih-alih selalu membuat
accounts.default.
Adapter patch setup tersebut menjaga penemuan contract-surface bawaan tetap lazy. Waktu impor tetap ringan; permukaan promosi dimuat hanya saat pertama kali digunakan alih-alih masuk kembali ke startup channel bawaan saat impor modul.
Ketika permukaan startup tersebut mencakup metode RPC gateway, pertahankan pada
prefix khusus Plugin. Namespace admin inti (config.*,
exec.approvals.*, wizard.*, update.*) tetap dicadangkan dan selalu diresolusikan
ke operator.admin, bahkan jika sebuah Plugin meminta scope yang lebih sempit.
Contoh:
Metadata katalog channel
Plugin channel dapat mengiklankan metadata setup/discovery melaluiopenclaw.channel dan
petunjuk instalasi melalui openclaw.install. Ini menjaga data katalog inti tetap bebas data.
Contoh:
openclaw.channel yang berguna di luar contoh minimal:
detailLabel: label sekunder untuk permukaan katalog/status yang lebih kayadocsLabel: override teks tautan untuk tautan dokumentasipreferOver: id Plugin/channel prioritas lebih rendah yang seharusnya dikalahkan entri katalog iniselectionDocsPrefix,selectionDocsOmitLabel,selectionExtras: kontrol salinan permukaan pemilihanmarkdownCapable: menandai channel sebagai mampu Markdown untuk keputusan pemformatan keluarexposure.configured: sembunyikan channel dari permukaan daftar channel yang dikonfigurasi saat disetel kefalseexposure.setup: sembunyikan channel dari picker setup/configure interaktif saat disetel kefalseexposure.docs: tandai channel sebagai internal/pribadi untuk permukaan navigasi dokumentasishowConfigured/showInSetup: alias legacy masih diterima demi kompatibilitas; pilihexposurequickstartAllowFrom: memilih channel ini ke alur quickstartallowFromstandarforceAccountBinding: mewajibkan binding akun eksplisit bahkan ketika hanya ada satu akunpreferSessionLookupForAnnounceTarget: memilih lookup sesi saat meresolusikan target announce
~/.openclaw/mpm/plugins.json~/.openclaw/mpm/catalog.json~/.openclaw/plugins/catalog.json
OPENCLAW_PLUGIN_CATALOG_PATHS (atau OPENCLAW_MPM_CATALOG_PATHS) ke
satu atau lebih file JSON (dipisahkan koma/titik koma/PATH). Setiap file seharusnya
berisi { "entries": [ { "name": "@scope/pkg", "openclaw": { "channel": {...}, "install": {...} } } ] }. Parser juga menerima "packages" atau "plugins" sebagai alias legacy untuk kunci "entries".
Entri katalog channel yang dihasilkan dan entri katalog instalasi provider mengekspos
fakta sumber instalasi yang telah dinormalisasi di samping blok openclaw.install mentah. Fakta
ternormalisasi tersebut mengidentifikasi apakah spesifikasi npm adalah versi persis atau selector mengambang,
apakah metadata integritas yang diharapkan ada, dan apakah path sumber lokal juga tersedia.
Konsumen seharusnya memperlakukan installSource sebagai field opsional aditif sehingga
entri lama yang dibuat manual dan shim kompatibilitas tidak harus mensintesisnya.
Ini memungkinkan onboarding dan diagnostik menjelaskan state source-plane tanpa mengimpor runtime Plugin.
Entri npm eksternal resmi seharusnya memilih npmSpec persis plus
expectedIntegrity. Nama package polos dan dist-tag tetap bekerja demi
kompatibilitas, tetapi menampilkan peringatan source-plane sehingga katalog dapat bergerak
menuju instalasi yang dipin dan diperiksa integritasnya tanpa merusak Plugin yang ada.
Saat onboarding menginstal dari path katalog lokal, onboarding mencatat sebuah
entri plugins.installs dengan source: "path" dan
sourcePath relatif-workspace jika memungkinkan. Path muat operasional absolut tetap berada di
plugins.load.paths; record instalasi menghindari duplikasi path workstation lokal
ke config jangka panjang. Ini menjaga instalasi pengembangan lokal tetap terlihat bagi
diagnostik source-plane tanpa menambahkan permukaan pengungkapan path filesystem mentah kedua.
Plugin mesin konteks
Plugin mesin konteks memiliki orkestrasi konteks sesi untuk ingest, assembly, dan Compaction. Daftarkan dari Plugin Anda denganapi.registerContextEngine(id, factory), lalu pilih mesin aktif dengan
plugins.slots.contextEngine.
Gunakan ini saat Plugin Anda perlu mengganti atau memperluas pipeline konteks default
alih-alih sekadar menambahkan pencarian memori atau hooks.
compact()
tetap diimplementasikan dan delegasikan secara eksplisit:
Menambahkan kemampuan baru
Saat sebuah Plugin memerlukan perilaku yang tidak cocok dengan API saat ini, jangan melewati sistem Plugin dengan reach-in privat. Tambahkan kemampuan yang hilang. Urutan yang direkomendasikan:- definisikan kontrak inti Tentukan perilaku bersama apa yang seharusnya dimiliki core: kebijakan, fallback, penggabungan config, siklus hidup, semantik yang menghadap channel, dan bentuk helper runtime.
- tambahkan permukaan pendaftaran/runtime Plugin yang bertipe
Perluas
OpenClawPluginApidan/atauapi.runtimedengan permukaan kemampuan bertipe yang paling kecil namun berguna. - wire konsumen core + channel/fitur Channel dan Plugin fitur seharusnya mengonsumsi kemampuan baru melalui core, bukan dengan mengimpor implementasi vendor secara langsung.
- daftarkan implementasi vendor Plugin vendor lalu mendaftarkan backend mereka terhadap kemampuan tersebut.
- tambahkan cakupan kontrak Tambahkan pengujian agar kepemilikan dan bentuk pendaftaran tetap eksplisit seiring waktu.
Checklist kemampuan
Saat Anda menambahkan kemampuan baru, implementasi biasanya seharusnya menyentuh permukaan ini bersama-sama:- tipe kontrak inti di
src/<capability>/types.ts - runner/helper runtime inti di
src/<capability>/runtime.ts - permukaan pendaftaran API Plugin di
src/plugins/types.ts - wiring registry Plugin di
src/plugins/registry.ts - eksposur runtime Plugin di
src/plugins/runtime/*saat Plugin fitur/channel perlu mengonsumsinya - helper capture/test di
src/test-utils/plugin-registration.ts - penegasan kepemilikan/kontrak di
src/plugins/contracts/registry.ts - dokumentasi operator/Plugin di
docs/
Template kemampuan
Pola minimal:- core memiliki kontrak kemampuan + orkestrasi
- Plugin vendor memiliki implementasi vendor
- Plugin fitur/channel mengonsumsi helper runtime
- pengujian kontrak menjaga kepemilikan tetap eksplisit
Terkait
- Plugin architecture — model dan bentuk kemampuan publik
- Plugin SDK subpaths
- Plugin SDK setup
- Building plugins